"Fossies" - the Fresh Open Source Software Archive

Member "schily-2021-09-18/sformat/fmt.c" (20 Aug 2021, 37414 Bytes) of package /linux/privat/schily-2021-09-18.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

A hint: This file contains one or more very long lines, so maybe it is better readable using the pure text view mode that shows the contents as wrapped lines within the browser window.


    1 /* @(#)fmt.c    1.100 21/08/20 Copyright 1986-1991, 93-97, 2000-2021 J. Schilling */
    2 #include <schily/mconfig.h>
    3 #ifndef lint
    4 static  UConst char sccsid[] =
    5     "@(#)fmt.c  1.100 21/08/20 Copyright 1986-1991, 93-97, 2000-2021 J. Schilling";
    6 #endif
    7 /*
    8  *  Format & check/repair SCSI disks
    9  *
   10  *  Copyright (c) 1986-1991, 93-97, 2000-2021 J. Schilling
   11  */
   12 /*
   13  * The contents of this file are subject to the terms of the
   14  * Common Development and Distribution License, Version 1.0 only
   15  * (the "License").  You may not use this file except in compliance
   16  * with the License.
   17  *
   18  * See the file CDDL.Schily.txt in this distribution for details.
   19  * A copy of the CDDL is also available via the Internet at
   20  * http://www.opensource.org/licenses/cddl1.txt
   21  *
   22  * When distributing Covered Code, include this CDDL HEADER in each
   23  * file and include the License file CDDL.Schily.txt from this distribution.
   24  */
   25 
   26 #include <schily/stdio.h>
   27 #include <schily/standard.h>
   28 #include <schily/signal.h>
   29 #include <schily/stdlib.h>
   30 #include <schily/unistd.h>
   31 #include <schily/string.h>
   32 #include <schily/time.h>
   33 #include <schily/errno.h>
   34 #define GT_COMERR       /* #define comerr gtcomerr */
   35 #define GT_ERROR        /* #define error gterror   */
   36 #include <schily/schily.h>
   37 #include <schily/libport.h>
   38 #include <schily/nlsdefs.h>
   39 
   40 #include <scg/scgcmd.h>
   41 #include <scg/scsireg.h>
   42 #include <scg/scsidefs.h>
   43 #include <scg/scsitransp.h>
   44 
   45 #include "defect.h"
   46 #include "scsicmds.h"
   47 #include "fmt.h"
   48 
   49 #define strindex(s1, s2)    strstr((s2), (s1))
   50 
   51 char    fmt_version[] = "3.7";
   52 
   53 long        thistime = 0;
   54 struct timeval  starttime;
   55 struct timeval  stoptime;
   56 
   57 char    *Sbuf;
   58 long    Sbufsize;
   59 int xdebug;
   60 int debug;
   61 int nomap;
   62 int nowait;
   63 int force;
   64 int ask;
   65 int noformat;
   66 int save_mp;
   67 int defmodes;
   68 int no_heuristic_defaults;
   69 int scsi_compliant;
   70 int ign_not_found;
   71 
   72 int Proto;
   73 int Prpart;
   74 int label;
   75 int translate_blk;
   76 int autoformat;
   77 int reformat_only;
   78 int disable_mdl;
   79 int reassign;
   80 int greassign;
   81 int veri;
   82 int repair;
   83 int refresh_only;
   84 int wrveri;
   85 int setmodes;
   86 int modesel;
   87 LOCAL   int deftimeout;
   88 /*#define   NVERI   5*/
   89 /*extern    int n_test_patterns;*/
   90 /*#define   NWVERI  n_test_patterns*/
   91 /*#define   CVERI   1000*/
   92 /*#define   CWVERI  1000*/
   93 int Nveri   = -1;
   94 int Cveri   = -1;
   95 int CWveri  = -1;
   96 long    Vstart  = 0;
   97 long    Vend    = -1;
   98 long    MAXbad  = -1;
   99 int S;
  100 int ESDI    = 0;
  101 int do_inq;
  102 int prgeom;
  103 int prcurgeom;
  104 int clearnull;
  105 int readnull;
  106 int damage;
  107 int prdefect;
  108 int seek;
  109 int Sstart;
  110 int Sstop;
  111 int help;
  112 int xhelp;
  113 int format_confirmed;
  114 int format_done;
  115 int randv;
  116 int randrw;
  117 long    RW = -1L;
  118 char    *datafile;
  119 BOOL    datfile_present;
  120 BOOL    datfile_chk = TRUE; /* No bad data, if no data base is present */
  121 
  122 struct  disk    cur_disk;
  123 struct  disk    alt_disk;
  124 
  125 extern  char    *Lname;
  126 extern  char    *Lproto;
  127 
  128 LOCAL   void    usage           __PR((int ret));
  129 LOCAL   void    xusage          __PR((int ret));
  130 EXPORT  int main            __PR((int ac, char **av));
  131 LOCAL   void    print_product       __PR((struct scsi_inquiry *ip));
  132 LOCAL   void    select_target       __PR((SCSI *scgp));
  133 LOCAL   void    select_unit     __PR((SCSI *scgp));
  134 LOCAL   int format_one      __PR((SCSI *scgp));
  135 EXPORT  void    getdev          __PR((SCSI *scgp, BOOL print));
  136 LOCAL   void    printdev        __PR((SCSI *scgp));
  137 LOCAL   void    translate_lba       __PR((SCSI *scgp));
  138 LOCAL   void    read_sector_header  __PR((SCSI *scgp));
  139 LOCAL   void    esdi_command        __PR((SCSI *scgp));
  140 LOCAL   long    estimate_format_time    __PR((struct disk *dp, int mult));
  141 EXPORT  void    estimate_times      __PR((struct disk *dp));
  142 EXPORT  void    print_fmt_time      __PR((struct disk *dp));
  143 EXPORT  char    *datestr        __PR((void));
  144 EXPORT  void    prdate          __PR((void));
  145 EXPORT  void    getstarttime        __PR((void));
  146 EXPORT  void    getstoptime     __PR((void));
  147 EXPORT  long    gettimediff     __PR((struct timeval *tp));
  148 EXPORT  long    prstats         __PR((void));
  149 EXPORT  void    helpexit        __PR((void));
  150 EXPORT  void    disk_null       __PR((struct disk *dp, int init));
  151 
  152 LOCAL void
  153 usage(ret)
  154     int ret;
  155 {
  156     error("Usage:\tformat [options] [dev=scsidev]|[target lun [scsibus]]\n");
  157     error("options:\n");
  158     error("\tdev=target SCSI target to use\n");
  159     error("\tscgopts=spec   SCSI options for libscg\n");
  160     error("\t-help,-h\tprint this help\n");
  161     error("\t-xhelp\t\tprint extended help\n");
  162     error("\t-version\tPrint version number.\n");
  163     error("\t-nomap\t\tDo not map SCSI address to logical disk name\n");
  164     error("\t-nowait\t\tDo not wait after formatting disk\n");
  165     error("\t-force\t\tForce to continue at certain errors\n");
  166     error("\t-ask\t\tAsk again at certain critical sections\n");
  167     error("\t-noformat\tForce not to format disk\n");
  168     error("\t-smp\t\tDo not try to save mode parameters\n");
  169     error("\tdata=name\tName of diskdata file (default: 'sformat.dat')\n");
  170 #ifdef  OLD
  171     error("\t-label,-l\tproduce disk label in file 'Label'\n");
  172     error("\tlname=name\tName of output Label (default: '%s')\n", Lname);
  173     error("\tlproto=name\tName of input  Label (default: '%s')\n", Lproto);
  174 #endif
  175     error("\t-tr,-t\t\ttranslate blocknumbers\n");
  176     error("\t-auto,-a\tautoformat mode (for production systems)\n");
  177     error("\t-dmdl\t\tdo not use manufacturer defect list\n");
  178     error("\t-r\t\treformat only mode (gives less messages on label menu)\n");
  179     error("\t-reassign\treassign block (fancy mode: for prefered use)\n");
  180     error("\t-greassign\treassign block (guru mode: don't use this)\n");
  181     error("\t-verify\t\tverify disk\n");
  182     error("\t-repair\t\tverify and repair disk\n");
  183     error("\t-refresh_only\trefresh only with -repair (do not reassign)\n");
  184     error("\t-modes\t\tintercative modesense/modeselect\n");
  185     error("\t-setmodes\tdo only a modeselect instead of formatting the disk\n");
  186     error("\t-wrveri\t\tdo write verify instead of verify\n");
  187     error("\t-randv\t\trandom verify-Test\n");
  188     error("\t-randrw\t\trandom R/W-Test\n");
  189     error("\t-seek\t\tdo seek tests\n");
  190     error("\t-inq\t\tget and print Inquiry Data\n");
  191     error("\t-prgeom\t\tget and print geometry Data\n");
  192     error("\t-prdefect\tget and print defect Data\n");
  193     error("\t-Proto\t\tgenerate data base entry for disk\n");
  194 
  195     error("\n");
  196     error("\tAll answers to non numeric questions\n");
  197     error("\texcept [y]es or [Y]ES are interpreted as if <no> has been entered\n");
  198     error("\tActions that may damage data must be confirmed with <yes>\n");
  199     exit(ret);
  200 }   
  201 
  202 LOCAL void
  203 xusage(ret)
  204     int ret;
  205 {
  206     error("Usage:\tformat [options] target lun [scsibus]\n");
  207     error("Extended options:\n");
  208     error("\tdebug=#,-d\tSet to # or increment misc debug level\n");
  209     error("\tkdebug=#,kd=#\tKernel debug value for scg driver\n");
  210     error("\txdebug=#,xd=#\tDebug level for eXternal disk database\n");
  211     error("\t-verbose,-v\tincrement SCSI verbose level by one (outdated)\n");
  212     error("\t-Verbose,-V\tincrement SCSI command transport verbose level by one\n");
  213     error("\t-silent,-s\tdo not print status of failed SCSI commands\n");
  214     error("\t-defmodes\tGet default mode parameters from disk\n");
  215     error("\t-no_defaults\tDo not set heuristic defaults\n");
  216     error("\t-scsi_compliant\tBe as SCSI-compliant as possible\n");
  217     error("\t-ign_not_found\tIgnore record not found errors on verify\n");
  218     error("\ttimeout=#\tTimeout for SCSI commands (default %d)\n", deftimeout);
  219     error("\tVL=#\t\tNumber of verify loops (default %d)\n", NVERI);
  220     error("\tRW=#\t\tNumber of random R/W loops\n");
  221     error("\t\t\t(default Number of physical Sectors / 100)\n");
  222     error("\tCveri=#\t\tNumber of blocks/verify\n");
  223     error("\tCWveri=#\tNumber of blocks/write-verify\n");
  224     error("\tVstart=#\tNumber of first block to verify\n");
  225     error("\tVend=#\tNumber of last block to verify\n");
  226     error("\tmaxbad=#\tNumber of max. bad blocks/verify loop before reformat \n");
  227 #ifdef  OLD
  228     error("\tnhead=#\t\tNumber of Heads\n");
  229     error("\tlhead=#\t\tNumber of logical Heads (Label)\n");
  230     error("\tpcyl=#\t\tNumber of physical Cylinders\n");
  231     error("\tatrk=#\t\tNumber of alternate Tracks/Volume\n");
  232     error("\tlacyl=#\t\tNumber of Label alternate Cylinders\n");
  233     error("\tlncyl=#\t\tNumber of data Cylinders (Label)\n");
  234     error("\ttpz=#\t\tNumber of Tracks/Zone\n");
  235     error("\tspt=#\t\tNumber of physical Sectors/Track\n");
  236     error("\tlspt=#\t\tNumber of logical Sectors/Track (Label)\n");
  237     error("\taspz=#\t\tNumber of alternate Sectors/Zone\n");
  238     error("\tsecsize=#\tNumber of Bytes/Sector\n");
  239     error("\trpm=#\t\tNumber of revolutions/minute\n");
  240     error("\ttrskew=#\tTrack skew\n");
  241     error("\tcylskew=#\tCylinder skew\n");
  242     error("\tinterlv=#\tInterleave\n");
  243     error("\tfmtpat=#\tFormat Pattern\n");
  244 #endif
  245 
  246     exit(ret);
  247 }   
  248 
  249 char opts[] = "version,dev*,scgopts*,kdebug#,kd#,xdebug#,xd#,debug#,d+,silent,s,verbose+,v+,Verbose+,V+,nomap,nowait,force,ask,noformat,smp,defmodes,no_defaults,scsi_compliant,ign_not_found,data*,Proto,Prpart,P,label,l,lname*,lproto*,tr,t,auto,a,dmdl,r,reassign,greassign,verify,repair,refresh_only,modes,setmodes,timeout#,noparity,wrveri,VL#,Cveri#,C#,Vstart#L,Vend#L,CWveri#,CW#,maxbad#L,randv,randrw,RW#L,S,ESDI#,inq,prgeom,prcurgeom,clearnull,readnull,damage,prdefect,seek,start,stop,nhead#l,lhead#l,pcyl#l,atrk#l,lacyl#l,lncyl#l,tpz#l,spt#l,lspt#l,aspz#l,secsize#l,rpm#l,trskew#l,cylskew#l,interlv#l,fmtpat#l,help,h,xhelp";
  250 
  251 #define MAXVERI 100
  252 
  253 EXPORT int
  254 main(ac, av)
  255     int ac;
  256     char    *av[];
  257 {
  258     int ret = 0;
  259     int fcount;
  260     int cac;
  261     char    * const *cav;
  262     int scsibus = -1;
  263     int target  = -1;
  264     int lun = -1;
  265     BOOL    prvers  = FALSE;
  266     int silent  = 0;
  267     int verbose = 0;
  268     int kdebug  = 0;
  269     int noparity = 0;
  270     SCSI    *scgp;
  271     char    *dev = NULL;
  272     char    *scgopts = NULL;
  273 
  274     save_args(ac, av);
  275 
  276     (void) setlocale(LC_ALL, "");
  277 
  278 #ifdef  USE_NLS
  279 #if !defined(TEXT_DOMAIN)   /* Should be defined by cc -D */
  280 #define TEXT_DOMAIN "sformat"   /* Use this only if it weren't */
  281 #endif
  282     { char  *dir;
  283     dir = searchfileinpath("share/locale", F_OK,
  284                     SIP_ANY_FILE|SIP_NO_PATH, NULL);
  285     if (dir)
  286         (void) bindtextdomain(TEXT_DOMAIN, dir);
  287     else
  288 #if defined(PROTOTYPES) && defined(INS_BASE)
  289     (void) bindtextdomain(TEXT_DOMAIN, INS_BASE "/share/locale");
  290 #else
  291     (void) bindtextdomain(TEXT_DOMAIN, "/usr/share/locale");
  292 #endif
  293     (void) textdomain(TEXT_DOMAIN);
  294     }
  295 #endif  /* USE_NLS */
  296     disk_null(&cur_disk, 1);
  297     disk_null(&alt_disk, 1);
  298 
  299     cac = --ac;
  300     cav = ++av;
  301 
  302     if (getallargs(&cac, &cav, opts,
  303 #ifndef lint        /* lint kann leider nur 52 args !!! */
  304             &prvers, &dev, &scgopts,
  305             &kdebug, &kdebug, &xdebug, &xdebug, &debug, &debug,
  306             &silent, &silent,
  307             &verbose, &verbose,
  308             &verbose, &verbose,
  309             &nomap,
  310             &nowait,
  311             &force, &ask,
  312             &noformat,
  313             &save_mp,
  314             &defmodes,
  315             &no_heuristic_defaults,
  316             &scsi_compliant,
  317             &ign_not_found,
  318             &datafile,
  319             &Proto, &Prpart, &Prpart,
  320             &label, &label,
  321             &Lname, &Lproto,
  322             &translate_blk, &translate_blk,
  323             &autoformat, &autoformat,
  324             &disable_mdl,
  325             &reformat_only,
  326             &reassign, &greassign,
  327             &veri, &repair, &refresh_only,
  328             &modesel, &setmodes,
  329             &deftimeout,
  330             &noparity,
  331             &wrveri, &Nveri, &Cveri, &Cveri,
  332             &Vstart, &Vend,
  333             &CWveri, &CWveri,
  334             &MAXbad,
  335             &randv,
  336             &randrw, &RW,
  337             &S,
  338             &ESDI,
  339             &do_inq,
  340             &prgeom, &prcurgeom,
  341             &clearnull,
  342             &readnull,
  343             &damage,
  344             &prdefect,
  345             &seek,
  346             &Sstart, &Sstop,
  347             &cur_disk.nhead, &cur_disk.lhead,
  348             &cur_disk.pcyl, &cur_disk.atrk,
  349             &cur_disk.lacyl, &cur_disk.lncyl,
  350             &cur_disk.tpz, &cur_disk.spt,
  351             &cur_disk.lspt, &cur_disk.aspz,
  352             &cur_disk.secsize,
  353             &cur_disk.rpm,
  354             &cur_disk.track_skew, &cur_disk.cyl_skew,
  355             &cur_disk.interleave, &cur_disk.fmt_pattern,
  356             &help, &help, &xhelp,
  357 
  358 #endif
  359                     0) < 0) {
  360         errmsgno(EX_BAD, "Bad flag: %s.\n", cav[0]);
  361         usage(EX_BAD);
  362     }
  363     if (help)
  364         usage(0);
  365     else if (xhelp)
  366         xusage(0);
  367     if (prvers) {
  368         gtprintf("sformat %s (%s-%s-%s)\n\n", fmt_version, HOST_CPU, HOST_VENDOR, HOST_OS);
  369         gtprintf("Copyright (C) 1986-1991, 93-97, 2000-2021 %s\n", _("Jörg Schilling"));
  370         gtprintf("This is free software; see the source for copying conditions.  There is NO\n");
  371         gtprintf("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
  372         exit(0);
  373     }
  374 
  375     if (Sstart && Sstop)
  376         comerrno(EX_BAD, "Only one of start/stop\n");
  377 
  378     if (getenv("FMT_SILENT"))
  379         silent = TRUE;
  380     if (getenv("FMT_AUTO"))
  381         autoformat = TRUE;
  382 
  383     if (autoformat)
  384         defmodes = TRUE;
  385 
  386     if (setmodes)
  387         noformat = TRUE;
  388 
  389     if (autoformat && (force || noformat))
  390         comerrno(EX_BAD, "Cannot specify force/noformat in auto mode\n");
  391 
  392     if (kdebug)
  393         silent = TRUE;
  394 
  395     if (Proto) {
  396         Prpart = TRUE;
  397         defmodes = TRUE;
  398         no_heuristic_defaults = TRUE;
  399         scsi_compliant = TRUE;
  400     }
  401 
  402     if (Nveri != -1 && (Nveri < 0 || Nveri > 1000))
  403         comerrno(EX_BAD, "Bad number of Verify loops\n");
  404     if (Cveri != -1 && (Cveri < 1 || Cveri > 65000))
  405         comerrno(EX_BAD, "Bad number of Sectors/Verify\n");
  406     if (CWveri != -1 && CWveri < 1)
  407         comerrno(EX_BAD, "Bad number of Sectors/Write-Verify\n");
  408     if (MAXbad != -1 && (MAXbad <= 0L || MAXbad > 127L))
  409         comerrno(EX_BAD, "Bad number of max. bad Blocks / verify loop\n");
  410     if (Vstart < 0L || (Vend > 0L && Vstart > Vend))
  411         comerrno(EX_BAD, "Bad verify start %ld.\n", Vstart);
  412 
  413     if (cur_disk.nhead == 0 || cur_disk.nhead > 32) /* XXX */
  414         comerrno(EX_BAD, "Bad number of heads\n");
  415     if (cur_disk.lhead == 0 || cur_disk.lhead > 32) /* XXX */
  416         comerrno(EX_BAD, "Bad number of logical heads\n");
  417 
  418     if (cur_disk.fmt_pattern < -1 || cur_disk.fmt_pattern > 0xFF)
  419         comerrno(EX_BAD, "Bad format pattern\n");
  420 
  421     save_mp ^= 1;
  422 
  423     fcount = 0;
  424     cac = ac;
  425     cav = av;
  426 
  427     while (getfiles(&cac, &cav, opts) > 0) {
  428         fcount++;
  429         switch (fcount) {
  430 
  431         case 1:
  432             if (*astoi(cav[0], &target) != '\0') {
  433                 errmsgno(EX_BAD,
  434                     "Target '%s' is not a Number.\n",
  435                                 cav[0]);
  436                 usage(EX_BAD);
  437                 /* NOTREACHED */
  438             }
  439             break;
  440         case 2:
  441             if (*astoi(cav[0], &lun) != '\0') {
  442                 errmsgno(EX_BAD,
  443                     "Lun '%s' is not a Number.\n",
  444                                 cav[0]);
  445                 usage(EX_BAD);
  446                 /* NOTREACHED */
  447             }
  448             break;
  449         case 3:
  450             if (*astoi(cav[0], &scsibus) != '\0') {
  451                 errmsgno(EX_BAD,
  452                     "Scsibus '%s' is not a Number.\n",
  453                                 cav[0]);
  454                 usage(EX_BAD);
  455                 /* NOTREACHED */
  456             }
  457             break;
  458         default:
  459             errmsgno(EX_BAD, "Unknown arg '%s'.\n", cav[0]);
  460             usage(EX_BAD);
  461             /* NOTREACHED */
  462         }
  463         cac--;
  464         cav++;
  465     }
  466     getstarttime();
  467 
  468     scg_remote();
  469     if (dev) {
  470         char    errstr[80];
  471 
  472 /*      if ((scgp = scg_open(dev, errstr, sizeof (errstr), debug, lverbose)) == (SCSI *)0)*/
  473         if ((scgp = scg_open(dev, errstr, sizeof (errstr), debug, 0)) == (SCSI *)0)
  474             comerr("%s%sCannot open SCSI driver.\n", errstr, errstr[0]?". ":"");
  475     } else {
  476         if (scsibus == -1 && target >= 0 && lun >= 0)
  477             scsibus = 0;
  478 
  479         scgp = scg_smalloc();
  480         scgp->debug = debug;
  481         scgp->kdebug = kdebug;
  482 
  483         scg_settarget(scgp, scsibus, target, lun);
  484         if (scg__open(scgp, NULL) <= 0)
  485             comerr("Cannot open SCSI driver.\n");
  486     }
  487     if (scgopts) {
  488         int i = scg_opts(scgp, scgopts);
  489         if (i <= 0)
  490             exit(i < 0 ? EX_BAD : 0);
  491     }
  492     scgp->silent = silent;
  493     scgp->verbose = verbose;
  494     scgp->debug = debug;
  495     scgp->kdebug = kdebug;
  496     if (deftimeout > 0)
  497         scgp->deftimeout = deftimeout;
  498     scgp->noparity = noparity;
  499 
  500     Sbufsize = scg_bufsize(scgp, 256*1024L);
  501     if ((Sbuf = scg_getbuf(scgp, Sbufsize)) == NULL)
  502         comerr("Cannot get SCSI I/O buffer.\n");
  503     if (debug)
  504         printf("bufsize: %ld bufaddr: %p\n", Sbufsize, Sbuf);
  505 
  506     if (CWveri > (Sbufsize/MIN_SECSIZE))
  507         comerrno(EX_BAD, "Too many Sectors/Write-Verify\n");
  508 
  509     if ((datfile_present = opendatfile(datafile)) == TRUE)
  510         datfile_chk = datfile_chksum();
  511 
  512     if (!autoformat) {
  513 /*      signal(SIGINT, sighandler);*/
  514     }
  515 
  516     gtprintf("sformat SCSI format/analysis/repair utilities\n");
  517     gtprintf("Release %s, Copyright J. Schilling\n\n", fmt_version);
  518 
  519     if (!datfile_chk) {
  520         if (datfile_present)
  521             error(
  522             "Disk database '%s' contains uncertified data.\n",
  523                             datfilename());
  524         if (autoformat) {
  525             error("Datenbasis ist zerstoert.\n");
  526             exit(EX_BAD);
  527         }
  528     }
  529 
  530 /* XXX schon vor scg__open()! */
  531 /*  if (scgp->scsibus < 0)*/
  532 /*      scgp->scsibus = 0;*/
  533     if (scg_target(scgp) < 0 || scg_target(scgp) > 7 || scg_lun(scgp) < 0 || scg_lun(scgp) > 7) {
  534         if (autoformat || scg_target(scgp) != -1 || scg_lun(scgp) != -1)
  535             errmsgno(EX_BAD, "Target or lun missing or bad\n");
  536         if (autoformat)
  537             exit(EX_BAD);
  538         select_target(scgp);
  539         exit(0);
  540     }
  541     if (prgeom || prcurgeom)
  542         ret = printgeom(scgp, prcurgeom);
  543     else
  544         ret = format_one(scgp);
  545     exit(ret);
  546     /* NOTREACHED */
  547     return (ret);       /* Keep lint happy */
  548 }   /* end of main() */
  549 
  550 LOCAL void
  551 print_product(ip)
  552     struct  scsi_inquiry *ip;
  553 {
  554     printf("'%.8s' ", ip->inq_vendor_info);
  555     printf("'%.16s' ", ip->inq_prod_ident);
  556     printf("'%.4s' ", ip->inq_prod_revision);
  557     if (ip->add_len < 31) {
  558         printf("NON CCS ");
  559     }
  560     scg_printdev(ip);
  561 }
  562 
  563 LOCAL void
  564 select_target(scgp)
  565     SCSI    *scgp;
  566 {
  567     int initiator;
  568 #ifdef  FMT
  569     int cscsibus = scg_scsibus(scgp);
  570     int ctarget  = scg_target(scgp);
  571     int clun     = scg_lun(scgp);
  572 #endif
  573     int n;
  574     int low = -1;
  575     int high    = -1;
  576     int bus;
  577     int tgt;
  578     int lun = 0;
  579     int err;
  580     BOOL    have_tgt;
  581 
  582     scgp->silent++;
  583 
  584     for (bus = 0; bus < 16; bus++) {
  585         scg_settarget(scgp, bus, 0, 0);
  586 
  587         if (!scg_havebus(scgp, bus))
  588             continue;
  589 
  590         initiator = scg_initiator_id(scgp);
  591         printf("scsibus%d:\n", bus);
  592 
  593         for (tgt = 0; tgt < 16; tgt++) {
  594             n = bus*100 + tgt;
  595 
  596             scg_settarget(scgp, bus, tgt, lun);
  597             seterrno(0);
  598             have_tgt = unit_ready(scgp) || scgp->scmd->error != SCG_FATAL;
  599             err = geterrno();
  600             if (err == EPERM || err == EACCES)
  601                 exit(EX_BAD);
  602 
  603             if (!have_tgt && tgt > 7) {
  604                 if (scgp->scmd->ux_errno == EINVAL)
  605                     break;
  606                 continue;
  607             }
  608 
  609 #ifdef  FMT
  610             if (print_disknames(bus, tgt, -1) < 8)
  611                 printf("\t");
  612             else
  613                 printf(" ");
  614 #else
  615             printf("\t");
  616 #endif
  617             if (printf("%d,%d,%d", bus, tgt, lun) < 8)
  618                 printf("\t");
  619             else
  620                 printf(" ");
  621             printf("%3d) ", n);
  622             if (tgt == initiator) {
  623                 printf("HOST ADAPTOR\n");
  624                 continue;
  625             }
  626             if (!have_tgt) {
  627                 printf("*\n");
  628                 continue;
  629             }
  630             if (low < 0)
  631                 low = n;
  632             high = n;
  633 
  634             getdev(scgp, FALSE);
  635             print_product(scgp->inq);
  636         }
  637     }
  638     scgp->silent--;
  639 
  640     if (low < 0)
  641         comerrno(EX_BAD, "No target found.\n");
  642     n = -1;
  643 #ifdef  FMT
  644     getint("Select target", &n, low, high);
  645     bus = n/100;
  646     tgt = n%100;
  647     scg_settarget(scgp, bus, tgt, lun);
  648     select_unit(scgp);
  649 
  650     scg_settarget(scgp, cscsibus, ctarget, clun);
  651 #else
  652     exit(0);
  653 #endif
  654 }
  655 
  656 LOCAL void
  657 select_unit(scgp)
  658     SCSI    *scgp;
  659 {
  660     int initiator;
  661     int clun    = scg_lun(scgp);
  662     int low = -1;
  663     int high    = -1;
  664     int lun;
  665 
  666     scgp->silent++;
  667 
  668     printf("scsibus%d target %d:\n", scg_scsibus(scgp), scg_target(scgp));
  669 
  670     initiator = scg_initiator_id(scgp);
  671     for (lun = 0; lun < 8; lun++) {
  672 
  673 #ifdef  FMT
  674         if (print_disknames(scg_scsibus(scgp), scg_target(scgp), lun) < 8)
  675             printf("\t");
  676         else
  677             printf(" ");
  678 #else
  679         printf("\t");
  680 #endif
  681         if (printf("%d,%d,%d", scg_scsibus(scgp), scg_target(scgp), lun) < 8)
  682             printf("\t");
  683         else
  684             printf(" ");
  685         printf("%3d) ", lun);
  686         if (scg_target(scgp) == initiator) {
  687             printf("HOST ADAPTOR\n");
  688             continue;
  689         }
  690         scg_settarget(scgp, scg_scsibus(scgp), scg_target(scgp), lun);
  691         if (!unit_ready(scgp) && scgp->scmd->error == SCG_FATAL) {
  692             printf("*\n");
  693             continue;
  694         }
  695         if (unit_ready(scgp)) {
  696             /* non extended sense illegal lun */
  697             if (scgp->scmd->sense.code == 0x25) {
  698                 printf("BAD UNIT\n");
  699                 continue;
  700             }
  701         }
  702         if (low < 0)
  703             low = lun;
  704         high = lun;
  705 
  706         getdev(scgp, FALSE);
  707         print_product(scgp->inq);
  708     }
  709     scgp->silent--;
  710 
  711     if (low < 0)
  712         comerrno(EX_BAD, "No lun found.\n");
  713     lun = -1;
  714 #ifdef  FMT
  715     getint("Select lun", &lun, low, high);
  716     scg_settarget(scgp, scg_scsibus(scgp), scg_target(scgp), lun);
  717     format_one(scgp);
  718 #else
  719     exit(0);
  720 #endif
  721 
  722     scg_settarget(scgp, scg_scsibus(scgp), scg_target(scgp), clun);
  723 }
  724 
  725 LOCAL int
  726 format_one(scgp)
  727     SCSI    *scgp;
  728 {
  729     struct disk *dp = &cur_disk;
  730     int ret = 0;
  731     int i;
  732 
  733     printf("scsibus%d target %d lun %d\n", scg_scsibus(scgp), scg_target(scgp), scg_lun(scgp));
  734     if (checkmount(scg_scsibus(scgp), scg_target(scgp), scg_lun(scgp), -1L, 0L)) {
  735         gtprintf("WARNING: Disk has mounted partitions. ");
  736         if (!yes("Continue? "))
  737             exit(EX_BAD);
  738     }
  739     if (do_inq)
  740         scgp->silent++;
  741     getdev(scgp, TRUE);
  742     if (scgp->scmd->error == SCG_FATAL)
  743         comerrno(EX_BAD, "Cannot select Drive.\n");
  744     if (!do_inq)
  745         printdev(scgp);
  746     else
  747         scgp->silent--;
  748     if (do_inq) {
  749         if (scgp->verbose && (scgp->inq->add_len+5) > sizeof (struct scsi_inquiry)) {
  750             inquiry(scgp, Sbuf, (int)(scgp->inq->add_len+5));
  751 
  752             for (i = 0; i < (int)scgp->inq->add_len+5; i++) {
  753                 if ((Sbuf[i]&0xFF) >= ' ' &&
  754                             (Sbuf[i]&0xFF) <= '~')
  755                     printf("%c", Sbuf[i]);
  756                 else
  757                     printf("\\%03o", Sbuf[i]&0xFF);
  758             }
  759             printf("\n");
  760         }
  761         return (0);
  762     }
  763     if (Sstart) {
  764         start_stop_unit(scgp, Sstart);
  765         return (0);
  766     }
  767     scgp->silent++;
  768     for (i = 0; ; i++) {
  769         if (unit_ready(scgp))
  770             break;
  771         if (i > 30 || scgp->scmd->error >= SCG_FATAL) {
  772             scg_printerr(scgp);
  773             comerrno(EX_BAD, "Drive not ready.\n");
  774         }
  775         if (scgp->scmd->scb.busy ||
  776             (scgp->scmd->scb.chk &&
  777             (scgp->scmd->sense_count >= 3 && scgp->scmd->sense.code >= 0x70 &&
  778                 ((struct scsi_ext_sense *)&scgp->scmd->sense)->key
  779                 == SC_NOT_READY)) ||
  780                 scgp->scmd->sense.code == 0x04 ||
  781                 scgp->scmd->u_sense.cmd_sense[0] == 0x84)
  782             sleep(1);
  783     }
  784     /*
  785      * Da ACB-5500 und die ACB-4000 Serie nicht zu unterscheiden sind,
  786      * wenn das Laufwerk nicht bereit ist, wird hier noch einmal
  787      * versucht, den Controllertyp zu bestimmen.
  788      */
  789     if (scgp->dev == DEV_ACB40X0)
  790         getdev(scgp, FALSE);
  791     scgp->silent--;
  792 
  793 
  794     scgp->silent++;
  795     if (read_capacity(scgp) >= 0)       /* Adaptec 40x0 reagiert uebel, wenn*/
  796         (void) seek_scsi(scgp, 0L); /* die Platte nicht formatiert ist */
  797     for (i = 0; i < 100; i++) {
  798         usleep(200000);
  799         if (unit_ready(scgp))
  800             break;
  801     }
  802     scgp->silent--;
  803     (void) rezero_unit(scgp);
  804 
  805     /*
  806      * Exit here on wrong device type?
  807      */
  808     if (scgp->inq->type == INQ_DASD || scgp->inq->type == INQ_ROMD ||
  809                         scgp->inq->type == INQ_OMEM) {
  810         read_sinfo(scgp, dp, FALSE);
  811         print_sinfo(stdout, scgp);
  812     }
  813 
  814     if (reassign || greassign) {
  815         reassign_one(scgp);
  816         /* NOTREACHED */
  817     } else if (translate_blk) {
  818         if (strindex("EMULEX", scgp->inq->inq_vendor_info))
  819             read_sector_header(scgp);
  820         else
  821             translate_lba(scgp);
  822         return (0);
  823     } else if (veri || repair) {
  824         int nbad = 0;
  825 
  826         verify_disk(scgp, dp, 0, Vstart, Vend, MAXbad);
  827         nbad = print_bad();
  828         if (!is_ccs(scgp->dev)) {       /* XXX Adaptec ?? */
  829             /* Only print them */
  830             (void) bad_to_def(scgp);
  831         } else if (repair && nbad > 0) {
  832             gtprintf("WARNING: Repair may change data on disk.\n");
  833             if (yes("Do you want to continue? "))
  834                 repair_found_blocks(scgp, nbad);
  835         }
  836         return (0);
  837     } else if (modesel) {
  838         do_modes(scgp);
  839         /* NOTREACHED */
  840     } else if (randv) {
  841             return (random_v_test(scgp, Vstart, Vend));
  842     } else if (randrw) {
  843         gtprintf("WARNING: Random read/write-test may destroy data.\n");
  844         if (yes("Do you want to continue? "))
  845             return (random_rw_test(scgp, Vstart, Vend));
  846         return (0);
  847     }
  848     else if (ESDI)
  849         esdi_command(scgp);
  850     else if (clearnull)
  851         clear_phys_null(scgp);
  852     else if (readnull)
  853         read_phys_null(scgp, scgp->dev != DEV_MD21 && scgp->dev != DEV_MD23);
  854     else if (damage)
  855         damage_phys_blk(scgp);
  856     else if (prdefect) {
  857         (void) read_defect_list(scgp, 1, SC_DEF_BLOCK, TRUE); flush();
  858         (void) read_defect_list(scgp, 1, SC_DEF_BFI, TRUE); flush();
  859         (void) read_defect_list(scgp, 1, SC_DEF_PHYS, TRUE); flush();
  860         (void) read_defect_list(scgp, 2, SC_DEF_BLOCK, TRUE); flush();
  861         (void) read_defect_list(scgp, 2, SC_DEF_BFI, TRUE); flush();
  862         (void) read_defect_list(scgp, 2, SC_DEF_PHYS, TRUE); flush();
  863         return (0);
  864     } else if (Sstart || Sstop) {
  865         start_stop_unit(scgp, Sstart);
  866         return (0);
  867     } else if (seek) {
  868         int err = 0;
  869         long    start = Vstart;
  870         long    end;
  871         long    amount;
  872 
  873         end = scgp->cap->c_baddr;
  874         if (start < 0 || start > end)
  875             start = 0L;
  876         if (Vend > 0 && Vend < end)
  877             end = Vend;
  878         amount = end - start + 1;
  879         printf("start: %ld end: %ld amount: %ld last baddr: %ld\n",
  880                     start, end, amount, (long)scgp->cap->c_baddr);
  881 
  882         gtprintf("Select full stroke or random seeks:\n");
  883         if (yes("Full stroke seek? ")) for (;;) {
  884             if (i == 0)
  885                 getstarttime();
  886             i++;
  887             if (read_scsi(scgp, Sbuf, start, 1) < 0)
  888                 err++;
  889             if (read_scsi(scgp, Sbuf, end, 1) < 0)
  890                 err++;
  891 
  892             if (i% 1000 == 0) {
  893                 getstoptime();
  894                 gtprintf("Total: %d errs: %d %ld.%03ldms/seek\n",
  895                     i, err,
  896                     gettimediff(0)/(i/1000),
  897                     gettimediff(0)%1000);
  898             }
  899         } else for (;;) {
  900             if (i == 0)
  901                 getstarttime();
  902             i++;
  903 #ifdef  HAVE_DRAND48
  904             if (read_scsi(scgp, Sbuf,
  905                     start + drand48() * amount, 1) < 0) {
  906 #else
  907             if (read_scsi(scgp, Sbuf,
  908                     start + rand() % amount, 1) < 0) {
  909 #endif
  910                 err++;
  911                 gtprintf("Gesamt: %d errs: %d\n", i, err);
  912             }
  913             if (i% 1000 == 0) {
  914                 getstoptime();
  915                 gtprintf("Total: %d errs: %d %ld.%03ldms/seek\n",
  916                     i, err,
  917                     gettimediff(0)/(i/1000),
  918                     gettimediff(0)%1000);
  919             }
  920         }
  921     }
  922 
  923     scgp->silent++;
  924     if (read_capacity(scgp) >= 0)       /* Adaptec 40x0 reagiert uebel, wenn*/
  925         (void) seek_scsi(scgp, 0L); /* die Platte nicht formatiert ist */
  926     for (i = 0; i < 100; i++) {
  927         usleep(100000);
  928         if (unit_ready(scgp))
  929             break;
  930     }
  931     scgp->silent--;
  932     (void) rezero_unit(scgp);
  933     if (scgp->inq->type != INQ_DASD && scgp->inq->type != INQ_ROMD &&
  934         scgp->inq->type != INQ_OMEM) {
  935         comerrno(EX_BAD, "Bad Device type: 0x%x\n", (int)scgp->inq->type);
  936     } else switch (scgp->dev) {
  937 
  938     case DEV_ACB40X0:
  939     case DEV_ACB4000:
  940     case DEV_ACB4010:
  941     case DEV_ACB4070:
  942     case DEV_ACB5500:   i = Adaptec4000(scgp);  break;
  943     case DEV_ACB4520A:
  944     case DEV_ACB4525:
  945     case DEV_MD21:
  946     case DEV_MD23:
  947     case DEV_NON_CCS_DSK:
  948     case DEV_CCS_GENDISK:
  949                 i = Emulex_MD21(scgp);  break;
  950     case DEV_SONY_SMO:
  951                 i = Emulex_MD21(scgp);  break; /* Temporaer */
  952     default:
  953     case DEV_UNKNOWN:   errmsgno(EX_BAD, "Unknown Device\n");
  954                 i = Emulex_MD21(scgp);  break;
  955     }
  956 
  957     prstats();
  958 
  959     if (i == FALSE) {
  960         if (autoformat) {
  961             error("A C H T U N G\n");
  962             error("Diese Platte laeszt sich nicht formatieren\n");
  963             error("Bitte Entwicklung benachrichtigen\n");
  964             exit(EX_BAD);
  965         } else {
  966             comerrno(EX_BAD, "Cannot format disk.\n");
  967         }
  968     }
  969 
  970     create_label(scgp, dp);
  971 
  972     ret = verify_and_repair_disk(scgp, dp);
  973 
  974     label_disk(scgp, dp);
  975     convert_def_blk(scgp);
  976     write_def_blk(scgp, TRUE);
  977     return (ret);
  978 }
  979 
  980 EXPORT void
  981 getdev(scgp, print)
  982     SCSI    *scgp;
  983     BOOL    print;
  984 {
  985     BOOL    got_inquiry = TRUE;
  986     register struct scsi_inquiry *inq = scgp->inq;
  987 
  988     fillbytes((caddr_t)inq, sizeof (*inq), '\0');
  989     scgp->dev = DEV_UNKNOWN;
  990     scgp->silent++;
  991     (void) unit_ready(scgp);
  992     if (scgp->scmd->error >= SCG_FATAL &&
  993                 !(scgp->scmd->scb.chk && scgp->scmd->sense_count > 0)) {
  994         scgp->silent--;
  995         return;
  996     }
  997 
  998 
  999 /*  if (scgp->scmd->error < SCG_FATAL || scgp->scmd->scb.chk && scgp->scmd->sense_count > 0){*/
 1000 
 1001     if (inquiry(scgp, (caddr_t)inq, sizeof (*inq)) < 0) {
 1002         got_inquiry = FALSE;
 1003         if (scgp->verbose) {
 1004             printf(
 1005         "error: %d scb.chk: %d sense_count: %d sense.code: 0x%x\n",
 1006                 scgp->scmd->error, (int)scgp->scmd->scb.chk,
 1007                 scgp->scmd->sense_count, (int)scgp->scmd->sense.code);
 1008         }
 1009             /*
 1010              * Folgende Kontroller kennen das Kommando
 1011              * INQUIRY nicht:
 1012              *
 1013              * ADAPTEC  ACB-4000, ACB-4010, ACB 4070
 1014              * SYSGEN   SC4000
 1015              *
 1016              * Leider reagieren ACB40X0 und ACB5500 identisch
 1017              * wenn drive not ready (code == not ready),
 1018              * sie sind dann nicht zu unterscheiden.
 1019              */
 1020 
 1021         if (scgp->scmd->scb.chk && scgp->scmd->sense_count == 4) {
 1022             /* Test auf SYSGEN           */
 1023             (void) qic02(scgp, 0x12);   /* soft lock on  */
 1024             if (qic02(scgp, 1) < 0) {   /* soft lock off */
 1025                 scgp->dev = DEV_ACB40X0;
 1026                 scgp->dev = acbdev(scgp);
 1027             } else {
 1028                 scgp->dev = DEV_SC4000;
 1029                 inq->type = INQ_SEQD;
 1030                 inq->removable = 1;
 1031             }
 1032         }
 1033     }
 1034     switch (inq->type) {
 1035 
 1036     case INQ_DASD:
 1037         if (inq->add_len == 0) {
 1038             if (scgp->dev == DEV_UNKNOWN && got_inquiry) {
 1039                 scgp->dev = DEV_ACB5500;
 1040                 strncpy(inq->inq_info_space,
 1041                     "ADAPTEC ACB-5500        FAKE",
 1042                     sizeof (inq->inq_info_space));
 1043 
 1044             } else switch (scgp->dev) {
 1045 
 1046             case DEV_ACB40X0:
 1047                 strncpy(inq->inq_info_space,
 1048                     "ADAPTEC ACB-40X0        FAKE",
 1049                     sizeof (inq->inq_info_space));
 1050                 break;
 1051             case DEV_ACB4000:
 1052                 strncpy(inq->inq_info_space,
 1053                     "ADAPTEC ACB-4000        FAKE",
 1054                     sizeof (inq->inq_info_space));
 1055                 break;
 1056             case DEV_ACB4010:
 1057                 strncpy(inq->inq_info_space,
 1058                     "ADAPTEC ACB-4010        FAKE",
 1059                     sizeof (inq->inq_info_space));
 1060                 break;
 1061             case DEV_ACB4070:
 1062                 strncpy(inq->inq_info_space,
 1063                     "ADAPTEC ACB-4070        FAKE",
 1064                     sizeof (inq->inq_info_space));
 1065                 break;
 1066             }
 1067         } else if (inq->add_len < 31) {
 1068             scgp->dev = DEV_NON_CCS_DSK;
 1069 
 1070         } else if (strindex("EMULEX", inq->inq_vendor_info)) {
 1071             if (strindex("MD21", inq->inq_prod_ident))
 1072                 scgp->dev = DEV_MD21;
 1073             if (strindex("MD23", inq->inq_prod_ident))
 1074                 scgp->dev = DEV_MD23;
 1075             else
 1076                 scgp->dev = DEV_CCS_GENDISK;
 1077         } else if (strindex("ADAPTEC", inq->inq_vendor_info)) {
 1078             if (strindex("ACB-4520", inq->inq_prod_ident))
 1079                 scgp->dev = DEV_ACB4520A;
 1080             if (strindex("ACB-4525", inq->inq_prod_ident))
 1081                 scgp->dev = DEV_ACB4525;
 1082             else
 1083                 scgp->dev = DEV_CCS_GENDISK;
 1084         } else if (strindex("SONY", inq->inq_vendor_info) &&
 1085                     strindex("SMO-C501", inq->inq_prod_ident)) {
 1086             scgp->dev = DEV_SONY_SMO;
 1087         } else {
 1088             scgp->dev = DEV_CCS_GENDISK;
 1089         }
 1090         break;
 1091 
 1092     case INQ_SEQD:
 1093         if (scgp->dev == DEV_SC4000) {
 1094             strncpy(inq->inq_info_space,
 1095                 "SYSGEN  SC4000          FAKE",
 1096                     sizeof (inq->inq_info_space));
 1097         } else if (inq->add_len == 0 &&
 1098                     inq->removable &&
 1099                         inq->ansi_version == 1) {
 1100             scgp->dev = DEV_MT02;
 1101             strncpy(inq->inq_info_space,
 1102                 "EMULEX  MT02            FAKE",
 1103                     sizeof (inq->inq_info_space));
 1104         }
 1105         break;
 1106 
 1107     case INQ_OPTD:
 1108         if (strindex("RXT-800S", inq->inq_prod_ident))
 1109             scgp->dev = DEV_RXT800S;
 1110         break;
 1111 
 1112     case INQ_PROCD:
 1113         if (strindex("BERTHOLD", inq->inq_vendor_info)) {
 1114             if (strindex("", inq->inq_prod_ident))
 1115                 scgp->dev = DEV_HRSCAN;
 1116         }
 1117         break;
 1118 
 1119     case INQ_SCAN:
 1120         scgp->dev = DEV_MS300A;
 1121         break;
 1122     }
 1123     scgp->silent--;
 1124     if (!print)
 1125         return;
 1126 
 1127     if (scgp->dev == DEV_UNKNOWN && !got_inquiry)
 1128         return;
 1129 
 1130     printf("Device type    : ");
 1131     scg_printdev(inq);
 1132     printf("Version        : %d\n", (int)inq->ansi_version);
 1133     printf("Response Format: %d\n", (int)inq->data_format);
 1134     if (inq->data_format >= 2) {
 1135         printf("Capabilities   : ");
 1136         if (inq->aenc)      printf("AENC ");
 1137         if (inq->termiop)   printf("TERMIOP ");
 1138         if (inq->reladr)    printf("RELADR ");
 1139         if (inq->wbus32)    printf("WBUS32 ");
 1140         if (inq->wbus16)    printf("WBUS16 ");
 1141         if (inq->sync)      printf("SYNC ");
 1142         if (inq->linked)    printf("LINKED ");
 1143         if (inq->cmdque)    printf("CMDQUE ");
 1144         if (inq->softreset) printf("SOFTRESET ");
 1145         printf("\n");
 1146     }
 1147     if (inq->add_len >= 31 ||
 1148             inq->inq_vendor_info[0] ||
 1149             inq->inq_prod_ident[0] ||
 1150             inq->inq_prod_revision[0]) {
 1151         printf("Vendor_info    : '%.8s'\n", inq->inq_vendor_info);
 1152         printf("Identifikation : '%.16s'\n", inq->inq_prod_ident);
 1153         printf("Revision       : '%.4s'\n", inq->inq_prod_revision);
 1154     }
 1155 }
 1156 
 1157 LOCAL void
 1158 printdev(scgp)
 1159     SCSI    *scgp;
 1160 {
 1161     gtprintf("Device seems to be: ");
 1162 
 1163     switch (scgp->dev) {
 1164 
 1165     case DEV_UNKNOWN:   printf("unknown");      break;
 1166     case DEV_ACB40X0:   printf("Adaptec 4000/4010/4070"); break;
 1167     case DEV_ACB4000:   printf("Adaptec 4000");     break;
 1168     case DEV_ACB4010:   printf("Adaptec 4010");     break;
 1169     case DEV_ACB4070:   printf("Adaptec 4070");     break;
 1170     case DEV_ACB5500:   printf("Adaptec 5500");     break;
 1171     case DEV_ACB4520A:  printf("Adaptec 4520A");    break;
 1172     case DEV_ACB4525:   printf("Adaptec 4525");     break;
 1173     case DEV_MD21:      printf("Emulex MD21");      break;
 1174     case DEV_MD23:      printf("Emulex MD23");      break;
 1175     case DEV_NON_CCS_DSK:   printf("Generic NON CCS Disk"); break;
 1176     case DEV_CCS_GENDISK:   printf("Generic CCS Disk"); break;
 1177     case DEV_SONY_SMO:  printf("Sony SMO-C501");    break;
 1178     case DEV_MT02:      printf("Emulex MT02");      break;
 1179     case DEV_SC4000:    printf("Sysgen SC4000");    break;
 1180     case DEV_RXT800S:   printf("Maxtor RXT800S");   break;
 1181     case DEV_HRSCAN:    printf("Berthold HR-Scanner");  break;
 1182     case DEV_MS300A:    printf("Microtek MS300A");  break;
 1183 
 1184     }
 1185     printf(".\n");
 1186 
 1187 }
 1188 
 1189 LOCAL void
 1190 translate_lba(scgp)
 1191     SCSI    *scgp;
 1192 {
 1193     struct scsi_def_list def;
 1194     long    baddr = 0L;
 1195     int i;
 1196 
 1197 loop:
 1198     getlong("Block Address", &baddr, 0L, 1000000L);
 1199 
 1200     fillbytes((caddr_t)&def, sizeof (def), '\0');
 1201     i = sizeof (struct scsi_def_bfi);   /* Ein Defekt */
 1202     i_to_2_byte(def.hd.length, i);
 1203 
 1204     if (translate(scgp, &def.def_bfi[0], baddr) >= 0) {
 1205         print_def_bfi(&def);
 1206     }
 1207     goto loop;
 1208 }
 1209 
 1210 LOCAL void
 1211 read_sector_header(scgp)
 1212     SCSI    *scgp;
 1213 {
 1214     struct  scsi_send_diag_cmd  cmd;
 1215     register struct scsi_sector_header  *header;
 1216     char    bh[512];
 1217     long    baddr = 0L;
 1218     register int i;
 1219     register int maxi;
 1220 
 1221 loop:
 1222     fillbytes((caddr_t)&cmd, sizeof (cmd), '\0');
 1223     fillbytes((caddr_t)bh, sizeof (bh), '\0');
 1224     cmd.cmd = 7;    /* Read Header */
 1225     getlong("Block Address", &baddr, 0L, 1000000L);
 1226     i_to_4_byte(cmd.addr, baddr);
 1227     cmd.addr[0] |= (yes("Physical Address? ")<<7);
 1228 /*  print_bk(baddr);*/
 1229 
 1230     if (send_diagnostic(scgp, (caddr_t)&cmd, sizeof (cmd)) >= 0)
 1231         if (receive_diagnostic(scgp, (caddr_t)bh, sizeof (bh)) >= 0) {
 1232             maxi = (sizeof (bh) - scg_getresid(scgp))/5;
 1233             for (i = 0; i < maxi; i++) {
 1234             header = (struct scsi_sector_header *)&bh[i*5];
 1235             printf("Cyl %4d  Head %2d  Sec %2d (%2d)%s %s %s\n",
 1236                 a_to_u_2_byte(header->cyl),
 1237                 header->head,
 1238                 header->sec, i,
 1239                 header->dt ? "Defective Track" : "",
 1240                 header->sp ? "Spare Sector" : "",
 1241                 header->rp ? "Has been replaced" : "");
 1242             }
 1243         }
 1244     goto loop;
 1245 }
 1246 
 1247 LOCAL void
 1248 esdi_command(scgp)
 1249     SCSI    *scgp;
 1250 {
 1251     struct  scsi_send_diag_cmd  cmd;
 1252     char    bh[512];
 1253     register int i;
 1254     register int maxi;
 1255 
 1256     fillbytes((caddr_t)&cmd, sizeof (cmd), '\0');
 1257     fillbytes((caddr_t)bh, sizeof (bh), '\0');
 1258     cmd.cmd = 4;    /* Pass Drive Command */
 1259     cmd.addr[0] = 0xFF;
 1260     i_to_2_byte(&cmd.addr[1], ESDI);
 1261 
 1262     if (send_diagnostic(scgp, (caddr_t)&cmd, sizeof (cmd)) >= 0)
 1263         if (receive_diagnostic(scgp, (caddr_t)bh, sizeof (bh)) >= 0) {
 1264             maxi = (sizeof (bh) - scg_getresid(scgp));
 1265             i = 0;
 1266             if (maxi)
 1267                 printf("ESDI Status: 0x%02X\n", bh[i++]&0xFF);
 1268             for (; i < maxi; i++) {
 1269                 printf("0x%02X %08Z\n",
 1270                     (int)bh[i]&0xFF, (int)bh[i]&0xFF);
 1271             }
 1272             printf("\n");
 1273             exit(0);
 1274         }
 1275     exit(127);
 1276 }
 1277 
 1278 /*---------------------------------------------------------------------------
 1279 |
 1280 |   Nhead + 1 damit die Spurwechselzeit beruecksichtigt wird
 1281 |   Addition von rpm/2 bzw. 30 bewirkt Rundung
 1282 |
 1283 +---------------------------------------------------------------------------*/
 1284 
 1285 LOCAL long
 1286 estimate_format_time(dp, mult)
 1287     struct disk *dp;
 1288     int mult;
 1289 {
 1290     long etime;
 1291 
 1292     if (dp->rpm < 0 || dp->pcyl < 0 || dp->nhead < 0)
 1293         etime = -1L;
 1294     else if (mult == 0 || dp->rpm == 0) /* Division duch 0 */
 1295         etime = 0L;
 1296     else
 1297         etime = (mult * dp->pcyl * (dp->nhead+1)
 1298             + dp->rpm/2) / dp->rpm * 60L;
 1299     return (etime);
 1300 }
 1301 
 1302 EXPORT void
 1303 estimate_times(dp)
 1304     struct disk *dp;
 1305 {
 1306     if (dp->fmt_time <= 0) {
 1307         dp->fmt_time = estimate_format_time(dp, 2);
 1308     } else if (dp->fmt_timeout < 0 || dp->fmt_timeout < 6 * dp->fmt_time) {
 1309         if (dp->flags & D_FTIME_FOUND) {
 1310             dp->fmt_timeout = 3 * dp->fmt_time;
 1311         } else {
 1312             dp->fmt_timeout = 6 * dp->fmt_time;
 1313         }
 1314     }
 1315     if (dp->veri_time <= 0)
 1316         dp->veri_time = estimate_format_time(dp,
 1317                     (int)(dp->interleave < 1 ? 1 :
 1318                     dp->interleave));
 1319 }
 1320 
 1321 EXPORT void
 1322 print_fmt_time(dp)
 1323     struct disk *dp;
 1324 {
 1325     if (dp->fmt_time > 0) {
 1326         gtprintf("Estimated time: %ld minutes%s\n",
 1327             (dp->fmt_time+30)/60,
 1328             dp->flags & D_FTIME_FOUND?" (known)":"");
 1329     }
 1330 }
 1331 
 1332 EXPORT void
 1333 print_fmt_timeout(dp)
 1334     struct disk *dp;
 1335 {
 1336     if (dp->fmt_timeout > 0) {
 1337         gtprintf("Format timeout: %ld minutes\n",
 1338             (dp->fmt_timeout+30)/60);
 1339     }
 1340 }
 1341 
 1342 EXPORT char *
 1343 datestr()
 1344 {
 1345     time_t  clck;
 1346 
 1347     clck = time((time_t *)0);
 1348     return (asctime(localtime(&clck)));
 1349 }
 1350 
 1351 EXPORT void
 1352 prdate()
 1353 {
 1354     printf("%s", datestr());
 1355 }
 1356 
 1357 EXPORT void
 1358 getstarttime()
 1359 {
 1360     if (gettimeofday(&starttime, (struct timezone *)0) < 0)
 1361         comerr("Cannot get start time\n");
 1362 }
 1363 
 1364 EXPORT void
 1365 getstoptime()
 1366 {
 1367     if (gettimeofday(&stoptime, (struct timezone *)0) < 0)
 1368         comerr("Cannot get stop time\n");
 1369 }
 1370 
 1371 EXPORT long
 1372 gettimediff(tp)
 1373     struct timeval *tp;
 1374 {
 1375     long    sec;
 1376     long    usec;
 1377     long    tmsec;
 1378 
 1379     sec = stoptime.tv_sec - starttime.tv_sec;
 1380     usec = stoptime.tv_usec - starttime.tv_usec;
 1381     tmsec = sec*1000 + usec/1000;
 1382 #ifdef  lint
 1383     tmsec = tmsec;  /* Bisz spaeter */
 1384 #endif
 1385     while (usec < 0) {
 1386         sec--;
 1387         usec += 1000000;
 1388     }
 1389     if (tp != (struct timeval *)0) {
 1390         tp->tv_sec = sec;
 1391         tp->tv_usec = usec;
 1392     }
 1393     return (sec + (usec / 500000));
 1394 }
 1395 
 1396 EXPORT long
 1397 prstats()
 1398 {
 1399     long        sec;
 1400     struct timeval  tv;
 1401 
 1402     getstoptime();
 1403     sec = gettimediff(&tv);
 1404 
 1405     gtprintf("Time total: %ld.%03ldsec\n", (long)tv.tv_sec, (long)tv.tv_usec/1000);
 1406     return (sec);
 1407 }
 1408 
 1409 EXPORT void
 1410 helpexit()
 1411 {
 1412     comerrno(EX_BAD, "Help.............\n");
 1413     /* NOTREACHED */
 1414 }
 1415 
 1416 #ifdef  used
 1417 initbuf()
 1418 {
 1419     register char   *cp;
 1420     register int    i;
 1421     register int    len;
 1422     static   char   str[128];
 1423         long    t;
 1424     extern  char    *strcat();
 1425 
 1426     cp = Sbuf;
 1427     t = time((time_t *)0);
 1428     sprintf(str, "J. Schilling  -Schreibtest- %s", ctime(&t));
 1429     len = strlen(str);
 1430     str[--len] = '\0';
 1431     len--;
 1432 
 1433     for (i = 0; i < Sbufsize; i++) {
 1434         if (i % 2048 == 0) {
 1435             (void) strcat(&cp[i], str);
 1436             i += len;
 1437         } else
 1438             cp[i] = i & 0xFF;
 1439     }
 1440 }
 1441 #endif
 1442 
 1443 EXPORT void
 1444 disk_null(dp, init)
 1445     struct disk *dp;
 1446     int     init;
 1447 {
 1448     register int i = sizeof (struct disk);
 1449     register char *p = (char *)dp;
 1450 
 1451     if (!init) {
 1452         if (dp->disk_type)
 1453             free(dp->disk_type);
 1454         if (dp->alt_disk_type)
 1455             free(dp->alt_disk_type);
 1456         if (dp->default_part)
 1457             free(dp->default_part);
 1458         if (dp->mode_pages)
 1459             free(dp->mode_pages);
 1460         if (dp->parts) {
 1461             struct node *pp = dp->parts;
 1462             struct node *ppp;
 1463 
 1464             while ((ppp = pp) != 0) {
 1465                 pp = ppp->n_next;
 1466                 free(ppp->n_data);
 1467                 free((char *)ppp);
 1468             }
 1469         }
 1470     }
 1471 
 1472     while (--i >= 0) {
 1473         *p++ = -1;
 1474     }
 1475     dp->flags       = 0;
 1476     dp->disk_type       = 0;
 1477     dp->alt_disk_type   = 0;
 1478     dp->default_part    = 0;
 1479     dp->mode_pages      = 0;
 1480     dp->parts       = 0;
 1481 }