1: /*
   2:  * SCCSID: @(#)rabads.c	3.3	12/30/87
   3:  */
   4: /*
   5:  *		LICENSED FROM DIGITAL EQUIPMENT CORPORATION
   6:  *			       COPYRIGHT (c)
   7:  *		       DIGITAL EQUIPMENT CORPORATION
   8:  *			  MAYNARD, MASSACHUSETTS
   9:  *			      1985, 1986, 1987
  10:  *			   ALL RIGHTS RESERVED
  11:  *
  12:  *	THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT
  13:  *	NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL
  14:  *	EQUIPMENT CORPORATION.  DIGITAL MAKES NO REPRESENTATIONS ABOUT
  15:  *	THE SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE.  IT IS
  16:  *	SUPPLIED "AS IS" WITHOUT EXPRESSED OR IMPLIED WARRANTY.
  17:  *
  18:  *	IF THE REGENTS OF THE UNIVERSITY OF CALIFORNIA OR ITS LICENSEES
  19:  *	MODIFY THE SOFTWARE IN A MANNER CREATING DERIVATIVE COPYRIGHT
  20:  *	RIGHTS, APPROPRIATE COPYRIGHT LEGENDS MAY BE PLACED ON THE
  21:  *	DERIVATIVE WORK IN ADDITION TO THAT SET FORTH ABOVE.
  22:  */
  23: 
  24: /*
  25:  * ULTRIX-11 stand-alone MSCP Disk Initialization
  26:  *
  27:  * Fred Canter
  28:  *	For RX33/RX50, reads all blocks and flags any bad ones.
  29:  *	For RD31/RD32/RD51/RD52/RD53/RD54 reads all blocks and rewrites any bad
  30:  *	blocks to force controller initiated replacement.
  31:  *	For RA60/RA80/RA81, reads all blocks and uses host initiated
  32:  *	replacement to revector any bad blocks.
  33:  *
  34:  * SECRET STUFF:
  35:  *
  36:  *	This program has the following undocumented commands/features,
  37:  *	used mainly for debugging:
  38:  *
  39:  * 1.	The "u" command is commented out. This was an unsuccessful
  40:  *	attempt to unreplace a block. I soon discovered that could
  41:  *	not be done.
  42:  *
  43:  * 2.	The "t all" feature of the table command causes all entries
  44:  *	in the RCT to be printed, not just the ones that represent
  45:  *	replaced blocks. Also allows RCT copy # selection.
  46:  *
  47:  * 3.	The "f" command (requires a simple password) causes the
  48:  *	specified block to be written with the "force error"
  49:  *	modifier. This is used for debugging.
  50:  *
  51:  * NOTE:
  52:  *	This program consists, for the most part, of straight-line
  53:  *	unoptimized code! Its only saving grace is that it works, at
  54:  *	least as far as I can tell so far! -- Fred Canter 8/5/84
  55:  *
  56:  */
  57: 
  58: #include "sa_defs.h"
  59: #include <sys/param.h>
  60: #include <sys/inode.h>
  61: #include "saio.h"
  62: #include "ra_saio.h"
  63: 
  64: /*#define	DEBUG	1	/* Include conditional code for debugging */
  65: 
  66: #define RD  0
  67: #define WRT 1
  68: #define RW  2
  69: #define ERR 0
  70: #define NOERR   1
  71: #define YES 1
  72: #define NO  0
  73: #define HELP    2
  74: 
  75: /*
  76:  * Bad block replacement strategy flags
  77:  */
  78: #define BB_COOP 0   /* Use MSCP cooperative replacement */
  79: #define BB_RWRT 1   /* (rd51/rd52) - rewriting a block replaces it */
  80: #define BB_NONE 2   /* RX33/RX50 - no bad block replacement */
  81: 
  82: struct dkinfo {
  83:     char    *di_type;   /* type name of disk */
  84:     char    *di_name;   /* ULTRIX-11 disk name */
  85:     daddr_t di_size;    /* size of entire volume in blocks */
  86:     int di_chunk;   /* number of sectors per read */
  87:     int di_flag;    /* replacement strategy to use */
  88:                 /* if set, just rewrite block to replace it. */
  89: } dkinfo[] = {
  90:     "ra60", "ra",   400176L,    32, BB_COOP,
  91:     "ra80", "ra",   236964L,    31, BB_COOP,
  92:     "ra81", "ra",   891072L,    32, BB_COOP,
  93:     "rx33", "rx",   2400L,      10, BB_NONE,
  94:     "rx50", "rx",   800L,       10, BB_NONE,
  95:     "rd31", "rd",   41560L,     20, BB_RWRT,
  96:     "rd32", "rd",   83204L,     20, BB_RWRT,
  97:     "rd51", "rd",   21600L,     18, BB_RWRT,
  98:     "rd52", "rd",   60480L,     18, BB_RWRT,
  99:     "rd53", "rd",   138672L,    18, BB_RWRT, /* RQDX3 NOT OPTIMUM */
 100:     "rd54", "rd",   311200L,    20, BB_RWRT, /* RQDX3 NOT OPTIMUM */
 101:     "rc25", "rc",   50902L,     31, BB_COOP,
 102:     0,
 103: };
 104: 
 105: char    buf[512*32];    /* disk read and replacement process buffer */
 106: 
 107: /*
 108:  * Bad block replacement process definitions.
 109:  */
 110: 
 111:                 /* Command Modifiers */
 112: #define MD_CMP  040000      /* Compare */
 113: #define MD_ERR  010000      /* Force Error */
 114: #define MD_SEC  01000       /* Suppress Error Correction */
 115: #define MD_SREC 0400        /* Suppress Error Recovery */
 116: #define MD_PRI  01      /* Primary replacement block */
 117: 
 118:                 /* End Message Flags */
 119: #define EF_BBR  0200        /* Bad block Reported */
 120: #define EF_BBU  0100        /* Bad Block Unreported */
 121: 
 122:                 /* Status or Event Codes */
 123: #define ST_MSK  037     /* Status/event code mask */
 124: #define ST_SUC  0       /* Success (includes subcode "normal") */
 125: #define ST_DAT  010     /* Data Error */
 126: #define MD_HCE  0110        /* Header Compare Error */
 127: 
 128:                 /* Revector Control Info flags */
 129: #define RCI_VP  02      /* Volume write protect flag */
 130: #define RCI_FE  0200        /* Forced error flag */
 131: #define RCI_BR  020000      /* Bad RBN flag */
 132: #define RCI_P2  040000      /* Phase 2 flag */
 133: #define RCI_P1  0100000     /* Phase 1 flag */
 134: 
 135:                 /* Block read check return values */
 136: #define BR_NBBR 0       /* no bad block reported */
 137: #define BR_BBR  1       /* bad block reported */
 138: #define BR_CECC 2       /* correctable ECC error */
 139: #define BR_UECC 3       /* uncorrectable ECC error */
 140: #define BR_NDE  4       /* non data error */
 141: #define BR_FEM  5       /* block written with "force error" modifier */
 142: #define BR_DEB  6       /* data error with bad block reported */
 143: 
 144: /*
 145:  * Variables used by the replacement process.
 146:  */
 147: 
 148: #ifdef  DEBUG
 149: int rp_bps;         /* interrupt replacement process at step ? */
 150: #endif DEBUG
 151: 
 152: daddr_t rp_lbn;         /* LBN of logical block being replaced */
 153: daddr_t rp_rbn;         /* RBN (Replacement Block Number) */
 154: int rp_didit;       /* Says block actually replaced */
 155: int rp_hblk;        /* RCT block of primary RBN descriptor */
 156: int rp_hoff;        /* RCT block offset of primary RBN descriptor */
 157: int rp_blk;         /* Current RCT block being searched */
 158: int rp_off;         /* Current RCT block offset */
 159: int rp_oblk;        /* RCT block number of OLD RBN */
 160: int rp_ooff;        /* RCT block offset of OLD RBN */
 161: int rp_delta;       /* RCT block search offset delta (ping-pong) */
 162: 
 163: int rp_irs;         /* Initial read of bad LBN successful */
 164: int rp_wcs7;        /* Step 7, write-compare sucessful */
 165: int rp_wcs8;        /* Step 8, write-compare sucessful */
 166: int rp_prev;        /* LBN was previously replaced */
 167: daddr_t rp_orbn;        /* If previously replaced, OLD RBN */
 168: daddr_t rp_orbd;        /* old RBN descriptor, in case replace fsils */
 169: int rp_pri;         /* RBN is primary replacement block */
 170: int rp_sec;         /* RBN is non-primary replacement block */
 171: int rp_l;           /* Number of LBNs per track */
 172: int rp_r;           /* Number of RBNs per track */
 173: int rp_dirty;       /* Phase (P1 | P2) of interrupted replacement */
 174: 
 175: /*
 176:  * Replacement process buffer pointers,
 177:  * segment the read/write buffer for use
 178:  * by the replacement process.
 179:  */
 180: 
 181: struct rct_rci *bp_rci = &buf[0]; /* RCT blk 0 - replacement cntrl info */
 182: char *bp_ir = &buf[512];      /* RCT blk 1 - image of bad LBN */
 183: union rctb *bp_rct1 = &buf[1024]; /* RCT blk F - first block being searched */
 184: union rctb *bp_rct2 = &buf[1536]; /* RCT blk S - second block (if needed) */
 185: int *bp_tp = &buf[2048];      /* test data pattern ( 0165555 0133333 ) */
 186: char *bp_tmp = &buf[2560];    /* scratch buffer */
 187: 
 188: /*
 189:  * Structure of RCT (Revector Control Table) block 0.
 190:  * Used during bad block replacement.
 191:  */
 192: 
 193: struct  rct_rci {
 194:     short   rt_vsn[4];  /* volume serial number */
 195:     short   rt_stat;    /* replacement process status word */
 196:     short   rt_rsvd;    /* reserved ??? */
 197:     union {         /* LBN being replaced */
 198:         short   ri_lbnw[2];
 199:         daddr_t ri_lbnl;
 200:     } rt_lbn;
 201:     union {         /* RBN - replacement block number */
 202:         short   ri_rbnw[2];
 203:         daddr_t ri_rbnl;
 204:     } rt_rbn;
 205:     union {         /* bad RBN - RBN being replaced */
 206:         short   ri_brbw[2];
 207:         daddr_t ri_brbl;
 208:     } rt_brb;
 209:     short   rt_pad[244];    /* bad to 512 byte block */
 210: };
 211: 
 212: /*
 213:  * Structure used to access an RCT block
 214:  * containing 128 RBN descriptors. The
 215:  * order (swap hi & lo words) must be reversed
 216:  * because of the way the V7 C compiler stores longs.
 217:  */
 218: 
 219: union   rctb {
 220:     daddr_t rbnd_l;     /* Access descriptor as a long */
 221:     short   rbnd_w[2];  /* Access descriptor as two shorts */
 222: };
 223: 
 224: /*
 225:  * External variables found in the MSCP disk driver (ra.c).
 226:  * Used to modifier driver operation for bad block
 227:  * replacement and get error status info from the driver.
 228:  */
 229: 
 230: #define RP_WRT  1
 231: #define RP_RD   2
 232: #define RP_REP  3
 233: #define RP_AC   4
 234: 
 235: extern  union {         /* RABADS RBN for ra.c */
 236:     daddr_t ra_rbnl;
 237:     short   ra_rbnw[2];
 238: } ra_rbn;
 239: extern int  ra_badc;    /* RABADS command flag in ra.c */
 240: extern int  ra_badm;    /* RABADS command modifier in ra.c */
 241: extern int  ra_ctid[];  /* MSCP controller type ID */
 242: extern char *ra_dct[];  /* Controller type name string */
 243: extern int  ra_stat[];  /* MSCP status/event code */
 244: extern int  ra_ecode[]; /* MSCP end code */
 245: extern int  ra_eflags[];    /* MSCP end message flags */
 246: extern struct   ra_drv  ra_drv[3][4];   /* Drive type info */
 247: 
 248: struct dkinfo *dip;
 249: daddr_t sbn, us, nblk, nbc, rbn, nb;
 250: daddr_t bn;
 251: int repcnt, badcnt, rsize;
 252: int fd, rcnt;
 253: int ask;        /* flag so table doesn't ask for a return */
 254: int allflag;
 255: int rwfem;
 256: int force;
 257: long    atol();
 258: int cn;
 259: int unit;
 260: char    line[50];
 261: char    fn[30];     /* file spec i.e., hp(0,0) */
 262: char    cmd[20];    /* command name */
 263: char    dt[20];     /* disk type rm03, etc */
 264: char    dn[2];      /* drive number */
 265: int firstblk;   /* flag for linear rct searching */
 266: int off_bottom; /* descriptor in RCT greater that 127 */
 267: int off_top;    /* descriptor in RCT less than zero */
 268: int first_level;    /* have completed first level search of the RCT block */
 269: int nondataerr; /* got a non-data error reading the block in step 7 */
 270: int bbr_recur;  /* BBR recursion counter */
 271: 
 272: char    *help[] =
 273: {
 274:     "",
 275:     "To correct typing mistakes, press <DELETE> to erase one character",
 276:     "or <CTRL/U> to erase the entire line.",
 277:     "",
 278:     "To execute a command, type the first letter of the command then",
 279:     "press <RETURN>. The program may prompt for additional information.",
 280:     "",
 281:     "The valid RABADS commands are:",
 282:     "",
 283:     "help    - Print this help message.",
 284:     "",
 285:     "exit    - Exit from the RABADS program.",
 286:     "",
 287:     "drives  - List the disks that can be initialized with RABADS.",
 288:     "",
 289:     "status  - Print the status and geometry of the specified disk.",
 290:     "",
 291:     "table   - Print the RCT (Revector Control Table) for a disk.",
 292:     "",
 293:     "init    - Do a read scan of the disk and replace any bad blocks.",
 294:     "",
 295:     "replace - Force replacement of a disk block.",
 296:     "",
 297:     0
 298: };
 299: 
 300: char    *fewarn[] =
 301: {
 302:     "",
 303:     "The block was written with the \"force error\" modifier, that is,",
 304:     "when the block is read report an error even if the read succeeds.",
 305:     "This indicates that the block has already been replaced but that",
 306:     "valid data could not be recovered from the bad block before it",
 307:     "was replaced. This may also indicate that a previous attempt to",
 308:     "replace the block failed for some reason. In either case, the",
 309:     "recommended procedure is to rewrite the block then reread it and",
 310:     "only replace the block if the reread fails.",
 311:     "",
 312:     "		    ****** CAUTION ******",
 313:     "",
 314:     "Rewriting the block will clear the \"forced error\", however, the",
 315:     "data in the block must be considered to have been corrupted. This",
 316:     "is because valid data could not be read from the block before it",
 317:     "was replaced.",
 318:     "",
 319:     0
 320: };
 321: 
 322: char    *bdwarn =
 323:   "\n\n\7\7\7DISK SHOULD NOT BE USED: \
 324:   \n    (has unreplaced bad blocks or uncleared \"forced error\" blocks!)\n";
 325: char    *pwstr = "qwerty";
 326: char    *feb_nc1 =
 327:   "was written with \"forced error\" - NOT CLEARED!\n";
 328: char    *feb_nc2 =
 329:   "(Data in this block must considered invalid!)\n";
 330: char    *ndemsg =
 331:   "(NON DATA ERROR: suspect faulty disk hardware or bad media!)\n";
 332: char    *rb_uecc =
 333:   "(Uncorrectable ECC error in replacement block!)\n";
 334: char    *rb_bad =
 335:   "(Hardware says replacement block bad, retry disk initialization!)\n";
 336: 
 337: extern int argflag; /* 0=interactive, 1=called by sdload */
 338: int rctcopy;
 339: 
 340: main()
 341: {
 342:     struct rct_rci *rtp;
 343:     register int i, j;
 344:     register char *p;
 345:     int s, cnt, k;
 346:     int found, rctend, rctrw;
 347:     long    *lp;
 348: 
 349:     printf("\n\nULTRIX-11 MSCP Disk Initialization Program\n");
 350:     if(argflag) {   /* called by SDLOAD, can only do init command */
 351:         cmd[0] = 'i';
 352:         cmd[1] = '\0';
 353:         goto do_i;
 354:     }
 355: retry:
 356:     ask = 1;
 357:     force = 0;
 358:     allflag = 0;
 359:     rctcopy = 0;
 360:     printf("\nrabads <help exit drives status table init replace>: ");
 361:     gets(cmd);
 362:     switch(cmd[0]) {
 363:     case 'f':
 364:         goto do_f;
 365:     case 'h':
 366:         for(i=0; help[i]; i++)
 367:             printf("\n%s", help[i]);
 368:         goto retry;
 369:     case 'e':
 370:         exit(NORMAL);
 371:     case 'd':
 372:         prtdsk();
 373:         goto retry;
 374:     case 's':
 375:         goto do_s;
 376:     case 't':
 377:         if(strcmp("t all", cmd) == 0)
 378:             allflag++;  /* print entire RCT */
 379:         if(strcmp("t go", cmd) == 0){
 380:             ask = 0;    /* don't stop to ask */
 381:             allflag++;  /* print entire RCT */
 382:         }
 383:         goto do_t;
 384:     case 'r':
 385:         goto do_r;
 386:     case 'i':
 387:         goto do_i;
 388:     case 0:
 389:         goto retry;
 390:     default:
 391:         printf("\n(%s) - not a valid command!\n", cmd);
 392:         goto retry;
 393:     }
 394: do_s:
 395:     if(dipset() < 0)
 396:         goto retry;
 397:     dskopen(NOERR, RD);
 398:     if(fd >= 0)
 399:         close(fd);
 400:     printf("\nMSCP controller: %s at micro-code revision %d",
 401:         ra_dct[cn], ra_ctid[cn] & 017);
 402:     printf("\nUnit %d: ", unit);
 403:     switch(ra_drv[cn][unit].ra_dt) {
 404:     case RC25:
 405:         printf("RC25");
 406:         break;
 407:     case RX33:
 408:         printf("RX33");
 409:         break;
 410:     case RX50:
 411:         printf("RX50");
 412:         break;
 413:     case RD31:
 414:         printf("RD31");
 415:         break;
 416:     case RD32:
 417:         printf("RD32");
 418:         break;
 419:     case RD51:
 420:         printf("RD51");
 421:         break;
 422:     case RD52:
 423:         printf("RD52");
 424:         break;
 425:     case RD53:
 426:         printf("RD53");
 427:         break;
 428:     case RD54:
 429:         printf("RD54");
 430:         break;
 431:     case RA60:
 432:         printf("RA60");
 433:         break;
 434:     case RA80:
 435:         printf("RA80");
 436:         break;
 437:     case RA81:
 438:         printf("RA81");
 439:         break;
 440:     default:
 441:         printf("UKNOWN or NONEXISTENT");
 442:         break;
 443:     }
 444:     printf(" status =");
 445:     if(ra_drv[cn][unit].ra_online)
 446:         printf(" ONLINE");
 447:     else
 448:         printf(" OFFLINE");
 449:     printf("\nLogical blocks per track\t= %d",
 450:         ra_drv[cn][unit].ra_trksz);
 451:     printf("\nReplacement blocks per track\t= %d",
 452:         ra_drv[cn][unit].ra_rbns);
 453:     printf("\nNumber of RCT copies\t\t= %d", ra_drv[cn][unit].ra_ncopy);
 454:     printf("\nSize of each RCT copy in blocks\t= %d",
 455:         ra_drv[cn][unit].ra_rctsz);
 456:     printf("\nHost area size in blocks\t= %D\n",
 457:         ra_drv[cn][unit].d_un.ra_dsize);
 458:     goto retry;
 459: do_u:       /* semi-secret stuff (unreplace block(s)) */
 460: /*
 461:  *******************************************************************************
 462: 	printf("\nPassword: ");
 463: 	gets(line);
 464: 	if(strcmp("farkle", line) != 0) {
 465: 		printf("\nReserved for Digital!\n");
 466: 		goto retry;
 467: 	}
 468: 	if(dipset() < 0)
 469: 		goto retry;
 470: 	dskopen(NOERR, RW);
 471: 	if(fd < 0) {
 472: 		printf("\nCan't open %s!\n", fn);
 473: 		goto retry;
 474: 	}
 475: 	if(rp_dirty) {
 476: 		printf("\nUnreplace aborted!\n");
 477: 		goto do_u_x;
 478: 	}
 479: 	s = ra_drv[cn][unit].ra_rctsz;
 480: 	if(s == 0) {
 481: 		printf("\nDisk does not have a Revector Control Table!");
 482: 		goto do_u_x;
 483: 	}
 484: do_u_bn:
 485: 	if(allflag == 0) {
 486: 		printf("\nBlock number: ");
 487: 		gets(line);
 488: 		if(line[0] == '\0')
 489: 			goto do_u_bn;
 490: 		bn = atol(line);
 491: 		if((bn < 0) || (bn >= ra_drv[cn][unit].d_un.ra_dsize))
 492: 			goto do_u_bn;
 493: 	}
 494: 	rctend = 0;
 495: 	rctrw = 0;
 496: 	for(i=2; i<s; i++) {
 497: 		if(rctmcr(i, bp_rct1) < 0) {
 498: 			printf("\nRCT multicopy read failed!\n");
 499: 			goto do_u_x;
 500: 		}
 501: 		found = 0;
 502: 		for(j=0; j<128; j++) {
 503: 			k = (bp_rct1[j].rbnd_w[0] >> 12) & 017;
 504: 			switch(k) {
 505: 			case 02:
 506: 			case 03:
 507: 				if(allflag) {
 508: 					found++;
 509: 					bp_rct1[j].rbnd_l = 0L;
 510: 					break;
 511: 				}
 512: 				if(bn == (bp_rct1[j].rbnd_l & ~036000000000)) {
 513: 					found++;
 514: 					bp_rct1[j].rbnd_l = 0L;
 515: 				}
 516: 				break;
 517: 			case 07:
 518: 				if(((ra_ctid[cn] >> 4) & 017) == RQDX1) {
 519: 					rctend++;
 520: 					break;
 521: 				} else
 522: 					continue;
 523: 			case 010:
 524: 				rctend++;
 525: 				break;
 526: 			default:
 527: 				continue;
 528: 			}
 529: 		}
 530: 		if(found) {
 531: 			if(rctmcw(i, bp_rct1) < 0) {
 532: 				printf("\nPANIC: RCT multicopy write failed!\n");
 533: 				exit(FATAL);
 534: 			}
 535: 			rctrw++;
 536: 		}
 537: 		if(rctend) {
 538: 			if(rctrw == 0)
 539: 				printf("\nBlock %D was not revectored!\n", bn);
 540: 			break;
 541: 		}
 542: 	}
 543:  *******************************************************************************
 544:  */
 545: do_u_x:
 546:     close(fd);
 547:     printf("\n");
 548:     goto retry;
 549: do_r:
 550:     if(dipset() < 0)
 551:         goto retry;
 552:     if(dip->di_flag == BB_NONE) {
 553:         printf("\nCannot replace blocks on an %s disk!\n",
 554:             dip->di_type);
 555:         goto retry;
 556:     }
 557:     dskopen(NOERR, RW);
 558:     if(fd < 0) {
 559:         printf("\nCan't open %s!\n", fn);
 560:         goto retry;
 561:     }
 562:     if(rp_dirty)
 563:         goto rp_s1; /* finish up interrupted replacement */
 564:     if(ra_drv[cn][unit].ra_rctsz == 0) {
 565:         printf("\nDisk does not have a Revector Control Table!");
 566:         goto do_u_x;
 567:     }
 568: do_r_bn:
 569:     printf("\nBlock number: ");
 570:     gets(line);
 571:     if(line[0] == '\0')
 572:         goto do_r_bn;
 573:     bn = atol(line);
 574:     if((bn < 0) || (bn >= ra_drv[cn][unit].d_un.ra_dsize))
 575:         goto do_r_bn;
 576:     if(dip->di_flag == BB_RWRT) {   /* cntlr will replace block if bad */
 577:         lseek(fd, (long)(bn*512), 0);
 578:         ra_badc = RP_RD;
 579:         read(fd, (char *)&buf, 512);
 580:     }
 581:     printf("\nBlock %D read check: ", bn);
 582:     s = brchk(bn);  /* read check block - see if really bad */
 583:     if((s == BR_BBR) || (s == BR_NBBR))
 584:         printf("SUCCEEDED - ");
 585:     else
 586:         printf("FAILED - ");
 587:     switch(s) {
 588:     case BR_BBR:
 589:     case BR_DEB:
 590:         printf("bad block reported\n");
 591:         break;
 592:     case BR_NBBR:
 593:         printf("no bad block reported\n");
 594:         if(dip->di_flag == BB_RWRT) {
 595:             printf("\n\7\7\7Disk controller replaces bad blocks,");
 596:             printf(" no way to force replacement!\n");
 597:             goto do_u_x;
 598:         }
 599:         printf("\nReally replace this block <y or n> ? ");
 600:         if(yes(0) == YES)
 601:             break;
 602:         else
 603:             goto do_u_x;
 604:     case BR_CECC:
 605:     case BR_UECC:
 606:         printf("data error\n");
 607:         break;
 608:     case BR_NDE:
 609:         printf("non data error\n");
 610:         printf("\n** - block connot be replaced!\n");
 611:         goto do_u_x;
 612:     case BR_FEM:
 613:         printf("block written with \"force error\" modifier\n");
 614:         for(i=0; fewarn[i]; i++)
 615:             printf("\n%s", fewarn[i]);
 616:         printf("\nRewrite the block <y or n> ? ");
 617:         if(yes(0) == NO)
 618:             goto do_u_x;
 619:         lseek(fd, (long)(bn*512), 0);
 620:         ra_badc = RP_WRT;
 621:         if(write(fd, (char *)bp_tmp, 512) != 512) {
 622:             printf("\n\7\7\7BLOCK REWRITE FAILED!\n");
 623:             goto do_u_x;
 624:         }
 625:         lseek(fd, (long)(bn*512), 0);
 626:         ra_badc = RP_RD;
 627:         if(dip->di_flag == BB_RWRT)
 628:             goto do_r_rq;
 629:         if(read(fd, (char *)bp_tmp, 512) == 512)
 630:             printf("\nREREAD SUCCEEDED: block not replaced!\n");
 631:         else
 632:             printf("\nREREAD FAILED: retry the replace command!\n");
 633:         goto do_u_x;
 634: do_r_rq:
 635:         if(read(fd, (char *)bp_tmp, 512) != 512) {
 636:             printf("\n\7\7\7Disk controller failed ");
 637:             printf("to replace bad block!\n");
 638:         } else
 639:             printf("\nDisk controller replaced block!\n");
 640:         goto do_u_x;
 641:     }
 642:     if(dip->di_flag == BB_COOP) {
 643:         printf("\nBLOCK: %D - replacement ", bn);
 644:         force++;    /* force replacement (see rp_s8:) */
 645:         rp_lbn = bn;
 646:         goto rp_s1;
 647:     }
 648:     goto do_u_x;
 649: do_f:
 650:     printf("\nPassword: ");
 651:     gets(line);
 652:     if(strcmp(line, pwstr) != 0) {
 653:         printf("\nSorry - reserved for Digital!\n");
 654:         goto retry;
 655:     }
 656:     if(dipset() < 0)
 657:         goto retry;
 658:     if(dip->di_flag == BB_NONE) {
 659:         printf("\nCannot replace blocks on an %s disk!\n",
 660:             dip->di_type);
 661:         goto retry;
 662:     }
 663:     dskopen(NOERR, RW);
 664:     if(fd < 0) {
 665:         printf("\nCan't open %s!\n", fn);
 666:         goto retry;
 667:     }
 668:     if(rp_dirty) {
 669:         printf("\nForce aborted!\n");
 670:         goto do_u_x;
 671:     }
 672:     if(ra_drv[cn][unit].ra_rctsz == 0) {
 673:         printf("\nDisk does not have a Revector Control Table!");
 674:         goto do_u_x;
 675:     }
 676: do_f_bn:
 677:     printf("\nBlock number: ");
 678:     gets(line);
 679:     if(line[0] == '\0')
 680:         goto do_f_bn;
 681:     bn = atol(line);
 682:     if((bn < 0) || (bn >= ra_drv[cn][unit].d_un.ra_dsize))
 683:         goto do_f_bn;
 684:     lseek(fd, (long)(bn*512), 0);
 685:     read(fd, buf, 512);
 686:     lseek(fd, (long)(bn*512), 0);
 687:     ra_badc = RP_WRT;
 688:     ra_badm = 010000;   /* MD_ERR (force error) */
 689:     write(fd, buf, 512);
 690:     goto do_u_x;
 691: do_t:
 692:     if(dipset() < 0)
 693:         goto retry;
 694:     dskopen(NOERR, RD);
 695:     if(fd < 0) {
 696:         printf("\nCan't open %s!\n", fn);
 697:         goto retry;
 698:     }
 699:     s = ra_drv[cn][unit].ra_rctsz;
 700:     if(s == 0) {
 701:         printf("\nDisk does not have a Revector Control Table!");
 702:         goto do_t_x;
 703:     }
 704:     if(allflag == 0)    /* if "t all" ask which copy */
 705:         goto do_t_n;
 706:     printf("\nRCT copy < ");
 707:     k = ra_drv[cn][unit].ra_ncopy;
 708:     for(i=0; i<k; i++)
 709:         printf("%d ", i+1);
 710:     printf(">: ");
 711:     gets(line);
 712:     rctcopy = atoi(line);
 713:     if((rctcopy < 0) || (rctcopy > k))
 714:         rctcopy = 0;
 715:     if(rctmcr(0, bp_rci) < 0)
 716:         goto do_t_err;
 717:     rtp = bp_rci;
 718:     i = rtp->rt_lbn.ri_lbnw[0]; /* reverse order */
 719:     rtp->rt_lbn.ri_lbnw[0] = rtp->rt_lbn.ri_lbnw[1];
 720:     rtp->rt_lbn.ri_lbnw[1] = i;
 721:     i = rtp->rt_rbn.ri_rbnw[0]; /* reverse order */
 722:     rtp->rt_rbn.ri_rbnw[0] = rtp->rt_rbn.ri_rbnw[1];
 723:     rtp->rt_rbn.ri_rbnw[1] = i;
 724:     i = rtp->rt_brb.ri_brbw[0]; /* reverse order */
 725:     rtp->rt_brb.ri_brbw[0] = rtp->rt_brb.ri_brbw[1];
 726:     rtp->rt_brb.ri_brbw[1] = i;
 727:     printf("\nRCT block 0: revector control information.\n");
 728:     printf("\nStatus bits: P1=%d ", rtp->rt_stat&RCI_P1 ? 1 : 0);
 729:     printf("P2=%d ", rtp->rt_stat&RCI_P2 ? 1 : 0);
 730:     printf("BR=%d ", rtp->rt_stat&RCI_BR ? 1 : 0);
 731:     printf("FE=%d ", rtp->rt_stat&RCI_FE ? 1 : 0);
 732:     printf("VP=%d ", rtp->rt_stat&RCI_VP ? 1 : 0);
 733:     printf("\nBad LBN\t= %D", rtp->rt_lbn.ri_lbnl);
 734:     printf("\nRBN\t= %D", rtp->rt_rbn.ri_rbnl);
 735:     printf("\nOld RBN\t= %D\n", rtp->rt_brb.ri_brbl);
 736:     printf("\nOctal dump RCT block 1 <y or n> ? ");
 737:     gets(line);
 738:     if(line[0] != 'y')
 739:         goto do_t_n;
 740:     if(rctmcr(1, bp_ir) < 0)
 741:         goto do_t_err;
 742:     printf("\nRCT block 1 contents:\n");
 743:     for(i=0; i<256; i++) {
 744:         if((i%8) == 0)
 745:             printf("\n    ");
 746:         printf("%o\t", bp_ir[i]);
 747:         if(i == 127)
 748:             if (ask)
 749:                 if(prfm())
 750:                     goto do_t_x;
 751:     }
 752:     if (ask)
 753:         if(prfm())
 754:             goto do_t_x;
 755: do_t_n:
 756:     cnt = -1;
 757:     for(i=2; i<s; i++) {
 758:         if(rctmcr(i, bp_rct1) < 0) {
 759: do_t_err:
 760:             printf("\nCANNOT READ REVECTOR CONTROL TABLE: ");
 761:             printf("RCT multicopy read failed!\n");
 762:             goto do_t_x;
 763:         }
 764:         for(j=0; j<128; j++) {
 765:             if((cnt == 16) || (cnt == -1)) {
 766:                 if(cnt == 16)
 767:                     if (ask)
 768:                         if(prfm())
 769:                             goto do_t_x;
 770:                 cnt = 0;
 771:                 printf("\nBlock\tOffset\tLBN\tCODE");
 772:                 printf("\n-----\t------\t---\t----");
 773:             }
 774:             k = (bp_rct1[j].rbnd_w[0] >> 12) & 017;
 775:             switch(k) {
 776:             case 02:
 777:             case 03:
 778:             case 04:
 779:             case 05:
 780:                 break;
 781:             case 07:
 782:                 if(((ra_ctid[cn] >> 4) & 017) == RQDX1) {
 783:                     if(allflag)
 784:                         break;
 785:                     else
 786:                         goto do_t_x;
 787:                 } else
 788:                     continue;
 789:             case 010:
 790:                 goto do_t_x;
 791:             default:
 792:                 if(allflag)
 793:                     break;
 794:                 else
 795:                     continue;
 796:             }
 797:             cnt++;
 798:             printf("\n%d\t%d\t%D\t", i, j,
 799:                 bp_rct1[j].rbnd_l & ~036000000000);
 800:             switch(k) {
 801:             case 00:
 802:                 printf("Unallocated replacement block");
 803:                 break;
 804:             case 02:
 805:                 printf("Allocated - primary RBN");
 806:                 break;
 807:             case 03:
 808:                 printf("Allocated - non-primary RBN");
 809:                 break;
 810:             case 04:
 811:             case 05:
 812:                 printf("Unusable replacement block");
 813:                 break;
 814:             default:
 815:                 printf("Unknown code (%o)", k);
 816:                 break;
 817:             }
 818:         }
 819:     }
 820: do_t_x:
 821:     close(fd);
 822:     printf("\n");
 823:     goto retry;
 824: do_i:
 825:     if(dipset() < 0)
 826:         goto retry;
 827:     dskopen(ERR, RW);
 828:     if(rp_dirty) {
 829:         printf("\nInitialization aborted!\n");
 830:         goto do_u_x;
 831:     }
 832:     us = ra_drv[cn][unit].d_un.ra_dsize;
 833:     printf("\nStarting block number < 0 >: ");
 834:     gets(line);
 835:     if(line[0] == '\0')
 836:         sbn = 0L;
 837:     else {
 838:         sbn = atol(line);
 839:         if((sbn < 0) || (sbn >= us)) {
 840:             printf("\nBad starting block!\n");
 841:     do_i_ex:
 842:             if(argflag)
 843:                 exit(FATAL);
 844:             else
 845:                 goto retry;
 846:         }
 847:     }
 848:     printf("\nNumber of blocks to check < %D >: ", us - sbn);
 849:     gets(line);
 850:     if(line[0] == '\0')
 851:         nblk = us - sbn;
 852:     else
 853:         nblk = atol(line);
 854:     if(nblk <= 0) {
 855:         printf("\nBad # of blocks!\n");
 856:         goto do_i_ex;
 857:     }
 858:     if(nblk > (us - sbn)) {
 859:         nblk = (us - sbn);
 860:         printf("\nToo many blocks, truncating to %D blocks!\n", nblk);
 861:     }
 862: do_i_rw:
 863:     if(dip->di_flag != BB_NONE) {
 864:         if(argflag == 0) {
 865:         printf("\nRewrite blocks written with \"forced error\" ");
 866:         printf("(? for help) <y or n> ? ");
 867:         rwfem = yes(HELP);
 868:         if(rwfem == HELP) {
 869:             for(i=0; fewarn[i]; i++)
 870:                 printf("\n%s", fewarn[i]);
 871:             goto do_i_rw;
 872:         }
 873:         } else
 874:         rwfem = YES;
 875:     }
 876:     printf("\nREADING...\n");
 877:     badcnt = 0;
 878:     repcnt = 0;
 879:     bn = sbn;
 880:     nbc = 0;
 881: do_i_lp:
 882:     nb = dip->di_chunk;
 883:     if((bn + nb) > us)
 884:         nb = (us - bn);
 885:     if((nb + nbc) > nblk)
 886:         nb = nblk - nbc;
 887:     rsize = nb * 512;
 888:     lseek(fd, (long)(bn*512), 0);
 889:     ra_badc = RP_AC;
 890:     rcnt = read(fd, (char *)&buf, rsize);
 891:     if(rcnt == rsize) {
 892: do_i_lp1:
 893:         bn += nb;
 894:         nbc += nb;
 895:         if(nbc >= nblk) {
 896: bg_loop:
 897:             close(fd);
 898:             printf("\n\n%D blocks checked", nbc);
 899:             printf("\n%d bad blocks found", badcnt);
 900:             printf("\n%d bad blocks replaced\n", repcnt);
 901:             if(argflag == 0) {
 902:                 if(repcnt != badcnt)
 903:                     printf("%s", bdwarn);
 904:                 else
 905:                     printf("\n");
 906:                 goto retry;
 907:             }
 908:             if(repcnt != badcnt)
 909:                 exit(HASBADS);
 910:             while(getchar() != '\n') ;  /* wait for <RETURN> */
 911:             exit(NORMAL);
 912:         }
 913:         goto do_i_lp;
 914:     }
 915:     for(rbn=bn; rbn<(bn+nb); rbn++) {
 916:         lseek(fd, (long)(rbn*512), 0);
 917:         ra_badc = RP_RD;
 918:         rcnt = read(fd, (char *)&buf, 512);
 919:         if(rcnt == 512)
 920:             continue;
 921:         badcnt++;
 922:         printf("\nBLOCK: %D - ", rbn);
 923:         switch(dip->di_flag) {  /* replacement strategy to use */
 924:         case BB_COOP:
 925:             if(ra_eflags[cn] & EF_BBR) {
 926:                 printf("replacement ");
 927:                 rp_lbn = rbn;
 928:                 goto rp_s1; /* go replace block */
 929:             } else if(ra_stat[cn] == ST_DAT) {  /* FEM */
 930:                 /* data error with force error modifier */
 931: do_i_rs:
 932:                 if(!rwfem) { /* NOT REWRITING FORCED ERRORS */
 933:                     printf("%s", feb_nc1); /* warn bad data */
 934:                     printf("%s", feb_nc2);
 935:                 } else {
 936:                     if(fembrw(0, rbn) == YES)
 937:                         badcnt--;
 938:                 }
 939:                 break;
 940:             } else {
 941:                 printf("(no bad block reported flag) ");
 942:                 printf("cannot be replaced!\n");
 943:                 deprnt();
 944:                 break;
 945:             }
 946: do_i_rg:            /* return here if replacement succeeded */
 947:             repcnt++;
 948:             printf("SUCCEEDED!\n");
 949:             s = brchk(rbn); /* read check replacement block */
 950:             if(s == BR_NBBR)
 951:                 break;  /* every thing is cool! */
 952:             if(s == BR_FEM) { /* replacement block - forced error */
 953:                 if(!rwfem) {
 954:                     printf("BLOCK: %D - ", rbn);
 955:                     printf("%s", feb_nc1);
 956:                     printf("%s", feb_nc2);
 957:                     repcnt--;
 958:                     break;
 959:                 }
 960:                 if(fembrw(1, rbn) == NO)
 961:                     repcnt--;
 962:                 break;
 963:             }
 964:             repcnt--;
 965:             printf("BLOCK: %D - ", rbn);
 966:             printf("replacement block read check FAILED!\n");
 967:             switch(s) {
 968:             case BR_UECC:
 969:                 printf("%s", rb_uecc);
 970:                 deprnt();
 971:                 break;
 972:             case BR_BBR:
 973:                 printf("%s", rb_bad);
 974:                 /* BAD REPLACEMENT BLOCK ?????? */
 975:                 /* should go back and rescan */
 976:                 break;
 977:             case BR_NDE:
 978:             default:
 979:                 printf("%s", ndemsg);
 980:                 deprnt();
 981:                 break;
 982:             }
 983:             break;
 984: do_i_rb:            /* return here if replacement failed */
 985:             printf("\nBLOCK: %D - replacement FAILED!\n", rbn);
 986:             break;
 987: do_i_ra:            /* return here if replacement aborted */
 988:                 /* i.e., block was not really bad */
 989:             printf("ABORTED (block not really bad)!\n");
 990:             lseek(fd, (long)(rbn*512), 0);
 991:             ra_badc = RP_RD;
 992:             read(fd, (char *)&buf, 512);
 993:             if(ra_stat[cn] != ST_DAT) {
 994:                 badcnt--;
 995:                 break;  /* NOT FORCED ERROR */
 996:             }
 997:             if(!rwfem) {
 998:                 printf("BLOCK: %D - ", rbn);
 999:                 printf("%s", feb_nc1);
1000:                 printf("%s", feb_nc2);
1001:                 break;
1002:             }
1003:             if(fembrw(1, rbn) == YES)
1004:                 badcnt--;
1005:             break;
1006:         case BB_NONE:
1007:             printf("%s: bad blocks cannot be replaced!\n",
1008:                 dip->di_type);
1009:             deprnt();
1010:             break;
1011:         case BB_RWRT:
1012:             if(ra_eflags[cn] & EF_BBR) {
1013:                 printf("replacement ");
1014:                 switch(brchk(rbn)) {    /* read check */
1015:                 case BR_NBBR:
1016:                     repcnt++;
1017:                     printf("SUCCEEDED!\n");
1018:                     break;
1019:                 case BR_FEM:
1020:                     printf("SUCCEEDED!\n");
1021:                     repcnt++;
1022:                     if(!rwfem) {
1023:                         printf("BLOCK: %D - ", rbn);
1024:                         printf("%s", feb_nc1);
1025:                         printf("%s", feb_nc2);
1026:                         repcnt--;
1027:                         break;
1028:                     }
1029:                     if(fembrw(1, rbn) == NO)
1030:                         repcnt--;
1031:                     break;
1032:                 case BR_UECC:
1033:                     printf("FAILED!\n");
1034:                     printf("%s", rb_uecc);
1035:                     deprnt();
1036:                     break;
1037:                 case BR_BBR:
1038:                     printf("FAILED!\n");
1039:                     printf("%s", rb_bad);
1040:                     /* BAD REPLACEMENT BLOCK ?????? */
1041:                     /* should go back and rescan */
1042:                     break;
1043:                 case BR_NDE:
1044:                 default:
1045:                     printf("FAILED!\n");
1046:                     printf("%s", ndemsg);
1047:                     deprnt();
1048:                     break;
1049:                 }
1050:             } else if(ra_stat[cn] == ST_DAT) { /* FEM */
1051:                 if(!rwfem) { /* NOT REWRITING FORCED ERRORS */
1052:                     printf("%s", feb_nc1); /* warn bad data */
1053:                     printf("%s", feb_nc2);
1054:                 } else {
1055:                     if(fembrw(0, rbn) == YES)
1056:                         badcnt--;
1057:                 }
1058:             } else {
1059:                 printf("cannot be replaced!\n");
1060:                 printf("%s", ndemsg);
1061:                 deprnt();
1062:             }
1063:             break;
1064:         }
1065:     }
1066:     goto do_i_lp1;
1067: 
1068: /*
1069:  * MSCP: host initiated bad block replacement algorithm
1070:  *
1071:  * I allow myself one editorial comment before proceeding:
1072:  *
1073:  *	Fred Canter "Good GOD Gertrude, you must be kidding!"
1074:  *
1075:  * Each step of the bad block replacement procedure is labeled
1076:  * so as to correspond to the steps in section 7.5 of the "DSA
1077:  * DISK FORMAT SPECIFICATION" Version 1.4.0.
1078:  */
1079: 
1080: rp_s1:
1081: #ifdef  DEBUG
1082:     if(rp_bps == 1)
1083:         goto do_u_x;
1084: #endif	DEBUG
1085: /*
1086:  * Step 1 is performed elsewhere in the program. Either the replacement
1087:  * process is initilated by an error with the BAD BLOCK REPORTED flag set,
1088:  * or the process is restarted because it was interrupted by a failure of
1089:  * some type. The latter case is detected when the unit is prought online.
1090:  */
1091:     rp_didit = 0;   /* clear block actually replaced indicator */
1092:             /* in case of interrupted replacement */
1093:     rp_prev = rp_pri = rp_sec = 0;
1094: 
1095: rp_s2:
1096: #ifdef  DEBUG
1097:     if(rp_bps == 2)
1098:         goto do_u_x;
1099: #endif	DEBUG
1100: /*
1101:  * The DSA spec calls for a soft lock of the unit, but because replacement
1102:  * is only done by this stand-alone program a lock is not necessary.
1103:  */
1104: 
1105: bbr_recur = 0;      /* initialize the BBR recursion counter to 0 */
1106: 
1107: rp_s3:
1108: #ifdef  DEBUG
1109:     if(rp_bps == 3)
1110:         goto do_u_x;
1111: #endif	DEBUG
1112: /*
1113:  * The first two steps were easy, but I don't expect this trend to continue.
1114:  */
1115: 
1116:     if(rp_dirty == 0)
1117:         goto rp_s4; /* NOT an interrupted replacement! */
1118: /*
1119:  * Interrupted replacement,
1120:  * Re-establish software context for Phase 1
1121:  * and Phase 2, if necessary.
1122:  * Yes, I know that RCT block 0 was read in
1123:  * during the dskopen()!
1124:  */
1125:     printf("\n\7\7\7COMPLETING INTERRUPTED BAD BLOCK REPLACEMENT");
1126:     printf(" (Phase %d)...\n", rp_dirty);
1127:     if(rctmcr(0, bp_rci) < 0) { /* revector control info */
1128:         rp_rcte(3, RD, 0);
1129:         goto rp_s18;
1130:     }
1131:     if(rctmcr(1, bp_ir) < 0) {  /* bad LBN image */
1132:         rp_rcte(3, RD, 1);
1133:         goto rp_s18;
1134:     }
1135:     rtp = (struct rct_rci *)bp_rci;
1136:     if(rtp->rt_stat & RCI_FE)   /* initial read sucessful or not */
1137:         rp_irs = NO;
1138:     else
1139:         rp_irs = YES;
1140: /*
1141:  * The DSA spec says that the LBN is only valid
1142:  * if the P1 bit is set, but I don't buy it!
1143:  * I never clear the LBN until after phase 2 is
1144:  * complete or a fatal error.
1145:  */
1146:     i = rtp->rt_lbn.ri_lbnw[0]; /* reverse order */
1147:     rtp->rt_lbn.ri_lbnw[0] = rtp->rt_lbn.ri_lbnw[1];
1148:     rtp->rt_lbn.ri_lbnw[1] = i;
1149:     rp_lbn = rtp->rt_lbn.ri_lbnl;   /* bad block's LBN */
1150:     printf("\nBLOCK: %D - replacement ", rp_lbn);
1151:     if(rp_dirty == 1)
1152:         goto rp_s7; /* Interrupted during phase one */
1153:     i = rtp->rt_rbn.ri_rbnw[0]; /* new RBN - reverse order */
1154:     rtp->rt_rbn.ri_rbnw[0] = rtp->rt_rbn.ri_rbnw[1];
1155:     rtp->rt_rbn.ri_rbnw[1] = i;
1156:     rp_rbn = rtp->rt_rbn.ri_rbnl;
1157:     i = rtp->rt_brb.ri_brbw[0]; /* old RBN - reverse order */
1158:     rtp->rt_brb.ri_brbw[0] = rtp->rt_brb.ri_brbw[1];
1159:     rtp->rt_brb.ri_brbw[1] = i;
1160:     if(rtp->rt_stat & RCI_BR) { /* previously replaced */
1161:         rp_prev = 1;
1162:         rp_orbn = rtp->rt_brb.ri_brbl;
1163:     }
1164:     rp_l = ra_drv[cn][unit].ra_trksz;   /* LBNs per track */
1165:     rp_r = ra_drv[cn][unit].ra_rbns;    /* RBNs per track */
1166:                         /* Primary RBN descriptor */
1167:     rp_hblk = (((rp_lbn / rp_l) * rp_r) / 128) + 2;
1168:     rp_hoff = ((rp_lbn / rp_l) * rp_r) % 128;
1169:     rp_blk = (rp_rbn / 128) + 2;        /* Actual RBN descriptor */
1170:     rp_off = rp_rbn % 128;
1171:     if((rp_blk == rp_hblk) && (rp_off == rp_hoff))  /* Primary RBN ? */
1172:         rp_pri = 1;
1173:     else
1174:         rp_sec = 1; /* YES, I know rp_sec not really used */
1175:     if(rp_prev) {       /* set saved old RBN desc, as best we can */
1176:         rp_orbd = rp_lbn;   /* LBN being replaced */
1177:         rp_oblk = (rp_orbn / 128) + 2;
1178:         rp_ooff = rp_orbn % 128;
1179:         if((rp_oblk == rp_hblk) && (rp_ooff == rp_hoff))
1180:             rp_orbd |= 04000000000; /* primary RBN */
1181:         else
1182:             rp_orbd |= 06000000000; /* non-primary RBN */
1183:     }
1184:     if(rctmcr(rp_blk, bp_rct1) < 0) {   /* First RCT block */
1185:         rp_rcte(3, RD, rp_blk);
1186:         goto rp_s18;
1187:     }
1188:     goto rp_s11;        /* finish up phase 2 */
1189: 
1190: rp_s4:
1191: #ifdef  DEBUG
1192:     if(rp_bps == 4)
1193:         goto do_u_x;
1194: #endif	DEBUG
1195: printf("4 ");
1196: /*
1197:  * Read the suspected bad block, remember whether or not the read succeeded.
1198:  * Also, remember if the forced error indicator was set.
1199:  */
1200:     rp_irs = NO;
1201:     p = bp_ir;
1202:     for(i=0; i<512; i++)
1203:         *p++ = 0;
1204:     lseek(fd, (long)(rp_lbn*512), 0);
1205:     ra_badc = RP_RD;
1206:     for (i=0; i < 4; i++)
1207:         if(read(fd, bp_ir, 512) == 512) {
1208:             rp_irs = YES;
1209:             break;
1210:         }
1211:         else {
1212:             if(ra_stat[cn] & ST_DAT)
1213:                 break;
1214:             rp_irs = NO;
1215:         }
1216: 
1217: 
1218: rp_s5:
1219: #ifdef  DEBUG
1220:     if(rp_bps == 5)
1221:         goto do_u_x;
1222: #endif	DEBUG
1223: printf("5 ");
1224: /*
1225:  * Save data read in step 4 in RCT block 1.
1226:  */
1227:     if(rctmcw(1, bp_ir) < 0) {
1228:         rp_rcte(4, WRT, 1);
1229:         goto rp_s18;
1230:     }
1231: 
1232: rp_s6:
1233: #ifdef  DEBUG
1234:     if(rp_bps == 6)
1235:         goto do_u_x;
1236: #endif	DEBUG
1237: printf("6 ");
1238: /*
1239:  * Begin phase 1, save info in RCT block 0.
1240:  */
1241:     if(rctmcr(0, bp_rci) < 0) {
1242:         rp_rcte(6, RD, 0);
1243:         goto rp_s18;
1244:     }
1245:     rtp = (struct rct_rci *)bp_rci;
1246:     rtp->rt_lbn.ri_lbnl = rp_lbn;
1247:     i = rtp->rt_lbn.ri_lbnw[0]; /* reverse order */
1248:     rtp->rt_lbn.ri_lbnw[0] = rtp->rt_lbn.ri_lbnw[1];
1249:     rtp->rt_lbn.ri_lbnw[1] = i;
1250:     rtp->rt_stat &= ~RCI_FE;
1251:     if(rp_irs == NO)
1252:         rtp->rt_stat |= RCI_FE;
1253:     rtp->rt_stat |= RCI_P1;
1254:     if(rctmcw(0, bp_rci) < 0) {
1255:         rp_rcte(6, WRT, 0);
1256:         goto rp_s17;
1257:     }
1258: 
1259: rp_s7:
1260: #ifdef  DEBUG
1261:     if(rp_bps == 7)
1262:         goto do_u_x;
1263: #endif	DEBUG
1264: printf("7 ");
1265: /*
1266:  * Check to see if the block is really bad.
1267:  *
1268:  * Read the block, then write customer data, then write inverted
1269:  * customer data.
1270:  */
1271: 
1272:     nondataerr = NO;
1273:     rp_wcs7 = YES;
1274:     if(rctmcr(1, bp_tmp) < 0) { /* Get best guess data from RCT blk 1 */
1275:         rp_rcte(7, RD, 1);
1276:         goto rp_s18;
1277:     }
1278:     for (i = 0; i < 4; i++) {
1279:         /* check for any data error */
1280:         lseek(fd, (long)(rp_lbn*512), 0);
1281:         ra_badc = RP_AC;
1282:         ra_badm = MD_SEC|MD_SREC;
1283:         if ((read(fd, buf, 512) != 512)
1284:             && ((ra_eflags[cn] & EF_BBR) || (ra_eflags[cn] & EF_BBU))
1285:             || (ra_stat[cn]  & 0xe8)) {
1286:             rp_wcs7 = NO;
1287:             break;
1288:         }
1289:     }
1290:     if (rp_wcs7 == NO && ((ra_stat[cn]  & 0xe8) != 0xe8)) {
1291:         /* printf(" nondata read failure status = 0x%x - aborting\n",
1292: 			ra_stat); GMM */
1293:         rp_wcs7 = YES;
1294:         nondataerr = YES;
1295:     }
1296:     if (rp_wcs7 == YES && ~nondataerr) {
1297:         bp_tp = &buf[2048];
1298:         bp_tmp = &buf[512];
1299:         for (j= 0; j < 512; j++)
1300:             *bp_tp++ = ~*bp_ir++;
1301:         bp_tp = &buf[2048];
1302:         bp_ir = &buf[512];
1303:         for (i = 0; i < 8; i++) {
1304:             if ((rp_wcs7 = blocktest(fd, !rp_irs, bp_ir)) == YES)
1305:                 rp_wcs7 = blocktest(fd, 0, bp_tp);
1306:             if (rp_wcs7 == NO)
1307:                 break;
1308:         }
1309:     }
1310: 
1311: 
1312: rp_s8:
1313: #ifdef  DEBUG
1314:     if(rp_bps == 8)
1315:         goto do_u_x;
1316: #endif	DEBUG
1317: printf("8 ");
1318: /*
1319:  * Bad block may be good, write saved bad block contents back
1320:  * out to bad block. May be a transient bad block error????
1321:  *
1322:  * NOTE: the "force" variable causes replacement regardless!
1323:  */
1324:     rp_wcs8 = YES;
1325:     lseek(fd, (long)(rp_lbn*512), 0);
1326:     ra_badc = RP_WRT;
1327:     ra_badm = MD_CMP;
1328:     if(rp_irs == NO)
1329:         ra_badm |= MD_ERR;
1330:     if(write(fd, (char *)bp_ir, 512) == 512) {
1331:         if(((ra_eflags[cn] & EF_BBR) == 0) &&
1332:             (rp_irs == YES)) {
1333:             if(force || (rp_wcs7 == NO))
1334:                 goto rp_s9;
1335:             else
1336:                 goto rp_s13;
1337:         }
1338:     }
1339:     if((ra_stat[cn] & 0xe8) &&  /* DATA ERROR with FORCED ERROR */
1340:        (rp_irs == NO) &&
1341:        ((ra_eflags[cn] & EF_BBR) == 0))
1342:             if(force)
1343:                 goto rp_s9;
1344:             else
1345:                 goto rp_s13;
1346: 
1347: rp_s9:
1348: #ifdef  DEBUG
1349:     if(rp_bps == 9)
1350:         goto do_u_x;
1351: #endif	DEBUG
1352: printf("9 ");
1353: /*
1354:  * Seach the RCT for the replacement block number (RBN) and
1355:  * whether or not the bad LBN was previously replaced, if so
1356:  * also get the old RBN.
1357:  */
1358: /* Set initial (hash) RCT block # and offset, init variables */
1359: 
1360:     if (bbr_recur >= 2) {
1361:         printf("Replacement Command Failure at LBN %d\n", rp_lbn);
1362:         goto rp_s16;
1363:     }
1364:     else
1365:         bbr_recur++;
1366:     firstblk = 0;
1367:     rp_prev = rp_pri = rp_sec = 0;
1368:     rp_l = ra_drv[cn][unit].ra_trksz;   /* LBNs per track */
1369:     rp_r = ra_drv[cn][unit].ra_rbns;    /* RBNs per track */
1370:     rp_hblk = (((rp_lbn / rp_l) * rp_r) / 128) + 2;
1371:     rp_hoff = ((rp_lbn / rp_l) * rp_r) % 128;
1372:     rp_blk = rp_hblk;
1373:     rp_off = rp_hoff;
1374: /* Check for primary RBN descriptor empty or matches this LBN */
1375: 
1376:     if(rctmcr(rp_blk, bp_rct1) < 0) {
1377:         rp_rcte(9, RD, rp_blk);
1378:         goto rp_s16;
1379:     }
1380:     if(rbempty()) {
1381:         rp_pri++;
1382:         goto rp_s9_f;   /* found RBN */
1383:     }
1384:     if(rbmatch()) {
1385:         rp_prev++;
1386:         rp_orbn = ((rp_blk - 2) * 128) + rp_off;
1387: /* OLDCODE	rp_orbn = bp_rct1[rp_off].rbnd_l & ~036000000000;	*/
1388:         rp_orbd = bp_rct1[rp_off].rbnd_l;
1389:     }
1390: /* Start ping-pong search */
1391: 
1392: 
1393:     first_level = YES;
1394:     off_bottom = off_top = NO;
1395:     rp_delta = 1;
1396:     do {
1397:         rp_off = rp_hoff + rp_delta;
1398:         if((rp_off >= 0) && (rp_off <= 127) && !rbnull()) {
1399:             if(rbempty()) {
1400:                 rp_sec++;
1401:                 goto rp_s9_f;       /* found RBN */
1402:             }
1403:             if(rbmatch()) {
1404:                 rp_prev++;
1405:                 rp_orbn = ((rp_blk - 2) * 128) + rp_off;
1406:                 rp_orbd = bp_rct1[rp_off].rbnd_l;
1407:             }
1408:         }
1409:         else {
1410:             if(rp_off > 127)
1411:                 off_bottom = YES;
1412:             if(rp_off < 0)
1413:                 off_top = YES;
1414:             if((off_top = YES) && (off_top == off_bottom))
1415:                 first_level == NO;
1416:         }
1417:         rp_delta = -rp_delta;
1418:         if(rp_delta >= 0)
1419:             rp_delta++;
1420:     }
1421:     while ((first_level) && (!rbnull()));
1422:     if(!rbnull())
1423:         rp_blk++;
1424:     else
1425:         rp_blk = 2;
1426:     firstblk++;
1427:     rp_off = rp_hoff = 0;
1428: 
1429: /* Start of linear search */
1430: 
1431: rp_s9_l:
1432:     if(rblast()) {  /* If primary in last RCT block, go to first block */
1433:         rp_blk = 2;
1434:         rp_off = 0;
1435:     }
1436: rp_s9_l1:
1437:     if(rctmcr(rp_blk, bp_rct1) < 0) {
1438:         rp_rcte(9, RD, rp_blk);
1439:         goto rp_s16;
1440:     }
1441:     rp_off = 0;
1442: rp_s9_l2:
1443:     if((rp_blk == rp_hblk) && (!firstblk )) {  /* search failed */
1444:         rp_rcte(9, -1, 0);  /* RP step 9 FAILED! - message */
1445:         printf("\nRCT search failed: no replacement block available!\n");
1446:         goto rp_s16;
1447:     }
1448:     if(rbempty()) {
1449:         rp_sec++;
1450:         goto rp_s9_f;       /* found RBN */
1451:     }
1452:     if(rbmatch()) {
1453:         rp_prev++;
1454:         rp_orbn = ((rp_blk - 2) * 128) + rp_off;
1455: /* OLDCODE	rp_orbn = bp_rct1[rp_off].rbnd_l & ~036000000000;	*/
1456:         rp_orbd = bp_rct1[rp_off].rbnd_l;
1457:     }
1458:     if(rbnull()) {
1459:         rp_blk = 2;
1460:         goto rp_s9_l1;
1461:     }
1462:     rp_off++;
1463:     if(rp_off > 127) {
1464:         rp_blk++;
1465:         firstblk = 0;
1466:         goto rp_s9_l1;
1467:     }
1468:     goto rp_s9_l2;
1469: rp_s9_f:
1470:     rp_rbn = ((rp_blk - 2) * 128) + rp_off;
1471: rp_s10:
1472: #ifdef  DEBUG
1473:     if(rp_bps == 10)
1474:         goto do_u_x;
1475: #endif	DEBUG
1476: /*
1477:  * Update RCT block 0 with RBN, BR flag, and say in phase 2.
1478:  */
1479: printf("10 ");
1480:     rtp->rt_rbn.ri_rbnl = rp_rbn;
1481:     i = rtp->rt_rbn.ri_rbnw[0]; /* reverse order */
1482:     rtp->rt_rbn.ri_rbnw[0] = rtp->rt_rbn.ri_rbnw[1];
1483:     rtp->rt_rbn.ri_rbnw[1] = i;
1484:     if(rp_prev) {
1485:         rtp->rt_brb.ri_brbl = rp_orbn;
1486:         i = rtp->rt_brb.ri_brbw[0]; /* reverse order */
1487:         rtp->rt_brb.ri_brbw[0] = rtp->rt_brb.ri_brbw[1];
1488:         rtp->rt_brb.ri_brbw[1] = i;
1489:         rtp->rt_stat |= RCI_BR;
1490:     }
1491:     rtp->rt_stat &= ~RCI_P1;
1492:     rtp->rt_stat |= RCI_P2;
1493:     if(rctmcw(0, bp_rci) < 0) {
1494:         rp_rcte(10, WRT, 0);
1495:         goto rp_s16;
1496:     }
1497: 
1498: rp_s11:
1499: #ifdef  DEBUG
1500:     if(rp_bps == 11)
1501:         goto do_u_x;
1502: #endif	DEBUG
1503: /*
1504:  * Update RCT to say block has been replaced.
1505:  */
1506: printf("11 ");
1507:     bp_rct1[rp_off].rbnd_l = rp_lbn;
1508:     if(rp_pri)
1509:         bp_rct1[rp_off].rbnd_w[0] |= 020000;
1510:     else
1511:         bp_rct1[rp_off].rbnd_w[0] |= 030000;
1512:     rp_oblk = (rp_orbn / 128) + 2;
1513:     rp_ooff = rp_orbn % 128;
1514:     if(rp_prev) {
1515:         if(rp_blk != rp_oblk) { /* rbn & old rbn in diff blks */
1516:             if(rctmcr(rp_oblk, bp_rct2) < 0) {
1517:                 rp_rcte(11, RD, rp_oblk);
1518:                 goto rp_s16;
1519:             }
1520:             bp_rct2[rp_ooff].rbnd_l = 010000000000L;
1521:         } else
1522:             bp_rct1[rp_ooff].rbnd_l = 010000000000L;
1523:     }
1524:     if(rctmcw(rp_blk, bp_rct1) < 0) {
1525:         rp_rcte(11, WRT, rp_blk);
1526:         goto rp_s15;
1527:     }
1528:     if(rp_prev && (rp_oblk != rp_blk)) {
1529:         if(rctmcw(rp_blk, bp_rct2) < 0) {
1530:             rp_rcte(11, WRT, rp_blk);
1531:             goto rp_s15;
1532:         }
1533:     }
1534: 
1535: rp_s12:
1536: #ifdef  DEBUG
1537:     if(rp_bps == 12)
1538:         goto do_u_x;
1539: #endif	DEBUG
1540: /*
1541:  * Use the REPLACE command to cause the controller
1542:  * to replace the bad block.
1543:  */
1544: printf("12 ");
1545:     lseek(fd, (long)(rp_lbn*512), 0);
1546:     ra_badc = RP_REP;
1547:     if(rp_pri)
1548:         ra_badm = MD_PRI;
1549:     ra_rbn.ra_rbnl = rp_rbn;    /* tell driver replacement block # */
1550:     write(fd, (char *)bp_ir, 512);  /* really a REPLACE command */
1551:     if((ra_stat[cn] & ST_MSK) != ST_SUC) {
1552:         rp_rcte(12, -1, 0); /* RP step 12 FAILED! - message */
1553:         printf("\nMSCP replace command failed!\n");
1554:         goto rp_s17;
1555:     }
1556:     if(rp_dirty == 2) goto rp_s120;
1557:     /*
1558: 	 * First, read the block and check for the Forced Error flag.
1559: 	 * All unused RBNs are written with the forced error flag, so
1560: 	 * it should be set if the replace command worked.
1561: 	 */
1562:     lseek(fd, (long)(rp_lbn*512), 0);
1563:     ra_badc = RP_RD;
1564:     read(fd, buf, 512);
1565:     if ((ra_stat[cn] & ST_DAT) != ST_DAT) {
1566:         rp_rcte(12, -1, 0); /* RP step 12 FAILED! - message */
1567:         printf("\nMSCP replace command failed!\n");
1568:         printf("RBN used for LBN %d did not contain Forced Error indicator.\n", rp_lbn);
1569:         /*printd2("ra_stat = 0x%x, ra_ecode = 0x%x, ra_eflags = 0x%x\n",
1570: 			ra_stat, ra_ecode, ra_eflags); */
1571:         goto rp_s17;
1572:     }
1573:     /*
1574: 	 * Read the date to be written to the replacement block
1575: 	 * from RCT block 1 -- just to be safe.
1576: 	 */
1577:     /* if (rctmcr(1, bp_ir) < 0) {
1578: 		rp_rcte(12, RD, 0);
1579: 		goto rp_s18;
1580: 	} */
1581: rp_s120:
1582:     lseek(fd, (long)(rp_lbn*512), 0);
1583:     ra_badc = RP_WRT;
1584:     ra_badm = MD_CMP;
1585:     if(rp_irs == NO)
1586:         ra_badm |= MD_ERR;
1587:     write(fd, (char *)bp_ir, 512);  /* write saved -> replacement block */
1588:     if((ra_stat[cn] & ST_MSK) == ST_SUC)
1589:         goto rp_s121;
1590:     if((ra_eflags[cn] & EF_BBR) != EF_BBR)
1591:         if((ra_stat[cn] == ST_DAT) && (rp_irs == NO))
1592:             goto rp_s121;
1593:     /* write - compare failed */
1594:     rp_rcte(12, -1, 0);
1595:     printf("\nWRITE-COMPARE operation on replacement block failed!\n");
1596:     /*
1597: 	 *  If a header compare error or a bad block reported, go back
1598: 	 *  to step 9 and try to find another RBN.
1599: 	 */
1600:     if((ra_stat[cn] != MD_HCE) || (ra_eflags[cn] & EF_BBR))
1601:         goto rp_s9;
1602:     else {
1603:         printf("Check the RCT, it MAY be corrupt!!\n");
1604:         if(cmd[0] = 'i')
1605:             goto bg_loop;
1606:         else {
1607:             goto do_u_x;
1608:         }
1609:     }
1610: rp_s121:    /* replacement succeeded */
1611:     rp_didit++;
1612: 
1613: rp_s13:
1614: #ifdef  DEBUG
1615:     if(rp_bps == 13)
1616:         goto do_u_x;
1617: #endif	DEBUG
1618: /*
1619:  * Update RCT block 0 to indicate replacement
1620:  * no longer in progress.
1621:  */
1622: printf("13 ");
1623:     rtp->rt_stat &= RCI_VP; /* clean out all but VP */
1624:     rtp->rt_lbn.ri_lbnl = 0L;
1625:     rtp->rt_rbn.ri_rbnl = 0L;
1626:     rtp->rt_brb.ri_brbl = 0L;
1627:     if(rctmcw(0, bp_rci) < 0) {
1628:         rp_rcte(13, WRT, 0);
1629:         goto rp_s17;
1630:     }
1631: 
1632: rp_s14:
1633: #ifdef  DEBUG
1634:     if(rp_bps == 14)
1635:         goto do_u_x;
1636: #endif	DEBUG
1637: /*
1638:  * Soft lock not used.
1639:  * Replacement completed, return!
1640:  */
1641:     if(cmd[0] == 'i') {
1642:         if(rp_didit)
1643:             goto do_i_rg;
1644:         else
1645:             goto do_i_ra;
1646:     } else {
1647:         if(fd > 0)
1648:             close(fd);
1649:         if(rp_dirty)
1650:             rp_dirty = 0;
1651:         if(rp_didit)
1652:             printf("SUCCEEDED!\n");
1653:         else
1654:             if (nondataerr) {
1655:                 printf("ABORTED (nondata error encontered)!\n");
1656:                 nondataerr = NO;
1657:             }
1658:             else
1659:                 printf("ABORTED (block not really bad)!\n");
1660:         goto retry;
1661:     }
1662: 
1663: rp_s15:
1664: #ifdef  DEBUG
1665:     if(rp_bps == 15)
1666:         goto do_u_x;
1667: #endif	DEBUG
1668: /*
1669:  * Restore RCT to say new RBN unusable and
1670:  * set bad LBN back to its original state.
1671:  * ECO: not sure what to do yet!
1672:  *	For now, say RBN unusable regardless!
1673:  */
1674: printf("15 ");
1675:     bp_rct1[rp_off].rbnd_l = 010000000000L;
1676:     if(rp_prev) {
1677:         if(rp_blk != rp_oblk)
1678:             bp_rct2[rp_ooff].rbnd_l = rp_orbd;
1679:         else
1680:             bp_rct1[rp_ooff].rbnd_l = rp_orbd;
1681:     }
1682:     if(rctmcw(rp_blk, bp_rct1) < 0)
1683:         rp_rcte(15, WRT, rp_blk);
1684:     if(rp_prev && (rp_blk != rp_oblk))
1685:         if(rctmcw(rp_oblk, bp_rct2) < 0)
1686:             rp_rcte(15, WRT, rp_oblk);
1687: 
1688: rp_s16:
1689: #ifdef  DEBUG
1690:     if(rp_bps == 16)
1691:         goto do_u_x;
1692: #endif	DEBUG
1693: /*
1694:  * Write saved date back to the bad LBN
1695:  * with forced error modifier.
1696:  */
1697: printf("16 ");
1698:     lseek(fd, (long)(rp_lbn*512), 0);
1699:     ra_badc = RP_WRT;
1700:     if(rp_irs == NO)
1701:         ra_badm = MD_ERR;
1702:     if(write(fd, (char *)bp_ir, 512) != 512) {
1703:         rp_rcte(16, -1, 0); /* RP step 16 FAILED! - message */
1704:         printf("\nRewrite of original data back to bad block failed!\n");
1705:     }
1706: 
1707: rp_s17:
1708: #ifdef  DEBUG
1709:     if(rp_bps == 17)
1710:         goto do_u_x;
1711: #endif	DEBUG
1712: /*
1713:  * Update RCT block 0 to say replacement
1714:  * no longer inprogress.
1715:  */
1716: printf("17 ");
1717:     rtp->rt_stat &= RCI_VP; /* clean out all but VP */
1718:     rtp->rt_lbn.ri_lbnl = 0L;
1719:     rtp->rt_rbn.ri_rbnl = 0L;
1720:     rtp->rt_brb.ri_brbl = 0L;
1721:     if(rctmcw(0, bp_rci) < 0)
1722:         rp_rcte(17, WRT, 0);
1723: 
1724: rp_s18:
1725: #ifdef  DEBUG
1726:     if(rp_bps == 18)
1727:         goto do_u_x;
1728: #endif	DEBUG
1729: /*
1730:  * Soft lock not used.
1731:  * Replacement failed, return!
1732:  */
1733:     if(cmd[0] == 'i')
1734:         goto do_i_rb;
1735:     else {
1736:         if(rp_dirty)
1737:             rp_dirty = 0;
1738:         printf("\n\7\7\7Block %D replacement FAILED!\n", rp_lbn);
1739:         if(fd > 0)
1740:             close(fd);
1741:         goto retry;
1742:     }
1743: }
1744: 
1745: /*
1746:  *  Write data to a block, and then read it -- thus testing the block
1747:  */
1748: 
1749: blocktest(fd, ucerr, bp)
1750: int fd;         /* file descriptor */
1751: char    *bp;
1752: int ucerr;          /* uncorrectable ECC error when reading
1753: 				 * the block the block to be replaced
1754: 				 */
1755: {
1756:     int i, count;
1757:     int block_good; /* true if block is thought to be good */
1758: 
1759:     block_good = YES;
1760:     lseek(fd, (long)(rp_lbn*512), 0);
1761:     ra_badc = RP_WRT;
1762:     ra_badm = (MD_CMP|MD_SEC|MD_SREC | (!ucerr ? 0 : MD_ERR));
1763:     if((((count = write(fd, bp, 512)) != 512) && (ra_eflags[cn] & EF_BBR)) ||
1764:         (ra_stat[cn] & 0xe8)) {
1765:         block_good = NO;
1766:     }
1767:     if (block_good == YES) {
1768:         for (i = 0; i < 4; i++) {
1769:             lseek(fd, (long)(rp_lbn*512), 0);
1770:             ra_badc = RP_AC;
1771:             ra_badm = MD_SEC|MD_SREC;
1772:             if(((read(fd, buf, 512) != 512) && (ra_eflags[cn] & EF_BBR)) ||
1773:                 (ra_stat[cn] & 0xe8)) {
1774:                 block_good = NO;
1775:                 break;
1776:             }
1777:         }
1778:     }
1779:     return (block_good);
1780: }
1781: /*
1782:  * RCT read/write fatal error message
1783:  *
1784:  * s	= step in replacement process
1785:  * rw	= failure was on read or write
1786:  *	= -1, print first line then return
1787:  * lbn	= block number
1788:  */
1789: 
1790: rp_rcte(s, rw, lbn)
1791: int s;
1792: int rw;
1793: int lbn;
1794: {
1795:     printf("\n\7\7\7Bad block replacement process step %d FAILED!", s);
1796:     if(rw == -1)
1797:         return;
1798:     printf("\nMulticopy %s", (rw == WRT) ? "write" : "read");
1799:     printf(" of RCT block %d FAILED!\n", lbn);
1800:     deprnt();   /* print disk error info */
1801: }
1802: 
1803: /*
1804:  * Open the disk and set file descriptor in fd.
1805:  * mode = how to open, read, write, read/write.
1806:  * err  = ignore errors (see if drive is there).
1807:  *
1808:  * If the disk has an RCT, read RCT block zero
1809:  * and set rp_dirty to the phase that was in
1810:  * progress if the replacement was interrupted.
1811:  * Otherwise, set rp_dirty to zero.
1812:  */
1813: dskopen(err, mode)
1814: int err;
1815: int mode;
1816: {
1817:     register struct rct_rci *rtp;
1818: 
1819:     if((fd = open(fn, mode)) <= 0) {
1820:         if(err == 0) {
1821:             printf("\nCan't open %s!\n", fn);
1822:             exit(FATAL);
1823:         }
1824:         return;
1825:     }
1826:     rp_dirty = 0;
1827:     if((ra_drv[cn][unit].ra_rctsz == 0) || (dip->di_flag != BB_COOP))
1828:         return;
1829:     if(rctmcr(0, bp_rci) < 0) {
1830:         printf("\n\7\7\7WARNING: cannot read RCT block zero for ");
1831:         printf("%s unit %d!\n", ra_dct[cn], unit);
1832:         return;
1833:     }
1834:     rtp = (struct rct_rci *)bp_rci;
1835:     if(rtp->rt_stat & RCI_P1)
1836:         rp_dirty = 1;
1837:     if(rtp->rt_stat & RCI_P2)
1838:         rp_dirty = 2;
1839:     if(rp_dirty == 0)
1840:         return;
1841:     printf("\n\7\7\7\t\t****** WARNING ******\n");
1842:     printf("\nA bad block replacement was interrupted during phase %d.\n",
1843:         rp_dirty);
1844:     if(cmd[0] == 'r')
1845:         return;
1846:     printf("\nAfter the current command completes, execute a replace");
1847:     printf("\ncommand by responding to the rabads < ..... >: prompt");
1848:     printf("\nwith the letter r followed by <RETURN>. This will");
1849:     printf("\ncause the interrupted replacement of be completed.\n");
1850: }
1851: 
1852: prtdsk()
1853: {
1854:     struct dkinfo *dp;
1855: 
1856:     printf("\nDisk\tULTRIX\tSize in");
1857:     printf("\nName\tName\tBlocks");
1858:     printf("\n----\t----\t------");
1859:     for(dp=dkinfo; dp->di_type; dp++){
1860:         printf("\n%s\t", dp->di_type);
1861:         printf("%s\t", dp->di_name);
1862:         printf("%D", dp->di_size);
1863:     }
1864:     printf("\n");
1865: }
1866: /*
1867:  * Drive information pointer set,
1868:  *	pointer into dkinfo table,
1869:  *	unit number,
1870:  *	MSCP controller number,
1871:  *	file name - ??(#,0).
1872:  */
1873: dipset()
1874: {
1875:     register int i;
1876: 
1877:     printf("\nDisk type < ");
1878:     for(i=0; dkinfo[i].di_type; i++) {
1879:         printf("%s ", dkinfo[i].di_type);
1880:     }
1881:     printf(">: ");
1882:     gets(dt);
1883:     for(dip=dkinfo; dip->di_type; dip++)
1884:         if(strcmp(dip->di_type, dt) == 0)
1885:             break;
1886:     if(dip->di_type == 0) {
1887:         printf("\n(%s) - not supported by RABADS!\n", dt);
1888: dip_x:
1889:         if(argflag)
1890:             exit(FATAL);
1891:         else
1892:             return(-1);
1893:     }
1894:     printf("\nUnit number < 0-3 >: ");
1895:     gets(dn);
1896:     if((strlen(dn) != 1) || (dn[0] < '0') || (dn[0] > '3')) {
1897:         printf("\nUnits 0 -> 3 only!\n");
1898:         goto dip_x;
1899:     }
1900:     unit = dn[0] - '0';
1901:     sprintf(fn, "%s(%s,0)", dip->di_name, dn);
1902:     for(i=0; devsw[i].dv_name; i++)
1903:         if(strcmp(dip->di_name, devsw[i].dv_name) == 0)
1904:             break;
1905:     cn = devsw[i].dv_cn;
1906: #ifdef  DEBUG
1907: 
1908:     printf("\nDEBUG: Break Point at replacement step ? ");
1909:     gets(line);
1910:     if(line[0] == '\0')
1911:         rp_bps = 0;
1912:     else
1913:         rp_bps = atoi(line);
1914: 
1915: #endif	DEBUG
1916:     return(0);
1917: }
1918: 
1919: /*
1920:  * RCT multicopy read,
1921:  *	lbn = sector of RCT to read.
1922:  *	bp = pointer to buffer.
1923:  *	Host area size is added to lbn.
1924:  * cn is MSCP cntlr number, unit is drive number,
1925:  * fd is the previously opened file descriptor,
1926:  * all are external to main().
1927:  */
1928: 
1929: rctmcr(lbn, bp)
1930: unsigned lbn;
1931: union rctb *bp;
1932: {
1933:     register int i, n, s;
1934:     daddr_t bn, boff;
1935: 
1936:     n = ra_drv[cn][unit].ra_ncopy;
1937:     s = ra_drv[cn][unit].ra_rctsz;
1938:     bn = ra_drv[cn][unit].d_un.ra_dsize + lbn;
1939:     for(i=0; i<n; i++) {
1940:         if(rctcopy && (rctcopy != (i+1)))
1941:             continue;
1942:         boff = bn * 512;
1943:         lseek(fd, (long)boff, 0);
1944:         ra_badc = RP_RD;    /* tell driver doing BADS funny business */
1945:         read(fd, (char *)bp, 512);
1946:         if(ra_stat[cn] == ST_SUC) {
1947:             if(lbn > 1)
1948:                 rctrev(bp);
1949:             return(0);
1950:         }
1951:         bn += s;
1952:     }
1953:     return(-1);
1954: }
1955: 
1956: /*
1957:  * RCT multicopy write,
1958:  *	lbn = sector of RCT to write.
1959:  *	bp = pointer to buffer.
1960:  *	Host area size is added to lbn.
1961:  * cn is the MSCP cntlr number, unit is drive number,
1962:  * fd is the previously opened file descriptor,
1963:  * all are external to main().
1964:  */
1965: 
1966: rctmcw(lbn, bp)
1967: unsigned lbn;
1968: union rctb *bp;
1969: {
1970:     register int i, n, s;
1971:     int ec, sc, fatal;
1972:     daddr_t bn, boff;
1973: 
1974:     n = ra_drv[cn][unit].ra_ncopy;
1975:     s = ra_drv[cn][unit].ra_rctsz;
1976:     bn = ra_drv[cn][unit].d_un.ra_dsize + lbn;
1977:     ec = fatal = 0;
1978:     if(lbn > 1)     /* only reverse blocks containing RBNs */
1979:         rctrev(bp);
1980:     for(i=0; i<n; i++, bn += s) {
1981:         boff = bn * 512;
1982:         lseek(fd, (long)boff, 0);
1983:         ra_badc = RP_WRT;   /* tells driver doing BADS funny business */
1984:         ra_badm = MD_CMP;
1985:         write(fd, (char *)bp, 512);
1986:         if(ra_stat[cn] == ST_SUC)
1987:             continue;
1988:         sc = (ra_stat[cn] >> 5) & 03777;
1989:         if((ra_stat[cn] & ST_MSK) == ST_DAT) {
1990:             if((sc != 2) && (sc != 3) && (sc != 7))
1991:                 continue; /* NOT - HCE, DATA SYNC, UNC ECC */
1992:             ec++;
1993:             lseek(fd, (long)boff, 0);
1994:             ra_badc = RP_WRT;
1995:             ra_badm = MD_ERR;
1996:             write(fd, (char *)bp, 512);
1997:             if((ra_stat[cn] & ST_MSK) == ST_SUC)
1998:                 continue;
1999:             sc = (ra_stat[cn] >> 5) & 03777;
2000:             if((ra_stat[cn] & ST_MSK) == ST_DAT) {
2001:                 if((sc != 2) && (sc != 3) && (sc != 7))
2002:                     continue;
2003:             }
2004:         }
2005:         fatal = -1;
2006:         break;
2007:     }
2008:     if(ec >= n)
2009:         fatal = -1;
2010:     return(fatal);
2011: }
2012: 
2013: /*
2014:  * Reverse the order of the RBN descriptors in bp_rct1[].
2015:  * ULTRIX-11 C still need hi order word first!
2016:  */
2017: 
2018: rctrev(bp)
2019: union rctb *bp;
2020: {
2021:     register union rctb *rbp;
2022:     register int i, j;
2023: 
2024:     rbp = bp;
2025:     for(i=0; i<128; i++) {
2026:         j = rbp[i].rbnd_w[0];
2027:         rbp[i].rbnd_w[0] = rbp[i].rbnd_w[1];
2028:         rbp[i].rbnd_w[1] = j;
2029:     }
2030: }
2031: 
2032: /*
2033:  * Print the disk error information that would
2034:  * have been printed by the driver if the ra_badc
2035:  * flag was not set.
2036:  */
2037: deprnt()
2038: {
2039:     printf("%s unit %d disk error: ",
2040:         ra_dct[cn], unit);
2041:     printf("endcode=%o flags=%o status=%o\n",
2042:         ra_ecode[cn], ra_eflags[cn], ra_stat[cn]);
2043:     printf("(FATAL ERROR)\n");
2044: }
2045: 
2046: rbempty()
2047: {
2048:     if((bp_rct1[rp_off].rbnd_l & 036000000000) == 0)
2049:         return(1);
2050:     else
2051:         return(0);
2052: }
2053: 
2054: rbmatch()
2055: {
2056:     if((bp_rct1[rp_off].rbnd_l & 04000000000) == 0)
2057:         return(0);
2058:     if(rp_lbn == (bp_rct1[rp_off].rbnd_l & ~036000000000))
2059:         return(1);
2060:     return(0);
2061: }
2062: 
2063: rbnull()
2064: {
2065:     if((bp_rct1[rp_off].rbnd_l & 036000000000) == 020000000000)
2066:         return(1);
2067:     else
2068:         return(0);
2069: }
2070: rblast()
2071: {
2072:     register int i;
2073: 
2074:     for(i=0; i<128; i++)
2075:         if((bp_rct1[i].rbnd_l & 036000000000) == 020000000000)
2076:             return(1);
2077:     return(0);
2078: }
2079: 
2080: prfm()
2081: {
2082:     register char c;
2083: 
2084:     printf("\n\nPress <RETURN> for more");
2085:     printf(" (<CTRL/C> to abort): ");
2086:     while((c=getchar()) != '\n') {
2087:         if(c == 03) /* <CTRL/C> */
2088:             return(1);
2089:     }
2090:     return(0);
2091: }
2092: 
2093: char    ynline[40];
2094: 
2095: yes(hlp)
2096: {
2097: yorn:
2098:     gets(ynline);
2099:     if((strcmp(ynline, "y") == 0) || (strcmp(ynline, "yes") == 0))
2100:         return(YES);
2101:     if((strcmp(ynline, "n") == 0) || (strcmp(ynline, "no") == 0))
2102:         return(NO);
2103:     if(hlp)
2104:         if((strcmp(ynline, "?") == 0) || (strcmp(ynline, "help") == 0))
2105:         return(HELP);
2106:     printf("\nPlease answer yes or no!\n");
2107:     goto yorn;
2108: }
2109: 
2110: /*
2111:  * Read a suspected bad block and
2112:  * return its status.
2113:  */
2114: 
2115: brchk(lbn)
2116: daddr_t lbn;
2117: {
2118:     register int i, s;
2119: 
2120:     for(i=0; i<100; i++) {
2121:         lseek(fd, (long)(lbn*512), 0);
2122:         ra_badc = RP_AC;
2123:         if(read(fd, (char *)&buf, 512) != 512)
2124:             break;
2125:     }
2126:     s = ra_stat[cn] & ST_MSK;
2127:     if(s == ST_SUC) {
2128:         if(ra_eflags[cn] & EF_BBR)
2129:             return(BR_BBR);
2130:         else
2131:             return(BR_NBBR);
2132:     } else if(s == ST_DAT) {
2133:         if((dip->di_flag != BB_RWRT) && (ra_eflags[cn] & EF_BBR))
2134:             return(BR_DEB);
2135:         switch((ra_stat[cn] >> 5) & 03777) {
2136:         case 0:
2137:             return(BR_FEM);
2138:         case 4:
2139:         case 8:
2140:         case 9:
2141:         case 10:
2142:         case 11:
2143:         case 12:
2144:         case 13:
2145:         case 14:
2146:         case 15:
2147:             /* can't happen - not allowing datagrams */
2148:             return(BR_CECC);
2149:         case 7:
2150:             return(BR_UECC);
2151:         default:
2152:             return(BR_NDE);
2153:         }
2154:     } else
2155:         return(BR_NDE);
2156: }
2157: 
2158: /*
2159:  * Conditionally print BLOCK # header message.
2160:  * Rewite a block that was written with "forced error".
2161:  * Return status of rewrite operation.
2162:  */
2163: 
2164: fembrw(hm, lbn)
2165: int hm;
2166: daddr_t lbn;
2167: {
2168:     if(hm)
2169:         printf("BLOCK: %D - ", lbn);
2170:     printf("rewrite to clear \"forced error\" ");
2171:     lseek(fd, (long)(lbn*512), 0);
2172:     ra_badc = RP_WRT;
2173:     write(fd, (char *)&buf, 512);
2174:     lseek(fd, (long)(lbn*512), 0);
2175:     if(read(fd, (char *)&buf, 512) == 512) {
2176:         printf("SUCCEEDED!\n");
2177:         return(YES);
2178:     } else {
2179:         printf("FAILED!\n");
2180:         deprnt();   /* print disk error info */
2181:         return(NO);
2182:     }
2183: }

