#ifndef lint static char sccsid[] = "@(#)verify.c 1.5 (Berkeley/CCI) 6/7/88"; #endif #include "vdfmt.h" #define verbose 1 /* ** */ verify() { extern boolean read_bad_sector_map(); cur.state = vfy; print("Starting verification on "); printf("controller %d, drive %d, ", cur.controller, cur.drive); printf("type %s.\n", lab->d_typename); if(is_formatted() == true) { if(read_bad_sector_map() == true) { if(bad_map->bs_id == D_INFO->id) { verify_users_data_area(); writelabel(); return; } } print("I can't verify drives with old formats.\n"); return; } print("I can't verify unformatted drives.\n"); } /* ** */ load_verify_patterns() { register int index; register struct flawpat *fp = (struct flawpat *)lab->d_pat; /* Init bad block pattern array */ for(index=0; index<MAXTRKSIZ; index++) { pattern_0[index] = fp->fp_pat[0]; pattern_1[index] = fp->fp_pat[1]; pattern_2[index] = fp->fp_pat[2]; pattern_3[index] = fp->fp_pat[3]; pattern_4[index] = fp->fp_pat[4]; pattern_5[index] = fp->fp_pat[5]; pattern_6[index] = fp->fp_pat[6]; pattern_7[index] = fp->fp_pat[7]; pattern_8[index] = fp->fp_pat[8]; pattern_9[index] = fp->fp_pat[9]; pattern_10[index] = fp->fp_pat[10]; pattern_12[index] = fp->fp_pat[12]; pattern_13[index] = fp->fp_pat[13]; pattern_14[index] = fp->fp_pat[14]; pattern_15[index] = fp->fp_pat[15]; } } /* ** */ verify_relocation_area() { cur.substate = sub_vfy; verify_cylinders((int)lab->d_ncylinders - NUMSYS, NUMREL, 16); sync_bad_sector_map(); } /* ** */ verify_users_data_area() { int pats = ops_to_do[cur.controller][cur.drive].numpat; cur.substate = sub_vfy; verify_cylinders(0, (int)lab->d_ncylinders - NUMSYS, pats); sync_bad_sector_map(); } /* ** */ verify_maintenence_area() { cur.substate = sub_vfy; verify_cylinders(lab->d_ncylinders - NUMSYS + NUMREL, NUMMNT, 16); sync_bad_sector_map(); } /* ** verify_cylinders does full track certification for every track ** on the cylinder. */ verify_cylinders(base_cyl, cyl_count, pats) int base_cyl, cyl_count, pats; { dskadr dskaddr; if (pats == 0) return; /* verify each track of each cylinder */ for (dskaddr.cylinder = base_cyl; dskaddr.cylinder < base_cyl + cyl_count; dskaddr.cylinder++) for (dskaddr.track = 0; dskaddr.track < lab->d_ntracks; dskaddr.track++) verify_track(&dskaddr, pats, verbose); } /* ** verify_track verifies a single track. If a full-track write fails, ** the sector is flagged; if a full-track read fails, then each sector ** is read individually to determine which sectors are really bad. ** If a sector is bad it is flagged as bad by flag_sector. */ verify_track(dskaddr, pats, verbosity) dskadr *dskaddr; int pats; int verbosity; { register int index, i; register int count; register long before; register long *after; register long offset = lab->d_secsize / sizeof(long); int pattern_count = pats; if (pats == 0) return; dskaddr->sector = (char)0; access_dsk((char *)pattern_address[0], dskaddr, VDOP_WD, lab->d_nsectors, 1); for (index = 0; index < pattern_count; index++) { if (!data_ok()) { if (dcb.operrsta & HEADER_ERROR && C_INFO->type == VDTYPE_SMDE) { flag_sector(dskaddr, dcb.operrsta, dcb.err_code, "write", verbosity); break; } else { indent(); vd_error("write track"); exdent(1); } #ifdef notdef /* * we presume that write errors will be detected * on read or data compare, * don't bother with extra testing. */ if (dcb.operrsta & DATA_ERROR) pattern_count = 16; #endif /* * Write track a sector at a time, * so that a write aborted on one sector * doesn't cause compare errors on all * subsequent sectors on the track. */ for (i = 0; i < lab->d_nsectors; i++) { dskaddr->sector = i; access_dsk((char *)pattern_address[index], dskaddr, VDOP_WD, 1,1); } dskaddr->sector = (char)0; } access_dsk((char *)scratch, dskaddr, VDOP_RD, lab->d_nsectors, 1); if (!data_ok()) { if (dcb.operrsta & HEADER_ERROR) { flag_sector(dskaddr, dcb.operrsta, dcb.err_code, "read", verbosity); break; } for (i = 0; i < lab->d_nsectors; i++) { dskaddr->sector = i; access_dsk((char *)&scratch[i * offset], dskaddr, VDOP_RD, 1,1); if (!data_ok()) flag_sector(dskaddr, dcb.operrsta, dcb.err_code, "read", verbosity); } dskaddr->sector = (char)0; } if (index+1 < pattern_count) access_dsk((char *)pattern_address[index+1], dskaddr, VDOP_WD, lab->d_nsectors, 0); count = lab->d_nsectors * offset; before = *pattern_address[index]; after = scratch; for (i = 0; i < count; ) { if (before != *(after++)) { dskaddr->sector = (char)(i / offset); flag_sector(dskaddr, 0, 0, "data compare", verbosity); i = (dskaddr->sector + 1) * offset; after = scratch + i; } else ++i; } if (index+1 < pattern_count) { poll(60); if (vdtimeout <= 0) { printf(" while writing track.\n"); _longjmp(abort_environ, 1); } } if (kill_processes == true) { sync_bad_sector_map(); _longjmp(quit_environ, 1); } } /* check again in case of header error */ if (kill_processes == true) { sync_bad_sector_map(); _longjmp(quit_environ, 1); } } flag_sector(dskaddr, status, ecode, func, verbosity) dskadr *dskaddr; long status; int ecode; char *func; int verbosity; { fmt_err error; bs_entry entry; int result; error.err_adr = *dskaddr; error.err_stat = status; (*C_INFO->code_pos)(&error, &entry); result = add_flaw(&entry); if (verbosity != 0 && result != 0) { indent(); print("%s error at sector %d (cyl %d trk %d sect %d)", func, to_sector(*dskaddr), dskaddr->cylinder, dskaddr->track, dskaddr->sector); if (status) { printf(",\n"); print(" status=%b", status, VDERRBITS); if (C_INFO->type == VDTYPE_SMDE && ecode) printf(", ecode=0x%x", ecode); } printf(".\n"); switch (result) { case 1: print("%s will be relocated.\n", (status & HEADER_ERROR && C_INFO->type == VDTYPE_SMDE) ? "Track" : "Sector"); break; case -1: print("Sector cannot be relocated.\n"); break; } exdent(1); } }