xref: /original-bsd/sys/tahoe/stand/vdformat/verify.c (revision 319dde04)
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