Defined functions

blocktest defined in line 1749; used 2 times
brchk defined in line 2115; used 3 times
deprnt defined in line 2037; used 9 times
dipset defined in line 1873; used 5 times
dskopen defined in line 1813; used 5 times
fembrw defined in line 2164; used 5 times
main defined in line 340; never used
prfm defined in line 2080; used 3 times
prtdsk defined in line 1852; used 1 times
rbempty defined in line 2046; used 3 times
rblast defined in line 2070; used 1 times
rbmatch defined in line 2054; used 3 times
rbnull defined in line 2063; used 4 times
rctmcr defined in line 1929; used 12 times
rctmcw defined in line 1966; used 9 times
rctrev defined in line 2018; used 2 times
rp_rcte defined in line 1790; used 22 times
yes defined in line 2095; used 3 times

Defined variables

allflag defined in line 254; used 6 times
ask defined in line 253; used 5 times
badcnt defined in line 251; used 9 times
bbr_recur defined in line 270; used 3 times
bdwarn defined in line 322; used 1 times
bn defined in line 250; used 30 times
bp_ir defined in line 182; used 13 times
bp_rci defined in line 181; used 12 times
bp_rct1 defined in line 183; used 22 times
bp_rct2 defined in line 184; used 5 times
bp_tmp defined in line 186; used 5 times
bp_tp defined in line 185; used 4 times
buf defined in line 105; used 22 times
cmd defined in line 262; used 11 times
cn defined in line 258; used 69 times
dip defined in line 248; used 21 times
dkinfo defined in line 89; used 4 times
dn defined in line 264; used 6 times
dt defined in line 263; used 3 times
fd defined in line 252; used 64 times
feb_nc1 defined in line 326; used 5 times
feb_nc2 defined in line 328; used 5 times
fewarn defined in line 300; used 4 times
first_level defined in line 268; used 3 times
firstblk defined in line 265; used 4 times
fn defined in line 261; used 6 times
force defined in line 256; used 4 times
help defined in line 272; used 2 times
line defined in line 260; used 21 times
nb defined in line 249; used 9 times
nbc defined in line 249; used 6 times
nblk defined in line 249; used 9 times
ndemsg defined in line 330; used 3 times
nondataerr defined in line 269; used 5 times
off_bottom defined in line 266; used 3 times
off_top defined in line 267; used 4 times
pwstr defined in line 325; used 1 times
rb_bad defined in line 334; used 2 times
rb_uecc defined in line 332; used 2 times
rbn defined in line 249; used 19 times
rcnt defined in line 252; used 4 times
rctcopy defined in line 338; used 7 times
repcnt defined in line 251; used 12 times
rp_blk defined in line 157; used 29 times
rp_bps defined in line 149; used 20 times
rp_delta defined in line 161; used 6 times
rp_didit defined in line 154; used 4 times
rp_dirty defined in line 173; used 16 times
rp_hblk defined in line 155; used 6 times
rp_hoff defined in line 156; used 7 times
rp_irs defined in line 163; used 13 times
rp_l defined in line 171; used 6 times
rp_lbn defined in line 152; used 24 times
rp_oblk defined in line 159; used 11 times
rp_off defined in line 158; used 28 times
rp_ooff defined in line 160; used 7 times
rp_orbd defined in line 168; used 8 times
rp_orbn defined in line 167; used 9 times
rp_prev defined in line 166; used 12 times
rp_pri defined in line 169; used 6 times
rp_r defined in line 172; used 6 times
rp_rbn defined in line 153; used 6 times
rp_sec defined in line 170; used 5 times
rp_wcs7 defined in line 164; used 9 times
rp_wcs8 defined in line 165; used 1 times
rsize defined in line 251; used 3 times
rwfem defined in line 255; used 8 times
sbn defined in line 249; used 9 times
unit defined in line 259; used 29 times
us defined in line 249; used 8 times
ynline defined in line 2093; used 7 times

