1 /* @(#)xmodes.c 1.26 09/10/16 Copyright 1991-2009 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static UConst char sccsid[] =
5 "@(#)xmodes.c 1.26 09/10/16 Copyright 1991-2009 J. Schilling";
6 #endif
7 /*
8 * Routines to handle external mode data (database)
9 *
10 * Copyright (c) 1991-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/standard.h>
28 #include <schily/utypes.h>
29 #include <schily/schily.h>
30 #include "fmt.h"
31
32 #include <schily/intcvt.h>
33
34 #include <scg/scsidefs.h>
35 #include <scg/scsireg.h>
36
37 EXPORT void ext_modeselect __PR((SCSI *scgp, struct disk *));
38 LOCAL int do_page __PR((SCSI *Scgp, struct disk *));
39 LOCAL BOOL set_page __PR((SCSI *scgp, struct disk *, int, int, BOOL));
40 LOCAL int set_vars __PR((u_char *, u_char *, int));
41 LOCAL int do_var __PR((u_char *, u_char *, int));
42 LOCAL int set_bits __PR((u_char *, u_char *, int, BOOL, long, int, int));
43 LOCAL int set_byte __PR((u_char *, u_char *, int, BOOL, long));
44 LOCAL int set_short __PR((u_char *, u_char *, int, BOOL, long));
45 LOCAL int set_3byte __PR((u_char *, u_char *, int, BOOL, long));
46 LOCAL int set_long __PR((u_char *, u_char *, int, BOOL, long));
47 LOCAL void xprint __PR((char *, long));
48 LOCAL void modewarning __PR((void));
49 #ifdef NONO
50 LOCAL int xset_bits __PR((u_char *, u_char *, int, long, int, int));
51 #endif
52
53 #ifdef FMT
54 extern int xdebug;
55 extern int save_mp;
56 #else
57 int xdebug = 1;
58 #endif
59
60 LOCAL BOOL modewarn = 1; /*XXX*/
61
62 #ifndef FMT
63 struct disk ds;
64
main(ac,av)65 main(ac, av)
66 int ac;
67 char **av;
68 {
69 char *name;
70
71 if (ac > 1)
72 name = av[1];
73 else
74 name = "hallo";
75
76 if (!opendatfile("mode_pages"))
77 return;
78
79 ds.mode_pages = name;
80 ext_modeselect(&ds);
81
82 closedatfile();
83 }
84 #endif
85
86
87 /*---------------------------------------------------------------------------
88 |
89 | Setzt beliebige Mode Seiten durch
90 | externe Steuerung ueber eine Datei.
91 |
92 +---------------------------------------------------------------------------*/
93
94 EXPORT void
ext_modeselect(scgp,dp)95 ext_modeselect(scgp, dp)
96 SCSI *scgp;
97 struct disk *dp;
98 {
99 if (!dp->mode_pages)
100 return;
101 if (xdebug)
102 printf("set_modes: mode_pages: '%s'\n", dp->mode_pages);
103
104 if (rewinddatfile() < 0)
105 return;
106 if (xdebug)
107 printf("ext_modeselect: data file OK\n");
108 if (scanfortable("mode_pages", dp->mode_pages) && nextline())
109 while (do_page(scgp, dp) == 1)
110 ;
111 }
112
113
114 /*---------------------------------------------------------------------------
115 |
116 | Parst einen Page Header Eintrag in der Steuerungsdatei
117 |
118 +---------------------------------------------------------------------------*/
119
120 LOCAL int
do_page(scgp,dp)121 do_page(scgp, dp)
122 SCSI *scgp;
123 struct disk *dp;
124 {
125 int type = 2; /* Default Werte */
126 int mpsave = 1; /* Modeparameter Sichern */
127 int page;
128 char *word;
129
130 if (xdebug) printf("do_page: line: %d curword: '%s'\n",
131 getlineno(), curword());
132
133 if ((word = scanforline("Page", NULL)) == NULL)
134 return (0);
135
136 if (word == NULL) /* EOF XXXX????? */
137 return (EOF);
138
139 word = nextitem();
140 if (*astoi(word, &page) != '\0') {
141 datfileerr("Bad page number '%s'", word);
142 return (0);
143 }
144
145 word = nextitem();
146 if (*word) {
147 if (streql(word, "current"))
148 type = 0;
149 else if (streql(word, "changeable"))
150 type = 1;
151 else if (streql(word, "default"))
152 type = 2;
153 else if (streql(word, "saved"))
154 type = 3;
155 else {
156 datfileerr("Bad page type '%s'", word);
157 return (0);
158 }
159 }
160
161 word = nextitem();
162 if (*word) {
163 if (streql(word, "noset"))
164 mpsave = -1;
165 else if (streql(word, "nosave"))
166 mpsave = 0;
167 else if (streql(word, "save"))
168 mpsave = 1;
169 else {
170 datfileerr("Bad save type '%s'", word);
171 return (0);
172 }
173 }
174
175 word = nextitem();
176 (void) garbage(word);
177
178 if (!nextline()) {
179 datfileerr("Premature EOF");
180 return (EOF);
181 }
182
183 set_page(scgp, dp, page, type, mpsave);
184 return (1);
185 }
186
187
188 /*---------------------------------------------------------------------------
189 |
190 | Setzt eine Mode Seite
191 |
192 +---------------------------------------------------------------------------*/
193
194 LOCAL BOOL
set_page(scgp,dp,page,type,mpsave)195 set_page(scgp, dp, page, type, mpsave)
196 SCSI *scgp;
197 struct disk *dp;
198 int page;
199 int type;
200 BOOL mpsave;
201 {
202 char name[16];
203 u_char mode[0x100];
204 u_char cmode[0x100];
205 u_char dmode[0x100];
206 int len;
207 struct scsi_mode_page_header *mp;
208 struct scsi_mode_page_header *cmp;
209 struct scsi_mode_page_header *smp;
210
211 fillbytes(mode, sizeof (mode), '\0');
212 fillbytes(cmode, sizeof (cmode), '\0');
213 fillbytes(dmode, sizeof (dmode), '\0');
214
215 sprintf(name, "Mode Page 0x%02X", page);
216 if (xdebug)
217 printf("%s (type %d)\n", name, type);
218 #ifdef FMT
219 if (!get_mode_params(scgp, page, name,
220 mode, cmode, dmode, (u_char *)0, &len))
221 return (FALSE);
222 if (len == 0)
223 return (TRUE);
224 #else
225 len = 32;
226 mode[0] = 32; /* L�nge */
227 dmode[0] = 32; /* L�nge */
228 mode[3] = 8; /* Blockdes L�nge */
229 dmode[3] = 8; /* Blockdes L�nge */
230 mode[10] = 2; /* Sectorsize */
231 dmode[10] = 2; /* Sectorsize */
232 mode[12] = 20; /* Pagel�nge */
233 dmode[12] = 20; /* Pagel�nge */
234 #endif
235
236 cmp = (struct scsi_mode_page_header *)
237 (cmode + sizeof (struct scsi_mode_header) +
238 ((struct scsi_mode_header *)cmode)->blockdesc_len);
239
240 switch (type) {
241
242 case 0: smp = (struct scsi_mode_page_header *)mode; break;
243 case 1: smp = (struct scsi_mode_page_header *)cmode; break;
244 case 2: smp = (struct scsi_mode_page_header *)dmode; break;
245 case 3:
246 default:
247 datfileerr("WARNING:\tSaved values currently not supported -\n\
248 using default values");
249 smp = (struct scsi_mode_page_header *)dmode; break;
250 }
251 mp = (struct scsi_mode_page_header *)
252 ((u_char *)smp + sizeof (struct scsi_mode_header) +
253 ((struct scsi_mode_header *)smp)->blockdesc_len);
254
255 set_vars((u_char *)mp, (u_char *)cmp,
256 len-((u_char *)mp-(u_char *)smp));
257 mp->parsave = 0;
258
259 if (xdebug) {
260 prbytes("Mode Sense Data", (u_char *)smp, len);
261 printf("mp: %lx mode: %lX mode-mp: %lld\n", (long)mp, (long)smp,
262 (Llong)((u_char *)mp-(u_char *)smp));
263 printf("mpsave: %d\n", mpsave);
264 }
265
266 if (mpsave < 0)
267 return (TRUE);
268
269 #ifdef FMT
270 return (set_mode_params(scgp, name, (u_char *) smp, len,
271 (save_mp && mpsave > 0), dp));
272 #else
273 return (0);
274 #endif
275 }
276
277
278 /*---------------------------------------------------------------------------
279 |
280 | Setzt die Page Variablen nach den
281 | Eintraegen in der Steuerungsdatei.
282 |
283 +---------------------------------------------------------------------------*/
284
285 LOCAL int
set_vars(mode,cmode,len)286 set_vars(mode, cmode, len)
287 u_char *mode;
288 u_char *cmode;
289 int len;
290 {
291 char *word;
292
293 for (;;) {
294 if ((word = scanforline("Byte", "Page")) == NULL)
295 return (0);
296 if (streql(word, "Page"))
297 return (1);
298
299 if (word == NULL) /* EOF XXX????? */
300 return (EOF);
301
302 do_var(mode, cmode, len);
303
304 if (!nextline())
305 return (EOF);
306 }
307 }
308
309
310 /*---------------------------------------------------------------------------
311 |
312 | Parst einen Page Variablen Eintrag in der Steuerungsdatei
313 |
314 +---------------------------------------------------------------------------*/
315
316 #define O_SET 1
317 #define O_AND 2
318 #define O_OR 3
319 #define O_PRINT 4
320
321 LOCAL int
do_var(mode,cmode,len)322 do_var(mode, cmode, len)
323 u_char *mode;
324 u_char *cmode;
325 int len;
326 {
327 char *word;
328 int idx;
329 int size;
330 int op;
331 BOOL donot = FALSE;
332 long val;
333 int bitno;
334 int nbits;
335 char prarg[80];
336
337 word = nextitem();
338
339 if (*astoi(word, &idx) != '\0' || idx < 0 || idx >= len) {
340 datfileerr("Bad byte offset '%s'", word);
341 return (0);
342 }
343 /*XXX*/
344 /*printf("offset: %d len: %d\n", idx, len);*/
345
346 word = nextitem();
347 if (streql(word, "bit")) {
348 size = 0;
349 word = nextitem();
350 word = astoi(word, &bitno);
351 if (*word) {
352 if (word[0] == '.' && word[1] == '.') {
353 if (*astoi(&word[2], &nbits) != '\0') {
354 datfileerr("Bad end bit '%s'", word);
355 return (0);
356 }
357 nbits -= bitno-1;
358 } else {
359 datfileerr("Bad bit range '%s'", word);
360 return (0);
361 }
362 } else
363 nbits = 1;
364 } else if (streql(word, "byte") || streql(word, "1byte"))
365 size = 1;
366 else if (streql(word, "short") || streql(word, "2byte"))
367 size = 2;
368 else if (streql(word, "3byte"))
369 size = 3;
370 else if (streql(word, "long") || streql(word, "4byte"))
371 size = 4;
372 else {
373 datfileerr("Bad val size '%s'", word);
374 return (0);
375 }
376
377 word = nextitem();
378 if (streql(word, "="))
379 op = O_SET;
380 else if (streql(word, "&="))
381 op = O_AND;
382 else if (streql(word, "|="))
383 op = O_OR;
384 else if (streql(word, "print"))
385 op = O_PRINT;
386 else if (streql(word, "printall")) {
387 prbytes(nextitem(), mode, len);
388 return (0);
389 } else if (streql(word, "printpages")) {
390 u_char *p = mode;
391 u_char *ep = &mode[len];
392
393 printf("%s", nextitem());
394 while (p < ep) {
395 printf("0x%x ", *p&0x3F);
396 p += p[1]+2;
397 }
398 printf("\n");
399 return (0);
400 } else {
401 datfileerr("Bad op '%s'", word);
402 return (0);
403 }
404
405 if (!isval(word = nextitem()))
406 return (0);
407
408 if (op == O_PRINT) {
409 *movebytes(word, prarg, sizeof (prarg)-1) = 0;
410 val = (long)prarg;
411 } else {
412 if (*word == '~') {
413 word++;
414 donot = TRUE;
415 }
416 if (*word == '\0')
417 word = nextitem();
418 if (*astol(word, &val) != '\0') {
419 datfileerr("Bad val '%s'", word);
420 return (0);
421 }
422 }
423
424 word = nextitem();
425 (void) garbage(word);
426
427 /*printf("idx: %d size: %d op: %d, val: %ld\n", idx, size, op, val);*/
428 /*XXX*/
429 #ifndef FMT
430 {int i;
431 for (i = 0; i < 20; i++)
432 cmode[i] = 0xFF;
433 }
434 #endif
435 switch (size) {
436
437 case 0:
438 return (set_bits(&mode[idx], &cmode[idx], op, donot, val,
439 bitno, nbits));
440 case 1:
441 return (set_byte(&mode[idx], &cmode[idx], op, donot, val));
442 case 2:
443 return (set_short(&mode[idx], &cmode[idx], op, donot, val));
444 case 3:
445 return (set_3byte(&mode[idx], &cmode[idx], op, donot, val));
446 case 4:
447 return (set_long(&mode[idx], &cmode[idx], op, donot, val));
448 default:
449 datfileerr("Bad size '%d' paranoia?", size);
450 return (0);
451 }
452 }
453
454 LOCAL int
set_bits(mode,cmode,op,donot,val,bitno,nbits)455 set_bits(mode, cmode, op, donot, val, bitno, nbits)
456 u_char *mode;
457 u_char *cmode;
458 int op;
459 BOOL donot;
460 long val;
461 int bitno;
462 int nbits;
463 {
464 long oval;
465 long lbitmask;
466 long bitmask;
467
468 if (bitno < 0 || bitno > 7) {
469 datfileerr("Bad start bit '%d'", bitno);
470 return (0);
471 }
472 if (nbits < 0 || (bitno+nbits-1) > 7) {
473 datfileerr("Bad end bit '%d'", bitno+nbits-1);
474 return (0);
475 }
476
477 for (lbitmask = 0, oval = 0; oval < nbits; oval++)
478 lbitmask |= 1 << oval;
479
480 bitmask = lbitmask << bitno;
481
482 if (op != O_PRINT) {
483 if (((unsigned long)val) > lbitmask) {
484 datfileerr("Bad bit val '%ld'", val);
485 return (0);
486 }
487
488 if (donot)
489 val = ~val & bitmask;
490 val <<= bitno;
491
492 if ((*cmode & bitmask) == 0) {
493 modewarning();
494 return (1); /* XXX Wir tun mal so als ob es geht */
495 }
496 }
497 oval = *mode & bitmask;
498
499 switch (op) {
500
501 case O_SET: break;
502 case O_AND: val = oval & val; break;
503 case O_OR: val = oval | val; break;
504 case O_PRINT:
505 xprint((char *)val, oval>>bitno); return (1);
506 }
507
508 *mode &= ~bitmask;
509 *mode |= val;
510 return (1);
511 }
512
513 LOCAL int
set_byte(mode,cmode,op,donot,val)514 set_byte(mode, cmode, op, donot, val)
515 u_char *mode;
516 u_char *cmode;
517 int op;
518 BOOL donot;
519 long val;
520 {
521 long oval;
522
523 if (op != O_PRINT) {
524 if (((unsigned long)val) > 0xFF) {
525 datfileerr("Bad byte val '%ld'", val);
526 return (0);
527 }
528
529 if (donot)
530 val = ~val & 0xFF;
531
532 if (*cmode == 0) {
533 modewarning();
534 return (1); /* XXX Wir tun mal so als ob es geht */
535 }
536 }
537 oval = *mode;
538
539 switch (op) {
540
541 case O_SET: break;
542 case O_AND: val = oval & val; break;
543 case O_OR: val = oval | val; break;
544 case O_PRINT: xprint((char *)val, oval); return (1);
545 }
546
547 *mode = val;
548 return (1);
549 }
550
551 LOCAL int
set_short(mode,cmode,op,donot,val)552 set_short(mode, cmode, op, donot, val)
553 u_char *mode;
554 u_char *cmode;
555 int op;
556 BOOL donot;
557 long val;
558 {
559 long oval;
560
561 if (op != O_PRINT) {
562 if (((unsigned long)val) > 0xFFFF) {
563 datfileerr("Bad 2byte val '%ld'", val);
564 return (0);
565 }
566
567 if (donot)
568 val = ~val & 0xFFFF;
569
570 if (a_to_u_2_byte(cmode) == 0) {
571 modewarning();
572 return (1); /* XXX Wir tun mal so als ob es geht */
573 }
574 }
575 oval = a_to_u_2_byte(mode);
576
577 switch (op) {
578
579 case O_SET: break;
580 case O_AND: val = oval & val; break;
581 case O_OR: val = oval | val; break;
582 case O_PRINT: xprint((char *)val, oval); return (1);
583 }
584
585 i_to_2_byte(mode, val);
586 return (1);
587 }
588
589 LOCAL int
set_3byte(mode,cmode,op,donot,val)590 set_3byte(mode, cmode, op, donot, val)
591 u_char *mode;
592 u_char *cmode;
593 int op;
594 BOOL donot;
595 long val;
596 {
597 long oval;
598
599 if (op != O_PRINT) {
600 if (((unsigned long)val) > 0xFFFFFF) {
601 datfileerr("Bad 3byte val '%ld'", val);
602 return (0);
603 }
604
605 if (donot)
606 val = ~val & 0xFFFFFF;
607
608 if (a_to_u_3_byte(cmode) == 0) {
609 modewarning();
610 return (1); /* XXX Wir tun mal so als ob es geht */
611 }
612 }
613 oval = a_to_u_3_byte(mode);
614
615 switch (op) {
616
617 case O_SET: break;
618 case O_AND: val = oval & val; break;
619 case O_OR: val = oval | val; break;
620 case O_PRINT: xprint((char *)val, oval); return (1);
621 }
622
623 i_to_3_byte(mode, val);
624 return (1);
625 }
626
627 LOCAL int
set_long(mode,cmode,op,donot,val)628 set_long(mode, cmode, op, donot, val)
629 u_char *mode;
630 u_char *cmode;
631 int op;
632 BOOL donot;
633 long val;
634 {
635 long oval;
636
637 if (op != O_PRINT) {
638 if (donot)
639 val = ~val;
640
641 if (a_to_4_byte(cmode) == 0) {
642 modewarning();
643 return (1); /* XXX Wir tun mal so als ob es geht */
644 }
645 }
646 oval = a_to_4_byte(mode);
647
648 switch (op) {
649
650 case O_SET: break;
651 case O_AND: val = oval & val; break;
652 case O_OR: val = oval | val; break;
653 case O_PRINT: xprint((char *)val, oval); return (1);
654 }
655
656 i_to_4_byte(mode, val);
657 return (1);
658 }
659
660 LOCAL void
xprint(fmt,val)661 xprint(fmt, val)
662 char *fmt;
663 long val;
664 {
665 register char c;
666
667 while ((c = *fmt++) != '\0') {
668 if (c == '%') {
669 c = *fmt++;
670 if (c == '\0')
671 break;
672 if (c == 'd')
673 printf("%ld", val);
674 else if (c == 'o')
675 printf("%lo", val);
676 else if (c == 'x')
677 printf("%lx", val);
678 else
679 putchar(c);
680 } else if (c == '\\') {
681 c = *fmt++;
682 if (c == '\0')
683 break;
684 if (c == 'n')
685 c = '\n';
686 else if (c == 't')
687 c = '\t';
688 putchar(c);
689 } else {
690 putchar(c);
691 }
692 }
693 }
694
695 LOCAL void
modewarning()696 modewarning()
697 {
698 if (modewarn)
699 datfileerr("WARNING: Controller does not support field");
700 }
701
702 #ifdef NONO
703 LOCAL int
xset_bits(mode,cmode,op,val,bitno,nbits)704 xset_bits(mode, cmode, op, val, bitno, nbits)
705 u_char *mode;
706 u_char *cmode;
707 int op;
708 long val;
709 int bitno;
710 int nbits;
711 {
712 long oval;
713 long lbitmask;
714 long bitmask;
715
716 if (bitno < 0 || bitno > 31) {
717 datfileerr("Bad start bit '%d'", bitno);
718 return (0);
719 }
720 if (nbits < 0 || (bitno+nbits-1) > 31) {
721 datfileerr("Bad end bit '%d'", bitno+nbits-1);
722 return (0);
723 }
724
725 for (lbitmask = 0, oval = 0; oval < nbits; oval++)
726 lbitmask |= 1 << oval;
727
728 bitmask = lbitmask << bitno;
729
730 if (((unsigned long)val) > lbitmask) {
731 datfileerr("Bad val '%d'", val);
732 return (0);
733 }
734 val <<= bitno;
735
736 if ((a_to_4_byte(cmode) & bitmask) == 0) {
737 modewarning();
738 return (1); /* XXX Wir tun mal so als ob es geht */
739 }
740 oval = a_to_4_byte(mode) & bitmask;
741
742 switch (op) {
743
744 case O_SET: break;
745 case O_AND: val = oval & val; break;
746 case O_OR: val = oval | val; break;
747 }
748
749 oval = a_to_4_byte(mode) & ~bitmask;
750 val |= oval;
751 i_to_4_byte(mode, val);
752 return (1);
753 }
754 #endif
755