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: }