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
verify()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
load_verify_patterns()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
verify_relocation_area()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
verify_users_data_area()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
verify_maintenence_area()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
verify_cylinders(base_cyl,cyl_count,pats)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
verify_track(dskaddr,pats,verbosity)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
flag_sector(dskaddr,status,ecode,func,verbosity)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