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