Commit | Line | Data |
---|---|---|
da7c5cc6 | 1 | /* |
0880b18e | 2 | * Copyright (c) 1980, 1986 Regents of the University of California. |
da7c5cc6 KM |
3 | * All rights reserved. The Berkeley software License Agreement |
4 | * specifies the terms and conditions for redistribution. | |
5 | */ | |
6 | ||
7 | #ifndef lint | |
8 | char copyright[] = | |
0880b18e | 9 | "@(#) Copyright (c) 1980, 1986 Regents of the University of California.\n\ |
da7c5cc6 KM |
10 | All rights reserved.\n"; |
11 | #endif not lint | |
71da8ead | 12 | |
da7c5cc6 | 13 | #ifndef lint |
0880b18e | 14 | static char sccsid[] = "@(#)format.c 7.1 (Berkeley) %G%"; |
da7c5cc6 | 15 | #endif not lint |
001cf9d7 | 16 | |
f5e63974 | 17 | |
001cf9d7 SL |
18 | /* |
19 | * Standalone program to do media checking | |
20 | * and record bad block information on any | |
0f3feeae | 21 | * disk with the appropriate driver and RM03-style headers. |
f5e63974 MK |
22 | * TODO: |
23 | * add new bad sectors to bad-sector table when formatting by track | |
24 | * (rearranging replacements ala bad144 -a) | |
25 | * multi-pass format for disks with skip-sector capability | |
001cf9d7 SL |
26 | */ |
27 | #include "../h/param.h" | |
28 | #include "../h/fs.h" | |
29 | #include "../h/inode.h" | |
30 | #include "../h/dkbad.h" | |
31 | #include "../h/vmmac.h" | |
32 | ||
33 | #include "saio.h" | |
34 | #include "savax.h" | |
35 | ||
36 | #define MAXBADDESC 126 /* size of bad block table */ | |
37 | #define CHUNK 48 /* max # of sectors/io operation */ | |
38 | #define SECTSIZ 512 /* standard sector size */ | |
39 | #define HDRSIZ 4 /* number of bytes in sector header */ | |
40 | ||
41 | #define SSERR 0 | |
42 | #define BSERR 1 | |
43 | ||
f834e141 MK |
44 | #define SSDEV(fd) (ioctl((fd), SAIOSSDEV, (char *)0) == 0) |
45 | #define MAXECCBITS 3 | |
001cf9d7 SL |
46 | |
47 | struct sector { | |
48 | u_short header1; | |
49 | u_short header2; | |
50 | char buf[SECTSIZ]; | |
51 | }; | |
52 | ||
53 | struct dkbad dkbad; /* bad sector table */ | |
f834e141 | 54 | struct dkbad oldbad; /* old bad sector table */ |
001cf9d7 SL |
55 | struct dkbad sstab; /* skip sector table */ |
56 | ||
57 | #define NERRORS 6 | |
c68cea4f SL |
58 | static char * |
59 | errornames[NERRORS] = { | |
0f3feeae | 60 | #define FE_BSE 0 |
001cf9d7 | 61 | "Bad sector", |
0f3feeae MK |
62 | #define FE_WCE 1 |
63 | "Write check", | |
001cf9d7 | 64 | #define FE_ECC 2 |
f834e141 | 65 | "Hard ECC", |
001cf9d7 SL |
66 | #define FE_HARD 3 |
67 | "Other hard", | |
68 | #define FE_TOTAL 4 | |
f834e141 | 69 | "Marked bad", |
001cf9d7 | 70 | #define FE_SSE 5 |
f834e141 | 71 | "Skipped", |
001cf9d7 SL |
72 | }; |
73 | ||
74 | int errors[NERRORS]; /* histogram of errors */ | |
c68cea4f | 75 | int pattern; |
f834e141 | 76 | int maxeccbits; |
001cf9d7 | 77 | |
71da8ead MK |
78 | /* |
79 | * Purdue/EE severe burnin patterns. | |
80 | */ | |
81 | unsigned short ppat[] = { | |
fb9e17ff | 82 | 0xf00f, 0xec6d, 0031463,0070707,0133333,0155555,0161616,0143434, |
71da8ead MK |
83 | 0107070,0016161,0034343,0044444,0022222,0111111,0125252, 052525, |
84 | 0125252,0125252,0125252,0125252,0125252,0125252,0125252,0125252, | |
85 | #ifndef SHORTPASS | |
86 | 0125252,0125252,0125252,0125252,0125252,0125252,0125252,0125252, | |
87 | 052525, 052525, 052525, 052525, 052525, 052525, 052525, 052525, | |
88 | #endif | |
89 | 052525, 052525, 052525, 052525, 052525, 052525, 052525, 052525 | |
90 | }; | |
91 | ||
92 | #define NPT (sizeof (ppat) / sizeof (short)) | |
fb9e17ff | 93 | int maxpass, npat; /* subscript to ppat[] */ |
71da8ead | 94 | int severe; /* nz if running "severe" burnin */ |
f834e141 | 95 | int ssdev; /* device supports skip sectors */ |
f5e63974 | 96 | int startcyl, endcyl, starttrack, endtrack; |
f834e141 MK |
97 | int nbads; /* subscript for bads */ |
98 | daddr_t bads[2*MAXBADDESC]; /* Bad blocks accumulated */ | |
71da8ead | 99 | |
001cf9d7 | 100 | char *malloc(); |
71da8ead | 101 | int qcompar(); |
001cf9d7 | 102 | char *prompt(); |
f5e63974 | 103 | daddr_t badsn(); |
001cf9d7 SL |
104 | extern int end; |
105 | ||
106 | main() | |
107 | { | |
108 | register int sector, sn; | |
71da8ead | 109 | int lastsector, tracksize, rtracksize; |
001cf9d7 SL |
110 | int unit, fd, resid, i, trk, cyl, debug; |
111 | struct st st; | |
112 | struct sector *bp, *cbp; | |
71da8ead | 113 | char *rbp, *rcbp; |
fb9e17ff | 114 | int pass; |
001cf9d7 SL |
115 | char *cp; |
116 | ||
117 | printf("Disk format/check utility\n\n"); | |
118 | ||
119 | again: | |
71da8ead MK |
120 | nbads = 0; |
121 | cp = prompt("Enable debugging (0=none, 1=bse, 2=ecc, 3=bse+ecc)? "); | |
001cf9d7 SL |
122 | debug = atoi(cp); |
123 | if (debug < 0) | |
124 | debug = 0; | |
125 | for (i = 0; i < NERRORS; i++) | |
126 | errors[i] = 0; | |
127 | fd = getdevice(); | |
128 | ioctl(fd, SAIODEVDATA, &st); | |
129 | printf("Device data: #cylinders=%d, #tracks=%d, #sectors=%d\n", | |
130 | st.ncyl, st.ntrak, st.nsect); | |
f834e141 MK |
131 | ssdev = SSDEV(fd); |
132 | if (ssdev) { | |
133 | ioctl(fd, SAIOSSI, (char *)0); /* set skip sector inhibit */ | |
134 | st.nsect++; | |
135 | st.nspc += st.ntrak; | |
136 | printf("(not counting skip-sector replacement)\n"); | |
137 | } | |
f5e63974 | 138 | getrange(&st); |
c68cea4f | 139 | if (getpattern()) |
001cf9d7 SL |
140 | goto again; |
141 | printf("Start formatting...make sure the drive is online\n"); | |
142 | ioctl(fd, SAIONOBAD, (char *)0); | |
f834e141 MK |
143 | ioctl(fd, SAIORETRIES, (char *)0); |
144 | ioctl(fd, SAIOECCLIM, (char *)maxeccbits); | |
001cf9d7 | 145 | ioctl(fd, SAIODEBUG, (char *)debug); |
001cf9d7 | 146 | tracksize = sizeof (struct sector) * st.nsect; |
71da8ead | 147 | rtracksize = SECTSIZ * st.nsect; |
001cf9d7 | 148 | bp = (struct sector *)malloc(tracksize); |
71da8ead | 149 | rbp = malloc(rtracksize); |
fb9e17ff MK |
150 | pass = 0; |
151 | npat = 0; | |
152 | more: | |
153 | for (; pass < maxpass; pass++) { | |
71da8ead MK |
154 | if (severe) |
155 | printf("Begin pass %d\n", pass); | |
156 | bufinit(bp, tracksize); | |
157 | if (severe) | |
158 | npat++; | |
001cf9d7 | 159 | /* |
71da8ead | 160 | * Begin check, for each track, |
001cf9d7 | 161 | * |
71da8ead MK |
162 | * 1) Write header and test pattern. |
163 | * 2) Read data. Hardware checks header and data ECC. | |
fb9e17ff | 164 | * Read data (esp on Eagles) is much faster than write check. |
001cf9d7 | 165 | */ |
f5e63974 MK |
166 | sector = ((startcyl * st.ntrak) + starttrack) * st.nsect; |
167 | lastsector = ((endcyl * st.ntrak) + endtrack) * st.nsect | |
168 | + st.nsect; | |
169 | for ( ; sector < lastsector; sector += st.nsect) { | |
71da8ead MK |
170 | cyl = sector / st.nspc; |
171 | trk = (sector % st.nspc) / st.nsect; | |
172 | for (i = 0; i < st.nsect; i++) { | |
173 | bp[i].header1 = | |
174 | (u_short) cyl | HDR1_FMT22 | HDR1_OKSCT; | |
175 | bp[i].header2 = ((u_short)trk << 8) + i; | |
176 | } | |
177 | if (sector && (sector % (st.nspc * 100)) == 0) | |
178 | printf("cylinder %d\n", cyl); | |
001cf9d7 | 179 | /* |
71da8ead MK |
180 | * Try and write the headers and data patterns into |
181 | * each sector in the track. Continue until such | |
182 | * we're done, or until there's less than a sector's | |
183 | * worth of data to transfer. | |
184 | * | |
185 | * The lseek call is necessary because of | |
186 | * the odd sector size (516 bytes) | |
001cf9d7 | 187 | */ |
71da8ead MK |
188 | for (resid = tracksize, cbp = bp, sn = sector;;) { |
189 | int cc; | |
190 | ||
191 | lseek(fd, sn * SECTSIZ, 0); | |
192 | ioctl(fd, SAIOHDR, (char *)0); | |
193 | cc = write(fd, cbp, resid); | |
194 | if (cc == resid) | |
195 | break; | |
196 | /* | |
197 | * Don't record errors during write, | |
198 | * all errors will be found during | |
f834e141 | 199 | * check performed below. |
71da8ead MK |
200 | */ |
201 | sn = iob[fd - 3].i_errblk; | |
202 | cbp += sn - sector; | |
203 | resid -= (sn - sector) * sizeof (struct sector); | |
204 | if (resid < sizeof (struct sector)) | |
205 | break; | |
206 | } | |
207 | /* | |
208 | * Read test patterns. | |
209 | * Retry remainder of track on error until | |
210 | * we're done, or until there's less than a | |
211 | * sector to verify. | |
212 | */ | |
213 | for (resid = rtracksize, rcbp = rbp, sn = sector;;) { | |
f834e141 | 214 | int cc, rsn; |
71da8ead MK |
215 | |
216 | lseek(fd, sn * SECTSIZ, 0); | |
217 | cc = read(fd, rcbp, resid); | |
218 | if (cc == resid) | |
219 | break; | |
220 | sn = iob[fd-3].i_errblk; | |
f834e141 MK |
221 | if (ssdev) { |
222 | rsn = sn - (sn / st.nsect); | |
223 | printf("data "); | |
224 | } else | |
225 | rsn = sn; | |
226 | printf("sector %d, read error\n\n", rsn); | |
71da8ead MK |
227 | if (recorderror(fd, sn, &st) < 0 && pass > 0) |
228 | goto out; | |
229 | /* advance past bad sector */ | |
230 | sn++; | |
f834e141 MK |
231 | resid = rtracksize - ((sn - sector) * SECTSIZ); |
232 | rcbp = rbp + ((sn - sector) * SECTSIZ); | |
71da8ead MK |
233 | if (resid < SECTSIZ) |
234 | break; | |
235 | } | |
001cf9d7 SL |
236 | } |
237 | } | |
238 | /* | |
239 | * Checking finished. | |
240 | */ | |
71da8ead | 241 | out: |
fb9e17ff MK |
242 | if (severe && maxpass < NPT) { |
243 | cp = prompt("More passes? (0 or number) "); | |
244 | maxpass = atoi(cp); | |
245 | if (maxpass > 0) { | |
246 | maxpass += pass; | |
247 | goto more; | |
248 | } | |
249 | } | |
71da8ead MK |
250 | if (severe && nbads) { |
251 | /* | |
252 | * Sort bads and insert in bad block table. | |
253 | */ | |
f834e141 | 254 | qsort(bads, nbads, sizeof (daddr_t), qcompar); |
71da8ead | 255 | severe = 0; |
fb9e17ff MK |
256 | errno = 0; |
257 | for (i = 0; i < nbads; i++) | |
71da8ead | 258 | recorderror(fd, bads[i], &st); |
71da8ead MK |
259 | severe++; |
260 | } | |
001cf9d7 | 261 | if (errors[FE_TOTAL] || errors[FE_SSE]) { |
001cf9d7 SL |
262 | /* change the headers of all the bad sectors */ |
263 | writebb(fd, errors[FE_SSE], &sstab, &st, SSERR); | |
264 | writebb(fd, errors[FE_TOTAL], &dkbad, &st, BSERR); | |
265 | } | |
f834e141 MK |
266 | if (errors[FE_TOTAL] || errors[FE_SSE]) { |
267 | printf("Errors:\n"); | |
268 | for (i = 0; i < NERRORS; i++) | |
269 | printf("%s: %d\n", errornames[i], errors[i]); | |
270 | printf("Total of %d hard errors revectored\n", | |
271 | errors[FE_TOTAL] + errors[FE_SSE]); | |
272 | } | |
f5e63974 MK |
273 | if (endcyl == st.ncyl - 1 && |
274 | (startcyl < st.ncyl - 1 || starttrack == 0)) { | |
275 | while (errors[FE_TOTAL] < MAXBADDESC) { | |
276 | int i = errors[FE_TOTAL]++; | |
001cf9d7 | 277 | |
f5e63974 MK |
278 | dkbad.bt_bad[i].bt_cyl = -1; |
279 | dkbad.bt_bad[i].bt_trksec = -1; | |
280 | } | |
281 | printf("\nWriting bad sector table at sector #%d\n", | |
282 | st.ncyl * st.nspc - st.nsect); | |
283 | /* place on disk */ | |
284 | for (i = 0; i < 10 && i < st.nsect; i += 2) { | |
285 | lseek(fd, SECTSIZ * (st.ncyl * st.nspc - st.nsect + i), 0); | |
286 | write(fd, &dkbad, sizeof (dkbad)); | |
287 | } | |
288 | } else if (errors[FE_TOTAL]) { | |
289 | struct bt_bad *bt; | |
290 | ||
291 | printf("New bad sectors (not added to table):\n"); | |
292 | bt = dkbad.bt_bad; | |
293 | for (i = 0; i < errors[FE_TOTAL]; i++) { | |
f834e141 | 294 | printf("bn %d (cn=%d, tn=%d, sn=%d)\n", badsn(bt, &st), |
f5e63974 MK |
295 | bt->bt_cyl, bt->bt_trksec>>8, bt->bt_trksec&0xff); |
296 | bt++; | |
297 | } | |
001cf9d7 SL |
298 | } |
299 | printf("Done\n"); | |
300 | ioctl(fd,SAIONOSSI,(char *)0); | |
301 | close(fd); | |
302 | #ifndef JUSTEXIT | |
303 | goto again; | |
304 | #endif | |
305 | } | |
306 | ||
71da8ead | 307 | qcompar(l1, l2) |
f834e141 | 308 | register daddr_t *l1, *l2; |
71da8ead MK |
309 | { |
310 | if (*l1 < *l2) | |
311 | return(-1); | |
312 | if (*l1 == *l2) | |
313 | return(0); | |
314 | return(1); | |
315 | } | |
316 | ||
f5e63974 MK |
317 | daddr_t |
318 | badsn(bt, st) | |
319 | register struct bt_bad *bt; | |
320 | register struct st *st; | |
321 | { | |
f834e141 MK |
322 | |
323 | if (ssdev) | |
324 | return ((bt->bt_cyl * st->ntrak + (bt->bt_trksec>>8)) * | |
325 | (st->nsect - 1) + (bt->bt_trksec&0xff)) - 1; | |
326 | else | |
327 | return ((bt->bt_cyl*st->ntrak + (bt->bt_trksec>>8)) * st->nsect | |
f5e63974 MK |
328 | + (bt->bt_trksec&0xff)); |
329 | } | |
330 | ||
001cf9d7 | 331 | /* |
f5e63974 | 332 | * Mark the bad/skipped sectors. |
f834e141 MK |
333 | * Bad sectors on skip-sector devices are assumed to be skipped also, |
334 | * and must be done after the (earlier) first skipped sector. | |
001cf9d7 SL |
335 | */ |
336 | writebb(fd, nsects, dbad, st, sw) | |
337 | int nsects, fd; | |
338 | struct dkbad *dbad; | |
339 | register struct st *st; | |
340 | { | |
341 | struct sector bb_buf; /* buffer for one sector plus 4 byte header */ | |
342 | register int i; | |
343 | int bn, j; | |
344 | struct bt_bad *btp; | |
345 | ||
346 | for (i = 0; i < nsects; i++) { | |
347 | btp = &dbad->bt_bad[i]; | |
348 | if (sw == BSERR) { | |
349 | bb_buf.header1 = HDR1_FMT22|btp->bt_cyl; | |
f834e141 | 350 | if (ssdev) |
001cf9d7 SL |
351 | bb_buf.header1 |= HDR1_SSF; |
352 | } else | |
353 | bb_buf.header1 = | |
354 | btp->bt_cyl | HDR1_FMT22 | HDR1_SSF | HDR1_OKSCT; | |
355 | bb_buf.header2 = btp->bt_trksec; | |
356 | bn = st->nspc * btp->bt_cyl + | |
357 | st->nsect * (btp->bt_trksec >> 8) + | |
0f3feeae | 358 | (btp->bt_trksec & 0xff); |
001cf9d7 SL |
359 | lseek(fd, bn * SECTSIZ, 0); |
360 | ioctl(fd, SAIOHDR, (char *)0); | |
361 | write(fd, &bb_buf, sizeof (bb_buf)); | |
001cf9d7 SL |
362 | /* |
363 | * If skip sector, mark all remaining | |
364 | * sectors on the track. | |
365 | */ | |
f834e141 MK |
366 | if (sw == SSERR) { |
367 | for (j = (btp->bt_trksec & 0xff) + 1, bn++; | |
368 | j < st->nsect; j++, bn++) { | |
369 | bb_buf.header2 = j | (btp->bt_trksec & 0xff00); | |
370 | lseek(fd, bn * SECTSIZ, 0); | |
371 | ioctl(fd, SAIOHDR, (char *)0); | |
372 | write(fd, &bb_buf, sizeof (bb_buf)); | |
373 | } | |
001cf9d7 SL |
374 | } |
375 | } | |
376 | } | |
377 | ||
378 | /* | |
379 | * Record an error, and if there's room, put | |
380 | * it in the appropriate bad sector table. | |
71da8ead MK |
381 | * |
382 | * If severe burnin store block in a list after making sure | |
383 | * we have not already found it on a prev pass. | |
001cf9d7 SL |
384 | */ |
385 | recorderror(fd, bn, st) | |
386 | int fd, bn; | |
387 | register struct st *st; | |
388 | { | |
f5e63974 | 389 | int cn, tn, sn; |
71da8ead MK |
390 | register i; |
391 | ||
392 | ||
393 | if (severe) { | |
394 | for (i = 0; i < nbads; i++) | |
395 | if (bads[i] == bn) | |
396 | return(0); /* bn already flagged */ | |
f834e141 | 397 | if (nbads >= (ssdev ? 2 * MAXBADDESC : MAXBADDESC)) { |
f5e63974 | 398 | printf("Bad sector table full, format terminating\n"); |
71da8ead MK |
399 | return(-1); |
400 | } | |
401 | bads[nbads++] = bn; | |
fb9e17ff MK |
402 | if (errno < EBSE || errno > EHER) |
403 | return(0); | |
404 | errno -= EBSE; | |
405 | errors[errno]++; | |
71da8ead MK |
406 | return(0); |
407 | } | |
fb9e17ff | 408 | if (errno >= EBSE && errno <= EHER) { |
fb9e17ff MK |
409 | errno -= EBSE; |
410 | errors[errno]++; | |
001cf9d7 | 411 | } |
001cf9d7 SL |
412 | cn = bn / st->nspc; |
413 | sn = bn % st->nspc; | |
414 | tn = sn / st->nsect; | |
415 | sn %= st->nsect; | |
f834e141 | 416 | if (ssdev) { /* if drive has skip sector capability */ |
f5e63974 | 417 | int ss = errors[FE_SSE]; |
001cf9d7 | 418 | |
f5e63974 MK |
419 | if (errors[FE_SSE] >= MAXBADDESC) { |
420 | /* this is bogus, we don't maintain skip sector table */ | |
421 | printf("Too many skip sector errors\n"); | |
422 | return(-1); | |
423 | } | |
424 | /* only one skip sector/track */ | |
425 | if (ss == 0 || | |
426 | tn != (sstab.bt_bad[ss - 1].bt_trksec >> 8) || | |
427 | cn != sstab.bt_bad[ss - 1].bt_cyl) { | |
f834e141 MK |
428 | /* |
429 | * Don't bother with skipping the extra sector | |
430 | * at the end of the track. | |
431 | */ | |
432 | if (sn == st->nsect - 1) | |
433 | return(0); | |
001cf9d7 SL |
434 | sstab.bt_bad[ss].bt_cyl = cn; |
435 | sstab.bt_bad[ss].bt_trksec = (tn<<8) + sn; | |
f5e63974 MK |
436 | errors[FE_SSE]++; |
437 | return(0); | |
001cf9d7 | 438 | } |
f5e63974 MK |
439 | } |
440 | if (errors[FE_TOTAL] >= MAXBADDESC) { | |
441 | printf("Too many bad sectors\n"); | |
442 | return(-1); | |
001cf9d7 SL |
443 | } |
444 | /* record the bad sector address and continue */ | |
0f3feeae | 445 | dkbad.bt_bad[errors[FE_TOTAL]].bt_cyl = cn; |
001cf9d7 | 446 | dkbad.bt_bad[errors[FE_TOTAL]++].bt_trksec = (tn << 8) + sn; |
71da8ead | 447 | return(0); |
001cf9d7 SL |
448 | } |
449 | ||
450 | /* | |
451 | * Allocate memory on a page-aligned address. | |
452 | * Round allocated chunk to a page multiple to | |
453 | * ease next request. | |
454 | */ | |
455 | char * | |
456 | malloc(size) | |
457 | int size; | |
458 | { | |
459 | char *result; | |
460 | static caddr_t last = 0; | |
461 | ||
462 | if (last == 0) | |
463 | last = (caddr_t)(((int)&end + 511) & ~0x1ff); | |
464 | size = (size + 511) & ~0x1ff; | |
465 | result = (char *)last; | |
466 | last += size; | |
467 | return (result); | |
468 | } | |
469 | ||
470 | /* | |
471 | * Prompt and verify a device name from the user. | |
472 | */ | |
473 | getdevice() | |
474 | { | |
475 | register char *cp; | |
476 | register struct devsw *dp; | |
477 | int fd; | |
478 | ||
479 | top: | |
480 | cp = prompt("Device to format? "); | |
481 | if ((fd = open(cp, 2)) < 0) { | |
482 | printf("Known devices are: "); | |
483 | for (dp = devsw; dp->dv_name; dp++) | |
484 | printf("%s ",dp->dv_name); | |
485 | printf("\n"); | |
486 | goto top; | |
487 | } | |
71da8ead MK |
488 | printf("Formatting drive %c%c%d on adaptor %d: ", |
489 | cp[0], cp[1], iob[fd - 3].i_unit % 8, iob[fd - 3].i_unit / 8); | |
001cf9d7 SL |
490 | cp = prompt("verify (yes/no)? "); |
491 | while (*cp != 'y' && *cp != 'n') | |
492 | cp = prompt("Huh, yes or no? "); | |
493 | if (*cp == 'y') | |
494 | return (fd); | |
495 | goto top; | |
496 | } | |
497 | ||
f5e63974 MK |
498 | /* |
499 | * Find range of tracks to format. | |
500 | */ | |
501 | getrange(st) | |
502 | struct st *st; | |
503 | { | |
504 | startcyl = getnum("Starting cylinder", 0, st->ncyl - 1, 0); | |
f5e63974 | 505 | starttrack = getnum("Starting track", 0, st->ntrak - 1, 0); |
f834e141 | 506 | endcyl = getnum("Ending cylinder", 0, st->ncyl - 1, st->ncyl - 1); |
f5e63974 MK |
507 | endtrack = getnum("Ending track", 0, st->ntrak - 1, st->ntrak - 1); |
508 | } | |
509 | ||
510 | getnum(s, low, high, dflt) | |
511 | { | |
512 | char buf[132]; | |
513 | unsigned val; | |
514 | ||
515 | while (1) { | |
516 | printf("%s (%d): ", s, dflt); | |
517 | gets(buf); | |
518 | if (buf[0] == 0) | |
519 | return (dflt); | |
520 | val = atoi(buf); | |
521 | if (val >= low && val <= high) | |
522 | return ((int)val); | |
523 | printf("Value must be in range [%d,%d]\n", low, high); | |
524 | } | |
525 | } | |
526 | ||
c68cea4f SL |
527 | static struct pattern { |
528 | long pa_value; | |
529 | char *pa_name; | |
530 | } pat[] = { | |
531 | { 0xf00ff00f, "RH750 worst case" }, | |
532 | { 0xec6dec6d, "media worst case" }, | |
533 | { 0xa5a5a5a5, "alternate 1's and 0's" }, | |
fb9e17ff | 534 | { 0xFFFFFFFF, "Severe burnin (up to 48 passes)" }, |
c68cea4f SL |
535 | { 0, 0 }, |
536 | }; | |
537 | ||
538 | getpattern() | |
539 | { | |
540 | register struct pattern *p; | |
541 | int npatterns; | |
542 | char *cp; | |
543 | ||
544 | printf("Available test patterns are:\n"); | |
545 | for (p = pat; p->pa_value; p++) | |
546 | printf("\t%d - (%x) %s\n", (p - pat) + 1, | |
547 | p->pa_value & 0xffff, p->pa_name); | |
548 | npatterns = p - pat; | |
549 | cp = prompt("Pattern (one of the above, other to restart)? "); | |
550 | pattern = atoi(cp) - 1; | |
fb9e17ff MK |
551 | if (pattern < 0 || pattern >= npatterns) |
552 | return(1); | |
71da8ead | 553 | severe = 0; |
fb9e17ff MK |
554 | maxpass = 1; |
555 | if (pat[pattern].pa_value == -1) { | |
71da8ead | 556 | severe = 1; |
fb9e17ff MK |
557 | cp = prompt("How many passes (up to 48)? "); |
558 | maxpass = atoi(cp); | |
559 | if (maxpass > NPT) | |
560 | maxpass = NPT; | |
561 | } | |
f834e141 MK |
562 | maxeccbits = getnum( |
563 | "Maximum number of bit errors to allow for soft ECC", | |
564 | 0, 11, MAXECCBITS); | |
fb9e17ff | 565 | return (0); |
c68cea4f SL |
566 | } |
567 | ||
568 | struct xsect { | |
569 | u_short hd1; | |
570 | u_short hd2; | |
571 | long buf[128]; | |
572 | }; | |
573 | ||
574 | /* | |
575 | * Initialize the buffer with the requested pattern. | |
576 | */ | |
577 | bufinit(bp, size) | |
578 | register struct xsect *bp; | |
579 | int size; | |
580 | { | |
581 | register struct pattern *pptr; | |
582 | register long *pp, *last; | |
583 | register struct xsect *lastbuf; | |
71da8ead | 584 | int patt; |
c68cea4f SL |
585 | |
586 | size /= sizeof (struct sector); | |
587 | lastbuf = bp + size; | |
71da8ead MK |
588 | if (severe) { |
589 | patt = ppat[npat] | ((long)ppat[npat] << 16); | |
590 | printf("Write pattern 0x%x\n", patt&0xffff); | |
591 | } else { | |
592 | pptr = &pat[pattern]; | |
593 | patt = pptr->pa_value; | |
594 | } | |
c68cea4f SL |
595 | while (bp < lastbuf) { |
596 | last = &bp->buf[128]; | |
597 | for (pp = bp->buf; pp < last; pp++) | |
71da8ead | 598 | *pp = patt; |
c68cea4f SL |
599 | bp++; |
600 | } | |
601 | } | |
602 | ||
001cf9d7 SL |
603 | char * |
604 | prompt(msg) | |
605 | char *msg; | |
606 | { | |
607 | static char buf[132]; | |
608 | ||
609 | printf("%s", msg); | |
610 | gets(buf); | |
611 | return (buf); | |
612 | } |