1: /* 2: * SCCSID: @(#)bads.c 3.1 3/26/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: * ULTRIX-11 standalone quick disk surface verifer 25: * 26: * Fred Canter 2/26/83 27: * Jerry Brenner 12/16/82 28: * 29: * Functionality: 30: * 31: * Scan: 32: * This routine prints the contents of the bad sector file 33: * on a disk pack, per DEC standard 144. 34: * It also scans a selected area for the disk for bad blocks 35: * by reading the data, this is a very gross check at best. 36: * 37: * This code arbitrarily limits the maximum number of 38: * bad sectors to the sectors per track count of that disk. 39: * e.g. RK06/07 maximum of 22 bad sectors. 40: * 41: */ 42: 43: #include "sa_defs.h" 44: #include <sys/param.h> 45: #include <sys/bads.h> 46: 47: /* 48: * This programs accesses physical devices only. 49: * Must use 512 instead of BSIZE (1024 for new file system). 50: * Fred Canter 6/12/85 51: */ 52: #undef BSIZE 53: #define BSIZE 512 54: 55: /* 56: * BAD144 info for disk bad blocking. A zero entry in 57: * di_size indicates that disk type has no bad blocking. 58: */ 59: #define NP -1 60: #define HP 1 61: #define HM 2 62: #define HJ 3 63: 64: struct dkinfo { 65: char *di_type; /* type name of disk */ 66: int di_flag; /* prtdsk() flags */ 67: char *di_name; /* ULTRIX-11 disk name */ 68: long di_size; /* size of entire volume in blocks */ 69: int di_nsect; /* sectors per track */ 70: int di_ntrak; /* tracks per cylinder */ 71: int di_wcpat[2]; /* worst case pattern */ 72: } dkinfo[] = { 73: "rk05", 0, "rk", 4872L, 12, 0, 0, 0, 74: "rl01", 0, "rl", 10240L, 20, 0, 0, 0, 75: "rl02", 0, "rl", 20480L, 20, 0, 0, 0, 76: "ml11", NP, "hp", 8192L, 16, 0, 0, 0, 77: "ml11_0", HP, "hp", 8192L, 16, 0, 0, 0, 78: "ml11_1", HM, "hm", 8192L, 16, 0, 0, 0, 79: "ml11_2", HJ, "hj", 8192L, 16, 0, 0, 0, 80: "rk06", 0, "hk", 22L*3L*411L, 22, 3, 0135143, 072307, 81: "rk07", 0, "hk", 22L*3L*815L, 22, 3, 0135143, 072307, 82: "rm02", NP, "hp", 32L*5L*823L, 32, 5, 0165555, 0133333, 83: "rm02_0", HP, "hp", 32L*5L*823L, 32, 5, 0165555, 0133333, 84: "rm02_1", HM, "hm", 32L*5L*823L, 32, 5, 0165555, 0133333, 85: "rm02_2", HJ, "hj", 32L*5L*823L, 32, 5, 0165555, 0133333, 86: "rm03", NP, "hp", 32L*5L*823L, 32, 5, 0165555, 0133333, 87: "rm03_0", HP, "hp", 32L*5L*823L, 32, 5, 0165555, 0133333, 88: "rm03_1", HM, "hm", 32L*5L*823L, 32, 5, 0165555, 0133333, 89: "rm03_2", HJ, "hj", 32L*5L*823L, 32, 5, 0165555, 0133333, 90: "rm05", NP, "hp", 32L*19L*823L, 32, 19, 0165555, 0133333, 91: "rm05_0", HP, "hp", 32L*19L*823L, 32, 19, 0165555, 0133333, 92: "rm05_1", HM, "hm", 32L*19L*823L, 32, 19, 0165555, 0133333, 93: "rm05_2", HJ, "hj", 32L*19L*823L, 32, 19, 0165555, 0133333, 94: "rp02", 0, "rp", 10L*20L*200L, 10, 0, 0, 0, 95: "rp03", 0, "rp", 10L*20L*400L, 10, 0, 0, 0, 96: "rp04", NP, "hp", 22L*19L*411L, 22, 19, 0165555, 0133333, 97: "rp04_0", HP, "hp", 22L*19L*411L, 22, 19, 0165555, 0133333, 98: "rp04_1", HM, "hm", 22L*19L*411L, 22, 19, 0165555, 0133333, 99: "rm04_2", HJ, "hj", 22L*19L*411L, 22, 19, 0165555, 0133333, 100: "rp05", NP, "hp", 22L*19L*411L, 22, 19, 0165555, 0133333, 101: "rp05_0", HP, "hp", 22L*19L*411L, 22, 19, 0165555, 0133333, 102: "rp05_1", HM, "hm", 22L*19L*411L, 22, 19, 0165555, 0133333, 103: "rp05_2", HJ, "hj", 22L*19L*411L, 22, 19, 0165555, 0133333, 104: "rp06", NP, "hp", 22L*19L*815L, 22, 19, 0165555, 0133333, 105: "rp06_0", HP, "hp", 22L*19L*815L, 22, 19, 0165555, 0133333, 106: "rp06_1", HM, "hm", 22L*19L*815L, 22, 19, 0165555, 0133333, 107: "rp06_2", HJ, "hj", 22L*19L*815L, 22, 19, 0165555, 0133333, 108: /* 109: * RA disks can't do full track reads because of buffer size. 110: * UDA50 buffering makes < full track reads plenty big enough. 111: * # sectors must divide evenly into total disk size 112: */ 113: "ra60", 0, "ra", 400176L, 28, 0, 0, 0, 114: "ra80", 0, "ra", 236964L, 28, 0, 0, 0, 115: "ra81", 0, "ra", 891072L, 32, 0, 0, 0, 116: "rx50", 0, "rx", 800L, 10, 0, 0, 0, 117: "rx33", 0, "rx", 2400L, 10, 0, 0, 0, 118: "rd31", 0, "rd", 41560L, 20, 0, 0, 0, 119: "rd32", 0, "rd", 83204L, 22, 0, 0, 0, 120: "rd51", 0, "rd", 21600L, 18, 0, 0, 0, 121: "rd52", 0, "rd", 60480L, 18, 0, 0, 0, 122: "rd53", 0, "rd", 138672L, 18, 0, 0, 0, 123: "rd54", 0, "rd", 311200L, 20, 0, 0, 0, 124: "rc25", 0, "rc", 50902L, 31, 0, 0, 0, 125: 0, 126: }; 127: 128: struct dkbad dkbad; 129: struct dkinfo *dip; 130: struct bt_bad *bt; 131: int i; 132: daddr_t bn; 133: long nblk, nbo; 134: int fd, rcnt; 135: long atol(); 136: char line[20]; 137: char fn[30]; /* file spec i.e., hp(0,0) */ 138: char dt[20]; /* disk type rm03, etc */ 139: char dn[2]; /* drive number */ 140: struct { 141: int t_cn; 142: int t_tn; 143: int t_sn; 144: }da; 145: char buf[(BSIZE+4)*32]; 146: union { 147: long serl; 148: int seri[2]; 149: }dsk; 150: char *bblock = "Block Cyl Trk Sec\n"; 151: 152: extern int argflag; /* 0=interactive, 1=called by sdload */ 153: 154: main() 155: { 156: printf("\n\nQuick Bad Block Scan Program\n"); 157: retry: 158: printf("\nDisk type <cr to exit, ? for list of disks>: "); 159: gets(dt); 160: if(dt[0] == '?'){ 161: prtdsk(); 162: goto retry; 163: } 164: if(strlen(dt) < 1) 165: exit(NORMAL); 166: for(dip=dkinfo; dip->di_type; dip++) 167: if(strcmp(dip->di_type, dt) == 0) 168: break; 169: if(dip->di_type == 0) { 170: printf("\n`%s' not a vaild disk type !\n", dt); 171: rt_xit: 172: if(argflag) 173: exit(FATAL); 174: else 175: goto retry; 176: } 177: if(dip->di_size == 0L){ 178: printf("\n`%s' not supported by standalone code !\n", dt); 179: goto rt_xit; 180: } 181: if(dip->di_nsect == 0){ 182: printf("\n`%s' not supported by Bads !\n", dt); 183: goto rt_xit; 184: } 185: printf("\nUnit number: "); 186: gets(dn); 187: if((strlen(dn) != 1) || (dn[0] < '0') || (dn[0] > '3')) { 188: printf("\nUnits 0 -> 3 only !\n"); 189: goto rt_xit; 190: } 191: sprintf(fn, "%s(%s,0)", dip->di_name, dn); 192: dskopen(0); 193: if(dip->di_ntrak){ 194: bn = dip->di_size - dip->di_nsect; 195: printf("\nPrint bad sector file <[y] or n> ? "); 196: gets(line); 197: if(line[0] == 'y' || line[0] == '\0') 198: if(showbad()) { 199: printf("\n\7\7\7Invalid or No bad sector file.\n"); 200: printf("Disk pack must be initialized with\n"); 201: printf("DSKINIT before use with ULTRIX-11.\n\n"); 202: if(argflag) 203: exit(NO_BBF); 204: } 205: } 206: printf("\nScan disk pack for bad blocks <[y] or n> ? "); 207: gets(line); 208: if(line[0] == 'y' || line[0] == '\0') 209: scanbad(); 210: close(fd); 211: goto retry; 212: } 213: 214: showbad(){ 215: if(readbad()){ 216: return(1); 217: } 218: dsk.seri[0] = dkbad.bt_csnh; 219: dsk.seri[1] = dkbad.bt_csnl; 220: printf("Cartridge serial number: %D\n", dsk.serl); 221: switch(dkbad.bt_flag) { 222: case -1: 223: printf("\nAlignment cartridge !\n"); 224: return(1); 225: break; 226: case 0: 227: break; 228: default: 229: printf("\nBad sector file flag word = %o\n" 230: , dkbad.bt_flag); 231: return(1); 232: } 233: printf("Block\t Cyl\t Trk\t Sec\n"); 234: for(i=0; i<(BSIZE/sizeof(long)); i++, bt++) { 235: if(bt->bt_cyl == 0177777) 236: break; 237: if(bt->bt_cyl == 0 && bt->bt_trksec == 0){ 238: dkbad.bt_mbz = -1; 239: printf("Pack has Invalid Bad Sector file\n"); 240: return(-1); 241: } 242: bn=((long)bt->bt_cyl * 243: (long)dip->di_ntrak+(long)(bt->bt_trksec>>8)) * 244: (long)dip->di_nsect + (long)(bt->bt_trksec&0377); 245: printf("%D\t %u\t %d\t %d\n", bn, bt->bt_cyl, 246: bt->bt_trksec>>8, bt->bt_trksec&0377); 247: } 248: return(0); 249: } 250: 251: scanbad(){ 252: int badcnt, rsize, j; 253: long rbn, rrbn; 254: 255: printf("\nBlock offset: "); 256: gets(line); 257: if(strlen(line) > 6 || (nbo = atol(line)) < 0 || nbo > dip->di_size){ 258: printf("\nBad offset !\n"); 259: return(1); 260: } 261: printf("\n# of blocks <cr for full pack>: "); 262: gets(line); 263: if(line[0] == '\0') 264: nblk = dip->di_size; 265: else 266: nblk = atol(line); 267: if(nblk <= 0) { 268: printf("\nBad # of blocks !\n"); 269: return(1); 270: } 271: if((nbo + nblk) > dip->di_size){ 272: nblk = dip->di_size - nbo; 273: printf("Offset + # of blocks too large\n"); 274: printf("Truncating # of blocks to %D\n", nblk); 275: } 276: rsize = dip->di_nsect * BSIZE; 277: printf("READING\n"); 278: for(badcnt = bn = 0; bn<nblk;) { 279: lseek(fd, (bn+nbo)*BSIZE, 0); 280: BAD_CMD->r[0] = BAD_CHK; 281: if(rsize <= 0 || rsize > (BSIZE*dip->di_nsect)) 282: rsize = BSIZE*dip->di_nsect; 283: rcnt = read(fd, buf, rsize); 284: if(rcnt < 0){ 285: rbn = bn+nbo; 286: if(dip->di_ntrak){ 287: btoa(rbn); 288: printf("\n\nFATAL Error at "); 289: printf("Block %D\t cyl %d\t trk %d\t sec %d\n" 290: , rbn, da.t_cn, da.t_tn, da.t_sn); 291: } 292: else { 293: printf("\n\nBAD BLOCK IN CLUSTER: "); 294: printf("finding actual block number\n"); 295: rrbn = bn+nbo; 296: for(j=0; ((j*BSIZE)<rsize); j++) { 297: lseek(fd, (long)(rrbn*BSIZE), 0); 298: rcnt = read(fd, (char *)&buf, BSIZE); 299: if(rcnt != BSIZE) { 300: badcnt++; 301: printf("%s%D\t\t\t\t%s", bblock, 302: rrbn, 303: "BAD BLOCK\n"); 304: } 305: rrbn++; 306: } 307: goto cont; 308: } 309: exit(FATAL); 310: } 311: else if(rcnt != rsize){ 312: badcnt++; 313: rbn = (bn+nbo) + (rcnt/BSIZE); 314: if(dip->di_ntrak){ 315: btoa(rbn); 316: printf("%s%D\t%d\t%d\t%d\t%s" 317: , bblock 318: , rbn, da.t_cn, da.t_tn, da.t_sn 319: ,"BAD BLOCK\n\n"); 320: } 321: else 322: printf("%s%D\t\t\t\t\t%s",bblock, rbn, "BAD BLOCK\n"); 323: bn = ++rbn - nbo; 324: rsize = (dip->di_nsect - ((rcnt/BSIZE)+1))* BSIZE; 325: } 326: else{ 327: cont: 328: bn += dip->di_nsect; 329: bn -= bn%dip->di_nsect; 330: rsize = dip->di_nsect * BSIZE; 331: } 332: if(badcnt >= dip->di_nsect && dip->di_ntrak){ 333: printf("\n\nTOO MANY BAD BLOCKS ON THIS PACK.\n"); 334: printf("ONLY %d BAD BLOCKS ALLOWED ON AN %s DISK\n" 335: , dip->di_nsect, dip->di_type); 336: printf("DO NOT USE THIS PACK\n"); 337: exit(FATAL); 338: } 339: } 340: printf("\n%D blocks checked\n", bn); 341: printf("%d bad blocks found\n", badcnt); 342: if(argflag && badcnt) 343: exit(HASBADS); 344: else 345: return(0); 346: } 347: 348: btoa(bn) 349: long bn; 350: { 351: da.t_cn = bn/(dip->di_ntrak*dip->di_nsect); 352: da.t_sn = bn%(dip->di_ntrak*dip->di_nsect); 353: da.t_tn = da.t_sn/dip->di_nsect; 354: da.t_sn = da.t_sn%dip->di_nsect; 355: } 356: 357: readbad() 358: { 359: int cnt; 360: 361: dkbad.bt_mbz = -1; 362: bn = dip->di_size - dip->di_nsect; /* first sector of last track */ 363: for(cnt = 0; cnt < 5; cnt++){ 364: lseek(fd, BSIZE * bn, 0); 365: printf("\nBad sector file at block %D of %s\n", bn, fn); 366: if(read(fd, &dkbad, sizeof(struct dkbad)) 367: != sizeof(struct dkbad)) { 368: bn += 2; 369: continue; 370: } 371: break; 372: } 373: if(cnt >= 5){ 374: printf("\nCan't read bad sector file for %s unit %s !\n" 375: , dip->di_type, dn); 376: exit(FATAL); 377: } 378: bt = dkbad.bt_badb; 379: if(dkbad.bt_mbz || (dkbad.bt_csnl == 0 && dkbad.bt_csnh == 0)){ 380: dkbad.bt_mbz = -1; 381: return(1); 382: } 383: return(0); 384: } 385: 386: dskopen(mode) 387: int mode; 388: { 389: if((fd = open(fn, mode)) <= 0) { 390: printf("\nCan't open %s !\n", fn); 391: exit(FATAL); 392: } 393: } 394: 395: prtdsk() 396: { 397: struct dkinfo *dp; 398: 399: printf("\nDisk\tULTRIX\tSize in"); 400: printf("\nName\tName\tBlocks\tComments"); 401: printf("\n----\t----\t------\t--------"); 402: for(dp=dkinfo; dp->di_type; dp++){ 403: if(dp->di_flag == NP) 404: continue; 405: printf("\n%s\t", dp->di_type); 406: printf("%s\t", dp->di_name); 407: printf("%D\t", dp->di_size); 408: if(dp->di_flag == HP) 409: printf("(first ) RH11/RH70 Controller"); 410: if(dp->di_flag == HM) 411: printf("(second ) RH11/RH70 Controller"); 412: if(dp->di_flag == HJ) 413: printf("(third ) RH11/RH70 Controller"); 414: } 415: printf("\n"); 416: }