1 /* @(#)modes.c	1.42 09/07/11 Copyright 1988-2009 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static	UConst char sccsid[] =
5 	"@(#)modes.c	1.42 09/07/11 Copyright 1988-2009 J. Schilling";
6 #endif
7 /*
8  *	Handle SCSI mode pages
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/time.h>
29 #include <schily/ioctl.h>
30 
31 #include <schily/standard.h>
32 #include <schily/schily.h>
33 
34 #include <scg/scgcmd.h>
35 #include <scg/scsireg.h>
36 #include <scg/scsidefs.h>
37 #include <scg/scsitransp.h>
38 
39 #include "scsicmds.h"
40 #include "fmt.h"
41 
42 extern	int	debug;
43 
44 extern	int	force;
45 extern	int	save_mp;
46 extern	int	defmodes;
47 extern	int	scsi_compliant;
48 
49 LOCAL	BOOL	has_mode_page			__PR((SCSI *scgp, int, char *, int *));
50 EXPORT	BOOL	get_mode_params			__PR((SCSI *scgp, int page, char *pagename,
51 							u_char *modep, u_char *cmodep, u_char *dmodep, u_char *smodep,
52 							int *lenp));
53 EXPORT	BOOL	set_mode_params			__PR((SCSI *scgp, char *, u_char *, int, int,
54 							struct disk *));
55 EXPORT	BOOL	set_error_rec_params		__PR((SCSI *scgp, struct disk *));
56 LOCAL	void	get_secsize			__PR((struct disk *, u_char *));
57 LOCAL	void	get_capacity			__PR((struct disk *, u_char *));
58 LOCAL	BOOL	get_format_defaults		__PR((SCSI *scgp, struct disk *));
59 LOCAL	BOOL	get_geom_defaults		__PR((SCSI *scgp, struct disk *));
60 LOCAL	BOOL	get_common_control_defaults	__PR((SCSI *scgp, struct disk *));
61 
62 LOCAL BOOL
has_mode_page(scgp,page,pagename,lenp)63 has_mode_page(scgp, page, pagename, lenp)
64 	SCSI	*scgp;
65 	int	page;
66 	char	*pagename;
67 	int	*lenp;
68 {
69 	u_char	mode[0x100];
70 	int	len = 1;				/* Nach SCSI Norm */
71 	int	try = 0;
72 	struct	scsi_mode_page_header *mp;
73 
74 again:
75 	fillbytes((caddr_t)mode, sizeof (mode), '\0');
76 	if (lenp)
77 		*lenp = 0;
78 
79 	(void) test_unit_ready(scgp);
80 	scgp->silent++;
81 /* Maxoptix bringt Aborted cmd 0x0B mit code 0x4E (overlapping cmds)*/
82 	if (mode_sense(scgp, mode, len, page, 2) < 0) {	/* Page n default */
83 		scgp->silent--;
84 		return (FALSE);
85 	} else {
86 		len = ((struct scsi_mode_header *)mode)->sense_data_len + 1;
87 	}
88 	if (mode_sense(scgp, mode, len, page, 2) < 0) {	/* Page n default */
89 		scgp->silent--;
90 		return (FALSE);
91 	}
92 	scgp->silent--;
93 
94 	if (scgp->verbose)
95 		prbytes("Mode Sense Data", mode, len - scg_getresid(scgp));
96 	mp = (struct scsi_mode_page_header *)
97 		(mode + sizeof (struct scsi_mode_header) +
98 		((struct scsi_mode_header *)mode)->blockdesc_len);
99 	if (scgp->verbose)
100 		prbytes("Mode Sense Data", (u_char *)mp, mp->p_len+2);
101 
102 	if (mp->p_len == 0) {
103 		if (!scsi_compliant && try == 0) {
104 			len = sizeof (struct scsi_mode_header) +
105 			((struct scsi_mode_header *)mode)->blockdesc_len;
106 			/*
107 			 * add sizeof page header (page # + len byte)
108 			 * (should normaly result in len == 14)
109 			 * this allowes to work with:
110 			 * 	Quantum Q210S	(wants at least 13)
111 			 * 	MD2x		(wants at least 4)
112 			 */
113 			len += 2;
114 			try++;
115 			goto again;
116 		}
117 		errmsgno(EX_BAD,
118 			"Warning: controller returns zero sized %s page.\n",
119 								pagename);
120 	}
121 
122 	if (lenp)
123 		*lenp = len;
124 	return (mp->p_len > 0);
125 }
126 
127 EXPORT BOOL
get_mode_params(scgp,page,pagename,modep,cmodep,dmodep,smodep,lenp)128 get_mode_params(scgp, page, pagename, modep, cmodep, dmodep, smodep, lenp)
129 	SCSI	*scgp;
130 	int	page;
131 	char	*pagename;
132 	u_char	*modep;
133 	u_char	*cmodep;
134 	u_char	*dmodep;
135 	u_char	*smodep;
136 	int	*lenp;
137 {
138 	int	len;
139 	BOOL	ret = TRUE;
140 
141 	if (lenp)
142 		*lenp = 0;
143 	if (!has_mode_page(scgp, page, pagename, &len)) {
144 		if (!scgp->silent) errmsgno(EX_BAD,
145 			"Warning: controller does not support %s page.\n",
146 								pagename);
147 		return (TRUE);	/* Hoffentlich klappt's trotzdem */
148 	}
149 	if (lenp)
150 		*lenp = len;
151 
152 	if (modep) {
153 		fillbytes(modep, 0x100, '\0');
154 		if (mode_sense(scgp, modep, len, page, 0) < 0) { /* Page x current */
155 			errmsgno(EX_BAD, "Cannot get %s data.\n", pagename);
156 			ret = FALSE;
157 		} else if (scgp->verbose) {
158 			prbytes("Mode Sense Data", modep, len - scg_getresid(scgp));
159 		}
160 	}
161 
162 	if (cmodep) {
163 		fillbytes(cmodep, 0x100, '\0');
164 		if (mode_sense(scgp, cmodep, len, page, 1) < 0) { /* Page x change */
165 			errmsgno(EX_BAD, "Cannot get %s mask.\n", pagename);
166 			ret = FALSE;
167 		} else if (scgp->verbose) {
168 			prbytes("Mode Sense Data", cmodep, len - scg_getresid(scgp));
169 		}
170 	}
171 
172 	if (dmodep) {
173 		fillbytes(dmodep, 0x100, '\0');
174 		if (mode_sense(scgp, dmodep, len, page, 2) < 0) { /* Page x default */
175 			errmsgno(EX_BAD, "Cannot get default %s data.\n",
176 								pagename);
177 			ret = FALSE;
178 		} else if (scgp->verbose) {
179 			prbytes("Mode Sense Data", dmodep, len - scg_getresid(scgp));
180 		}
181 	}
182 
183 	if (smodep) {
184 		fillbytes(smodep, 0x100, '\0');
185 		if (mode_sense(scgp, smodep, len, page, 3) < 0) { /* Page x saved */
186 			errmsgno(EX_BAD, "Cannot get saved %s data.\n", pagename);
187 			ret = FALSE;
188 		} else if (scgp->verbose) {
189 			prbytes("Mode Sense Data", smodep, len - scg_getresid(scgp));
190 		}
191 	}
192 
193 	return (ret);
194 }
195 
196 EXPORT BOOL
set_mode_params(scgp,pagename,modep,len,save,dp)197 set_mode_params(scgp, pagename, modep, len, save, dp)
198 	SCSI	*scgp;
199 	char	*pagename;
200 	u_char	*modep;
201 	int	len;
202 	int	save;
203 	struct disk	*dp;
204 {
205 	int	i;
206 
207 	((struct scsi_modesel_header *)modep)->sense_data_len	= 0;
208 	((struct scsi_modesel_header *)modep)->res2		= 0;
209 
210 	i = ((struct scsi_mode_header *)modep)->blockdesc_len;
211 	if (i > 0) {
212 		/*
213 		 * Not only set the old "nblock" field to zero but also
214 		 * clear the "density" field that is used for the MSB
215 		 * of the disk size for "bigger disks".
216 		 */
217 		((struct scsi_mode_data *)modep)->blockdesc.density = 0;
218 		i_to_3_byte(
219 			((struct scsi_mode_data *)modep)->blockdesc.nlblock,
220 								0);
221 #ifdef	__DISKTEST__
222 		/*
223 		 * Test data to set a specific disk size.
224 		 */
225 		((struct scsi_mode_data *)modep)->blockdesc.density = 4;
226 		i_to_3_byte(
227 			((struct scsi_mode_data *)modep)->blockdesc.nlblock,
228 								0x3d6720);
229 #endif
230 		i_to_3_byte(((struct scsi_mode_data *)modep)->blockdesc.lblen,
231 							dp->secsize);
232 	}
233 
234 	if (mode_select(scgp, modep, len, save, scgp->inq->ansi_version >= 2) < 0) {
235 		if (mode_select(scgp, modep, len, 0, scgp->inq->ansi_version >= 2) < 0) {
236 			errmsgno(EX_BAD,
237 			    "Warning: using default %s data.\n", pagename);
238 		}
239 	}
240 	return (TRUE);
241 }
242 
243 EXPORT BOOL
set_error_rec_params(scgp,dp)244 set_error_rec_params(scgp, dp)
245 	SCSI		*scgp;
246 	struct disk	*dp;
247 {
248 	u_char	mode[0x100];
249 	u_char	cmode[0x100];
250 	int	len;
251 	BOOL	mp_save;
252 	struct	scsi_mode_page_01 *mp;
253 	struct	scsi_mode_page_01 *cmp;
254 
255 	fillbytes((caddr_t)mode, sizeof (mode), '\0');
256 	fillbytes((caddr_t)cmode, sizeof (cmode), '\0');
257 
258 	if (!get_mode_params(scgp, 1, "error recovery parameter",
259 				(u_char *)0, cmode, mode, (u_char *)0, &len))
260 		return (FALSE);
261 	if (len == 0)
262 		return (TRUE);
263 
264 	cmp = (struct scsi_mode_page_01 *)
265 		(cmode + sizeof (struct scsi_mode_header) +
266 		((struct scsi_mode_header *)cmode)->blockdesc_len);
267 	mp = (struct scsi_mode_page_01 *)
268 		(mode + sizeof (struct scsi_mode_header) +
269 		((struct scsi_mode_header *)mode)->blockdesc_len);
270 	mp_save = save_mp && mp->parsave;
271 	mp->parsave = 0;
272 
273 #ifdef	__nono__
274 	if (cmp->rd_retry_count != 0)	/*XXX*/
275 		mp->tranfer_block = 1;	/*XXX*/
276 #endif
277 
278 	if (dp->rd_retry_count >= 0 && cmp->rd_retry_count != 0)
279 		mp->rd_retry_count = dp->rd_retry_count;
280 
281 	if (dp->wr_retry_count >= 0 && cmp->wr_retry_count != 0)
282 		mp->wr_retry_count = dp->wr_retry_count;
283 
284 	if (dp->recov_timelim >= 0 &&
285 	    a_to_u_2_byte(cmp->recov_timelim) != 0)
286 		i_to_2_byte(mp->recov_timelim, dp->recov_timelim);
287 
288 	return (set_mode_params(scgp, "error recovery parameter", mode, len, mp_save, dp));
289 }
290 
291 EXPORT BOOL
set_disre_params(scgp,dp)292 set_disre_params(scgp, dp)
293 	SCSI		*scgp;
294 	struct disk	*dp;
295 {
296 	u_char	mode[0x100];
297 	u_char	cmode[0x100];
298 	int	len;
299 	BOOL	mp_save;
300 	struct	scsi_mode_page_02 *mp;
301 	struct	scsi_mode_page_02 *cmp;
302 
303 	fillbytes((caddr_t)mode, sizeof (mode), '\0');
304 	fillbytes((caddr_t)cmode, sizeof (cmode), '\0');
305 
306 	if (!get_mode_params(scgp, 2, "disre parameter",
307 				(u_char *)0, cmode, mode, (u_char *)0, &len))
308 		return (FALSE);
309 	if (len == 0)
310 		return (TRUE);
311 
312 	cmp = (struct scsi_mode_page_02 *)
313 		(cmode + sizeof (struct scsi_mode_header) +
314 		((struct scsi_mode_header *)cmode)->blockdesc_len);
315 	mp = (struct scsi_mode_page_02 *)
316 		(mode + sizeof (struct scsi_mode_header) +
317 		((struct scsi_mode_header *)mode)->blockdesc_len);
318 	mp_save = save_mp && mp->parsave;
319 	mp->parsave = 0;
320 
321 	if (dp->buf_full_ratio >= 0 && cmp->buf_full_ratio != 0)
322 		mp->buf_full_ratio = dp->buf_full_ratio;
323 
324 	if (dp->buf_empt_ratio >= 0 && cmp->buf_empt_ratio != 0)
325 		mp->buf_empt_ratio = dp->buf_empt_ratio;
326 
327 	if (dp->bus_inact_limit >= 0 &&
328 	    a_to_u_2_byte(cmp->bus_inact_limit) != 0)
329 		i_to_2_byte(mp->bus_inact_limit, dp->bus_inact_limit);
330 
331 	if (dp->disc_time_limit >= 0 &&
332 	    a_to_u_2_byte(cmp->disc_time_limit) != 0)
333 		i_to_2_byte(mp->disc_time_limit, dp->disc_time_limit);
334 
335 	if (dp->conn_time_limit >= 0 &&
336 	    a_to_u_2_byte(cmp->conn_time_limit) != 0)
337 		i_to_2_byte(mp->conn_time_limit, dp->conn_time_limit);
338 
339 	if (dp->max_burst_size >= 0 &&
340 	    a_to_u_2_byte(cmp->max_burst_size) != 0)
341 		i_to_2_byte(mp->max_burst_size, dp->max_burst_size);
342 
343 	if (dp->data_tr_dis_ctl >= 0 && cmp->data_tr_dis_ctl != 0)
344 		mp->data_tr_dis_ctl = dp->data_tr_dis_ctl;
345 
346 #ifdef	OLD
347 /*XXX*/						/* 4.0 ms max Connect time */
348 	if (a_to_u_2_byte(cmp->bus_inact_limit) != 0)
349 		i_to_2_byte(mp->bus_inact_limit, 40);
350 #endif
351 
352 	return (set_mode_params(scgp, "disre parameter", mode, len, mp_save, dp));
353 }
354 
355 EXPORT BOOL
set_format_params(scgp,dp)356 set_format_params(scgp, dp)
357 	SCSI		*scgp;
358 	struct disk	*dp;
359 {
360 	u_char	mode[0x100];
361 	u_char	cmode[0x100];
362 	int	len;
363 	int	i;
364 	BOOL	mp_save;
365 	struct	scsi_mode_page_03 *mp;
366 	struct	scsi_mode_page_03 *cmp;
367 
368 	fillbytes((caddr_t)mode, sizeof (mode), '\0');
369 	fillbytes((caddr_t)cmode, sizeof (cmode), '\0');
370 
371 	if (!get_mode_params(scgp, 3, "format parameter",
372 				(u_char *)0, cmode, mode, (u_char *)0, &len))
373 		return (FALSE);
374 	if (len == 0)
375 		return (TRUE);
376 
377 	i = ((struct scsi_mode_header *)mode)->blockdesc_len;
378 	if (i == 0)
379 		errmsgno(EX_BAD,
380 		"Warning: No Blockdesriptor, can't set logical Blocksize.\n");
381 	if (i > 8)
382 		errmsgno(EX_BAD, "More than one Blockdesriptor ???\n");
383 
384 	cmp = (struct scsi_mode_page_03 *)
385 		(cmode + sizeof (struct scsi_mode_header) +
386 		((struct scsi_mode_header *)cmode)->blockdesc_len);
387 	mp = (struct scsi_mode_page_03 *)
388 		(mode + sizeof (struct scsi_mode_header) +
389 		((struct scsi_mode_header *)mode)->blockdesc_len);
390 	mp_save = save_mp && mp->parsave;
391 	mp->parsave = 0;
392 
393 	if (a_to_u_2_byte(cmp->trk_per_zone) != 0)
394 		i_to_2_byte(mp->trk_per_zone, dp->tpz);
395 
396 	if (a_to_u_2_byte(cmp->alt_sec_per_zone) != 0)
397 		i_to_2_byte(mp->alt_sec_per_zone, dp->aspz);
398 
399 	if (a_to_u_2_byte(cmp->alt_trk_per_vol) != 0)
400 		i_to_2_byte(mp->alt_trk_per_vol, dp->atrk);
401 
402 	if (a_to_u_2_byte(cmp->sect_per_trk) != 0)
403 		i_to_2_byte(mp->sect_per_trk, dp->spt);
404 
405 	if (a_to_u_2_byte(cmp->bytes_per_phys_sect) != 0 &&
406 						dp->phys_secsize > 0)
407 		i_to_2_byte(mp->bytes_per_phys_sect, dp->phys_secsize);
408 
409 	if (a_to_u_2_byte(cmp->trk_skew) != 0)
410 		i_to_2_byte(mp->trk_skew, dp->track_skew);
411 
412 	if (a_to_u_2_byte(cmp->cyl_skew) != 0)
413 		i_to_2_byte(mp->cyl_skew, dp->cyl_skew);
414 
415 #ifdef	OLD
416 	/*
417 	 * Der MD21 hat leider die Felde Sectors per Track und
418 	 * Physical Sectorsize auf Null gesetzt,
419 	 * wenn ein Hardsektoriertes Laufwerk angeschloszen ist.
420 	 * XXX Ist die Methode mode und cmode zu verunden ueberhaupt
421 	 * richtig ???
422 	 */
423 	mp = (struct scsi_mode_page_03 *)
424 		(cmode + sizeof (struct scsi_mode_header) +
425 		((struct scsi_mode_header *)cmode)->blockdesc_len);
426 	if (a_to_u_2_byte(mp->sect_per_trk) == 0)
427 		i_to_2_byte(mp->sect_per_trk, dp->spt);
428 	if (a_to_u_2_byte(mp->bytes_per_phys_sect) == 0)
429 		i_to_2_byte(mp->bytes_per_phys_sect, dp->secsize);
430 #endif
431 
432 	return (set_mode_params(scgp, "format parameter", mode, len, mp_save, dp));
433 }
434 
435 EXPORT BOOL
set_geom(scgp,dp)436 set_geom(scgp, dp)
437 	SCSI		*scgp;
438 	struct disk	*dp;
439 {
440 	u_char	mode[0x100];
441 	u_char	cmode[0x100];
442 	int	len;
443 	BOOL	mp_save;
444 	struct	scsi_mode_page_04 *mp;
445 	struct	scsi_mode_page_04 *cmp;
446 
447 	fillbytes((caddr_t)mode, sizeof (mode), '\0');
448 	fillbytes((caddr_t)cmode, sizeof (cmode), '\0');
449 
450 	if (!get_mode_params(scgp, 4, "geometry",
451 				(u_char *)0, cmode, mode, (u_char *)0, &len))
452 		return (FALSE);
453 	if (len == 0)
454 		return (TRUE);
455 
456 	cmp = (struct scsi_mode_page_04 *)
457 		(cmode + sizeof (struct scsi_mode_header) +
458 		((struct scsi_mode_header *)cmode)->blockdesc_len);
459 	mp = (struct scsi_mode_page_04 *)
460 		(mode + sizeof (struct scsi_mode_header) +
461 		((struct scsi_mode_header *)mode)->blockdesc_len);
462 	mp_save = save_mp && mp->parsave;
463 	mp->parsave = 0;
464 
465 	if (a_to_u_3_byte(cmp->ncyl) != 0)
466 		i_to_3_byte(mp->ncyl, dp->pcyl);
467 
468 	if (cmp->nhead != 0)
469 		mp->nhead = dp->nhead;
470 
471 	if (cmp->rot_pos_locking != 0)
472 		mp->rot_pos_locking = dp->rot_pos_locking;
473 
474 	if (cmp->rotational_off != 0)
475 		mp->rotational_off = dp->rotational_off;
476 
477 	return (set_mode_params(scgp, "geometry", mode, len, mp_save, dp));
478 }
479 
480 EXPORT BOOL
set_common_control(scgp,dp)481 set_common_control(scgp, dp)
482 	SCSI		*scgp;
483 	struct disk	*dp;
484 {
485 	u_char	mode[0x100];
486 	u_char	cmode[0x100];
487 	int	len;
488 	BOOL	mp_save;
489 	struct	scsi_mode_page_0A *mp;
490 	struct	scsi_mode_page_0A *cmp;
491 
492 	fillbytes((caddr_t)mode, sizeof (mode), '\0');
493 	fillbytes((caddr_t)cmode, sizeof (cmode), '\0');
494 
495 	if (!get_mode_params(scgp, 0xA, "common device control",
496 				(u_char *)0, cmode, mode, (u_char *)0, &len))
497 		return (FALSE);
498 	if (len == 0)
499 		return (TRUE);
500 
501 	cmp = (struct scsi_mode_page_0A *)
502 		(cmode + sizeof (struct scsi_mode_header) +
503 		((struct scsi_mode_header *)cmode)->blockdesc_len);
504 	mp = (struct scsi_mode_page_0A *)
505 		(mode + sizeof (struct scsi_mode_header) +
506 		((struct scsi_mode_header *)mode)->blockdesc_len);
507 	mp_save = save_mp && mp->parsave;
508 	mp->parsave = 0;
509 
510 	if (cmp->queue_alg_mod != 0)
511 		mp->queue_alg_mod = dp->queue_alg_mod;
512 
513 	if (cmp->dis_queuing != 0)
514 		mp->dis_queuing = dp->dis_queuing;
515 
516 	return (TRUE);
517 }
518 
519 
520 EXPORT void
get_mode_defaults(scgp,dp)521 get_mode_defaults(scgp, dp)
522 	SCSI		*scgp;
523 	struct disk	*dp;
524 {
525 	get_error_rec_defaults(scgp, dp);
526 	get_disre_defaults(scgp, dp);
527 	get_geom_defaults(scgp, dp); /* nhead wird in set_format_defaults gebraucht */
528 	get_format_defaults(scgp, dp);
529 	if (dp->secsize < 0) {
530 		if (read_capacity(scgp) < 0)
531 			return;
532 		if (scgp->cap->c_bsize > 0)
533 			dp->secsize = scgp->cap->c_bsize;
534 	}
535 	scgp->silent++;
536 	get_common_control_defaults(scgp, dp);
537 	scgp->silent--;
538 }
539 
540 LOCAL void
get_secsize(dp,modep)541 get_secsize(dp, modep)
542 	struct disk	*dp;
543 	u_char	*modep;
544 {
545 	long	tmp;
546 
547 	if (dp->secsize < 0 &&
548 			((struct scsi_mode_header *)modep)->blockdesc_len) {
549 		tmp = a_to_u_3_byte(((struct scsi_mode_data *)modep)->
550 							blockdesc.lblen);
551 		if (tmp != 0)
552 			dp->secsize = tmp;
553 	}
554 }
555 
556 LOCAL void
get_capacity(dp,modep)557 get_capacity(dp, modep)
558 	struct disk	*dp;
559 	u_char	*modep;
560 {
561 	long	tmp;
562 
563 	if (dp->capacity < 0 &&
564 			((struct scsi_mode_header *)modep)->blockdesc_len) {
565 		tmp = a_to_u_3_byte(((struct scsi_mode_data *)modep)->
566 							blockdesc.nlblock);
567 		if (tmp != 0)
568 			dp->capacity = tmp;
569 	}
570 }
571 
572 EXPORT BOOL
get_error_rec_defaults(scgp,dp)573 get_error_rec_defaults(scgp, dp)
574 	SCSI		*scgp;
575 	struct disk	*dp;
576 {
577 	u_char	mode[0x100];
578 	u_char	cmode[0x100];
579 	int	len;
580 	long	tmp;
581 	long	ctmp;
582 	struct	scsi_mode_page_01 *mp;
583 	struct	scsi_mode_page_01 *cmp;
584 
585 	fillbytes((caddr_t)mode, sizeof (mode), '\0');
586 	fillbytes((caddr_t)cmode, sizeof (cmode), '\0');
587 
588 	if (defmodes == 0 && dp->formatted > 0 &&
589 		get_mode_params(scgp, 1, "error recovery parameter",
590 				mode, cmode, (u_char *)0, (u_char *)0, &len))
591 		;
592 	else if (!get_mode_params(scgp, 1, "error recovery parameter",
593 				(u_char *)0, cmode, mode, (u_char *)0, &len))
594 		return (FALSE);
595 	if (len == 0)
596 		return (TRUE);
597 
598 	cmp = (struct scsi_mode_page_01 *)
599 		(cmode + sizeof (struct scsi_mode_header) +
600 		((struct scsi_mode_header *)cmode)->blockdesc_len);
601 	mp = (struct scsi_mode_page_01 *)
602 		(mode + sizeof (struct scsi_mode_header) +
603 		((struct scsi_mode_header *)mode)->blockdesc_len);
604 
605 	get_secsize(dp, mode);
606 	get_capacity(dp, mode);
607 
608 	if (dp->rd_retry_count < 0 && cmp->rd_retry_count != 0)
609 		dp->rd_retry_count = mp->rd_retry_count;
610 
611 	if (dp->wr_retry_count < 0 && cmp->wr_retry_count != 0)
612 		dp->wr_retry_count = mp->wr_retry_count;
613 
614 	tmp  = a_to_u_2_byte(mp->recov_timelim);
615 	ctmp = a_to_u_2_byte(cmp->recov_timelim);
616 	if (dp->recov_timelim < 0 && ctmp != 0)
617 		dp->recov_timelim = tmp;
618 
619 	return (TRUE);
620 }
621 
622 EXPORT BOOL
get_disre_defaults(scgp,dp)623 get_disre_defaults(scgp, dp)
624 	SCSI		*scgp;
625 	struct disk	*dp;
626 {
627 	u_char	mode[0x100];
628 	u_char	cmode[0x100];
629 	int	len;
630 	long	tmp;
631 	long	ctmp;
632 	struct	scsi_mode_page_02 *mp;
633 	struct	scsi_mode_page_02 *cmp;
634 
635 	fillbytes((caddr_t)mode, sizeof (mode), '\0');
636 	fillbytes((caddr_t)cmode, sizeof (cmode), '\0');
637 
638 	if (defmodes == 0 && dp->formatted > 0 &&
639 		get_mode_params(scgp, 2, "disre parameter",
640 				mode, cmode, (u_char *)0, (u_char *)0, &len))
641 		;
642 	else if (!get_mode_params(scgp, 2, "disre parameter",
643 				(u_char *)0, cmode, mode, (u_char *)0, &len))
644 		return (FALSE);
645 	if (len == 0)
646 		return (TRUE);
647 
648 	cmp = (struct scsi_mode_page_02 *)
649 		(cmode + sizeof (struct scsi_mode_header) +
650 		((struct scsi_mode_header *)cmode)->blockdesc_len);
651 	mp = (struct scsi_mode_page_02 *)
652 		(mode + sizeof (struct scsi_mode_header) +
653 		((struct scsi_mode_header *)mode)->blockdesc_len);
654 
655 	get_secsize(dp, mode);
656 	get_capacity(dp, mode);
657 
658 	if (dp->buf_full_ratio < 0 && cmp->buf_full_ratio != 0)
659 		dp->buf_full_ratio = mp->buf_full_ratio;
660 
661 	if (dp->buf_empt_ratio < 0 && cmp->buf_empt_ratio != 0)
662 		dp->buf_empt_ratio = mp->buf_empt_ratio;
663 
664 	tmp  = a_to_u_2_byte(mp->bus_inact_limit);
665 	ctmp = a_to_u_2_byte(cmp->bus_inact_limit);
666 	if (dp->bus_inact_limit < 0 && ctmp != 0)
667 		dp->bus_inact_limit = tmp;
668 
669 	tmp  = a_to_u_2_byte(mp->disc_time_limit);
670 	ctmp = a_to_u_2_byte(cmp->disc_time_limit);
671 	if (dp->disc_time_limit < 0 && ctmp != 0)
672 		dp->disc_time_limit = tmp;
673 
674 	tmp  = a_to_u_2_byte(mp->conn_time_limit);
675 	ctmp = a_to_u_2_byte(cmp->conn_time_limit);
676 	if (dp->conn_time_limit < 0 && ctmp != 0)
677 		dp->conn_time_limit = tmp;
678 
679 	tmp  = a_to_u_2_byte(mp->max_burst_size);
680 	ctmp = a_to_u_2_byte(cmp->max_burst_size);
681 	if (dp->max_burst_size < 0 && ctmp != 0)
682 		dp->max_burst_size = tmp;
683 
684 	if (dp->data_tr_dis_ctl < 0 && cmp->data_tr_dis_ctl != 0)
685 		dp->data_tr_dis_ctl = mp->data_tr_dis_ctl;
686 
687 	return (TRUE);
688 }
689 
690 LOCAL BOOL
get_format_defaults(scgp,dp)691 get_format_defaults(scgp, dp)
692 	SCSI		*scgp;
693 	struct disk	*dp;
694 {
695 	u_char	mode[0x100];
696 	u_char	cmode[0x100];
697 	int	len;
698 	long	tmp;
699 	struct	scsi_mode_page_03 *mp;
700 	struct	scsi_mode_page_03 *cmp;
701 
702 	fillbytes((caddr_t)mode, sizeof (mode), '\0');
703 	fillbytes((caddr_t)cmode, sizeof (cmode), '\0');
704 
705 	if (defmodes == 0 && dp->formatted > 0 &&
706 		get_mode_params(scgp, 3, "format parameter",
707 				mode, cmode, (u_char *)0, (u_char *)0, &len))
708 		;
709 	else if (!get_mode_params(scgp, 3, "format parameter",
710 				(u_char *)0, cmode, mode, (u_char *)0, &len))
711 		return (FALSE);
712 	if (len == 0)
713 		return (TRUE);
714 
715 	cmp = (struct scsi_mode_page_03 *)
716 		(cmode + sizeof (struct scsi_mode_header) +
717 		((struct scsi_mode_header *)cmode)->blockdesc_len);
718 	mp = (struct scsi_mode_page_03 *)
719 		(mode + sizeof (struct scsi_mode_header) +
720 		((struct scsi_mode_header *)mode)->blockdesc_len);
721 
722 	get_secsize(dp, mode);
723 	get_capacity(dp, mode);
724 
725 	tmp = a_to_u_2_byte(mp->trk_per_zone);
726 	if (dp->tpz < 0)
727 		dp->tpz = tmp;
728 	tmp = a_to_u_2_byte(cmp->trk_per_zone);
729 	if (dp->tpz < 0 || tmp != 0) {
730 		dp->mintpz = 0;
731 		dp->maxtpz = 0xFFFF;
732 	} else {
733 		dp->mintpz = dp->maxtpz = dp->tpz;
734 	}
735 
736 	tmp = a_to_u_2_byte(mp->alt_sec_per_zone);
737 	if (dp->aspz < 0)
738 		dp->aspz = tmp;
739 
740 	tmp = a_to_u_2_byte(mp->alt_trk_per_vol);
741 	if (dp->atrk < 0)
742 		dp->atrk = tmp;
743 
744 	tmp = a_to_u_2_byte(mp->sect_per_trk);
745 	if (dp->spt < 0 && tmp != 0)
746 		dp->spt = tmp;
747 
748 	tmp = a_to_u_2_byte(mp->bytes_per_phys_sect);
749 	if (dp->phys_secsize < 0 && tmp != 0) {
750 		long ctmp = a_to_u_2_byte(cmp->bytes_per_phys_sect);
751 
752 		if (ctmp != 0)
753 			dp->phys_secsize = tmp;
754 
755 		if (debug) printf("phys_secsize: %ld change: %ld (0x%lX)\n",
756 							tmp, ctmp, ctmp);
757 	}
758 
759 	tmp = a_to_u_2_byte(mp->interleave);
760 	if (dp->interleave < 0)
761 		dp->interleave = tmp;
762 
763 	tmp = a_to_u_2_byte(mp->trk_skew);
764 	if (dp->track_skew < 0)
765 		dp->track_skew = tmp;
766 
767 	tmp = a_to_u_2_byte(mp->cyl_skew);
768 	if (dp->cyl_skew < 0)
769 		dp->cyl_skew = tmp;
770 
771 	return (TRUE);
772 }
773 
774 LOCAL BOOL
get_geom_defaults(scgp,dp)775 get_geom_defaults(scgp, dp)
776 	SCSI		*scgp;
777 	struct disk	*dp;
778 {
779 	u_char	mode[0x100];
780 	int	len;
781 	long	tmp;
782 	struct	scsi_mode_page_04 *mp;
783 
784 	fillbytes((caddr_t)mode, sizeof (mode), '\0');
785 
786 	if (defmodes == 0 && dp->formatted > 0 &&
787 		get_mode_params(scgp, 4, "geometry",
788 			mode, (u_char *)0, (u_char *)0, (u_char *)0, &len))
789 		;
790 	else if (!get_mode_params(scgp, 4, "geometry",
791 			(u_char *)0, (u_char *)0, mode, (u_char *)0, &len))
792 		return (FALSE);
793 	if (len == 0)
794 		return (TRUE);
795 
796 	mp = (struct scsi_mode_page_04 *)
797 		(mode + sizeof (struct scsi_mode_header) +
798 		((struct scsi_mode_header *)mode)->blockdesc_len);
799 
800 	get_secsize(dp, mode);
801 	get_capacity(dp, mode);
802 
803 	tmp = a_to_u_3_byte(mp->ncyl);
804 	if (dp->pcyl < 0 && tmp != 0)
805 		dp->pcyl = tmp;
806 
807 	if (dp->nhead < 0 && mp->nhead != 0)
808 		dp->nhead = mp->nhead;
809 
810 	tmp = a_to_u_2_byte(mp->rotation_rate);
811 	if (dp->rpm < 0 && tmp != 0)
812 		dp->rpm = tmp;
813 
814 	tmp = mp->rot_pos_locking;
815 	if (dp->rot_pos_locking < 0)
816 		dp->rot_pos_locking = tmp;
817 
818 	tmp = mp->rotational_off;
819 	if (dp->rotational_off < 0)
820 		dp->rotational_off = tmp;
821 
822 	return (TRUE);
823 }
824 
825 LOCAL BOOL
get_common_control_defaults(scgp,dp)826 get_common_control_defaults(scgp, dp)
827 	SCSI		*scgp;
828 	struct disk	*dp;
829 {
830 	u_char	mode[0x100];
831 	int	len;
832 	struct	scsi_mode_page_0A *mp;
833 
834 	fillbytes((caddr_t)mode, sizeof (mode), '\0');
835 
836 	if (defmodes == 0 && dp->formatted > 0 &&
837 		get_mode_params(scgp, 0xA, "common device control",
838 			mode, (u_char *)0, (u_char *)0, (u_char *)0, &len))
839 		;
840 	else if (!get_mode_params(scgp, 0xA, "common device control",
841 			(u_char *)0, (u_char *)0, mode, (u_char *)0, &len))
842 		return (FALSE);
843 	if (len == 0)
844 		return (TRUE);
845 
846 	mp = (struct scsi_mode_page_0A *)
847 		(mode + sizeof (struct scsi_mode_header) +
848 		((struct scsi_mode_header *)mode)->blockdesc_len);
849 
850 	dp->queue_alg_mod = mp->queue_alg_mod;
851 	dp->dis_queuing = mp->dis_queuing;
852 
853 	return (TRUE);
854 }
855 
856 
857 EXPORT BOOL
get_sony_format_defaults(scgp,dp)858 get_sony_format_defaults(scgp, dp)
859 	SCSI		*scgp;
860 	struct disk	*dp;
861 {
862 	u_char	mode[0x100];
863 	int	len;
864 	long	tmp;
865 	struct	sony_mode_page_20 *mp;
866 
867 	fillbytes((caddr_t)mode, sizeof (mode), '\0');
868 
869 	if (defmodes == 0 && dp->formatted > 0 &&
870 		get_mode_params(scgp, 0x20, "sony format",
871 			mode, (u_char *)0, (u_char *)0, (u_char *)0, &len))
872 		;
873 	else if (!get_mode_params(scgp, 0x20, "sony format",
874 			(u_char *)0, (u_char *)0, mode, (u_char *)0, &len))
875 		return (FALSE);
876 	if (len == 0)
877 		return (TRUE);
878 
879 	mp = (struct sony_mode_page_20 *)
880 		(mode + sizeof (struct scsi_mode_header) +
881 		((struct scsi_mode_header *)mode)->blockdesc_len);
882 
883 	get_secsize(dp, mode);
884 	get_capacity(dp, mode);
885 
886 	if (dp->fmt_mode < 0)
887 		dp->fmt_mode = mp->format_mode;
888 
889 	tmp = a_to_u_2_byte(mp->spare_band_size);
890 	if (dp->fmt_mode > 1 && dp->spare_band_size < 0)
891 		dp->spare_band_size = tmp;
892 
893 printf("mode: %d spare_band: %ld\n", mp->format_mode, tmp);
894 
895 	return (TRUE);
896 }
897 
898 EXPORT BOOL
set_sony_params(scgp,dp)899 set_sony_params(scgp, dp)
900 	SCSI		*scgp;
901 	struct disk	*dp;
902 {
903 	u_char	mode[0x100];
904 	u_char	cmode[0x100];
905 	int	len;
906 	BOOL	mp_save;
907 	struct	sony_mode_page_20 *mp;
908 #ifdef	notneeded
909 	struct	sony_mode_page_20 *cmp;
910 #endif
911 
912 	if (force && yes("Abort? "))
913 		return (FALSE);
914 	fillbytes((caddr_t)mode, sizeof (mode), '\0');
915 	fillbytes((caddr_t)cmode, sizeof (cmode), '\0');
916 
917 	if (!get_mode_params(scgp, 0x20, "sony format",
918 				(u_char *)0, cmode, mode, (u_char *)0, &len))
919 		return (FALSE);
920 	if (len == 0)
921 		return (TRUE);
922 
923 #ifdef	notneeded
924 	cmp = (struct sony_mode_page_20 *)
925 		(cmode + sizeof (struct scsi_mode_header) +
926 		((struct scsi_mode_header *)cmode)->blockdesc_len);
927 #endif
928 	mp = (struct sony_mode_page_20 *)
929 		(mode + sizeof (struct scsi_mode_header) +
930 		((struct scsi_mode_header *)mode)->blockdesc_len);
931 	mp_save = save_mp && mp->parsave;
932 	mp->parsave = 0;
933 
934 	mp->format_mode = dp->fmt_mode;
935 
936 	if (mp->format_mode <= 1) {
937 		fillbytes((char *)&mp->format_type,
938 			sizeof (*mp) - ((char *)&mp->format_type-(char *)mp),
939 									'\0');
940 	} else {
941 		mp->format_type = 1;
942 		i_to_4_byte(mp->num_bands, 1);
943 #ifdef	OLD
944 		{ int t;				/*XXX aspt ??? */
945 			t = dp->spt;
946 			if (dp->tpz != 0)
947 				t -= dp->aspz/dp->tpz;
948 			t *= dp->atrk;
949 			i_to_2_byte(mp->spare_band_size, t);
950 		}
951 #else
952 		i_to_2_byte(mp->spare_band_size, dp->spare_band_size);
953 #endif
954 	}
955 
956 	return (set_mode_params(scgp, "sony format", mode, len, mp_save, dp));
957 }
958