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