1 /* @(#)defect.c 1.39 09/07/13 Copyright 1988-2009 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static UConst char sccsid[] =
5 "@(#)defect.c 1.39 09/07/13 Copyright 1988-2009 J. Schilling";
6 #endif
7 /*
8 * Handle defect lists (user level copy)
9 *
10 * Copyright (c) 1988-2009 J. Schilling
11 */
12 /*
13 * The contents of this file are subject to the terms of the
14 * Common Development and Distribution License, Version 1.0 only
15 * (the "License"). You may not use this file except in compliance
16 * with the License.
17 *
18 * See the file CDDL.Schily.txt in this distribution for details.
19 * A copy of the CDDL is also available via the Internet at
20 * http://www.opensource.org/licenses/cddl1.txt
21 *
22 * When distributing Covered Code, include this CDDL HEADER in each
23 * file and include the License file CDDL.Schily.txt from this distribution.
24 */
25
26 #include <schily/stdio.h>
27 #include <schily/utypes.h>
28 #include <schily/param.h> /* Include various defs needed with some OS */
29 #include <schily/standard.h>
30 #include <schily/stdlib.h>
31 #include <schily/intcvt.h>
32 #include <schily/schily.h>
33
34 #include "dsklabel.h"
35
36 #include <scg/scgcmd.h>
37 #include <scg/scsidefs.h>
38 #include <scg/scsireg.h>
39 #include <scg/scsitransp.h>
40
41 #include "scsicmds.h"
42 #include "defect.h"
43
44 #include "fmt.h"
45
46 defect def;
47
48 extern char *Sbuf;
49 extern long Sbufsize;
50 extern int autoformat;
51 extern struct dk_label *d_label;
52
53 EXPORT void convert_def_blk __PR((SCSI *scgp));
54 EXPORT void write_def_blk __PR((SCSI *scgp, BOOL));
55 EXPORT void read_def_blk __PR((SCSI *scgp));
56 LOCAL BOOL scan_def __PR((SCSI *scgp));
57 LOCAL int read_def __PR((SCSI *scgp, long def_blk));
58 EXPORT BOOL edit_def_blk __PR((void));
59 LOCAL void add_def __PR((BOOL));
60 EXPORT void add_def_bfi __PR((struct scsi_def_bfi *));
61 LOCAL void del_def __PR((void));
62 LOCAL void list_def __PR((void));
63 LOCAL void conv_def __PR((BOOL));
64 LOCAL int cmp_def_bfi __PR((struct scsi_def_bfi *, struct scsi_def_bfi *));
65 LOCAL void sort_def __PR((void));
66
67 EXPORT void
convert_def_blk(scgp)68 convert_def_blk(scgp)
69 SCSI *scgp;
70 {
71 register struct scsi_def_list *l;
72 register int ndef;
73 register int n;
74 register int i;
75 int length;
76
77 if (is_ccs(scgp->dev) && read_defect_list(scgp, 3, SC_DEF_BFI, FALSE) >= 0)
78 l = (struct scsi_def_list *)Sbuf;
79 else
80 l = (struct scsi_def_list *)&def;
81 length = a_to_u_2_byte(l->hd.length);
82 ndef = length/sizeof (l->def_bfi[0]);
83 for (n = 0, i = 0; i < ndef; i++) {
84 if (*(long *)l->def_bfi[i].bfi == -1)
85 continue;
86 if (n == 127) {
87 if (!autoformat) {
88 errmsgno(EX_BAD,
89 "Notice: Too many defects for SUN defect list format.\n");
90 errmsgno(EX_BAD,
91 "Notice: This is not a problem with SCSI disks.\n");
92 }
93 break;
94 }
95 def.d_def[n++] = l->def_bfi[i];
96 }
97 n *= sizeof (struct scsi_def_bfi);
98
99 i_to_2_byte(&def.d_magic, DMAGIC);
100 i_to_2_byte(&def.d_size, n);
101 }
102
103 /*---------------------------------------------------------------------------
104 |
105 | XXX Die Defektliste steht auf dem letzten Alternativen Zylinder
106 | auf Kopf 0 und 1.
107 | Alt: Die Defektliste steht auf dem 1. Alternativen Zylinder
108 | Beginn auf Kopf 0 (9 Kopien).
109 | Neu: Die Defektliste steht auf dem 2. Alternativen Zylinder
110 | Kopf 0 und 1 (2 Kopien).
111 |
112 +---------------------------------------------------------------------------*/
113 EXPORT void
write_def_blk(scgp,v)114 write_def_blk(scgp, v)
115 SCSI *scgp;
116 BOOL v;
117 {
118 long def_blk;
119 /*extern int verbose;*/
120
121 def_blk = d_label->dkl_ncyl + d_label->dkl_acyl - 1;
122 def_blk *= d_label->dkl_nhead * d_label->dkl_nsect;
123
124 def_blk = d_label->dkl_ncyl;
125 def_blk *= d_label->dkl_nhead * d_label->dkl_nsect;
126
127 /*printf("def_blk %d\n", def_blk); verbose=1;*/
128 i_to_2_byte(&def.d_magic, DMAGIC);
129 if (write_scsi(scgp, (caddr_t)&def, def_blk, 2) < 0)
130 error("Could not write defect to disk\n");
131 /*verbose=0;*/
132
133 def_blk += d_label->dkl_nsect;
134
135 if (write_scsi(scgp, (caddr_t)&def, def_blk, 2) < 0)
136 error("Could not write defect to disk\n");
137
138 if (v)
139 printf("Defect list written on disk.\n");
140 }
141
142 EXPORT void
read_def_blk(scgp)143 read_def_blk(scgp)
144 SCSI *scgp;
145 {
146 long def_blk;
147 int ret;
148
149 def_blk = d_label->dkl_ncyl + d_label->dkl_acyl - 1;
150 def_blk *= d_label->dkl_nhead * d_label->dkl_nsect;
151
152 def_blk = d_label->dkl_ncyl;
153 def_blk *= d_label->dkl_nhead * d_label->dkl_nsect;
154
155 printf("def: %ld\n", def_blk);
156 if ((ret = read_def(scgp, def_blk)) < 1) {
157 printf("d_magic: %x d_size: %ld\n",
158 a_to_u_2_byte(&def.d_magic),
159 (long)a_to_u_2_byte(&def.d_size)/sizeof (struct scsi_def_bfi));
160 def_blk += d_label->dkl_nsect;
161 if ((ret = read_def(scgp, def_blk)) < 0) {
162 error("Could not read defect from disk\n");
163 }
164 printf("d_magic: %x d_size: %ld\n",
165 a_to_u_2_byte(&def.d_magic),
166 (long)a_to_u_2_byte(&def.d_size)/sizeof (struct scsi_def_bfi));
167 }
168 if (ret != TRUE) {
169 scan_def(scgp);
170 }
171
172 printf("d_magic: %x d_size: %ld\n",
173 a_to_u_2_byte(&def.d_magic),
174 (long)a_to_u_2_byte(&def.d_size)/sizeof (struct scsi_def_bfi));
175
176 if (a_to_u_2_byte(&def.d_magic) == DMAGIC) {
177 print_def_bfi((struct scsi_def_list *)&def);
178 printf("Defect list read from disk.\n");
179 } else {
180 i_to_2_byte(&def.d_magic, 0);
181 i_to_2_byte(&def.d_size, 0);
182 }
183 }
184
185 LOCAL BOOL
scan_def(scgp)186 scan_def(scgp)
187 SCSI *scgp;
188 {
189 int i;
190 long l;
191 defect xdef;
192
193 scgp->silent++;
194 if (read_capacity(scgp) < 0) {
195 scgp->silent--;
196 return (FALSE);
197 }
198 scgp->silent--;
199 l = scgp->cap->c_baddr - 1; /* Ist 2 Sektoren lang */
200 for (i = 0; i < scgp->cap->c_baddr/300; i++, l--)
201 if (read_def(scgp, l) == TRUE) {
202 printf("Scan for defect list: found at: %ld n: %d\n",
203 l, i);
204 xdef = def;
205 /* return (TRUE);*/
206 } else if (a_to_u_4_byte(&def.d_magic) == 0x89898989) {
207 printf("Scan for defect list: New found at: %ld n: %d\n",
208 l, i);
209 }
210 if (a_to_u_2_byte(&xdef.d_magic) == DMAGIC)
211 def = xdef;
212 printf("Scan for defect list: NOT found : %ld n: %d\n", l, i);
213 return (FALSE);
214 }
215
216 LOCAL int
read_def(scgp,def_blk)217 read_def(scgp, def_blk)
218 SCSI *scgp;
219 long def_blk;
220 {
221 fillbytes((caddr_t)&def, sizeof (def), '\0');
222 if (read_scsi(scgp, (caddr_t)&def, def_blk, 2) < 0)
223 return (-1);
224 return (a_to_u_2_byte(&def.d_magic) == DMAGIC);
225 }
226
227 EXPORT BOOL
edit_def_blk()228 edit_def_blk()
229 {
230 char line[128];
231 char *linep;
232 int n;
233 int rll = 0;
234
235 i_to_2_byte(&def.d_magic, 0); /* clean up SCSI def format field */
236 for (;;) {
237 printf("def> ");
238 flush();
239 if ((n = getline(line, 80)) == 0)
240 /* return (FALSE);*/
241 continue;
242 if (n == EOF)
243 exit(EX_BAD);
244 linep = skipwhite(line);
245 switch (linep[0]) {
246
247 case '?':
248 case 'h':
249 case 'H':
250 printf("Available commands are:\n");
251 printf("a add defect\n");
252 printf("d delete defect\n");
253 printf("l list defect\n");
254 printf("q quit this loop\n");
255 printf("r disk is not RLL (default)\n");
256 printf("R disk is RLL (multiply bfi by 1.5)\n");
257 printf("c convert defect list from/to RLL\n");
258 break;
259 case 'r':
260 rll = 0;
261 break;
262 case 'R':
263 rll = 1;
264 break;
265 case 'c':
266 case 'C':
267 conv_def(rll);
268 break;
269 case 'a':
270 case 'A':
271 add_def(rll);
272 break;
273 case 'd':
274 case 'D':
275 del_def();
276 break;
277 case 'l':
278 case 'L':
279 list_def();
280 break;
281 case 's':
282 case 'S':
283 sort_def();
284 break;
285 case 'q':
286 case 'Q':
287 return (TRUE);
288 default:
289 continue;
290 }
291 }
292 }
293
294 LOCAL void
add_def(rll)295 add_def(rll)
296 BOOL rll;
297 {
298 register struct scsi_def_list *l;
299 register int i;
300 long n;
301 int length;
302
303 printf("add\n");
304
305 l = (struct scsi_def_list *)&def;
306 length = a_to_u_2_byte(l->hd.length);
307 i = length/sizeof (l->def_bfi[0]);
308 if (i >= 127) {
309 error("Too many defects.\n");
310 return;
311 }
312
313 n = -1L;
314 getlong("Enter Cylinder", &n, 0L, 2048L);
315 i_to_3_byte(l->def_bfi[i].cyl, n);
316 n = -1L;
317 getlong("Enter Head", &n, 0L, 2048L);
318 l->def_bfi[i].head = n;
319 n = -1L;
320 getlong("Enter Bfi", &n, 0L, 40960L);
321 if (rll)
322 n += n/2;
323 i_to_4_byte(l->def_bfi[i].bfi, n);
324
325 length += sizeof (l->def_bfi[0]);
326 i_to_2_byte(l->hd.length, length);
327 sort_def();
328 }
329
330 EXPORT void
add_def_bfi(dp)331 add_def_bfi(dp)
332 struct scsi_def_bfi *dp;
333 {
334 register struct scsi_def_list *l;
335 register int i;
336 int length;
337
338 l = (struct scsi_def_list *)&def;
339 length = a_to_u_2_byte(l->hd.length);
340 i = length/sizeof (l->def_bfi[0]);
341 if (i >= 127) {
342 error("Too many defects.\n");
343 return;
344 }
345 l->def_bfi[i] = *dp;
346
347 length += sizeof (l->def_bfi[0]);
348 i_to_2_byte(l->hd.length, length);
349 sort_def();
350 }
351
352 LOCAL void
del_def()353 del_def()
354 {
355 register struct scsi_def_list *l;
356 register int i;
357 long n;
358 int length;
359
360 printf("del\n");
361
362 l = (struct scsi_def_list *)&def;
363 length = a_to_u_2_byte(l->hd.length);
364 i = length/sizeof (l->def_bfi[0]);
365 n = -1L;
366 getlong("Enter Defect to delete", &n, 0L, 2048L);
367 if (n >= i)
368 return;
369
370 movebytes((char *)&l->def_bfi[n+1], (char *)&l->def_bfi[n],
371 (i-n-1)*sizeof (struct scsi_def_bfi));
372 length -= sizeof (l->def_bfi[0]);
373 i_to_2_byte(l->hd.length, length);
374 }
375
376 LOCAL void
list_def()377 list_def()
378 {
379 printf("list\n");
380 print_def_bfi((struct scsi_def_list *)&def);
381 }
382
383 LOCAL void
conv_def(rll)384 conv_def(rll)
385 BOOL rll;
386 {
387 register struct scsi_def_list *l;
388 register int i;
389 register int n;
390 long d;
391 int length;
392
393 l = (struct scsi_def_list *)&def;
394 length = a_to_u_2_byte(l->hd.length);
395 n = length/sizeof (l->def_bfi[0]);
396
397 for (i = 0; i < n; i++) {
398 d = a_to_4_byte(l->def_bfi[i].bfi);
399 if (rll)
400 d += d/2;
401 else
402 d -= d/3;
403 i_to_4_byte(l->def_bfi[i].bfi, d);
404 }
405 }
406
407 LOCAL int
cmp_def_bfi(a,b)408 cmp_def_bfi(a, b)
409 struct scsi_def_bfi *a;
410 struct scsi_def_bfi *b;
411 {
412 if (a_to_u_3_byte(a->cyl) > a_to_u_3_byte(b->cyl))
413 return (1);
414 if (a_to_u_3_byte(a->cyl) == a_to_u_3_byte(b->cyl)) {
415 if (a->head > b->head)
416 return (1);
417 if (a->head == b->head) {
418 if (a_to_4_byte(a->bfi) > a_to_4_byte(b->bfi))
419 return (1);
420 if (a_to_4_byte(a->bfi) == a_to_4_byte(b->bfi))
421 return (0);
422 }
423 }
424 return (-1);
425 }
426
427 LOCAL void
sort_def()428 sort_def()
429 {
430 register struct scsi_def_list *l;
431 register int i;
432 int length;
433
434 l = (struct scsi_def_list *)&def;
435 length = a_to_u_2_byte(l->hd.length);
436 i = length/sizeof (l->def_bfi[0]);
437
438 qsort((char *)&l->def_bfi[0], i, sizeof (struct scsi_def_bfi),
439 (int (*)__PR((const void *, const void *)))cmp_def_bfi);
440 }
441