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