1 /* 2 * Copyright (c) 1988 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Computer Consoles Inc. 7 * 8 * Redistribution and use in source and binary forms are permitted 9 * provided that the above copyright notice and this paragraph are 10 * duplicated in all such forms and that any documentation, 11 * advertising materials, and other materials related to such 12 * distribution and use acknowledge that the software was developed 13 * by the University of California, Berkeley. The name of the 14 * University may not be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19 */ 20 21 #ifndef lint 22 char copyright[] = 23 "@(#) Copyright (c) 1988 The Regents of the University of California.\n\ 24 All rights reserved.\n"; 25 #endif /* not lint */ 26 27 #ifndef lint 28 static char sccsid[] = "@(#)dlmpcc.c 5.3 (Berkeley) 10/19/88"; 29 #endif /* not lint */ 30 31 /* 32 * MPCC Download and Configuration Program. 33 */ 34 #include <stdio.h> 35 #include <ctype.h> 36 #include <fcntl.h> 37 #include <sys/ioctl.h> 38 #include <errno.h> 39 40 #include <sys/types.h> 41 #include <tahoevba/mpreg.h> 42 #include <stdio.h> 43 44 #include "scnhdr.h" 45 46 #define MAXMPCC 16 47 48 char *MPCCTAB = "/etc/mpcctab"; 49 int resetflg = 0; 50 51 main(argc, argv) 52 char *argv[]; 53 { 54 int bd; 55 56 if (argc == 1) { 57 for (bd = 0; bd < MAXMPCC; bd++) 58 if (bldmap(bd) != -1) 59 download(bd); 60 exit(0); 61 } 62 for (argc--, argv++; argc > 0; argc--, argv++) { 63 bd = atoi(argv[0]); 64 if (strcmp(argv[0], "-r") == 0) { 65 resetflg = 1; 66 continue; 67 } 68 if (bd > MAXMPCC || bd < 0) { 69 printf("Illegal Board Number=> %d\n", bd); 70 continue; 71 } 72 if (bldmap(bd) == -1) 73 continue; 74 download(bd); 75 } 76 exit(0); 77 } 78 79 /* 80 * Build Load Module Map 81 */ 82 struct bdcf cf; 83 struct abdcf bdasy; 84 85 #define LINESIZE 128 86 87 bldmap(dlbd) 88 int dlbd; /* board to be downloaded */ 89 { 90 FILE *tabfp; 91 int bd, port, count; 92 char *bdstr, *strtok(), protocol, line[LINESIZE]; 93 char *lptr, *lptr1, *lptr2; 94 95 protocol = '\0'; 96 /* open the configuration file for reading */ 97 if ((tabfp = fopen(MPCCTAB, "r")) == NULL) { 98 printf("No Configuration File: %s\n", MPCCTAB); 99 return (-1); 100 } 101 for (;;) { 102 if (fgets(&line[0], LINESIZE-1, tabfp) == NULL) { 103 fclose(tabfp); 104 return (-1); 105 } 106 count++; 107 line[strlen(line)-1] = '\0'; 108 lptr = strtok(line, ':'); 109 if (tolower(*lptr) != 'm') 110 continue; 111 lptr = strtok((char *)0, ':'); 112 bd = atoi(lptr); 113 if (bd == dlbd) 114 break; 115 } 116 cf.fccstimer = 20; /* default to 1 sec (20 * 50ms) */ 117 cf.fccsports = 0; /* no ports are fccs */ 118 cf.fccssoc = 0; /* no ports switch on close */ 119 for (port = 0; port < MPMAXPORT; port++) 120 cf.protoports[port] = MPPROTO_UNUSED; 121 /* check for the keywords following the board number */ 122 lptr1 = (char *)0; 123 lptr2 = (char *)0; 124 while (*lptr) { 125 lptr = strtok((char *)0, ':'); 126 if (!strncmp(lptr, "FCCS", 4)) { 127 lptr1 = lptr; 128 continue; 129 } 130 if (!strncmp(lptr, "SOC", 3)) { 131 lptr2 = lptr; 132 continue; 133 } 134 } 135 /* process the board and port characteristics */ 136 while (fgets(&line[0], LINESIZE-1, tabfp) != NULL) { 137 count++; 138 line[strlen(line)-1] = '\0'; 139 if (!line[0]) /* if newline only */ 140 continue; 141 lptr = strtok(line, ':'); 142 if (tolower(*lptr) == 'm') 143 break; 144 if (*lptr == '#') /* ignore comment */ 145 continue; 146 if (tolower(*lptr) == 'p' && tolower(*(lptr+1)) == 'o') { 147 /* PORT */ 148 port = atoi(lptr = strtok((char *)0, ':')); 149 protocol = *(lptr = strtok((char *)0, ':')); 150 switch (cf.protoports[port] = protocol) { 151 case '3' : /* ASYNCH 32 port */ 152 case 'A' : /* ASYNCH */ 153 break; 154 case 'B': /* BISYNCH */ 155 break; 156 case 'S': /* SDLC */ 157 snapargs(port, lptr); 158 break; 159 case 'X': /* X25 */ 160 x25pargs(port, lptr); 161 break; 162 default: 163 printf( 164 "No protocol specified on PROTOCOL line in configuration file %s:%d: %s\n", 165 MPCCTAB, count, line); 166 protocol = 'A'; 167 break; 168 } 169 continue; 170 } 171 if (tolower(*lptr) == 'p' && tolower(*(lptr+1)) == 'r') { 172 /* PROTOCOL */ 173 #ifdef notdef 174 if(protocol) { 175 printf( 176 "second protocol specified on PROTOCOL line in configuration file %s:%d: %s\n", 177 MPCCTAB, count, line); 178 continue; 179 } 180 #endif 181 lptr = strtok((char *) 0, ':'); 182 switch (protocol = *lptr) { 183 case '3': /* ASYNCH 32 port */ 184 case 'A': /* ASYNCH */ 185 asybargs(lptr); 186 break; 187 case 'B': /* BISYNCH */ 188 break; 189 case 'S': /* SDLC */ 190 snabargs(lptr); 191 break; 192 case 'X': /* X25 */ 193 x25bargs(lptr); 194 break; 195 default: 196 printf( 197 "No protocol specified on PROTOCOL line in configuration file %s:%d: %s\n", 198 MPCCTAB, count, line); 199 protocol = 'A'; 200 break; 201 } 202 continue; 203 } 204 printf("Error in configuration file %s,line %d, %s\n", 205 MPCCTAB, count, line); 206 } 207 fclose(tabfp); 208 mkldnm(); 209 return (0); 210 } 211 212 /* 213 * decode x25 arguments for board 214 * 215 * for X.25, the arguments are N1, N2, T1, T2, T3, T4, K). 216 */ 217 x25bargs(args) 218 char *args; 219 { 220 } 221 222 /* 223 * decode sna arguments for board 224 * for SNA, the arguments are N1, N2, T1, T2, T3, T4, K). 225 */ 226 snabargs(args) 227 char *args; 228 { 229 } 230 231 /* 232 * decode async arguments for board 233 */ 234 asybargs(args) 235 char *args; 236 { 237 238 bdasy.xmtbsz = atoi(strtok((char *)0, ':')); 239 } 240 241 /* 242 * decode x25 arguments for port 243 */ 244 x25pargs(port,args) 245 int port; 246 char *args; 247 { 248 } 249 250 /* 251 * decode sna arguments for port 252 */ 253 snapargs(port, args) 254 int port; 255 char *args; 256 { 257 } 258 259 gethi() 260 { 261 int i; 262 263 for (i = MPMAXPORT-1; i >= 0 && cf.protoports[i] == 0; i--) 264 ; 265 return (i); 266 } 267 268 getlo() 269 { 270 int i; 271 272 for (i = 0; i < MPMAXPORT && cf.protoports[i] == 0; i++) 273 ; 274 return (i); 275 } 276 277 prntmap(board) 278 int board; 279 { 280 int j; 281 282 printf("\nMPCC #: %d\n", board); 283 for (j = 0; j < MPMAXPORT; j++) { 284 printf("port: %d %c", j, cf.protoports[j]); 285 switch (cf.protoports[j]) { 286 case '3': case 'A': 287 printf("\n"); 288 break; 289 case 'B': 290 break; 291 case 'S': 292 break; 293 case 'X': 294 break; 295 default: 296 printf("Unused\n"); 297 break; 298 } 299 } 300 printf("ldname: %s, ", cf.loadname); 301 printf("hiport: %d, loport: %d\n", gethi(), getlo()); 302 if (cf.fccsports != 0) 303 printf("FCCS\n"); 304 switch (cf.protoports[0]) { 305 case '3': case 'A': 306 printf("xmtsize: %d\n", bdasy.xmtbsz); 307 break; 308 case 'B': 309 break; 310 case 'S': 311 break; 312 case 'X': 313 break; 314 } 315 printf("protoports: %s\n", cf.protoports); 316 } 317 318 /* 319 * Make Load Module Name 320 * 321 * if any port is 'ASYNCH" 322 * add 'a' to load module name 323 * if any port is 'BISYNCH' 324 * add 'b' to load module name 325 * if any port is 'SDLC' 326 * add 's' to load module name 327 * if any port is 'X25' 328 * add 'x' to load module name 329 */ 330 mkldnm() 331 { 332 static char *pcols = "ABSX3"; 333 char *proto; 334 int j, offset; 335 336 offset = 0; 337 for (proto = pcols; *proto; proto++) { 338 for (j = 0; j < MPMAXPORT; j++) { 339 if (cf.protoports[j] == *proto) { 340 if (*proto == '3') 341 cf.loadname[offset] = '3'; 342 else 343 cf.loadname[offset] = tolower(*proto); 344 offset++; 345 break; 346 } 347 } 348 cf.loadname[offset] = '\0'; 349 } 350 } 351 352 /* 353 * if a string is passed as an argument, 354 * save it in the local string area 355 * set the local index to the start of the string 356 * else 357 * set start to the current character in the string 358 * while the character is not the separator, 359 * and the character is not NULL 360 * skip the character 361 */ 362 static 363 char * 364 strtok(s, c) 365 char *s, c; 366 { 367 static char locals[LINESIZE]; 368 static int i; 369 char *start; 370 371 if (s != 0) { 372 strcpy(locals, s); 373 i = 0; 374 } 375 for (start = &locals[i] ; locals[i] && locals[i] != c; i++) 376 ; 377 if (locals[i]) { 378 locals[i] = '\0'; 379 i++; 380 } 381 while (*start == ' ') 382 start++; 383 return (start); 384 } 385 386 short bits[] = { 1, 2, 4, 8, 16, 32, 64, 128 }; 387 fccs(line, tptr, pptr) 388 char *line, *tptr, *pptr; 389 { 390 u_short ports, num, time; 391 392 ports = 0; 393 line = strtok(line, ','); 394 while (*(line = strtok((char *) 0, ',')) != '\0') { 395 num = (short) atoi(line); 396 if (num >= 0 && num < 8) 397 ports |= bits[num]; 398 else if (num >= 50 && num < 6400) 399 time = num / 50; 400 else 401 printf("bad value for FCCS: %d\n", num); 402 } 403 *pptr = ports; 404 *tptr = time; 405 } 406 407 soc(line, sptr) 408 char *line, *sptr; 409 { 410 u_short ports, num; 411 412 ports = 0; 413 line = strtok(line, ','); 414 while (*(line = strtok((char *) 0, ',')) != '\0') { 415 num = atoi(line); 416 if (num >= 0 && num < 8) 417 ports |= bits[num]; 418 else 419 printf("bad value for SOC: %d\n",num); 420 } 421 *sptr = ports; 422 } 423 424 char buffer[MPDLBUFSIZE]; 425 extern int errno; 426 struct head1 { 427 long magic; 428 long fill[12]; 429 struct scnhdr text; 430 struct scnhdr data; 431 struct scnhdr bss; 432 } header1; 433 434 download(mpccnum) 435 int mpccnum; 436 { 437 char dlname[LINESIZE], fullname[LINESIZE]; 438 char *ldname, *ppmap; 439 int dlfd, ldfd; 440 char *it; 441 short i; 442 char hilo[2]; 443 long realsize; 444 445 sprintf(dlname, "/dev/mpcc%d", mpccnum); 446 if (*cf.loadname == '3') 447 sprintf(fullname, "/etc/mpcc32"); 448 else 449 sprintf(fullname, "/etc/mpccdl"); 450 if ((cf.loadname[0]) == '\0') 451 return (-1); 452 if ((dlfd = open(dlname, O_RDWR)) == MP_DLERROR) { 453 printf("Can not open %s\n",dlname); 454 return (-1); 455 } 456 if ((ldfd = open(fullname, O_RDONLY)) == MP_DLERROR) { 457 close(dlfd); 458 printf("Can not access protocol code file: %s\n", fullname); 459 return (-1); 460 } 461 if (dlokay(dlfd,mpccnum) == MP_DLERROR) { 462 close(ldfd); 463 close(dlfd); 464 return (-1); 465 } 466 printf("Downloading MPCC #%x\n", mpccnum); 467 /* read executable file header */ 468 if (read(ldfd, &header1, sizeof(header1)) != sizeof(header1)) { 469 printf("Can not read %s\n", fullname); 470 return (-1); 471 } 472 /* place at start of text space */ 473 if (lseek(ldfd, header1.text.s_scnptr , (int) 0) == -1) { 474 printf("lseek error(text): %d", errno); 475 return (-1); 476 } 477 /* send text */ 478 realsize = header1.data.s_paddr - header1.text.s_paddr; 479 if (dl(ldfd, dlfd, realsize) == -1) { 480 ioctl(dlfd, MPIORESETBOARD, 0L); 481 return (-1); 482 } 483 /* place at start of data space */ 484 if (lseek(ldfd, header1.data.s_scnptr , (int) 0) == -1) { 485 printf("lseek error(data): %d", errno); 486 return (-1); 487 } 488 /* send initialized data */ 489 realsize = header1.bss.s_paddr - header1.data.s_paddr; 490 if (dl(ldfd, dlfd, realsize) == -1) { 491 ioctl(dlfd, MPIORESETBOARD, 0L); 492 return (-1); 493 } 494 /* signal end of code */ 495 if (ioctl(dlfd, MPIOENDCODE, (char *) 0) == MP_DLERROR) { 496 printf("MPIOENDCODE ioctl failed\n"); 497 ioctl(dlfd, MPIORESETBOARD, 0L); 498 return (-1); 499 } 500 /* download configuration information */ 501 if (config(dlfd) == -1) { 502 ioctl(dlfd, MPIORESETBOARD, 0L); 503 return (-1); 504 } 505 /* write port/protocol map */ 506 ppmap = (char *)&cf.protoports[0]; 507 tknzmap(ppmap); 508 if (ioctl(dlfd, MPIOPORTMAP, ppmap) == MP_DLERROR) { 509 printf("MPIOPORTMAP ioctl failed\n"); 510 ioctl(dlfd, MPIORESETBOARD, 0L); 511 return (-1); 512 } 513 /* signal end of download */ 514 if (ioctl(dlfd, MPIOENDDL, (char *) 0) == MP_DLERROR) { 515 printf("MPIOENDDL ioctl failed\n"); 516 ioctl(dlfd, MPIORESETBOARD, 0L); 517 return (-1); 518 } 519 close(dlfd); 520 close(ldfd); 521 printf("Download Complete and Successful\n"); 522 return (0); 523 } 524 525 dlokay(bdfd, mpccnum) 526 int bdfd, mpccnum; 527 { 528 char answer; 529 530 if (resetflg) { 531 printf("Reseting MPCC #%x\n",mpccnum); 532 ioctl(bdfd, MPIORESETBOARD, 0L); 533 sleep(10); 534 } 535 if (ioctl(bdfd, MPIOSTARTDL, 0) == MP_DLERROR) { 536 if (errno == EBUSY) { 537 printf("MPCC #%x has already been downloaded.\n", 538 mpccnum); 539 printf("Do you want to re-download it?: "); 540 fscanf(stdin,"%c",&answer); 541 while (getchar() != '\n') 542 ; 543 if ((answer | 0x60) != 'y') 544 return (MP_DLERROR); 545 ioctl(bdfd, MPIORESETBOARD, 0L); 546 sleep(10); 547 if (ioctl(bdfd, MPIOSTARTDL, (char *) 0) == MP_DLERROR) { 548 printf("Can't download MPCC #%x\n", mpccnum); 549 return (MP_DLERROR); 550 } 551 } else { 552 switch (errno) { 553 case ENODEV: 554 printf("MPCC #%x not in system\n", mpccnum); 555 break; 556 case EACCES: 557 printf("Download area in use, try later\n"); 558 break; 559 case ENOSPC: 560 printf("MPCC #%x already being downloaded\n", 561 mpccnum); 562 break; 563 default: 564 printf("Unknown response from MPCC #%x\n", 565 mpccnum); 566 break; 567 } 568 return (MP_DLERROR); 569 } 570 } 571 return (0); 572 } 573 574 dl(dskfd, bdfd, size) 575 int dskfd, bdfd; 576 long size; 577 { 578 int bytes; 579 580 while (size > 0) { 581 bytes = (size < MPDLBUFSIZE) ? (int) size : MPDLBUFSIZE; 582 if ((bytes = read(dskfd, buffer, bytes)) == MP_DLERROR) { 583 close(dskfd); 584 close(bdfd); 585 printf("Download-Can't read buffer\n"); 586 return (-1); 587 } 588 if (write(bdfd, buffer, bytes) == MP_DLERROR) { 589 close(dskfd); 590 close(bdfd); 591 printf("Download-Can't write buffer\n"); 592 return (-1); 593 } 594 size -= bytes; 595 } 596 return (0); 597 } 598 599 /* 600 * download each protocol's configuration data 601 * and the configuration data for tboard. 602 */ 603 config(dlfd) 604 int dlfd; 605 { 606 register int i; 607 char *ldname; 608 609 for (ldname = cf.loadname; *ldname; ldname++) { 610 switch (*ldname) { 611 case '3': case 'a': 612 if (ioctl(dlfd, MPIOASYNCNF, &bdasy) == MP_DLERROR) { 613 printf("async ioctl failed\n"); 614 return (-1); 615 } 616 break; 617 case 'b': 618 break; 619 case 'x': 620 break; 621 622 case 's': 623 break; 624 } 625 } 626 } 627 628 /* 629 * tokenize the protoport string, 630 * (change from the letter to the corresponding number). 631 */ 632 tknzmap(map) 633 char *map; 634 { 635 short i; 636 637 for (i = 0; i < MPMAXPORT; i++) { 638 switch (*map) { 639 case '3' : *map = MPPROTO_ASYNC; break; 640 case 'A' : *map = MPPROTO_ASYNC; break; 641 case 'B' : *map = MPPROTO_BISYNC; break; 642 case 'S' : *map = MPPROTO_SNA; break; 643 case 'X' : *map = MPPROTO_X25; break; 644 default: *map = MPPROTO_UNUSED; break; 645 } 646 map++; 647 } 648 } 649