1 /* $OpenBSD: ukcutil.c,v 1.27 2023/09/06 05:00:37 jsg Exp $ */
2
3 /*
4 * Copyright (c) 1999-2001 Mats O Jansson. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #include <sys/types.h>
28 #include <sys/device.h>
29
30 #include <ctype.h>
31 #include <err.h>
32 #include <errno.h>
33 #include <limits.h>
34 #include <nlist.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38
39 #include "cmd.h"
40 #include "exec.h"
41 #include "ukc.h"
42 #include "misc.h"
43
44 extern int ukc_mod_kernel;
45
46 struct cfdata *
get_cfdata(int idx)47 get_cfdata(int idx)
48 {
49 return((struct cfdata *)(adjust((caddr_t)nl[P_CFDATA].n_value) +
50 idx * sizeof(struct cfdata)));
51 }
52
53 short *
get_locnamp(int idx)54 get_locnamp(int idx)
55 {
56 return((short *)(adjust((caddr_t)nl[S_LOCNAMP].n_value) +
57 idx * sizeof(short)));
58 }
59
60 static caddr_t *
get_locnames(int idx)61 get_locnames(int idx)
62 {
63 return((caddr_t *)(adjust((caddr_t)nl[P_LOCNAMES].n_value) +
64 idx * sizeof(caddr_t)));
65 }
66
67 static long *
get_extraloc(int nslots)68 get_extraloc(int nslots)
69 {
70 long *extralocp, *locp;
71 int *rextralocp, *textralocp;
72
73 extralocp = (long *)adjust((caddr_t)nl[IA_EXTRALOC].n_value);
74 rextralocp = (int *)adjust((caddr_t)nl[I_REXTRALOC].n_value);
75 textralocp = (int *)adjust((caddr_t)nl[I_TEXTRALOC].n_value);
76 if (*rextralocp < nslots)
77 return (NULL);
78
79 locp = &extralocp[*textralocp - *rextralocp];
80 *rextralocp -= nslots;
81 return locp;
82 }
83
84 static char *
get_pdevnames(int idx)85 get_pdevnames(int idx)
86 {
87 caddr_t *p;
88
89 p = (caddr_t *)adjust((caddr_t)nl[P_PDEVNAMES].n_value +
90 idx * sizeof(caddr_t));
91 return(char *)adjust((caddr_t)*p);
92
93 }
94
95 static struct pdevinit *
get_pdevinit(int idx)96 get_pdevinit(int idx)
97 {
98 return((struct pdevinit *)(adjust((caddr_t)nl[S_PDEVINIT].n_value) +
99 idx * sizeof(struct pdevinit)));
100 }
101
102 int
more(void)103 more(void)
104 {
105 int quit = 0;
106 cmd_t cmd;
107
108 if (cnt != -1) {
109 if (cnt > 0 && cnt == lines) {
110 printf("--- more ---");
111 fflush(stdout);
112 ask_cmd(&cmd);
113 cnt = 0;
114 if (cmd.cmd[0] == 'q' || cmd.cmd[0] == 'Q')
115 quit = 1;
116 }
117 cnt++;
118 }
119 return (quit);
120 }
121
122 static void
pnum(long val)123 pnum(long val)
124 {
125 if (val > -2 && val < 16) {
126 printf("%ld", val);
127 return;
128 }
129
130 switch (base) {
131 case 8:
132 printf("0%lo", val);
133 break;
134 case 10:
135 printf("%ld", val);
136 break;
137 case 16:
138 default:
139 printf("0x%lx", val);
140 break;
141 }
142 }
143
144 static void
pdevnam(short devno)145 pdevnam(short devno)
146 {
147 struct cfdata *cd;
148 struct cfdriver *cdrv;
149
150 cd = get_cfdata(devno);
151
152 cdrv = (struct cfdriver *)adjust((caddr_t)cd->cf_driver);
153 printf("%s", adjust((caddr_t)cdrv->cd_name));
154
155 switch (cd->cf_fstate) {
156 case FSTATE_NOTFOUND:
157 case FSTATE_DNOTFOUND:
158 printf("%d", cd->cf_unit);
159 break;
160 case FSTATE_FOUND:
161 printf("*FOUND*");
162 break;
163 case FSTATE_STAR:
164 case FSTATE_DSTAR:
165 printf("*");
166 break;
167 default:
168 printf("*UNKNOWN*");
169 break;
170 }
171 }
172
173 void
pdev(short devno)174 pdev(short devno)
175 {
176 struct pdevinit *pi;
177 struct cfdata *cd;
178 short *s, *ln;
179 long *i;
180 caddr_t *p;
181 char c;
182
183 if (nopdev == 0) {
184 if (devno > maxdev && devno <= totdev) {
185 printf("%3d free slot (for add)\n", devno);
186 return;
187 }
188 if (devno > totdev && devno <= totdev + maxpseudo) {
189 pi = get_pdevinit(devno - totdev -1);
190 printf("%3d %s count %d", devno,
191 get_pdevnames(devno - totdev - 1),
192 abs(pi->pdev_count));
193 if (pi->pdev_count < 0)
194 printf(" disable");
195 printf(" (pseudo device)\n");
196 return;
197 }
198 }
199
200 if (devno > maxdev) {
201 printf("Unknown devno (max is %d)\n", maxdev);
202 return;
203 }
204
205 cd = get_cfdata(devno);
206
207 printf("%3d ", devno);
208 pdevnam(devno);
209 printf(" at");
210
211 c = ' ';
212 s = (short *)adjust((caddr_t)cd->cf_parents);
213 if (*s == -1)
214 printf(" root");
215 while (*s != -1) {
216 printf("%c", c);
217 pdevnam(*s);
218 c = '|';
219 s++;
220 }
221 switch (cd->cf_fstate) {
222 case FSTATE_NOTFOUND:
223 case FSTATE_FOUND:
224 case FSTATE_STAR:
225 break;
226 case FSTATE_DNOTFOUND:
227 case FSTATE_DSTAR:
228 printf(" disable");
229 break;
230 default:
231 printf(" ???");
232 break;
233 }
234
235 i = (long *)adjust((caddr_t)cd->cf_loc);
236 ln = get_locnamp(cd->cf_locnames);
237 while (*ln != -1) {
238 p = get_locnames(*ln);
239 printf(" %s ", adjust((caddr_t)*p));
240 ln++;
241 pnum(*i);
242 i++;
243 }
244 printf(" flags 0x%x\n", cd->cf_flags);
245 }
246
247 static int
numberl(const char * c,long * val)248 numberl(const char *c, long *val)
249 {
250 char *ep;
251
252 errno = 0;
253 *val = strtol(c, &ep, 0);
254 if (*c == '\0' || (!isspace((unsigned char)*ep) && *ep != '\0') ||
255 (errno == ERANGE && (*val == LONG_MAX || *val == LONG_MIN)))
256 return (-1);
257 return (0);
258 }
259
260 int
number(const char * c,int * val)261 number(const char *c, int *val)
262 {
263 long v;
264 int ret = numberl(c, &v);
265
266 if (ret == 0) {
267 if (v <= INT_MAX && v >= INT_MIN)
268 *val = (int)v;
269 else
270 ret = -1;
271 }
272 return (ret);
273 }
274
275 int
device(char * cmd,int * len,short * unit,short * state)276 device(char *cmd, int *len, short *unit, short *state)
277 {
278 short u = 0, s = FSTATE_FOUND;
279 int l = 0;
280 char *c;
281
282 c = cmd;
283 while (*c >= 'a' && *c <= 'z') {
284 l++;
285 c++;
286 }
287
288 if (*c == '*') {
289 s = FSTATE_STAR;
290 c++;
291 } else {
292 while (*c >= '0' && *c <= '9') {
293 s = FSTATE_NOTFOUND;
294 u = u*10 + *c - '0';
295 c++;
296 }
297 }
298 while (*c == ' ' || *c == '\t' || *c == '\n')
299 c++;
300
301 if (*c == '\0') {
302 *len = l;
303 *unit = u;
304 *state = s;
305 return(0);
306 }
307 return(-1);
308 }
309
310 int
attr(char * cmd,int * val)311 attr(char *cmd, int *val)
312 {
313 short attr = -1, i = 0, l = 0;
314 caddr_t *p;
315 char *c;
316
317 c = cmd;
318 while (*c != ' ' && *c != '\t' && *c != '\n' && *c != '\0') {
319 c++;
320 l++;
321 }
322
323 p = get_locnames(0);
324
325 while (i <= maxlocnames) {
326 if (strlen((char *)adjust((caddr_t)*p)) == l) {
327 if (strncasecmp(cmd, adjust((caddr_t)*p), l) == 0)
328 attr = i;
329 }
330 p++;
331 i++;
332 }
333 if (attr == -1)
334 return (-1);
335
336 *val = attr;
337 return(0);
338 }
339
340 static int
modifyl(char * item,long * val)341 modifyl(char *item, long *val)
342 {
343 cmd_t cmd;
344 long a;
345
346 ukc_mod_kernel = 1;
347 while (1) {
348 printf("%s [", item);
349 pnum(*val);
350 printf("] ? ");
351 fflush(stdout);
352
353 ask_cmd(&cmd);
354
355 if (strlen(cmd.cmd) != 0) {
356 if (strlen(cmd.args) == 0) {
357 if (numberl(cmd.cmd, &a) == 0) {
358 *val = a;
359 return (1);
360 } else
361 printf("Unknown argument\n");
362 } else
363 printf("Too many arguments\n");
364 } else
365 return (0);
366 }
367 }
368
369 void
modify(char * item,int * val)370 modify(char *item, int *val)
371 {
372 long a = *val;
373
374 while (modifyl(item, &a)) {
375 if (a <= INT_MAX && a >= INT_MIN) {
376 *val = (int)a;
377 break;
378 }
379 printf("Out of range argument\n");
380 }
381 }
382
383 void
change(int devno)384 change(int devno)
385 {
386 int i, share = 0;
387 long *j = NULL, *l = NULL;
388 struct cfdata *cd, *c;
389 struct pdevinit *pi;
390 short *ln, *lk;
391 caddr_t *p;
392
393 ukc_mod_kernel = 1;
394 if (devno <= maxdev) {
395 pdev(devno);
396 if (!ask_yn("change"))
397 return;
398
399 cd = get_cfdata(devno);
400
401 /*
402 * Search for some other driver sharing this
403 * locator table. if one does, we may need to
404 * replace the locators with a new copy.
405 */
406 c = get_cfdata(0);
407 for (i = 0; c->cf_driver; i++) {
408 if (i != devno && c->cf_loc == cd->cf_loc)
409 share = 1;
410 c++;
411 }
412
413 ln = get_locnamp(cd->cf_locnames);
414 l = (long *)adjust((caddr_t)cd->cf_loc);
415
416 if (share) {
417 if (oldkernel) {
418 printf("Can't do that on this kernel\n");
419 return;
420 }
421
422 lk = ln;
423 i = 0;
424 while (*lk != -1) {
425 lk++;
426 i++;
427 }
428 lk = ln;
429
430 j = l = get_extraloc(i);
431 if (l == NULL) {
432 printf("Not enough space to change device.\n");
433 return;
434 }
435 if (i)
436 bcopy(adjust((caddr_t)cd->cf_loc), l,
437 sizeof(long) * i);
438 }
439
440 while (*ln != -1) {
441 p = get_locnames(*ln);
442 modifyl((char *)adjust(*p), l);
443 ln++;
444 l++;
445 }
446 modify("flags", &cd->cf_flags);
447
448 if (share) {
449 if (bcmp(adjust((caddr_t)cd->cf_loc),
450 j, sizeof(long) * i)) {
451 cd->cf_loc = (long *)readjust((caddr_t)j);
452 }
453 }
454
455 printf("%3d ", devno);
456 pdevnam(devno);
457 printf(" changed\n");
458 pdev(devno);
459 return;
460 }
461
462 if (nopdev == 0) {
463 if (devno > maxdev && devno <= totdev) {
464 printf("%3d can't change free slot\n", devno);
465 return;
466 }
467
468 if (devno > totdev && devno <= totdev + maxpseudo) {
469 pdev(devno);
470 if (ask_yn("change")) {
471 pi = get_pdevinit(devno-totdev-1);
472 modify("count", &pi->pdev_count);
473 printf("%3d %s changed\n", devno,
474 get_pdevnames(devno - totdev - 1));
475 pdev(devno);
476 }
477 return;
478 }
479 }
480
481 printf("Unknown devno (max is %d)\n", totdev+maxpseudo);
482 }
483
484 void
change_history(int devno,char * str)485 change_history(int devno, char *str)
486 {
487 int i, share = 0;
488 long *j = NULL, *l = NULL;
489 struct cfdata *cd, *c;
490 struct pdevinit *pi;
491 short *ln, *lk;
492
493 ukc_mod_kernel = 1;
494
495 if (devno <= maxdev) {
496
497 pdev(devno);
498 cd = get_cfdata(devno);
499
500 /*
501 * Search for some other driver sharing this
502 * locator table. if one does, we may need to
503 * replace the locators with a new copy.
504 */
505 c = get_cfdata(0);
506 for (i = 0; c->cf_driver; i++) {
507 if (i != devno && c->cf_loc == cd->cf_loc)
508 share = 1;
509 c++;
510 }
511
512 ln = get_locnamp(cd->cf_locnames);
513 l = (long *)adjust((caddr_t)cd->cf_loc);
514
515 if (share) {
516 if (oldkernel) {
517 printf("Can't do that on this kernel\n");
518 return;
519 }
520
521 lk = ln;
522 i = 0;
523 while (*lk != -1) {
524 lk++;
525 i++;
526 }
527 lk = ln;
528
529 j = l = get_extraloc(i);
530 if (l == NULL) {
531 printf("Not enough space to change device.\n");
532 return;
533 }
534 if (i)
535 bcopy(adjust((caddr_t)cd->cf_loc), l,
536 sizeof(long) * i);
537 }
538
539 while (*ln != -1) {
540 *l = atoi(str);
541 if (*str == '-')
542 str++;
543 while (*str >= '0' && *str <= '9')
544 str++;
545 if (*str == ' ')
546 str++;
547 ln++;
548 l++;
549 }
550
551 if (*str) {
552 cd->cf_flags = atoi(str);
553 if (*str == '-')
554 str++;
555 while (*str >= '0' && *str <= '9')
556 str++;
557 if (*str == ' ')
558 str++;
559 }
560
561 if (share) {
562 if (bcmp(adjust((caddr_t)cd->cf_loc),
563 j, sizeof(long) * i)) {
564 cd->cf_loc = (long *)readjust((caddr_t)j);
565 }
566 }
567
568 printf("%3d ", devno);
569 pdevnam(devno);
570 printf(" changed\n");
571 pdev(devno);
572 return;
573 }
574
575 if (nopdev == 0) {
576 if (devno > maxdev && devno <= totdev) {
577 printf("%3d can't change free slot\n", devno);
578 return;
579 }
580 if (devno > totdev && devno <= totdev + maxpseudo) {
581 pdev(devno);
582 pi = get_pdevinit(devno-totdev-1);
583
584 if (*str) {
585 pi->pdev_count = atoi(str);
586 if (*str == '-')
587 str++;
588 while (*str >= '0' && *str <= '9')
589 str++;
590 if (*str == ' ')
591 str++;
592 }
593
594 printf("%3d %s changed\n", devno,
595 get_pdevnames(devno - totdev - 1));
596 pdev(devno);
597 return;
598 }
599 }
600
601 printf("Unknown devno (max is %d)\n", totdev + maxpseudo);
602 }
603
604 void
disable(int devno)605 disable(int devno)
606 {
607 struct cfdata *cd;
608 struct pdevinit *pi;
609 int done = 0;
610
611 if (devno <= maxdev) {
612
613 cd = get_cfdata(devno);
614
615 switch (cd->cf_fstate) {
616 case FSTATE_NOTFOUND:
617 cd->cf_fstate = FSTATE_DNOTFOUND;
618 break;
619 case FSTATE_STAR:
620 cd->cf_fstate = FSTATE_DSTAR;
621 break;
622 case FSTATE_DNOTFOUND:
623 case FSTATE_DSTAR:
624 done = 1;
625 break;
626 default:
627 printf("Error unknown state\n");
628 break;
629 }
630
631 printf("%3d ", devno);
632 pdevnam(devno);
633 if (done) {
634 printf(" already");
635 } else {
636 ukc_mod_kernel = 1;
637 }
638 printf(" disabled\n");
639
640 return;
641 }
642
643 if (nopdev == 0) {
644 if (devno > maxdev && devno <= totdev) {
645 printf("%3d can't disable free slot\n", devno);
646 return;
647 }
648 if (devno > totdev && devno <= totdev + maxpseudo) {
649 pi = get_pdevinit(devno-totdev-1);
650
651 printf("%3d %s", devno,
652 get_pdevnames(devno - totdev - 1));
653 if (pi->pdev_count < 1) {
654 printf(" already");
655 } else {
656 ukc_mod_kernel = 1;
657 pi->pdev_count*=-1;
658 }
659 printf(" disabled\n");
660 return;
661 }
662 }
663
664 printf("Unknown devno (max is %d)\n", totdev+maxpseudo);
665
666 }
667
668 void
enable(int devno)669 enable(int devno)
670 {
671 struct cfdata *cd;
672 struct pdevinit *pi;
673 int done = 0;
674
675 if (devno <= maxdev) {
676 cd = get_cfdata(devno);
677
678 switch (cd->cf_fstate) {
679 case FSTATE_DNOTFOUND:
680 cd->cf_fstate = FSTATE_NOTFOUND;
681 break;
682 case FSTATE_DSTAR:
683 cd->cf_fstate = FSTATE_STAR;
684 break;
685 case FSTATE_NOTFOUND:
686 case FSTATE_STAR:
687 done = 1;
688 break;
689 default:
690 printf("Error unknown state\n");
691 break;
692 }
693
694 printf("%3d ", devno);
695 pdevnam(devno);
696 if (done) {
697 printf(" already");
698 } else {
699 ukc_mod_kernel = 1;
700 }
701 printf(" enabled\n");
702
703 return;
704 }
705
706 if (nopdev == 0) {
707 if (devno > maxdev && devno <= totdev) {
708 printf("%3d can't enable free slot\n", devno);
709 return;
710 }
711 if (devno > totdev && devno <= totdev + maxpseudo) {
712 pi = get_pdevinit(devno-totdev-1);
713
714 printf("%3d %s", devno,
715 get_pdevnames(devno - totdev - 1));
716 if (pi->pdev_count > 0) {
717 printf(" already");
718 } else {
719 ukc_mod_kernel = 1;
720 pi->pdev_count*=-1;
721 }
722 printf(" enabled\n");
723 return;
724 }
725 }
726
727 printf("Unknown devno (max is %d)\n", totdev+maxpseudo);
728 }
729
730 void
show(void)731 show(void)
732 {
733 caddr_t *p;
734 int i = 0;
735
736 cnt = 0;
737
738 p = get_locnames(0);
739
740 while (i <= maxlocnames) {
741 if (more())
742 break;
743 printf("%s\n", (char *)adjust(*p));
744 p++;
745 i++;
746 }
747
748 cnt = -1;
749 }
750
751 void
common_attr_val(short attr,int * val,char routine)752 common_attr_val(short attr, int *val, char routine)
753 {
754 int i = 0;
755 struct cfdata *cd;
756 long *l;
757 short *ln;
758 int quit = 0;
759
760 cnt = 0;
761
762 cd = get_cfdata(0);
763
764 while (cd->cf_attach != 0) {
765 l = (long *)adjust((caddr_t)cd->cf_loc);
766 ln = get_locnamp(cd->cf_locnames);
767 while (*ln != -1) {
768 if (*ln == attr) {
769 if (val == NULL) {
770 quit = more();
771 pdev(i);
772 } else {
773 if (*val == *l) {
774 quit = more();
775 switch (routine) {
776 case UC_ENABLE:
777 enable(i);
778 break;
779 case UC_DISABLE:
780 disable(i);
781 break;
782 case UC_SHOW:
783 pdev(i);
784 break;
785 default:
786 printf("Unknown routine /%c/\n",
787 routine);
788 break;
789 }
790 }
791 }
792 }
793 if (quit)
794 break;
795 ln++;
796 l++;
797 }
798 if (quit)
799 break;
800 i++;
801 cd++;
802 }
803
804 cnt = -1;
805 }
806
807 void
show_attr(char * cmd)808 show_attr(char *cmd)
809 {
810 char *c;
811 caddr_t *p;
812 short attr = -1, i = 0, l = 0;
813 int a;
814
815 c = cmd;
816 while (*c != ' ' && *c != '\t' && *c != '\n' && *c != '\0') {
817 c++;
818 l++;
819 }
820 while (*c == ' ' || *c == '\t' || *c == '\n') {
821 c++;
822 }
823
824 p = get_locnames(0);
825
826 while (i <= maxlocnames) {
827 if (strlen((char *)adjust(*p)) == l) {
828 if (strncasecmp(cmd, adjust(*p), l) == 0)
829 attr = i;
830 }
831 p++;
832 i++;
833 }
834
835 if (attr == -1) {
836 printf("Unknown attribute\n");
837 return;
838 }
839
840 if (*c == '\0') {
841 common_attr_val(attr, NULL, UC_SHOW);
842 } else {
843 if (number(c, &a) == 0) {
844 common_attr_val(attr, &a, UC_SHOW);
845 } else {
846 printf("Unknown argument\n");
847 }
848 }
849 }
850
851 void
common_dev(char * dev,int len,short unit,short state,char routine)852 common_dev(char *dev, int len, short unit, short state, char routine)
853 {
854 struct cfdata *cd;
855 struct cfdriver *cdrv;
856 int i = 0;
857
858 switch (routine) {
859 case UC_CHANGE:
860 break;
861 default:
862 cnt = 0;
863 break;
864 }
865
866 cnt = 0;
867
868 cd = get_cfdata(0);
869
870 while (cd->cf_attach != 0) {
871 cdrv = (struct cfdriver *)adjust((caddr_t)cd->cf_driver);
872
873 if (strlen((char *)adjust(cdrv->cd_name)) == len) {
874 /*
875 * Ok, if device name is correct
876 * If state == FSTATE_FOUND, look for "dev"
877 * If state == FSTATE_STAR, look for "dev*"
878 * If state == FSTATE_NOTFOUND, look for "dev0"
879 */
880 if (!strncasecmp(dev,(char *)adjust(cdrv->cd_name), len) &&
881 (state == FSTATE_FOUND ||
882 (state == FSTATE_STAR &&
883 (cd->cf_fstate == FSTATE_STAR ||
884 cd->cf_fstate == FSTATE_DSTAR)) ||
885 (state == FSTATE_NOTFOUND &&
886 cd->cf_unit == unit &&
887 (cd->cf_fstate == FSTATE_NOTFOUND ||
888 cd->cf_fstate == FSTATE_DNOTFOUND)))) {
889 if (more())
890 break;
891 switch (routine) {
892 case UC_CHANGE:
893 change(i);
894 break;
895 case UC_ENABLE:
896 enable(i);
897 break;
898 case UC_DISABLE:
899 disable(i);
900 break;
901 case UC_FIND:
902 pdev(i);
903 break;
904 default:
905 printf("Unknown routine /%c/\n",
906 routine);
907 break;
908 }
909 }
910 }
911 i++;
912 cd++;
913 }
914
915 if (nopdev == 0) {
916 for (i = 0; i < maxpseudo; i++) {
917 if (!strncasecmp(dev, (char *)get_pdevnames(i), len) &&
918 state == FSTATE_FOUND) {
919 switch (routine) {
920 case UC_CHANGE:
921 change(totdev+1+i);
922 break;
923 case UC_ENABLE:
924 enable(totdev+1+i);
925 break;
926 case UC_DISABLE:
927 disable(totdev+1+i);
928 break;
929 case UC_FIND:
930 pdev(totdev+1+i);
931 break;
932 default:
933 printf("Unknown pseudo routine /%c/\n",
934 routine);
935 break;
936 }
937 }
938 }
939 }
940
941 switch (routine) {
942 case UC_CHANGE:
943 break;
944 default:
945 cnt = -1;
946 break;
947 }
948 }
949
950 void
common_attr(char * cmd,int attr,char routine)951 common_attr(char *cmd, int attr, char routine)
952 {
953 char *c;
954 short l = 0;
955 int a;
956
957 c = cmd;
958 while (*c != ' ' && *c != '\t' && *c != '\n' && *c != '\0') {
959 c++;
960 l++;
961 }
962 while (*c == ' ' || *c == '\t' || *c == '\n') {
963 c++;
964 }
965 if (*c == '\0') {
966 printf("Value missing for attribute\n");
967 return;
968 }
969
970 if (number(c, &a) == 0) {
971 common_attr_val(attr, &a, routine);
972 } else {
973 printf("Unknown argument\n");
974 }
975 }
976
977 void
add_read(char * prompt,char field,char * dev,int len,int * val)978 add_read(char *prompt, char field, char *dev, int len, int *val)
979 {
980 int ok = 0;
981 int a;
982 cmd_t cmd;
983 struct cfdata *cd;
984 struct cfdriver *cdrv;
985
986 *val = -1;
987
988 while (!ok) {
989 printf("%s ? ", prompt);
990 fflush(stdout);
991
992 ask_cmd(&cmd);
993
994 if (strlen(cmd.cmd) != 0) {
995 if (number(cmd.cmd, &a) == 0) {
996 if (a > maxdev) {
997 printf("Unknown devno (max is %d)\n",
998 maxdev);
999 } else {
1000 cd = get_cfdata(a);
1001 cdrv = (struct cfdriver *)
1002 adjust((caddr_t)cd->cf_driver);
1003 if (strncasecmp(dev,
1004 (char *)adjust(cdrv->cd_name),
1005 len) != 0 &&
1006 field == 'a') {
1007 printf("Not same device type\n");
1008 } else {
1009 *val = a;
1010 ok = 1;
1011 }
1012 }
1013 } else if (cmd.cmd[0] == '?') {
1014 common_dev(dev, len, 0,
1015 FSTATE_FOUND, UC_FIND);
1016 } else if (cmd.cmd[0] == 'q' ||
1017 cmd.cmd[0] == 'Q') {
1018 ok = 1;
1019 } else {
1020 printf("Unknown argument\n");
1021 }
1022 } else {
1023 ok = 1;
1024 }
1025 }
1026
1027 }
1028
1029 void
add(char * dev,int len,short unit,short state)1030 add(char *dev, int len, short unit, short state)
1031 {
1032 int i = 0, found = 0, *p;
1033 short *pv;
1034 struct cfdata new, *cd, *cdp;
1035 struct cfdriver *cdrv;
1036 int val, max_unit, star_unit;
1037
1038 ukc_mod_kernel = 1;
1039
1040 bzero(&new, sizeof(struct cfdata));
1041
1042 if (maxdev == totdev) {
1043 printf("No more space for new devices.\n");
1044 return;
1045 }
1046
1047 if (state == FSTATE_FOUND) {
1048 printf("Device not complete number or * is missing\n");
1049 return;
1050 }
1051
1052 cd = get_cfdata(0);
1053
1054 while (cd->cf_attach != 0) {
1055 cdrv = (struct cfdriver *)adjust((caddr_t)cd->cf_driver);
1056
1057 if (strlen((char *)adjust(cdrv->cd_name)) == len &&
1058 strncasecmp(dev, (char *)adjust(cdrv->cd_name), len) == 0)
1059 found = 1;
1060 cd++;
1061 }
1062
1063 if (!found) {
1064 printf("No device of this type exists.\n");
1065 return;
1066 }
1067
1068 add_read("Clone Device (DevNo, 'q' or '?')", 'a', dev, len, &val);
1069
1070 if (val != -1) {
1071 cd = get_cfdata(val);
1072 new = *cd;
1073 new.cf_unit = unit;
1074 new.cf_fstate = state;
1075 add_read("Insert before Device (DevNo, 'q' or '?')",
1076 'i', dev, len, &val);
1077 }
1078
1079 if (val != -1) {
1080
1081 /* Insert the new record */
1082 cdp = cd = get_cfdata(maxdev+1);
1083 cdp--;
1084 for (i = maxdev; val <= i; i--) {
1085 *cd-- = *cdp--;
1086 }
1087 cd = get_cfdata(val);
1088 *cd = new;
1089
1090 /* Fix indexs in pv */
1091 p = (int *)adjust((caddr_t)nl[I_PV_SIZE].n_value);
1092 pv = (short *)adjust((caddr_t)nl[SA_PV].n_value);
1093 for (i = 0; i < *p; i++) {
1094 if (*pv != 1 && *pv >= val)
1095 *pv = *pv + 1;
1096 pv++;
1097 }
1098
1099 /* Fix indexs in cfroots */
1100 p = (int *)adjust((caddr_t)nl[I_CFROOTS_SIZE].n_value);
1101 pv = (short *)adjust((caddr_t)nl[SA_CFROOTS].n_value);
1102 for (i = 0; i < *p; i++) {
1103 if (*pv != 1 && *pv >= val)
1104 *pv = *pv + 1;
1105 pv++;
1106 }
1107
1108 maxdev++;
1109
1110 max_unit = -1;
1111
1112 /* Find max unit number of the device type */
1113
1114 cd = get_cfdata(0);
1115
1116 while (cd->cf_attach != 0) {
1117 cdrv = (struct cfdriver *)
1118 adjust((caddr_t)cd->cf_driver);
1119
1120 if (strlen((char *)adjust(cdrv->cd_name)) == len &&
1121 strncasecmp(dev, (char *)adjust(cdrv->cd_name),
1122 len) == 0) {
1123 switch (cd->cf_fstate) {
1124 case FSTATE_NOTFOUND:
1125 case FSTATE_DNOTFOUND:
1126 if (cd->cf_unit > max_unit)
1127 max_unit = cd->cf_unit;
1128 break;
1129 default:
1130 break;
1131 }
1132 }
1133 cd++;
1134 }
1135
1136 /*
1137 * For all * entries set unit number to max+1, and update
1138 * cf_starunit1 if necessary.
1139 */
1140 max_unit++;
1141 star_unit = -1;
1142 cd = get_cfdata(0);
1143 while (cd->cf_attach != 0) {
1144 cdrv = (struct cfdriver *)
1145 adjust((caddr_t)cd->cf_driver);
1146
1147 if (strlen((char *)adjust(cdrv->cd_name)) == len &&
1148 strncasecmp(dev, (char *)adjust(cdrv->cd_name),
1149 len) == 0) {
1150 switch (cd->cf_fstate) {
1151 case FSTATE_NOTFOUND:
1152 case FSTATE_DNOTFOUND:
1153 if (cd->cf_unit > star_unit)
1154 star_unit = cd->cf_unit;
1155 break;
1156 default:
1157 break;
1158 }
1159 }
1160 cd++;
1161 }
1162 star_unit++;
1163
1164 cd = get_cfdata(0);
1165 while (cd->cf_attach != 0) {
1166 cdrv = (struct cfdriver *)
1167 adjust((caddr_t)cd->cf_driver);
1168
1169 if (strlen((char *)adjust(cdrv->cd_name)) == len &&
1170 strncasecmp(dev, (char *)adjust(cdrv->cd_name),
1171 len) == 0) {
1172 switch (cd->cf_fstate) {
1173 case FSTATE_STAR:
1174 case FSTATE_DSTAR:
1175 cd->cf_unit = max_unit;
1176 if (cd->cf_starunit1 < star_unit)
1177 cd->cf_starunit1 = star_unit;
1178 break;
1179 default:
1180 break;
1181 }
1182 }
1183 cd++;
1184 }
1185
1186 pdev(val);
1187 }
1188
1189 /* cf_attach, cf_driver, cf_unit, cf_fstate, cf_loc, cf_flags,
1190 cf_parents, cf_locnames, cf_locnames and cf_ivstubs */
1191 }
1192
1193 void
add_history(int devno,short unit,short state,int newno)1194 add_history(int devno, short unit, short state, int newno)
1195 {
1196 int i = 0, *p;
1197 short *pv;
1198 struct cfdata new, *cd, *cdp;
1199 struct cfdriver *cdrv;
1200 int val, max_unit;
1201 int len;
1202 char *dev;
1203
1204 ukc_mod_kernel = 1;
1205
1206 bzero(&new, sizeof(struct cfdata));
1207 cd = get_cfdata(devno);
1208 new = *cd;
1209 new.cf_unit = unit;
1210 new.cf_fstate = state;
1211
1212 val = newno;
1213
1214 cdrv = (struct cfdriver *) adjust((caddr_t)cd->cf_driver);
1215 dev = adjust((caddr_t)cdrv->cd_name);
1216 len = strlen(dev);
1217
1218 /* Insert the new record */
1219 cdp = cd = get_cfdata(maxdev+1);
1220 cdp--;
1221 for (i = maxdev; val <= i; i--)
1222 *cd-- = *cdp--;
1223 cd = get_cfdata(val);
1224 *cd = new;
1225
1226 /* Fix indexs in pv */
1227 p = (int *)adjust((caddr_t)nl[I_PV_SIZE].n_value);
1228 pv = (short *)adjust((caddr_t)nl[SA_PV].n_value);
1229 for (i = 0; i < *p; i++) {
1230 if (*pv != 1 && *pv >= val)
1231 *pv = *pv + 1;
1232 pv++;
1233 }
1234
1235 /* Fix indexs in cfroots */
1236 p = (int *)adjust((caddr_t)nl[I_CFROOTS_SIZE].n_value);
1237 pv = (short *)adjust((caddr_t)nl[SA_CFROOTS].n_value);
1238 for (i = 0; i < *p; i++) {
1239 if (*pv != 1 && *pv >= val)
1240 *pv = *pv + 1;
1241 pv++;
1242 }
1243
1244 maxdev++;
1245 max_unit = -1;
1246
1247 /* Find max unit number of the device type */
1248 cd = get_cfdata(0);
1249 while (cd->cf_attach != 0) {
1250 cdrv = (struct cfdriver *)
1251 adjust((caddr_t)cd->cf_driver);
1252
1253 if (strlen((char *)adjust(cdrv->cd_name)) == len &&
1254 strncasecmp(dev, (char *)adjust(cdrv->cd_name),
1255 len) == 0) {
1256 switch (cd->cf_fstate) {
1257 case FSTATE_NOTFOUND:
1258 case FSTATE_DNOTFOUND:
1259 if (cd->cf_unit > max_unit)
1260 max_unit = cd->cf_unit;
1261 break;
1262 default:
1263 break;
1264 }
1265 }
1266 cd++;
1267 }
1268
1269 /* For all * entries set unit number to max+1 */
1270 max_unit++;
1271 cd = get_cfdata(0);
1272 while (cd->cf_attach != 0) {
1273 cdrv = (struct cfdriver *)
1274 adjust((caddr_t)cd->cf_driver);
1275
1276 if (strlen((char *)adjust(cdrv->cd_name)) == len &&
1277 strncasecmp(dev, (char *)adjust(cdrv->cd_name),
1278 len) == 0) {
1279 switch (cd->cf_fstate) {
1280 case FSTATE_STAR:
1281 case FSTATE_DSTAR:
1282 cd->cf_unit = max_unit;
1283 break;
1284 default:
1285 break;
1286 }
1287 }
1288 cd++;
1289 }
1290
1291 printf("%3d ", newno);
1292 pdevnam(newno);
1293 printf(" added\n");
1294 pdev(val);
1295 }
1296
1297 int
config(void)1298 config(void)
1299 {
1300 extern char *cmdfile;
1301 cmd_t cmd;
1302 int i, st;
1303
1304 /* Set up command table pointer */
1305 cmd.table = cmd_table;
1306
1307 if (cmdfile == NULL)
1308 printf("Enter 'help' for information\n");
1309
1310 /* Edit cycle */
1311 do {
1312 again:
1313 /* Get input */
1314 if (cmdfile == NULL) {
1315 printf("ukc> ");
1316 fflush(stdout);
1317 }
1318 ask_cmd(&cmd);
1319
1320 if (cmd.cmd[0] == '\0') {
1321 if (cmdfile != NULL)
1322 return 1;
1323 goto again;
1324 }
1325 for (i = 0; cmd_table[i].cmd != NULL; i++)
1326 if (strstr(cmd_table[i].cmd, cmd.cmd) ==
1327 cmd_table[i].cmd)
1328 break;
1329
1330 /* Quick hack to put in '?' == 'help' */
1331 if (!strcmp(cmd.cmd, "?"))
1332 i = 0;
1333
1334 /* Check for valid command */
1335 if (cmd_table[i].cmd == NULL) {
1336 if (cmdfile == NULL) {
1337 printf("Invalid command '%s'\n", cmd.cmd);
1338 exit(1);
1339 }
1340 printf("Invalid command '%s'. Try 'help'.\n", cmd.cmd);
1341 continue;
1342 } else
1343 strlcpy(cmd.cmd, cmd_table[i].cmd, sizeof cmd.cmd);
1344
1345 /* Call function */
1346 st = cmd_table[i].fcn(&cmd);
1347
1348 /* Update status */
1349 if (st == CMD_EXIT)
1350 break;
1351 if (st == CMD_SAVE)
1352 break;
1353 } while (1);
1354
1355 return (st == CMD_SAVE);
1356 }
1357
1358 void
process_history(int len,char * buf)1359 process_history(int len, char *buf)
1360 {
1361 char *c;
1362 int devno, newno;
1363 short unit, state;
1364
1365 if (len == 0) {
1366 printf("History is empty\n");
1367 return;
1368 }
1369
1370 printf("Processing history...\n");
1371
1372 buf[len] = 0;
1373
1374 c = buf;
1375
1376 while (*c != '\0') {
1377 switch (*c) {
1378 case 'a':
1379 c++;
1380 c++;
1381 devno = atoi(c);
1382 while (*c >= '0' && *c <= '9')
1383 c++;
1384 c++;
1385 unit = atoi(c);
1386 if (*c == '-') c++;
1387 while (*c >= '0' && *c <= '9')
1388 c++;
1389 c++;
1390 state = atoi(c);
1391 if (*c == '-')
1392 c++;
1393 while (*c >= '0' && *c <= '9')
1394 c++;
1395 c++;
1396 newno = atoi(c);
1397 while (*c >= '0' && *c <= '9')
1398 c++;
1399 add_history(devno, unit, state, newno);
1400 while (*c != '\n')
1401 c++;
1402 c++;
1403 break;
1404 case 'c':
1405 c++;
1406 c++;
1407 devno = atoi(c);
1408 while (*c >= '0' && *c <= '9')
1409 c++;
1410 if (*c == ' ')
1411 c++;
1412 if (*c != '\n')
1413 change_history(devno, c);
1414 while (*c != '\n')
1415 c++;
1416 c++;
1417 break;
1418 case 'd':
1419 c++;
1420 devno = atoi(c);
1421 disable(devno);
1422 while (*c != '\n')
1423 c++;
1424 c++;
1425 break;
1426 case 'e':
1427 c++;
1428 devno = atoi(c);
1429 enable(devno);
1430 while (*c != '\n')
1431 c++;
1432 c++;
1433 break;
1434 case 'q':
1435 while (*c != '\0')
1436 c++;
1437 break;
1438 default:
1439 printf("unknown command %c\n", *c);
1440 while (*c != '\0' && *c != '\n')
1441 c++;
1442 break;
1443 }
1444 }
1445 }
1446