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