1 #ifndef lint 2 static char sccsid[] = "@(#)verify.c 1.5 (Berkeley/CCI) 06/07/88"; 3 #endif 4 5 #include "vdfmt.h" 6 7 #define verbose 1 8 9 /* 10 ** 11 */ 12 13 verify() 14 { 15 extern boolean read_bad_sector_map(); 16 17 cur.state = vfy; 18 print("Starting verification on "); 19 printf("controller %d, drive %d, ", cur.controller, cur.drive); 20 printf("type %s.\n", lab->d_typename); 21 22 if(is_formatted() == true) { 23 if(read_bad_sector_map() == true) { 24 if(bad_map->bs_id == D_INFO->id) { 25 verify_users_data_area(); 26 writelabel(); 27 return; 28 } 29 } 30 print("I can't verify drives with old formats.\n"); 31 return; 32 } 33 print("I can't verify unformatted drives.\n"); 34 } 35 36 37 /* 38 ** 39 */ 40 41 load_verify_patterns() 42 { 43 register int index; 44 register struct flawpat *fp = (struct flawpat *)lab->d_pat; 45 46 /* Init bad block pattern array */ 47 for(index=0; index<MAXTRKSIZ; index++) { 48 pattern_0[index] = fp->fp_pat[0]; 49 pattern_1[index] = fp->fp_pat[1]; 50 pattern_2[index] = fp->fp_pat[2]; 51 pattern_3[index] = fp->fp_pat[3]; 52 pattern_4[index] = fp->fp_pat[4]; 53 pattern_5[index] = fp->fp_pat[5]; 54 pattern_6[index] = fp->fp_pat[6]; 55 pattern_7[index] = fp->fp_pat[7]; 56 pattern_8[index] = fp->fp_pat[8]; 57 pattern_9[index] = fp->fp_pat[9]; 58 pattern_10[index] = fp->fp_pat[10]; 59 pattern_12[index] = fp->fp_pat[12]; 60 pattern_13[index] = fp->fp_pat[13]; 61 pattern_14[index] = fp->fp_pat[14]; 62 pattern_15[index] = fp->fp_pat[15]; 63 } 64 } 65 66 67 /* 68 ** 69 */ 70 71 verify_relocation_area() 72 { 73 cur.substate = sub_vfy; 74 verify_cylinders((int)lab->d_ncylinders - NUMSYS, NUMREL, 16); 75 sync_bad_sector_map(); 76 } 77 78 79 /* 80 ** 81 */ 82 83 verify_users_data_area() 84 { 85 int pats = ops_to_do[cur.controller][cur.drive].numpat; 86 87 cur.substate = sub_vfy; 88 verify_cylinders(0, (int)lab->d_ncylinders - NUMSYS, pats); 89 sync_bad_sector_map(); 90 } 91 92 93 /* 94 ** 95 */ 96 97 verify_maintenence_area() 98 { 99 cur.substate = sub_vfy; 100 verify_cylinders(lab->d_ncylinders - NUMSYS + NUMREL, NUMMNT, 16); 101 sync_bad_sector_map(); 102 } 103 104 105 /* 106 ** verify_cylinders does full track certification for every track 107 ** on the cylinder. 108 */ 109 110 verify_cylinders(base_cyl, cyl_count, pats) 111 int base_cyl, cyl_count, pats; 112 { 113 dskadr dskaddr; 114 115 if (pats == 0) 116 return; 117 /* verify each track of each cylinder */ 118 for (dskaddr.cylinder = base_cyl; 119 dskaddr.cylinder < base_cyl + cyl_count; dskaddr.cylinder++) 120 for (dskaddr.track = 0; dskaddr.track < lab->d_ntracks; 121 dskaddr.track++) 122 verify_track(&dskaddr, pats, verbose); 123 } 124 125 126 /* 127 ** verify_track verifies a single track. If a full-track write fails, 128 ** the sector is flagged; if a full-track read fails, then each sector 129 ** is read individually to determine which sectors are really bad. 130 ** If a sector is bad it is flagged as bad by flag_sector. 131 */ 132 133 verify_track(dskaddr, pats, verbosity) 134 dskadr *dskaddr; 135 int pats; 136 int verbosity; 137 { 138 register int index, i; 139 register int count; 140 register long before; 141 register long *after; 142 register long offset = lab->d_secsize / sizeof(long); 143 int pattern_count = pats; 144 145 if (pats == 0) 146 return; 147 dskaddr->sector = (char)0; 148 access_dsk((char *)pattern_address[0], dskaddr, VDOP_WD, 149 lab->d_nsectors, 1); 150 for (index = 0; index < pattern_count; index++) { 151 if (!data_ok()) { 152 if (dcb.operrsta & HEADER_ERROR && 153 C_INFO->type == VDTYPE_SMDE) { 154 flag_sector(dskaddr, dcb.operrsta, 155 dcb.err_code, "write", verbosity); 156 break; 157 } else { 158 indent(); 159 vd_error("write track"); 160 exdent(1); 161 } 162 #ifdef notdef 163 /* 164 * we presume that write errors will be detected 165 * on read or data compare, 166 * don't bother with extra testing. 167 */ 168 if (dcb.operrsta & DATA_ERROR) 169 pattern_count = 16; 170 #endif 171 /* 172 * Write track a sector at a time, 173 * so that a write aborted on one sector 174 * doesn't cause compare errors on all 175 * subsequent sectors on the track. 176 */ 177 for (i = 0; i < lab->d_nsectors; i++) { 178 dskaddr->sector = i; 179 access_dsk((char *)pattern_address[index], 180 dskaddr, VDOP_WD, 1,1); 181 } 182 dskaddr->sector = (char)0; 183 } 184 access_dsk((char *)scratch, dskaddr, VDOP_RD, 185 lab->d_nsectors, 1); 186 if (!data_ok()) { 187 if (dcb.operrsta & HEADER_ERROR) { 188 flag_sector(dskaddr, dcb.operrsta, 189 dcb.err_code, "read", verbosity); 190 break; 191 } 192 for (i = 0; i < lab->d_nsectors; i++) { 193 dskaddr->sector = i; 194 access_dsk((char *)&scratch[i * offset], 195 dskaddr, VDOP_RD, 1,1); 196 if (!data_ok()) 197 flag_sector(dskaddr, dcb.operrsta, 198 dcb.err_code, "read", verbosity); 199 } 200 dskaddr->sector = (char)0; 201 } 202 if (index+1 < pattern_count) 203 access_dsk((char *)pattern_address[index+1], 204 dskaddr, VDOP_WD, lab->d_nsectors, 0); 205 count = lab->d_nsectors * offset; 206 before = *pattern_address[index]; 207 after = scratch; 208 for (i = 0; i < count; ) { 209 if (before != *(after++)) { 210 dskaddr->sector = (char)(i / offset); 211 flag_sector(dskaddr, 0, 0, 212 "data compare", verbosity); 213 i = (dskaddr->sector + 1) * offset; 214 after = scratch + i; 215 } else 216 ++i; 217 } 218 if (index+1 < pattern_count) { 219 poll(60); 220 if (vdtimeout <= 0) { 221 printf(" while writing track.\n"); 222 _longjmp(abort_environ, 1); 223 } 224 } 225 if (kill_processes == true) { 226 sync_bad_sector_map(); 227 _longjmp(quit_environ, 1); 228 } 229 } 230 /* check again in case of header error */ 231 if (kill_processes == true) { 232 sync_bad_sector_map(); 233 _longjmp(quit_environ, 1); 234 } 235 } 236 237 238 flag_sector(dskaddr, status, ecode, func, verbosity) 239 dskadr *dskaddr; 240 long status; 241 int ecode; 242 char *func; 243 int verbosity; 244 { 245 fmt_err error; 246 bs_entry entry; 247 int result; 248 249 error.err_adr = *dskaddr; 250 error.err_stat = status; 251 (*C_INFO->code_pos)(&error, &entry); 252 result = add_flaw(&entry); 253 if (verbosity != 0 && result != 0) { 254 indent(); 255 print("%s error at sector %d (cyl %d trk %d sect %d)", 256 func, to_sector(*dskaddr), dskaddr->cylinder, 257 dskaddr->track, dskaddr->sector); 258 if (status) { 259 printf(",\n"); 260 print(" status=%b", status, VDERRBITS); 261 if (C_INFO->type == VDTYPE_SMDE && ecode) 262 printf(", ecode=0x%x", ecode); 263 } 264 printf(".\n"); 265 switch (result) { 266 case 1: 267 print("%s will be relocated.\n", 268 (status & HEADER_ERROR && 269 C_INFO->type == VDTYPE_SMDE) ? "Track" : "Sector"); 270 break; 271 case -1: 272 print("Sector cannot be relocated.\n"); 273 break; 274 } 275 exdent(1); 276 } 277 } 278