1 /* $OpenBSD: ukcutil.c,v 1.17 2008/03/24 21:35:03 maja 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 #ifndef LINT 28 static char rcsid[] = "$OpenBSD: ukcutil.c,v 1.17 2008/03/24 21:35:03 maja Exp $"; 29 #endif 30 31 #include <sys/types.h> 32 #include <sys/time.h> 33 #include <sys/device.h> 34 #include <limits.h> 35 #include <nlist.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <string.h> 39 40 #include "cmd.h" 41 #include "exec.h" 42 #include "ukc.h" 43 #include "misc.h" 44 45 extern int ukc_mod_kernel; 46 47 struct cfdata * 48 get_cfdata(int idx) 49 { 50 return((struct cfdata *)(adjust((caddr_t)nl[P_CFDATA].n_value) + 51 idx * sizeof(struct cfdata))); 52 } 53 54 short * 55 get_locnamp(int idx) 56 { 57 return((short *)(adjust((caddr_t)nl[S_LOCNAMP].n_value) + 58 idx * sizeof(short))); 59 } 60 61 caddr_t * 62 get_locnames(int idx) 63 { 64 return((caddr_t *)(adjust((caddr_t)nl[P_LOCNAMES].n_value) + 65 idx * sizeof(caddr_t))); 66 } 67 68 int * 69 get_extraloc(int idx) 70 { 71 return((int *)(adjust((caddr_t)nl[IA_EXTRALOC].n_value) + 72 idx * sizeof(int))); 73 } 74 75 char * 76 get_pdevnames(int idx) 77 { 78 caddr_t *p; 79 80 p = (caddr_t *)adjust((caddr_t)nl[P_PDEVNAMES].n_value + 81 idx * sizeof(caddr_t)); 82 return(char *)adjust((caddr_t)*p); 83 84 } 85 86 struct pdevinit * 87 get_pdevinit(int idx) 88 { 89 return((struct pdevinit *)(adjust((caddr_t)nl[S_PDEVINIT].n_value) + 90 idx * sizeof(struct pdevinit))); 91 } 92 93 int 94 more(void) 95 { 96 int quit = 0; 97 cmd_t cmd; 98 99 if (cnt != -1) { 100 if (cnt > 0 && cnt == lines) { 101 printf("--- more ---"); 102 fflush(stdout); 103 ask_cmd(&cmd); 104 cnt = 0; 105 if (cmd.cmd[0] == 'q' || cmd.cmd[0] == 'Q') 106 quit = 1; 107 } 108 cnt++; 109 } 110 return (quit); 111 } 112 113 void 114 pnum(int val) 115 { 116 if (val > -2 && val < 16) { 117 printf("%d", val); 118 return; 119 } 120 121 switch (base) { 122 case 8: 123 printf("0%o", val); 124 break; 125 case 10: 126 printf("%d", val); 127 break; 128 case 16: 129 default: 130 printf("0x%x", val); 131 break; 132 } 133 } 134 135 void 136 pdevnam(short devno) 137 { 138 struct cfdata *cd; 139 struct cfdriver *cdrv; 140 141 cd = get_cfdata(devno); 142 143 cdrv = (struct cfdriver *)adjust((caddr_t)cd->cf_driver); 144 145 #if defined(OLDSCSIBUS) 146 if (strlen(adjust((caddr_t)cdrv->cd_name)) == 0) 147 printf("oldscsibus"); 148 #endif 149 printf("%s", adjust((caddr_t)cdrv->cd_name)); 150 151 switch (cd->cf_fstate) { 152 case FSTATE_NOTFOUND: 153 case FSTATE_DNOTFOUND: 154 printf("%d", cd->cf_unit); 155 break; 156 case FSTATE_FOUND: 157 printf("*FOUND*"); 158 break; 159 case FSTATE_STAR: 160 case FSTATE_DSTAR: 161 printf("*"); 162 break; 163 default: 164 printf("*UNKNOWN*"); 165 break; 166 } 167 } 168 169 void 170 pdev(short devno) 171 { 172 struct pdevinit *pi; 173 struct cfdata *cd; 174 short *s, *ln; 175 int *i; 176 caddr_t *p; 177 char c; 178 179 if (nopdev == 0) { 180 if (devno > maxdev && devno <= totdev) { 181 printf("%3d free slot (for add)\n", devno); 182 return; 183 } 184 if (devno > totdev && devno <= totdev + maxpseudo) { 185 pi = get_pdevinit(devno - totdev -1); 186 printf("%3d %s count %d", devno, 187 get_pdevnames(devno - totdev - 1), 188 abs(pi->pdev_count)); 189 if (pi->pdev_count < 0) 190 printf(" disable"); 191 printf(" (pseudo device)\n"); 192 return; 193 } 194 } 195 196 if (devno > maxdev) { 197 printf("Unknown devno (max is %d)\n", maxdev); 198 return; 199 } 200 201 cd = get_cfdata(devno); 202 203 printf("%3d ", devno); 204 pdevnam(devno); 205 printf(" at"); 206 207 c = ' '; 208 s = (short *)adjust((caddr_t)cd->cf_parents); 209 if (*s == -1) 210 printf(" root"); 211 while (*s != -1) { 212 printf("%c", c); 213 pdevnam(*s); 214 c = '|'; 215 s++; 216 } 217 switch (cd->cf_fstate) { 218 case FSTATE_NOTFOUND: 219 case FSTATE_FOUND: 220 case FSTATE_STAR: 221 break; 222 case FSTATE_DNOTFOUND: 223 case FSTATE_DSTAR: 224 printf(" disable"); 225 break; 226 default: 227 printf(" ???"); 228 break; 229 } 230 231 i = (int *)adjust((caddr_t)cd->cf_loc); 232 ln = get_locnamp(cd->cf_locnames); 233 while (*ln != -1) { 234 p = get_locnames(*ln); 235 printf(" %s ", adjust((caddr_t)*p)); 236 ln++; 237 pnum(*i); 238 i++; 239 } 240 printf(" flags 0x%x\n", cd->cf_flags); 241 } 242 243 int 244 number(const char *c, int *val) 245 { 246 int neg = 0, base = 10; 247 u_int num = 0; 248 249 if (*c == '-') { 250 neg = 1; 251 c++; 252 } 253 if (*c == '0') { 254 base = 8; 255 c++; 256 if (*c == 'x' || *c == 'X') { 257 base = 16; 258 c++; 259 } 260 } 261 while (*c != '\n' && *c != '\t' && *c != ' ' && *c != '\0') { 262 u_char cc = *c; 263 264 if (cc >= '0' && cc <= '9') 265 cc = cc - '0'; 266 else if (cc >= 'a' && cc <= 'f') 267 cc = cc - 'a' + 10; 268 else if (cc >= 'A' && cc <= 'F') 269 cc = cc - 'A' + 10; 270 else 271 return (-1); 272 273 if (cc > base) 274 return (-1); 275 num = num * base + cc; 276 c++; 277 } 278 279 if (neg && num > INT_MAX) /* overflow */ 280 return (1); 281 *val = neg ? - num : num; 282 return (0); 283 } 284 285 int 286 device(char *cmd, int *len, short *unit, short *state) 287 { 288 short u = 0, s = FSTATE_FOUND; 289 int l = 0; 290 char *c; 291 292 c = cmd; 293 while (*c >= 'a' && *c <= 'z') { 294 l++; 295 c++; 296 } 297 298 if (*c == '*') { 299 s = FSTATE_STAR; 300 c++; 301 } else { 302 while (*c >= '0' && *c <= '9') { 303 s = FSTATE_NOTFOUND; 304 u = u*10 + *c - '0'; 305 c++; 306 } 307 } 308 while (*c == ' ' || *c == '\t' || *c == '\n') 309 c++; 310 311 if (*c == '\0') { 312 *len = l; 313 *unit = u; 314 *state = s; 315 return(0); 316 } 317 return(-1); 318 } 319 320 int 321 attr(char *cmd, int *val) 322 { 323 short attr = -1, i = 0, l = 0; 324 caddr_t *p; 325 char *c; 326 327 c = cmd; 328 while (*c != ' ' && *c != '\t' && *c != '\n' && *c != '\0') { 329 c++; 330 l++; 331 } 332 333 p = get_locnames(0); 334 335 while (i <= maxlocnames) { 336 if (strlen((char *)adjust((caddr_t)*p)) == l) { 337 if (strncasecmp(cmd, adjust((caddr_t)*p), l) == 0) 338 attr = i; 339 } 340 p++; 341 i++; 342 } 343 if (attr == -1) 344 return (-1); 345 346 *val = attr; 347 return(0); 348 } 349 350 void 351 modify(char *item, int *val) 352 { 353 cmd_t cmd; 354 int a; 355 356 ukc_mod_kernel = 1; 357 while (1) { 358 printf("%s [", item); 359 pnum(*val); 360 printf("] ? "); 361 fflush(stdout); 362 363 ask_cmd(&cmd); 364 365 if (strlen(cmd.cmd) != 0) { 366 if (strlen(cmd.args) == 0) { 367 if (number(cmd.cmd, &a) == 0) { 368 *val = a; 369 break; 370 } else 371 printf("Unknown argument\n"); 372 } else 373 printf("Too many arguments\n"); 374 } else 375 break; 376 } 377 } 378 379 void 380 change(int devno) 381 { 382 int i, share = 0, *j = NULL, *k = NULL, *l; 383 struct cfdata *cd, *c; 384 struct pdevinit *pi; 385 short *ln, *lk; 386 caddr_t *p; 387 388 ukc_mod_kernel = 1; 389 if (devno <= maxdev) { 390 pdev(devno); 391 if (!ask_yn("change")) 392 return; 393 394 cd = get_cfdata(devno); 395 396 /* 397 * Search for some other driver sharing this 398 * locator table. if one does, we may need to 399 * replace the locators with a new copy. 400 */ 401 c = get_cfdata(0); 402 for (i = 0; c->cf_driver; i++) { 403 if (i != devno && c->cf_loc == cd->cf_loc) 404 share = 1; 405 c++; 406 } 407 408 ln = get_locnamp(cd->cf_locnames); 409 l = (int *)adjust((caddr_t)cd->cf_loc); 410 411 if (share) { 412 if (oldkernel) { 413 printf("Can't do that on this kernel\n"); 414 return; 415 } 416 417 lk = ln; 418 i = 0; 419 while (*lk != -1) { 420 lk++; 421 i++; 422 } 423 lk = ln; 424 425 j = (int *)adjust((caddr_t)nl[I_NEXTRALOC].n_value); 426 k = (int *)adjust((caddr_t)nl[I_UEXTRALOC].n_value); 427 if ((i + *k) > *j) { 428 printf("Not enough space to change device.\n"); 429 return; 430 } 431 432 j = l = get_extraloc(*k); 433 bcopy(adjust((caddr_t)cd->cf_loc), 434 l, sizeof(int) * i); 435 } 436 437 while (*ln != -1) { 438 p = get_locnames(*ln); 439 modify((char *)adjust(*p), l); 440 ln++; 441 l++; 442 } 443 modify("flags", &cd->cf_flags); 444 445 if (share) { 446 if (bcmp(adjust((caddr_t)cd->cf_loc), j, 447 sizeof(int) * i)) { 448 cd->cf_loc = (int *)readjust((caddr_t)j); 449 *k = *k + i; 450 } 451 } 452 453 printf("%3d ", devno); 454 pdevnam(devno); 455 printf(" changed\n"); 456 pdev(devno); 457 return; 458 } 459 460 if (nopdev == 0) { 461 if (devno > maxdev && devno <= totdev) { 462 printf("%3d can't change free slot\n", devno); 463 return; 464 } 465 466 if (devno > totdev && devno <= totdev + maxpseudo) { 467 pdev(devno); 468 if (ask_yn("change")) { 469 pi = get_pdevinit(devno-totdev-1); 470 modify("count", &pi->pdev_count); 471 printf("%3d %s changed\n", devno, 472 get_pdevnames(devno - totdev - 1)); 473 pdev(devno); 474 } 475 return; 476 } 477 } 478 479 printf("Unknown devno (max is %d)\n", totdev+maxpseudo); 480 } 481 482 void 483 change_history(int devno, char *str) 484 { 485 int i, share = 0, *j = NULL, *k = NULL, *l; 486 struct cfdata *cd, *c; 487 struct pdevinit *pi; 488 short *ln, *lk; 489 490 ukc_mod_kernel = 1; 491 492 if (devno <= maxdev) { 493 494 pdev(devno); 495 cd = get_cfdata(devno); 496 497 /* 498 * Search for some other driver sharing this 499 * locator table. if one does, we may need to 500 * replace the locators with a new copy. 501 */ 502 c = get_cfdata(0); 503 for (i = 0; c->cf_driver; i++) { 504 if (i != devno && c->cf_loc == cd->cf_loc) 505 share = 1; 506 c++; 507 } 508 509 ln = get_locnamp(cd->cf_locnames); 510 l = (int *)adjust((caddr_t)cd->cf_loc); 511 512 if (share) { 513 if (oldkernel) { 514 printf("Can't do that on this kernel\n"); 515 return; 516 } 517 518 lk = ln; 519 i = 0; 520 while (*lk != -1) { 521 lk++; 522 i++; 523 } 524 lk = ln; 525 526 j = (int *)adjust((caddr_t)nl[I_NEXTRALOC].n_value); 527 k = (int *)adjust((caddr_t)nl[I_UEXTRALOC].n_value); 528 if ((i + *k) > *j) { 529 printf("Not enough space to change device.\n"); 530 return; 531 } 532 533 j = l = get_extraloc(*k); 534 bcopy(adjust((caddr_t)cd->cf_loc), 535 l, sizeof(int) * i); 536 } 537 538 while (*ln != -1) { 539 *l = atoi(str); 540 if (*str == '-') 541 str++; 542 while (*str >= '0' && *str <= '9') 543 str++; 544 if (*str == ' ') 545 str++; 546 ln++; 547 l++; 548 } 549 550 if (*str) { 551 cd->cf_flags = atoi(str); 552 if (*str == '-') 553 str++; 554 while (*str >= '0' && *str <= '9') 555 str++; 556 if (*str == ' ') 557 str++; 558 } 559 560 if (share) { 561 if (bcmp(adjust((caddr_t)cd->cf_loc), 562 j, sizeof(int) * i)) { 563 cd->cf_loc = (int *)readjust((caddr_t)j); 564 *k = *k + i; 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 int *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 = (int *)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(void) 1299 { 1300 cmd_t cmd; 1301 int i, st; 1302 1303 /* Set up command table pointer */ 1304 cmd.table = cmd_table; 1305 1306 printf("Enter 'help' for information\n"); 1307 1308 /* Edit cycle */ 1309 do { 1310 again: 1311 printf("ukc> "); 1312 fflush(stdout); 1313 ask_cmd(&cmd); 1314 1315 if (cmd.cmd[0] == '\0') 1316 goto again; 1317 for (i = 0; cmd_table[i].cmd != NULL; i++) 1318 if (strstr(cmd_table[i].cmd, cmd.cmd) == 1319 cmd_table[i].cmd) 1320 break; 1321 1322 /* Quick hack to put in '?' == 'help' */ 1323 if (!strcmp(cmd.cmd, "?")) 1324 i = 0; 1325 1326 /* Check for valid command */ 1327 if (cmd_table[i].cmd == NULL) { 1328 printf("Invalid command '%s'. Try 'help'.\n", cmd.cmd); 1329 continue; 1330 } else 1331 strlcpy(cmd.cmd, cmd_table[i].cmd, sizeof cmd.cmd); 1332 1333 /* Call function */ 1334 st = cmd_table[i].fcn(&cmd); 1335 1336 /* Update status */ 1337 if (st == CMD_EXIT) 1338 break; 1339 if (st == CMD_SAVE) 1340 break; 1341 } while (1); 1342 1343 return (st == CMD_SAVE); 1344 } 1345 1346 void 1347 process_history(int len, char *buf) 1348 { 1349 char *c; 1350 int devno, newno; 1351 short unit, state; 1352 struct timezone *tz; 1353 1354 if (len == 0) { 1355 printf("History is empty\n"); 1356 return; 1357 } 1358 1359 printf("Processing history...\n"); 1360 1361 buf[len] = 0; 1362 1363 c = buf; 1364 1365 while (*c != NULL) { 1366 switch (*c) { 1367 case 'a': 1368 c++; 1369 c++; 1370 devno = atoi(c); 1371 while (*c >= '0' && *c <= '9') 1372 c++; 1373 c++; 1374 unit = atoi(c); 1375 if (*c == '-') c++; 1376 while (*c >= '0' && *c <= '9') 1377 c++; 1378 c++; 1379 state = atoi(c); 1380 if (*c == '-') 1381 c++; 1382 while (*c >= '0' && *c <= '9') 1383 c++; 1384 c++; 1385 newno = atoi(c); 1386 while (*c >= '0' && *c <= '9') 1387 c++; 1388 add_history(devno, unit, state, newno); 1389 while (*c != '\n') 1390 c++; 1391 c++; 1392 break; 1393 case 'c': 1394 c++; 1395 c++; 1396 devno = atoi(c); 1397 while (*c >= '0' && *c <= '9') 1398 c++; 1399 if (*c == ' ') 1400 c++; 1401 if (*c != '\n') 1402 change_history(devno, c); 1403 while (*c != '\n') 1404 c++; 1405 c++; 1406 break; 1407 case 'd': 1408 c++; 1409 devno = atoi(c); 1410 disable(devno); 1411 while (*c != '\n') 1412 c++; 1413 c++; 1414 break; 1415 case 'e': 1416 c++; 1417 devno = atoi(c); 1418 enable(devno); 1419 while (*c != '\n') 1420 c++; 1421 c++; 1422 break; 1423 case 't': 1424 c++; 1425 c++; 1426 tz = (struct timezone *)adjust((caddr_t)nl[TZ_TZ]. 1427 n_value); 1428 tz->tz_minuteswest = atoi(c); 1429 while (*c != ' ') 1430 c++; 1431 c++; 1432 tz->tz_dsttime = atoi(c); 1433 while (*c != '\n') 1434 c++; 1435 c++; 1436 ukc_mod_kernel = 1; 1437 break; 1438 case 'q': 1439 while (*c != NULL) 1440 c++; 1441 break; 1442 default: 1443 printf("unknown command %c\n", *c); 1444 while (*c != NULL && *c != '\n') 1445 c++; 1446 break; 1447 } 1448 } 1449 } 1450