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