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