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