1 /* $OpenBSD: ukcutil.c,v 1.25 2019/09/06 21:30:31 cheloha 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 * 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 * 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 * 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 * 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 * 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 1298 config_fromfile(const char *cmdfile) { 1299 FILE *fp; 1300 cmd_t cmd; 1301 int i; 1302 1303 fp = fopen(cmdfile, "r"); 1304 if (fp == NULL) 1305 err(1, "open %s", cmdfile); 1306 1307 /* Set up command table pointer */ 1308 cmd.table = cmd_table; 1309 1310 /* Edit cycle */ 1311 do { 1312 char lbuf[100]; 1313 1314 /* Get input */ 1315 if (fgets(lbuf, sizeof lbuf, fp) == NULL) 1316 break; 1317 parse_cmd(&cmd, lbuf); 1318 1319 if (cmd.cmd[0] == '\0') 1320 continue; 1321 for (i = 0; cmd_table[i].cmd != NULL; i++) 1322 if (strstr(cmd_table[i].cmd, cmd.cmd) == 1323 cmd_table[i].cmd) 1324 break; 1325 1326 /* Check for valid command */ 1327 if (cmd_table[i].cmd == NULL) { 1328 printf("Invalid command '%s'\n", cmd.cmd); 1329 exit(1); 1330 } 1331 strlcpy(cmd.cmd, cmd_table[i].cmd, sizeof cmd.cmd); 1332 1333 /* Call function */ 1334 cmd_table[i].fcn(&cmd); 1335 1336 } while (1); 1337 return 1; 1338 } 1339 1340 int 1341 config(void) 1342 { 1343 extern char *cmdfile; 1344 cmd_t cmd; 1345 int i, st; 1346 1347 /* Set up command table pointer */ 1348 cmd.table = cmd_table; 1349 1350 if (cmdfile != NULL) { 1351 return config_fromfile(cmdfile); 1352 } 1353 1354 printf("Enter 'help' for information\n"); 1355 1356 /* Edit cycle */ 1357 do { 1358 again: 1359 printf("ukc> "); 1360 fflush(stdout); 1361 ask_cmd(&cmd); 1362 1363 if (cmd.cmd[0] == '\0') 1364 goto again; 1365 for (i = 0; cmd_table[i].cmd != NULL; i++) 1366 if (strstr(cmd_table[i].cmd, cmd.cmd) == 1367 cmd_table[i].cmd) 1368 break; 1369 1370 /* Quick hack to put in '?' == 'help' */ 1371 if (!strcmp(cmd.cmd, "?")) 1372 i = 0; 1373 1374 /* Check for valid command */ 1375 if (cmd_table[i].cmd == NULL) { 1376 printf("Invalid command '%s'. Try 'help'.\n", cmd.cmd); 1377 continue; 1378 } else 1379 strlcpy(cmd.cmd, cmd_table[i].cmd, sizeof cmd.cmd); 1380 1381 /* Call function */ 1382 st = cmd_table[i].fcn(&cmd); 1383 1384 /* Update status */ 1385 if (st == CMD_EXIT) 1386 break; 1387 if (st == CMD_SAVE) 1388 break; 1389 } while (1); 1390 1391 return (st == CMD_SAVE); 1392 } 1393 1394 void 1395 process_history(int len, char *buf) 1396 { 1397 char *c; 1398 int devno, newno; 1399 short unit, state; 1400 1401 if (len == 0) { 1402 printf("History is empty\n"); 1403 return; 1404 } 1405 1406 printf("Processing history...\n"); 1407 1408 buf[len] = 0; 1409 1410 c = buf; 1411 1412 while (*c != '\0') { 1413 switch (*c) { 1414 case 'a': 1415 c++; 1416 c++; 1417 devno = atoi(c); 1418 while (*c >= '0' && *c <= '9') 1419 c++; 1420 c++; 1421 unit = atoi(c); 1422 if (*c == '-') c++; 1423 while (*c >= '0' && *c <= '9') 1424 c++; 1425 c++; 1426 state = atoi(c); 1427 if (*c == '-') 1428 c++; 1429 while (*c >= '0' && *c <= '9') 1430 c++; 1431 c++; 1432 newno = atoi(c); 1433 while (*c >= '0' && *c <= '9') 1434 c++; 1435 add_history(devno, unit, state, newno); 1436 while (*c != '\n') 1437 c++; 1438 c++; 1439 break; 1440 case 'c': 1441 c++; 1442 c++; 1443 devno = atoi(c); 1444 while (*c >= '0' && *c <= '9') 1445 c++; 1446 if (*c == ' ') 1447 c++; 1448 if (*c != '\n') 1449 change_history(devno, c); 1450 while (*c != '\n') 1451 c++; 1452 c++; 1453 break; 1454 case 'd': 1455 c++; 1456 devno = atoi(c); 1457 disable(devno); 1458 while (*c != '\n') 1459 c++; 1460 c++; 1461 break; 1462 case 'e': 1463 c++; 1464 devno = atoi(c); 1465 enable(devno); 1466 while (*c != '\n') 1467 c++; 1468 c++; 1469 break; 1470 case 'q': 1471 while (*c != '\0') 1472 c++; 1473 break; 1474 default: 1475 printf("unknown command %c\n", *c); 1476 while (*c != '\0' && *c != '\n') 1477 c++; 1478 break; 1479 } 1480 } 1481 } 1482