1 /* @(#)xdisk.c	1.33 12/03/16 Copyright 1991-2012 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static	UConst char sccsid[] =
5 	"@(#)xdisk.c	1.33 12/03/16 Copyright 1991-2012 J. Schilling";
6 #endif
7 /*
8  *	Routines to handle external disk definitions
9  *
10  *	Copyright (c) 1991-2012 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/stdlib.h>
28 #include <schily/standard.h>
29 #include <schily/string.h>
30 #include <schily/utypes.h>
31 #include <schily/schily.h>
32 #ifdef	HAVE_STDC_HEADERS
33 #	include <stddef.h>
34 #	define	soff(str, fld)	offsetof(struct str, fld)
35 #else
36 #	include <struct.h>
37 #	define	soff(str, fld)	fldoff(str, fld)
38 #endif
39 #include <scg/scsireg.h>
40 #include <scg/scsitransp.h>
41 
42 #include "fmt.h"
43 
44 #ifdef	FMT
45 extern	int	xdebug;
46 extern	int	debug;
47 extern	int	save_mp;
48 extern	int	autoformat;
49 #else
50 	int	xdebug = 1;
51 #endif
52 
53 struct  dsk_fnd {
54 	struct disk	disk;
55 	int		match;
56 	char		name[512];
57 };
58 
59 LOCAL	struct dsk_fnd *expand_df	__PR((struct dsk_fnd *, int));
60 LOCAL	BOOL	fuzzy_capacity	__PR((struct disk *, struct dsk_fnd *));
61 EXPORT	BOOL	pdisk_eql	__PR((struct disk *dp1, struct disk *dp2));
62 LOCAL	BOOL	add_disk	__PR((char *, struct disk *, struct dsk_fnd *));
63 LOCAL	void	check_deflt	__PR((struct dsk_fnd *, int *, int));
64 LOCAL	void	use_disk	__PR((struct disk *, struct dsk_fnd *, int));
65 LOCAL	void	select_disk	__PR((SCSI *scgp, struct disk *, struct dsk_fnd *, int, int));
66 EXPORT	BOOL	get_ext_diskdata __PR((SCSI *scgp, char *name, struct disk *dp));
67 LOCAL	int	do_disk		__PR((char *, struct disk *, BOOL));
68 LOCAL	void	set_diskitem	__PR((struct disk *, char *, char *, char *));
69 LOCAL	BOOL	set_diskvar	__PR((char *, struct disk *));
70 LOCAL	void	copy_disk	__PR((struct disk *, struct disk *));
71 EXPORT	int	cmp_disk	__PR((struct disk *dp1, struct disk *dp2));
72 LOCAL	BOOL	disk_eql	__PR((struct disk *, struct disk *));
73 EXPORT	BOOL	has_error_rec_params	__PR((struct disk *dp));
74 EXPORT	BOOL	has_disre_params __PR((struct disk *dp));
75 LOCAL	void	copy_vendor_info __PR((char *, struct scsi_inquiry *));
76 EXPORT	void	prdisk		__PR((FILE *f, struct disk *dp, struct scsi_inquiry *ip));
77 EXPORT	int	need_params		__PR((struct disk *dp, int type));
78 EXPORT	int	need_label_params	__PR((struct disk *dp));
79 EXPORT	int	need_geom_params	__PR((struct disk *dp));
80 EXPORT	int	need_scsi_params	__PR((struct disk *dp));
81 EXPORT	int	need_error_rec_params	__PR((struct disk *dp));
82 EXPORT	int	need_disre_params	__PR((struct disk *dp));
83 
84 
85 #define	K_NONE	0x01	/* This entry is not used but might be in database */
86 #define	K_NDB	0x02	/* This entry must not be in the database */
87 #define	K_LABEL	0x04	/* This is a label - not a disk - parameter */
88 #define	K_IGN	0x08	/* Inore this entry when comparing parameters */
89 #define	K_COPY	0x10	/* Copy this parameter even if dest is initialized */
90 #define	K_INIT	0x20	/* Copy over only to non initialized parameters */
91 #define	K_BOOL	0x40	/* This is a boolean entry */
92 
93 #define	K_GEOM	0x0100	/* This is a disk geometry parameter */
94 #define	K_SCSI	0x0200	/* This is a SCSI parameter */
95 #define	K_ERREC	0x0400	/* This is an error recovery parameter */
96 #define	K_DISRE	0x0800	/* This is a disconnect/reconnect parameter */
97 
98 #define	K_N	0x1000	/* We don't need to fill this out */
99 
100 #define	lfld(ptr, off)		((long *)(((char *)(ptr)) + (off)))
101 
102 struct keyw {
103 	char	*name;
104 	int	flags;
105 	int	off;
106 } keyw[] = {
107 
108 /* Disk Label geometry */
109 { "lhead",		K_INIT|K_LABEL,		soff(disk, lhead) },
110 { "lacyl",		K_INIT|K_LABEL,		soff(disk, lacyl) },
111 { "lpcyl",		K_INIT|K_LABEL,		soff(disk, lpcyl) },
112 { "lncyl",		K_INIT|K_LABEL,		soff(disk, lncyl) },
113 { "lspt",		K_INIT|K_LABEL,		soff(disk, lspt) },
114 { "lapc",		K_INIT|K_LABEL|K_N,	soff(disk, lapc) },
115 
116 /* Disk Geometry */
117 { "nhead",		K_INIT|K_GEOM,		soff(disk, nhead) },
118 { "pcyl",		K_INIT|K_GEOM,		soff(disk, pcyl) },
119 { "atrk",		K_INIT|K_GEOM,		soff(disk, atrk) },
120 { "tpz",		K_INIT|K_GEOM,		soff(disk, tpz) },
121 { "spt",		K_INIT|K_GEOM,		soff(disk, spt) },
122 { "mintpz",		K_INIT|K_GEOM|K_N|K_NDB, soff(disk, mintpz) },
123 { "maxtpz",		K_INIT|K_GEOM|K_N|K_NDB, soff(disk, maxtpz) },
124 { "aspz",		K_INIT|K_GEOM,		soff(disk, aspz) },
125 { "secsize",		K_INIT|K_GEOM,		soff(disk, secsize) },
126 { "phys_secsize",	K_INIT|K_GEOM|K_N,	soff(disk, phys_secsize) },
127 			/*
128 			 * ignore capacity on compares
129 			 * use fuzzy compare instead
130 			 */
131 { "capacity",		K_INIT|K_N|K_IGN,	soff(disk, capacity) },
132 { "min_capacity",	K_NONE|K_N,		soff(disk, dummy) },
133 { "rpm",		K_INIT|K_GEOM,		soff(disk, rpm) },
134 { "track_skew",		K_INIT|K_GEOM,		soff(disk, track_skew) },
135 { "cyl_skew",		K_INIT|K_GEOM,		soff(disk, cyl_skew) },
136 
137 { "reduced_curr",	K_INIT|K_GEOM|K_N,	soff(disk, reduced_curr) },
138 { "write_precomp",	K_INIT|K_GEOM|K_N,	soff(disk, write_precomp) },
139 { "step_rate",		K_INIT|K_GEOM|K_N,	soff(disk, step_rate) },
140 
141 { "rot_pos_locking",	K_INIT|K_GEOM|K_N,	soff(disk, rot_pos_locking) },
142 { "rotational_off",	K_INIT|K_GEOM|K_N,	soff(disk, rotational_off) },
143 
144 { "interleave",		K_INIT|K_GEOM,		soff(disk, interleave) },
145 { "fmt_pattern",	K_INIT|K_GEOM,		soff(disk, fmt_pattern) },
146 
147 { "fmt_mode",		K_INIT|K_GEOM|K_N,	soff(disk, fmt_mode) },
148 { "spare_band_size",	K_INIT|K_GEOM|K_N,	soff(disk, spare_band_size) },
149 
150 /* SCSI parameters */
151 { "def_lst_format",	K_INIT|K_SCSI,		soff(disk, def_lst_format) },
152 { "split_wv_cmd",	K_INIT|K_SCSI|K_BOOL,	soff(disk, split_wv_cmd) },
153 
154 /* Error recovery */
155 { "rd_retry_count",	K_INIT|K_ERREC|K_N,	soff(disk, rd_retry_count) },
156 { "wr_retry_count",	K_INIT|K_ERREC|K_N,	soff(disk, wr_retry_count) },
157 { "recov_timelim",	K_INIT|K_ERREC|K_N,	soff(disk, recov_timelim) },
158 
159 /* Disconnect / reconnect */
160 { "buf_full_ratio",	K_INIT|K_DISRE|K_N,	soff(disk, buf_full_ratio) },
161 { "buf_empt_ratio",	K_INIT|K_DISRE|K_N,	soff(disk, buf_empt_ratio) },
162 { "bus_inact_limit",	K_INIT|K_DISRE|K_N,	soff(disk, bus_inact_limit) },
163 { "disc_time_limit",	K_INIT|K_DISRE|K_N,	soff(disk, disc_time_limit) },
164 { "conn_time_limit",	K_INIT|K_DISRE|K_N,	soff(disk, conn_time_limit) },
165 { "max_burst_size",	K_INIT|K_DISRE|K_N,	soff(disk, max_burst_size) },
166 { "data_tr_dis_ctl",	K_INIT|K_DISRE|K_N,	soff(disk, data_tr_dis_ctl) },
167 
168 /* Common device control */
169 { "queue_alg_mod",	K_INIT|K_SCSI|K_N,	soff(disk, queue_alg_mod) },
170 { "dis_queuing",	K_INIT|K_SCSI|K_BOOL|K_N,
171 						soff(disk, dis_queuing) },
172 
173 { "gap1",		K_INIT|K_IGN,		soff(disk, gap1) },
174 { "gap2",		K_INIT|K_IGN,		soff(disk, gap2) },
175 { "int_cyl",		K_INIT|K_IGN|K_N,	soff(disk, int_cyl) },
176 { "fmt_time",		K_INIT|K_IGN,		soff(disk, fmt_time) },
177 { "fmt_timeout",	K_INIT|K_IGN|K_N,	soff(disk, fmt_timeout) },
178 { "veri_time",		K_INIT|K_IGN|K_N,	soff(disk, veri_time) },
179 { "veri_count",		K_INIT|K_IGN|K_N,	soff(disk, veri_count) },
180 { "wr_veri_count",	K_INIT|K_IGN|K_N,	soff(disk, wr_veri_count) },
181 { "veri_loops",		K_INIT|K_IGN|K_N,	soff(disk, veri_loops) },
182 { "default_data",	K_INIT|K_IGN|K_N|K_BOOL, soff(disk, default_data) },
183 { "bridge_controller",	K_INIT|K_SCSI|K_IGN|K_N|K_BOOL,
184 						soff(disk, bridge_controller) },
185 
186 };
187 
188 #define	NKEYW	(sizeof (keyw) / sizeof (keyw[0]))
189 
190 struct keyw	*keywNKEYW = &keyw[NKEYW];
191 
192 #ifdef	FMT
193 #else
main(ac,av)194 main(ac, av)
195 	int	ac;
196 	char	**av;
197 {
198 	char	*name;
199 	struct disk	test_disk;
200 
201 	if (ac > 1)
202 		name = av[1];
203 	else {
204 		name = "QUANTUM P105S 910-10-94xA.1 ";
205 		test_disk.nhead = 6;
206 		test_disk.pcyl = 1019;
207 	}
208 
209 	if (!opendatfile("sformat.dat"))
210 		return;
211 
212 	get_ext_diskdata(name, &test_disk);
213 
214 	closedatfile();
215 }
216 #endif
217 
218 LOCAL struct dsk_fnd *
expand_df(df,found)219 expand_df(df, found)
220 	struct dsk_fnd	*df;
221 	int		found;
222 {
223 	struct dsk_fnd	*xdf;
224 
225 	xdf = (struct  dsk_fnd *) realloc(df,
226 					sizeof (struct  dsk_fnd) * (found+1));
227 	disk_null(&xdf[found].disk, 1);
228 	return (xdf);
229 }
230 
231 LOCAL BOOL
fuzzy_capacity(dp,df)232 fuzzy_capacity(dp, df)
233 	struct disk	*dp;
234 	struct dsk_fnd	*df;
235 {
236 	double	dc;	/* current disk */
237 	double	fc;	/* found disk from database */
238 
239 	/*
240 	 * if capacity is not known this is a match
241 	 */
242 	if (dp->capacity < 0 || df->disk.capacity < 0)
243 		return (TRUE);
244 
245 	if (dp->secsize < 0)
246 		dc = dp->capacity * 512.0;
247 	else
248 		dc = dp->capacity * (dp->secsize * 1.0);
249 	if (df->disk.secsize < 0) {
250 		if (dp->secsize > 0)
251 			fc = df->disk.capacity * (dp->secsize * 1.0);
252 		else
253 			fc = df->disk.capacity * 512.0;
254 	} else
255 		fc = df->disk.capacity * (df->disk.secsize * 1.0);
256 
257 	if (debug || xdebug) {
258 		printf("fuzzy_cap current: %g found: %g (limits: %g, %g)\n",
259 						dc, fc, dc/1.3, dc*1.3);
260 	}
261 
262 	/*
263 	 * XXX NOTE:	Some versions of Sunpro C compile 1.3 t0 1.0 if
264 	 * XXX		in german locale.
265 	 * XXX		If fuzzy capacity does not work as expected:
266 	 * XXX		check your C-compiler.
267 	 */
268 	if ((dc * 1.3) < fc || (dc / 1.3) > fc)
269 		return (FALSE);
270 
271 	if (xdebug) printf("fuzzy_cap: TRUE\n");
272 	return (TRUE);
273 }
274 
275 EXPORT BOOL
pdisk_eql(dp1,dp2)276 pdisk_eql(dp1, dp2)
277 	struct disk	*dp1;
278 	struct disk	*dp2;
279 {
280 	return ((dp1->nhead <= 0 || dp1->nhead == dp2->nhead) &&
281 			(dp1->pcyl <= 0 || dp1->pcyl == dp2->pcyl));
282 }
283 
284 LOCAL BOOL
add_disk(name,dp,df)285 add_disk(name, dp, df)
286 	char		*name;
287 	struct disk	*dp;
288 	struct dsk_fnd	*df;
289 {
290 	if (pdisk_eql(dp, &df->disk) && fuzzy_capacity(dp, df)) {
291 		strcpy(df->name, name);
292 		return (TRUE);
293 	}
294 	return (FALSE);
295 }
296 
297 LOCAL void
check_deflt(df,deflt,found)298 check_deflt(df, deflt, found)
299 	struct dsk_fnd	*df;
300 	int		*deflt;
301 	int		found;
302 {
303 	if (df->disk.default_data > 0) {
304 		if (*deflt >= 0) {
305 			if (!autoformat) {
306 				datfileerr("second default_data for '%s'",
307 					df->name);
308 			} else {
309 				comerrno(EX_BAD,
310 					"Die Datenbasis besitzt mehrere default Diskparameter fuer diese Platte.\n");
311 			/* NOTREACHED */
312 			}
313 		} else {
314 			*deflt = found;
315 		}
316 	}
317 }
318 
319 LOCAL void
use_disk(dp,df,this)320 use_disk(dp, df, this)
321 	struct disk	*dp;
322 	struct dsk_fnd	*df;
323 	int		this;
324 {
325 	copy_disk(&df[this].disk, dp);
326 	if (dp->disk_type)
327 		free(dp->disk_type);
328 	dp->disk_type = permstring(df[this].name);
329 }
330 
331 #define	item_equal(a, b)	(((a) <  0 && (b) <  0) || ((a) == (b)))
332 
333 LOCAL void
select_disk(scgp,dp,df,found,deflt)334 select_disk(scgp, dp, df, found, deflt)
335 	SCSI		*scgp;
336 	struct disk	*dp;
337 	struct dsk_fnd	*df;
338 	int		found;
339 	int		deflt;
340 {
341 	int	i;
342 	int	this = -1;
343 	int	match = -1;
344 	int	max = -1;
345 	int	ndbentry = found;
346 	BOOL	selected = FALSE;
347 	BOOL	bridge	 = FALSE;
348 
349 	for (i = 0; i < found; i++) {
350 		df[i].match = cmp_disk(dp, &df[i].disk);
351 		if (df[i].match > max &&
352 			item_equal(dp->secsize, df[i].disk.secsize) &&
353 			/*
354 			 * Sony Format Mode
355 			 */
356 			item_equal(dp->fmt_mode, df[i].disk.fmt_mode)) {
357 			max = df[i].match;
358 			match = i;
359 		}
360 		if (disk_eql(dp, &df[i].disk))
361 			this = i;
362 	}
363 	if (this < 0) {
364 		/*
365 		 * This disk is not known in database.
366 		 * Create an entry for it (name == INQUIRY).
367 		 */
368 		this = i;
369 		disk_null(&df[this].disk, 0);
370 		copy_disk(dp, &df[this].disk);
371 		df[this].disk.flags |= D_DISK_CURRENT;
372 		df[this].match = cmp_disk(dp, &df[this].disk);
373 		copy_vendor_info(df[this].name, scgp->inq);
374 		found++;
375 	}
376 	/*
377 	 * If the disk is unformatted or has no label
378 	 * use default database entry au current selection.
379 	 * Otherwise use current disk settings.
380 	 */
381 	if (dp->formatted <= 0)
382 		this = (deflt < 0) ? this : deflt;
383 
384 	for (i = 0; i < ndbentry; i++) {
385 		if (df[0].disk.bridge_controller > 0)
386 			bridge = TRUE;
387 	}
388 
389 	max = 0;
390 	if (autoformat) {
391 		if (deflt < 0) {
392 			/* Paranoia */
393 			comerrno(EX_BAD,
394 				"Die Datenbasis besitzt keine default Diskparameter fuer diese Platte.\n");
395 			/* NOTREACHED */
396 		}
397 		use_disk(dp, df, this = deflt);
398 	} else do {
399 		if (xdebug) printf("found: %d deflt: %d this: %d match: %d\n",
400 						found, deflt, this, match);
401 
402 		if ((deflt >= 0) && (deflt != this)) {
403 			printf("WARNING: disk settings differ from default\n");
404 			selected = TRUE;
405 		}
406 		if (found > ndbentry) {
407 			printf("WARNING: disk settings differ from all database entries\n");
408 			if (bridge) {
409 				printf("\tThis may because an unknown disk is connected to the controller\n");
410 				printf("\tor because the current disk is not formatted as noted in database.\n");
411 				printf("\tIf this is an unknown disk, use the current parameters ...\n");
412 				printf("\totherwise:\n");
413 			}
414 			printf("\tCheck if you really want the disk settings to be\n");
415 			printf("\tdifferent from the settings in the database entry.\n");
416 			selected = TRUE;
417 		}
418 		if ((found > 1 && deflt < 0) ||
419 		    (found > 1 && (selected ||
420 				yes("Select alternate disk type? ")))) {
421 			printf("Available disk types:\n");
422 			for (i = 0; i < found; i++) {
423 				printf("%s%2d)%s%s(%2d)\t\"%s\"\n",
424 							i == this ? "*":" ",
425 							i,
426 							i == deflt ? "+":" ",
427 							i == match ? "~":" ",
428 							df[i].match,
429 							df[i].name);
430 			}
431 			if (max++ == 0 && ndbentry == 1 && found > 1 &&
432 					!yes("Don't use database entry or view selection? ")) {
433 				this = 0;	/* The one and only database entry */
434 				selected = FALSE;
435 			} else {
436 				getint("Select disk", &this, 0, found - 1);
437 				selected = TRUE;
438 			}
439 		}
440 		use_disk(dp, df, this);
441 
442 		if (found > 1 && selected)
443 			prdisk(stdout, dp, scgp->inq);
444 
445 	} while (selected && found > 1 && !yes("Use this disk parameters? "));
446 
447 	if (deflt < 0)
448 		deflt = 0;
449 	if (this >= ndbentry) {
450 		printf("WARNING: using non database entry\n");
451 		printf("If you deny the next question there will be no label from data base.\n");
452 		if (yes("Use label list from default entry? ")) {
453 			dp->disk_type = permstring(df[deflt].name);
454 			dp->default_part = df[deflt].disk.default_part;
455 		}
456 		if (dp->mode_pages == 0 && df[deflt].disk.mode_pages) {
457 			printf("If you deny the next question there will be no mode pages from data base.\n");
458 			if (yes("Use mode page list from default entry? "))
459 				dp->mode_pages = df[deflt].disk.mode_pages;
460 		}
461 	}
462 }
463 
464 EXPORT BOOL
get_ext_diskdata(scgp,name,dp)465 get_ext_diskdata(scgp, name, dp)
466 	SCSI		*scgp;
467 	char		*name;
468 	struct disk	*dp;
469 {
470 	int	found = 0;
471 	int	inq_found = 0;		/* Vendor & Product */
472 	int	firmw_found = 0;	/* Vendor & Product & Firmware */
473 	BOOL	ign_firmw = FALSE;
474 	int	deflt = -1;
475 	char	nbuf[512];
476 	struct  dsk_fnd *disks_found;
477 
478 again:
479 	if (rewinddatfile() < 0)
480 		return (FALSE);
481 
482 	if (xdebug)
483 		printf("scan for disk: %.28s\n", name);
484 
485 	disks_found = (struct  dsk_fnd *) malloc(sizeof (struct  dsk_fnd));
486 	disk_null(&disks_found[found].disk, 1);
487 
488 	/*
489 	 * scan for next disk entry
490 	 */
491 	while (scanfortable("disk_type", NULL)) {
492 		int	i;
493 		strcpy(nbuf, curword());
494 		/*
495 		 * parse current disk entry and tell if it matched
496 		 */
497 		switch (i = do_disk(name, &disks_found[found].disk, ign_firmw)) {
498 
499 		case D_INQ_FOUND|D_FIRMW_FOUND:
500 			firmw_found++;
501 			disks_found[found].disk.flags |=
502 						D_INQ_FOUND|D_FIRMW_FOUND;
503 			if (add_disk(nbuf, dp, &disks_found[found])) {
504 				check_deflt(&disks_found[found], &deflt, found);
505 				disks_found[found].disk.flags |=
506 						D_DISK_FOUND;
507 				found++;
508 				disks_found = expand_df(disks_found, found);
509 			}
510 			break;
511 		case D_INQ_FOUND:
512 			inq_found++;
513 			/*
514 			 * Don't increment found here,
515 			 * we must not use this entry.
516 			 */
517 			break;
518 		default:
519 			printf("illegal return code %X from do_disk()\n", i);
520 		case 0:	break;
521 		}
522 	}
523 	if (found) {
524 		/*
525 		 * Wenn nur ein Eintrag vorhanden ist, dann ist er
526 		 * in jedem Fall der Default Eintrag.
527 		 */
528 		if (found == 1)
529 			deflt = 0;
530 		printf("Default Disk type: '%s'\n",
531 				deflt < 0 ? "none" : disks_found[deflt].name);
532 		if (deflt < 0 && autoformat) {
533 			comerrno(EX_BAD,
534 				"Die Datenbasis besitzt keine default Diskparameter fuer diese Platte.\n");
535 			/* NOTREACHED */
536 		}
537 		if (deflt >= 0 && disks_found[deflt].disk.default_part) {
538 			printf("Default partition: '%s'\n",
539 					disks_found[deflt].disk.default_part);
540 		} else if (autoformat) {
541 			comerrno(EX_BAD,
542 				"Die Datenbasis besitzt keine default Partition fuer diese Platte.\n");
543 			/* NOTREACHED */
544 		}
545 		if (deflt >= 0 && disks_found[deflt].disk.mode_pages) {
546 			printf("Mode Pages:        '%s'\n",
547 					disks_found[deflt].disk.mode_pages);
548 		}
549 		if (autoformat ||
550 			!yes("Ignore database disk parameters from '%s'? ",
551 							datfilename())) {
552 			select_disk(scgp, dp, disks_found, found, deflt);
553 			free(disks_found);
554 			return (TRUE);
555 		}
556 	} else if (autoformat) {
557 		/* EMPTY */ ;		/* Checked below */
558 	} else if (firmw_found) {
559 		errmsgno(EX_BAD,
560 			"WARNING: Inquiry OK (%d controller matches) but no disk found.\n", firmw_found);
561 	} else if (inq_found) {
562 		errmsgno(EX_BAD,
563 			"WARNING: Inquiry OK (%d controller matches) but no matching firmware found.\n", inq_found);
564 		if (yes("Try to use entry for other firmware? ")) {
565 			ign_firmw = TRUE;
566 			goto again;
567 		} else {
568 			/*
569 			 * Report that we found vendor & product.
570 			 */
571 			dp->flags |= D_INQ_FOUND;
572 		}
573 	}
574 	if (autoformat) {
575 		comerrno(EX_BAD,
576 			"Diese Platte besitzt keine Produktfreigabe.\n");
577 		/* NOTREACHED */
578 	}
579 	free(disks_found);
580 	return (FALSE);
581 }
582 
583 
584 /*---------------------------------------------------------------------------
585 |
586 |	Parst einen Disk Eintrag in der Steuerungsdatei
587 |	Returnwert zeigt an, ob dieser Eintrag passend war.
588 |
589 +---------------------------------------------------------------------------*/
590 
591 LOCAL int
do_disk(name,dp,ign_firmw)592 do_disk(name, dp, ign_firmw)
593 	char		*name;
594 	struct disk	*dp;
595 	BOOL		ign_firmw;
596 {
597 	char	inqname[80];
598 	char	defpart[80];
599 	char	mpages[80];
600 	int	ret = 0;
601 
602 	disk_null(dp, 0);
603 	if (xdebug) printf("do_disk: line: %d curword: '%s'\n",
604 						getlineno(), curword());
605 	(void) garbage(skipwhite(peekword()));
606 	if (!nextline())
607 		return (FALSE);
608 
609 	while (scanforline(NULL, NULL) != NULL) {
610 		if ((ret & D_FIRMW_FOUND) == 0)
611 			inqname[0] = defpart[0] = mpages[0] = 0;
612 
613 		set_diskitem(dp, inqname, defpart, mpages);
614 		if ((ret & D_FIRMW_FOUND) == 0 && *inqname) {
615 			if (xdebug) {
616 				printf("name: %.28s\n", name);
617 				printf("DATA: %.28s\n", inqname);
618 			}
619 			/*
620 			 * allow short inquiry entry in database
621 			 * to match i.e. all firmware
622 			 */
623 			if (strncmp(name, inqname, strlen(inqname)) == 0)
624 				ret = D_INQ_FOUND|D_FIRMW_FOUND;
625 			else if (strncmp(name, inqname, 24) == 0) {
626 				ret = D_INQ_FOUND;
627 				if (ign_firmw)
628 					ret |= D_FIRMW_FOUND;
629 			}
630 		}
631 	}
632 	if (past_df_sig())
633 		dp->flags = D_DB_BAD;
634 	if (dp->fmt_time > 0)
635 		dp->flags |= D_FTIME_FOUND;
636 	if (dp->veri_time > 0)
637 		dp->flags |= D_VTIME_FOUND;
638 
639 	if (ret & D_FIRMW_FOUND) {
640 		if (xdebug)
641 			printf("defpart: '%s' mpages: '%s'\n", defpart, mpages);
642 		if (defpart[0])
643 			dp->default_part = permstring(defpart);
644 		if (mpages[0])
645 			dp->mode_pages   = permstring(mpages);
646 	}
647 	return (ret);
648 }
649 
650 LOCAL void
set_diskitem(dp,inqname,defpart,mpages)651 set_diskitem(dp, inqname, defpart, mpages)
652 	struct disk	*dp;
653 	char		*inqname;
654 	char		*defpart;
655 	char		*mpages;
656 {
657 	char	*word;
658 
659 	for (word = curword(); *word; word = nextword()) {
660 		if (streql(word, ":"))
661 			continue;
662 		if (streql(word, "inquiry")) {
663 			if (!set_stringvar("Inquiry Name", inqname, 28))
664 				break;
665 		} else if (streql(word, "default_partition")) {
666 			if (!set_stringvar("Partition Name", defpart, 79))
667 				break;
668 		} else if (streql(word, "mode_pages")) {
669 			if (!set_stringvar("Modepage Name", mpages, 79))
670 				break;
671 		} else if (!set_diskvar(word, dp))
672 			break;
673 	}
674 	(void) nextword();
675 }
676 
677 LOCAL BOOL
set_diskvar(word,dp)678 set_diskvar(word, dp)
679 	char		*word;
680 	struct disk	*dp;
681 {
682 	register struct keyw *kp = keyw;
683 
684 	long	*valp = (long *)0;
685 	long	l;
686 
687 	if (xdebug) printf("diskvar: '%s' : ", word);
688 
689 	for (; kp < keywNKEYW; kp++) {
690 		if ((kp->name != NULL) &&
691 				((kp->flags & (K_LABEL|K_NDB)) == 0) &&
692 						streql(word, kp->name)) {
693 			valp = lfld(dp, kp->off);
694 			break;
695 		}
696 	}
697 
698 	if (kp >= keywNKEYW) {
699 		skip_illvar("disk", word);
700 		return (FALSE);
701 	}
702 
703 	if (!checkequal())
704 		return (FALSE);
705 
706 	if (!isval(word = nextword()))
707 		return (FALSE);
708 	if (kp->flags & K_BOOL) {
709 		if (streql(word, "TRUE")) {
710 			l = TRUE;
711 		} else if (streql(word, "FALSE")) {
712 			l = FALSE;
713 		} else {
714 			datfileerr("%s: not a bool '%s'", kp->name, word);
715 			return (FALSE);
716 		}
717 	} else if (*astol(word, &l) != '\0') {
718 		datfileerr("%s: not a number '%s'", kp->name, word);
719 		return (FALSE);
720 	}
721 	*valp = l;
722 
723 	if (xdebug) printf("%ld\n", *valp);
724 	return (TRUE);
725 }
726 
727 LOCAL void
copy_disk(from,to)728 copy_disk(from, to)
729 	register struct disk *from;
730 	register struct disk *to;
731 {
732 	register struct keyw *kp = keyw;
733 
734 	for (; kp < keywNKEYW; kp++) {
735 		if (kp->flags & K_COPY)
736 			*lfld(to, kp->off) = *lfld(from, kp->off);
737 		else if (kp->flags & K_INIT) {
738 			if (*lfld(from, kp->off) >= 0)
739 				*lfld(to, kp->off) = *lfld(from, kp->off);
740 		}
741 	}
742 
743 	to->flags |= from->flags;
744 
745 	if (from->disk_type) {
746 		to->disk_type = from->disk_type;
747 	}
748 	if (from->default_part) {
749 		if (to->default_part)
750 			free(to->default_part);
751 		to->default_part = from->default_part;
752 	}
753 	if (from->mode_pages) {
754 		if (to->mode_pages)
755 			free(to->mode_pages);
756 		to->mode_pages = from->mode_pages;
757 	}
758 	if (from->parts) {
759 		/*XXX*/
760 		to->parts = from->parts;
761 	}
762 	if (from->bridge_controller > 0) {
763 		to->bridge_controller = TRUE;
764 	}
765 }
766 
767 EXPORT int
cmp_disk(dp1,dp2)768 cmp_disk(dp1, dp2)
769 	register struct disk *dp1;
770 	register struct disk *dp2;
771 {
772 	register struct keyw *kp = keyw;
773 	register int	n = 0;
774 
775 	for (; kp < keywNKEYW; kp++) {
776 		if ((kp->flags & (K_NONE|K_IGN)) == 0 &&
777 				*lfld(dp1, kp->off) >= 0 &&
778 				*lfld(dp1, kp->off) == *lfld(dp2, kp->off)) {
779 			n++;
780 		} else {
781 			if (xdebug == 0)
782 				continue;
783 
784 			if (*lfld(dp1, kp->off) == -1)
785 				continue;
786 			printf("name:%-16s off:%3d flags:%02X 1:%9ld 2:%9ld\n",
787 				kp->name, kp->off, kp->flags,
788 				*lfld(dp1, kp->off), *lfld(dp2, kp->off));
789 		}
790 	}
791 	return (n);
792 }
793 
794 LOCAL BOOL
disk_eql(dp1,dp2)795 disk_eql(dp1, dp2)
796 	register struct disk *dp1;
797 	register struct disk *dp2;
798 {
799 	register struct keyw *kp = keyw;
800 	register int	diffs = 0;
801 
802 	/*
803 	 * Zwei Platten sind gleich, wenn alle in beiden Strukturen definierten
804 	 * d.h. != -1 Felder gleich sind.
805 	 */
806 	for (; kp < keywNKEYW; kp++) {
807 		if ((kp->flags & (K_NONE|K_LABEL|K_IGN)) == 0 &&
808 				*lfld(dp1, kp->off) >= 0 &&
809 				*lfld(dp2, kp->off) >= 0 &&
810 				*lfld(dp1, kp->off) != *lfld(dp2, kp->off)) {
811 			if (xdebug)
812 				printf("not equal: %-10s %ld != %ld\n",
813 				kp->name,
814 				*lfld(dp1, kp->off), *lfld(dp2, kp->off));
815 			diffs++;
816 		}
817 	}
818 	if (xdebug)
819 		printf("total of %d diff%s.\n", diffs, diffs > 1?"s":"");
820 	return (diffs == 0);
821 }
822 
823 EXPORT BOOL
has_error_rec_params(dp)824 has_error_rec_params(dp)
825 	register struct disk	*dp;
826 {
827 	if (dp->rd_retry_count >= 0 ||
828 			dp->wr_retry_count >= 0 ||
829 			dp->recov_timelim >= 0) {
830 		return (TRUE);
831 	}
832 	return (FALSE);
833 }
834 
835 EXPORT BOOL
has_disre_params(dp)836 has_disre_params(dp)
837 	register struct disk	*dp;
838 {
839 	if (dp->buf_full_ratio >= 0 ||
840 			dp->buf_empt_ratio >= 0 ||
841 			dp->bus_inact_limit >= 0 ||
842 			dp->disc_time_limit >= 0 ||
843 			dp->conn_time_limit >= 0 ||
844 			dp->max_burst_size >= 0 ||
845 			dp->data_tr_dis_ctl >= 0) {
846 		return (TRUE);
847 	}
848 	return (FALSE);
849 }
850 
851 
852 LOCAL void
copy_vendor_info(s,ip)853 copy_vendor_info(s, ip)
854 	char			*s;
855 	struct scsi_inquiry	*ip;
856 {
857 	sprintf(s, "CURRENT %.28s", ip->inq_vendor_info);
858 }
859 
860 EXPORT void
prdisk(f,dp,ip)861 prdisk(f, dp, ip)
862 	register FILE *f;
863 	register struct disk		*dp;
864 	register struct scsi_inquiry	*ip;
865 {
866 	int	neednl = 0;
867 
868 	fprintf(f, "disk_type = \"%s\"\n", dp->disk_type);
869 	fprintf(f, "\tinquiry = \"%.28s\" :\n", ip->inq_vendor_info);
870 	if (dp->bridge_controller > 0)
871 		fprintf(f, "\tbridge_controller = TRUE :\n");
872 #ifdef	nono
873 	if (dp->fmt_time <= 0 || dp->veri_time <= 0)
874 		estimate_times(dp);
875 #endif
876 	if (dp->fmt_time > 0) {
877 		fprintf(f, "\tfmt_time = %ld :", dp->fmt_time);
878 		neednl++;
879 	}
880 
881 	if (dp->veri_time > 0) {
882 		fprintf(f, "%sveri_time = %ld :",
883 					neednl?" ":"\t", dp->veri_time);
884 		neednl++;
885 	}
886 	if (neednl)
887 		fprintf(f, "\n");
888 	neednl = 0;
889 
890 	fprintf(f, "\tnhead = %ld : ", dp->nhead);
891 	fprintf(f, "pcyl = %ld : ", dp->pcyl);
892 	fprintf(f, "spt = %ld : ", dp->spt);
893 	fprintf(f, "secsize = %ld :\n", dp->secsize);
894 
895 	if (dp->reduced_curr >= 0 ||
896 			dp->write_precomp >= 0 || dp->step_rate >= 0) {
897 		fprintf(f, "\treduced_curr = %ld : ", dp->reduced_curr);
898 		fprintf(f, "write_precomp = %ld : ", dp->write_precomp);
899 		fprintf(f, "step_rate = %ld :\n", dp->step_rate);
900 	}
901 	if (dp->atrk > 0 || dp->tpz != 1 || dp->aspz > 0) {
902 		fprintf(f, "\tatrk = %ld : ", dp->atrk);
903 		fprintf(f, "tpz = %ld : ", dp->tpz);
904 		fprintf(f, "aspz = %ld : ", dp->aspz);
905 		neednl++;
906 	}
907 	if (dp->phys_secsize > 0 && dp->phys_secsize != dp->secsize) {
908 		fprintf(f, "phys_secsize = %ld :", dp->phys_secsize);
909 		neednl++;
910 	}
911 	if (neednl)
912 		fprintf(f, "\n");
913 	if (dp->cur_capacity > 0) {
914 		fprintf(f, "\tcapacity = %ld :\n", dp->cur_capacity);
915 	}
916 	if (dp->track_skew > 0 || dp->cyl_skew > 0) {
917 		fprintf(f, "\ttrack_skew = %ld : ", dp->track_skew);
918 		fprintf(f, "cyl_skew = %ld :\n", dp->cyl_skew);
919 	}
920 	if (dp->fmt_mode >= 0 || dp->spare_band_size >= 0) {
921 		fprintf(f, "\tfmt_mode = %ld : ", dp->fmt_mode);
922 		fprintf(f, "spare_band_size = %ld :\n", dp->spare_band_size);
923 	}
924 	if (dp->def_lst_format >= 0 && dp->def_lst_format != SC_DEF_BLOCK) {
925 		fprintf(f, "\tdef_lst_format = %ld :\n", dp->def_lst_format);
926 	}
927 	if (dp->split_wv_cmd > 0) {
928 		fprintf(f, "\tsplit_wv_cmd = %s :\n",
929 					dp->split_wv_cmd?"TRUE":"FALSE");
930 	}
931 	neednl = 0;
932 	if (dp->queue_alg_mod >= 0) {
933 		fprintf(f, "\tqueue_alg_mod = %ld :", dp->queue_alg_mod);
934 		neednl++;
935 	}
936 	if (dp->dis_queuing > 0) {
937 		fprintf(f, "%sdis_queuing = TRUE :", neednl?" ":"\t");
938 		neednl++;
939 	}
940 	if (neednl)
941 		fprintf(f, "\n");
942 
943 	fprintf(f, "\tinterleave = %ld : ", dp->interleave);
944 	fprintf(f, "rpm = %ld :", dp->rpm);
945 	if (dp->fmt_pattern > 0)
946 		fprintf(f, " fmt_pattern = %ld :", dp->fmt_pattern);
947 	fprintf(f, "\n");
948 
949 	if (has_error_rec_params(dp)) {
950 		int	n = 0;
951 
952 		fprintf(f, "\t");
953 		if (dp->rd_retry_count >= 0) {
954 			fprintf(f, "rd_retry_count = %ld :",
955 						dp->rd_retry_count);
956 			n++;
957 		}
958 		if (dp->wr_retry_count >= 0) {
959 			fprintf(f, "%swr_retry_count = %ld :", n ? " " : "",
960 						dp->wr_retry_count);
961 			n++;
962 		}
963 		if (dp->recov_timelim >= 0) {
964 			fprintf(f, "%srecov_timelim = %ld :", n ? " " : "",
965 						dp->recov_timelim);
966 			n++;
967 		}
968 		fprintf(f, "\n");
969 	}
970 	if (has_disre_params(dp)) {
971 		int	n = -1;
972 
973 		fprintf(f, "\t");
974 		if (dp->buf_full_ratio >= 0) {
975 			n++;
976 			fprintf(f, "buf_full_ratio = %ld :",
977 						dp->buf_full_ratio);
978 		}
979 		if (dp->buf_empt_ratio >= 0) {
980 			n++;
981 			fprintf(f, "%sbuf_empt_ratio = %ld :", n ? " " : "",
982 						dp->buf_empt_ratio);
983 		}
984 		if (dp->bus_inact_limit >= 0) {
985 			if (++n >= 3) { fprintf(f, "\n\t"); n = 0; }
986 
987 			fprintf(f, "%sbus_inact_limit = %ld :", n ? " " : "",
988 						dp->bus_inact_limit);
989 		}
990 		if (dp->disc_time_limit >= 0) {
991 			if (++n >= 3) { fprintf(f, "\n\t"); n = 0; }
992 
993 			fprintf(f, "%sdisc_time_limit = %ld :", n ? " " : "",
994 						dp->disc_time_limit);
995 		}
996 		if (dp->conn_time_limit >= 0) {
997 			if (++n >= 3) { fprintf(f, "\n\t"); n = 0; }
998 
999 			fprintf(f, "%sconn_time_limit = %ld :", n ? " " : "",
1000 						dp->conn_time_limit);
1001 		}
1002 		if (dp->max_burst_size >= 0) {
1003 			if (++n >= 3) { fprintf(f, "\n\t"); n = 0; }
1004 
1005 			fprintf(f, "%smax_burst_size = %ld :", n ? " " : "",
1006 						dp->max_burst_size);
1007 		}
1008 		if (dp->data_tr_dis_ctl >= 0) {
1009 			if (++n >= 3) { fprintf(f, "\n\t"); n = 0; }
1010 
1011 			fprintf(f, "%sdata_tr_dis_ctl = %ld :", n ? " " : "",
1012 						dp->data_tr_dis_ctl);
1013 		}
1014 		fprintf(f, "\n");
1015 	}
1016 
1017 	fprintf(f, "\tdefault_partition = \"%s\" :\n\n", dp->default_part);
1018 }
1019 
1020 EXPORT	int
need_params(dp,type)1021 need_params(dp, type)
1022 	register struct disk	*dp;
1023 	register int		type;
1024 {
1025 	register struct keyw *kp = keyw;
1026 	register int	n = 0;
1027 
1028 	for (; kp < keywNKEYW; kp++) {
1029 		if ((kp->flags & K_N) != 0)
1030 			continue;
1031 		if ((kp->flags & type) == 0)
1032 			continue;
1033 
1034 		if (*lfld(dp, kp->off) != -1)
1035 			continue;
1036 		n++;
1037 /*		if (xdebug == 0)*/
1038 /*			continue;*/
1039 
1040 		printf("name:%-16s off:%3d flags:%02X == -1\n",
1041 				kp->name, kp->off, kp->flags);
1042 	}
1043 	return (n);
1044 }
1045 
1046 EXPORT	int
need_label_params(dp)1047 need_label_params(dp)
1048 	struct disk	*dp;
1049 {
1050 	return (need_params(dp, K_LABEL));
1051 }
1052 
1053 EXPORT	int
need_geom_params(dp)1054 need_geom_params(dp)
1055 	struct disk	*dp;
1056 {
1057 	return (need_params(dp, K_GEOM));
1058 }
1059 
1060 EXPORT	int
need_scsi_params(dp)1061 need_scsi_params(dp)
1062 	struct disk	*dp;
1063 {
1064 	return (need_params(dp, K_SCSI));
1065 }
1066 
1067 /* NOT NEEDED */
1068 EXPORT	int
need_error_rec_params(dp)1069 need_error_rec_params(dp)
1070 	struct disk	*dp;
1071 {
1072 	return (need_params(dp, K_ERREC));
1073 }
1074 
1075 /* NOT NEEDED */
1076 EXPORT	int
need_disre_params(dp)1077 need_disre_params(dp)
1078 	struct disk	*dp;
1079 {
1080 	return (need_params(dp, K_DISRE));
1081 }
1082