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 }