xref: /original-bsd/old/dlmpcc/dlmpcc.c (revision f1324ba5)
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