Defined struct's

dkinfo defined in line 82; used 4 times
rct_rci defined in line 193; used 11 times

Defined union's

rctb defined in line 219; used 10 times

Defined macros

BB_COOP defined in line 78; used 6 times
BB_NONE defined in line 80; used 5 times
BB_RWRT defined in line 79; used 10 times
BR_BBR defined in line 137; used 2 times
BR_CECC defined in line 138; used 1 times
BR_DEB defined in line 142; used 1 times
BR_FEM defined in line 141; used 2 times
BR_NBBR defined in line 136; used 3 times
BR_NDE defined in line 140; used 2 times
BR_UECC defined in line 139; used 1 times
EF_BBR defined in line 119; used 12 times
EF_BBU defined in line 120; used 1 times
ERR defined in line 69; used 1 times
HELP defined in line 73; used 3 times
MD_CMP defined in line 112; used 4 times
MD_ERR defined in line 113; used 5 times
MD_HCE defined in line 126; used 1 times
MD_PRI defined in line 116; used 1 times
MD_SEC defined in line 114; used 3 times
MD_SREC defined in line 115; used 3 times
NO defined in line 72; used 24 times
NOERR defined in line 70; used 4 times
RCI_BR defined in line 131; used 3 times
RCI_FE defined in line 130; used 4 times
RCI_P1 defined in line 133; used 4 times
RCI_P2 defined in line 132; used 3 times
RCI_VP defined in line 129; used 3 times
RD defined in line 66; used 10 times
RP_AC defined in line 233; used 4 times
RP_RD defined in line 231; used 7 times
RP_REP defined in line 232; used 1 times
RP_WRT defined in line 230; used 9 times
RW defined in line 68; used 3 times
ST_DAT defined in line 125; used 10 times
ST_MSK defined in line 123; used 6 times
ST_SUC defined in line 124; used 6 times
WRT defined in line 67; used 10 times
YES defined in line 71; used 22 times
Last modified: 1989-01-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 8488
Valid CSS Valid XHTML 1.0 Strict