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