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