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.6 (Berkeley) 01/17/91";
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 <tahoe/vba/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
main(argc,argv)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
bldmap(dlbd)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 */
x25bargs(args)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 */
snabargs(args)214 snabargs(args)
215 char *args;
216 {
217 }
218
219 /*
220 * decode async arguments for board
221 */
asybargs(args)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 */
x25pargs(port,args)232 x25pargs(port,args)
233 int port;
234 char *args;
235 {
236 }
237
238 /*
239 * decode sna arguments for port
240 */
snapargs(port,args)241 snapargs(port, args)
242 int port;
243 char *args;
244 {
245 }
246
gethi()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
getlo()256 getlo()
257 {
258 int i;
259
260 for (i = 0; i < MPMAXPORT && cf.protoports[i] == 0; i++)
261 ;
262 return (i);
263 }
264
prntmap(board)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 */
mkldnm()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 *
strtok(s,c)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 };
fccs(line,tptr,pptr)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
soc(line,sptr)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
download(mpccnum)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
dlokay(bdfd,mpccnum)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
dl(dskfd,bdfd,size)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 */
config(dlfd)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 */
tknzmap(map)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