+#ifndef lint
+static char sccsid[] = "@(#)dlmpcc.c 5.1 (Berkeley from CCI) %G%";
+#endif
+
+/*
+ * MPCC Download and Configuration Program.
+ */
+#include <stdio.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <tahoevba/mpreg.h>
+#include <stdio.h>
+
+#include "scnhdr.h"
+
+#define MAXMPCC 16
+
+char *MPCCTAB = "/etc/mpcctab";
+int resetflg = 0;
+
+main(argc, argv)
+ char *argv[];
+{
+ int bd;
+
+ if (argc == 1) {
+ for (bd = 0; bd < MAXMPCC; bd++)
+ if (bldmap(bd) != -1)
+ download(bd);
+ exit(0);
+ }
+ for (argc--, argv++; argc > 0; argc--, argv++) {
+ bd = atoi(argv[0]);
+ if (strcmp(argv[0], "-r") == 0) {
+ resetflg = 1;
+ continue;
+ }
+ if (bd > MAXMPCC || bd < 0) {
+ printf("Illegal Board Number=> %d\n", bd);
+ continue;
+ }
+ if (bldmap(bd) == -1)
+ continue;
+ download(bd);
+ }
+ exit(0);
+}
+
+/*
+ * Build Load Module Map
+ */
+struct bdcf cf;
+struct abdcf bdasy;
+
+#define LINESIZE 128
+
+bldmap(dlbd)
+ int dlbd; /* board to be downloaded */
+{
+ FILE *tabfp;
+ int bd, port, count;
+ char *bdstr, *strtok(), protocol, line[LINESIZE];
+ char *lptr, *lptr1, *lptr2;
+
+ protocol = '\0';
+ /* open the configuration file for reading */
+ if ((tabfp = fopen(MPCCTAB, "r")) == NULL) {
+ printf("No Configuration File: %s\n", MPCCTAB);
+ return (-1);
+ }
+ for (;;) {
+ if (fgets(&line[0], LINESIZE-1, tabfp) == NULL) {
+ fclose(tabfp);
+ return (-1);
+ }
+ count++;
+ line[strlen(line)-1] = '\0';
+ lptr = strtok(line, ':');
+ if (tolower(*lptr) != 'm')
+ continue;
+ lptr = strtok((char *)0, ':');
+ bd = atoi(lptr);
+ if (bd == dlbd)
+ break;
+ }
+ cf.fccstimer = 20; /* default to 1 sec (20 * 50ms) */
+ cf.fccsports = 0; /* no ports are fccs */
+ cf.fccssoc = 0; /* no ports switch on close */
+ for (port = 0; port < MPMAXPORT; port++)
+ cf.protoports[port] = MPPROTO_UNUSED;
+ /* check for the keywords following the board number */
+ lptr1 = (char *)0;
+ lptr2 = (char *)0;
+ while (*lptr) {
+ lptr = strtok((char *)0, ':');
+ if (!strncmp(lptr, "FCCS", 4)) {
+ lptr1 = lptr;
+ continue;
+ }
+ if (!strncmp(lptr, "SOC", 3)) {
+ lptr2 = lptr;
+ continue;
+ }
+ }
+ /* process the board and port characteristics */
+ while (fgets(&line[0], LINESIZE-1, tabfp) != NULL) {
+ count++;
+ line[strlen(line)-1] = '\0';
+ if (!line[0]) /* if newline only */
+ continue;
+ lptr = strtok(line, ':');
+ if (tolower(*lptr) == 'm')
+ break;
+ if (*lptr == '#') /* ignore comment */
+ continue;
+ if (tolower(*lptr) == 'p' && tolower(*(lptr+1)) == 'o') {
+ /* PORT */
+ port = atoi(lptr = strtok((char *)0, ':'));
+ protocol = *(lptr = strtok((char *)0, ':'));
+ switch (cf.protoports[port] = protocol) {
+ case '3' : /* ASYNCH 32 port */
+ case 'A' : /* ASYNCH */
+ break;
+ case 'B': /* BISYNCH */
+ break;
+ case 'S': /* SDLC */
+ snapargs(port, lptr);
+ break;
+ case 'X': /* X25 */
+ x25pargs(port, lptr);
+ break;
+ default:
+ printf(
+"No protocol specified on PROTOCOL line in configuration file %s:%d: %s\n",
+ MPCCTAB, count, line);
+ protocol = 'A';
+ break;
+ }
+ continue;
+ }
+ if (tolower(*lptr) == 'p' && tolower(*(lptr+1)) == 'r') {
+ /* PROTOCOL */
+#ifdef notdef
+ if(protocol) {
+ printf(
+"second protocol specified on PROTOCOL line in configuration file %s:%d: %s\n",
+ MPCCTAB, count, line);
+ continue;
+ }
+#endif
+ lptr = strtok((char *) 0, ':');
+ switch (protocol = *lptr) {
+ case '3': /* ASYNCH 32 port */
+ case 'A': /* ASYNCH */
+ asybargs(lptr);
+ break;
+ case 'B': /* BISYNCH */
+ break;
+ case 'S': /* SDLC */
+ snabargs(lptr);
+ break;
+ case 'X': /* X25 */
+ x25bargs(lptr);
+ break;
+ default:
+ printf(
+"No protocol specified on PROTOCOL line in configuration file %s:%d: %s\n",
+ MPCCTAB, count, line);
+ protocol = 'A';
+ break;
+ }
+ continue;
+ }
+ printf("Error in configuration file %s,line %d, %s\n",
+ MPCCTAB, count, line);
+ }
+ fclose(tabfp);
+ mkldnm();
+ return (0);
+}
+
+/*
+ * decode x25 arguments for board
+ *
+ * for X.25, the arguments are N1, N2, T1, T2, T3, T4, K).
+ */
+x25bargs(args)
+ char *args;
+{
+}
+
+/*
+ * decode sna arguments for board
+ * for SNA, the arguments are N1, N2, T1, T2, T3, T4, K).
+ */
+snabargs(args)
+ char *args;
+{
+}
+
+/*
+ * decode async arguments for board
+ */
+asybargs(args)
+char *args;
+{
+
+ bdasy.xmtbsz = atoi(strtok((char *)0, ':'));
+}
+
+/*
+ * decode x25 arguments for port
+ */
+x25pargs(port,args)
+ int port;
+ char *args;
+{
+}
+
+/*
+ * decode sna arguments for port
+ */
+snapargs(port, args)
+ int port;
+ char *args;
+{
+}
+
+gethi()
+{
+ int i;
+
+ for (i = MPMAXPORT-1; i >= 0 && cf.protoports[i] == 0; i--)
+ ;
+ return (i);
+}
+
+getlo()
+{
+ int i;
+
+ for (i = 0; i < MPMAXPORT && cf.protoports[i] == 0; i++)
+ ;
+ return (i);
+}
+
+prntmap(board)
+ int board;
+{
+ int j;
+
+ printf("\nMPCC #: %d\n", board);
+ for (j = 0; j < MPMAXPORT; j++) {
+ printf("port: %d %c", j, cf.protoports[j]);
+ switch (cf.protoports[j]) {
+ case '3': case 'A':
+ printf("\n");
+ break;
+ case 'B':
+ break;
+ case 'S':
+ break;
+ case 'X':
+ break;
+ default:
+ printf("Unused\n");
+ break;
+ }
+ }
+ printf("ldname: %s, ", cf.loadname);
+ printf("hiport: %d, loport: %d\n", gethi(), getlo());
+ if (cf.fccsports != 0)
+ printf("FCCS\n");
+ switch (cf.protoports[0]) {
+ case '3': case 'A':
+ printf("xmtsize: %d\n", bdasy.xmtbsz);
+ break;
+ case 'B':
+ break;
+ case 'S':
+ break;
+ case 'X':
+ break;
+ }
+ printf("protoports: %s\n", cf.protoports);
+}
+
+/*
+ * Make Load Module Name
+ *
+ * if any port is 'ASYNCH"
+ * add 'a' to load module name
+ * if any port is 'BISYNCH'
+ * add 'b' to load module name
+ * if any port is 'SDLC'
+ * add 's' to load module name
+ * if any port is 'X25'
+ * add 'x' to load module name
+ */
+mkldnm()
+{
+ static char *pcols = "ABSX3";
+ char *proto;
+ int j, offset;
+
+ offset = 0;
+ for (proto = pcols; *proto; proto++) {
+ for (j = 0; j < MPMAXPORT; j++) {
+ if (cf.protoports[j] == *proto) {
+ if (*proto == '3')
+ cf.loadname[offset] = '3';
+ else
+ cf.loadname[offset] = tolower(*proto);
+ offset++;
+ break;
+ }
+ }
+ cf.loadname[offset] = '\0';
+ }
+}
+
+/*
+ * if a string is passed as an argument,
+ * save it in the local string area
+ * set the local index to the start of the string
+ * else
+ * set start to the current character in the string
+ * while the character is not the separator,
+ * and the character is not NULL
+ * skip the character
+ */
+static
+char *
+strtok(s, c)
+ char *s, c;
+{
+ static char locals[LINESIZE];
+ static int i;
+ char *start;
+
+ if (s != 0) {
+ strcpy(locals, s);
+ i = 0;
+ }
+ for (start = &locals[i] ; locals[i] && locals[i] != c; i++)
+ ;
+ if (locals[i]) {
+ locals[i] = '\0';
+ i++;
+ }
+ while (*start == ' ')
+ start++;
+ return (start);
+}
+
+short bits[] = { 1, 2, 4, 8, 16, 32, 64, 128 };
+fccs(line, tptr, pptr)
+ char *line, *tptr, *pptr;
+{
+ u_short ports, num, time;
+
+ ports = 0;
+ line = strtok(line, ',');
+ while (*(line = strtok((char *) 0, ',')) != '\0') {
+ num = (short) atoi(line);
+ if (num >= 0 && num < 8)
+ ports |= bits[num];
+ else if (num >= 50 && num < 6400)
+ time = num / 50;
+ else
+ printf("bad value for FCCS: %d\n", num);
+ }
+ *pptr = ports;
+ *tptr = time;
+}
+
+soc(line, sptr)
+ char *line, *sptr;
+{
+ u_short ports, num;
+
+ ports = 0;
+ line = strtok(line, ',');
+ while (*(line = strtok((char *) 0, ',')) != '\0') {
+ num = atoi(line);
+ if (num >= 0 && num < 8)
+ ports |= bits[num];
+ else
+ printf("bad value for SOC: %d\n",num);
+ }
+ *sptr = ports;
+}
+
+char buffer[MPDLBUFSIZE];
+extern int errno;
+struct head1 {
+ long magic;
+ long fill[12];
+ struct scnhdr text;
+ struct scnhdr data;
+ struct scnhdr bss;
+} header1;
+
+download(mpccnum)
+ int mpccnum;
+{
+ char dlname[LINESIZE], fullname[LINESIZE];
+ char *ldname, *ppmap;
+ int dlfd, ldfd;
+ char *it;
+ short i;
+ char hilo[2];
+ long realsize;
+
+ sprintf(dlname, "/dev/mpcc%d", mpccnum);
+ if (*cf.loadname == '3')
+ sprintf(fullname, "/etc/mpcc32");
+ else
+ sprintf(fullname, "/etc/mpcc%s", cf.loadname);
+ if ((cf.loadname[0]) == '\0')
+ return (-1);
+ if ((dlfd = open(dlname, O_RDWR)) == MP_DLERROR) {
+ printf("Can not open %s\n",dlname);
+ return (-1);
+ }
+ if ((ldfd = open(fullname, O_RDONLY)) == MP_DLERROR) {
+ close(dlfd);
+ printf("Can not access protocol code file: %s\n", fullname);
+ return (-1);
+ }
+ if (dlokay(dlfd,mpccnum) == MP_DLERROR) {
+ close(ldfd);
+ close(dlfd);
+ return (-1);
+ }
+ printf("Downloading MPCC #%x\n", mpccnum);
+ /* read executable file header */
+ if (read(ldfd, &header1, sizeof(header1)) != sizeof(header1)) {
+ printf("Can not read %s\n", fullname);
+ return (-1);
+ }
+ /* place at start of text space */
+ if (lseek(ldfd, header1.text.s_scnptr , (int) 0) == -1) {
+ printf("lseek error(text): %d", errno);
+ return (-1);
+ }
+ /* send text */
+ realsize = header1.data.s_paddr - header1.text.s_paddr;
+ if (dl(ldfd, dlfd, realsize) == -1) {
+ ioctl(dlfd, MPIORESETBOARD, 0L);
+ return (-1);
+ }
+ /* place at start of data space */
+ if (lseek(ldfd, header1.data.s_scnptr , (int) 0) == -1) {
+ printf("lseek error(data): %d", errno);
+ return (-1);
+ }
+ /* send initialized data */
+ realsize = header1.bss.s_paddr - header1.data.s_paddr;
+ if (dl(ldfd, dlfd, realsize) == -1) {
+ ioctl(dlfd, MPIORESETBOARD, 0L);
+ return (-1);
+ }
+ /* signal end of code */
+ if (ioctl(dlfd, MPIOENDCODE, (char *) 0) == MP_DLERROR) {
+ printf("MPIOENDCODE ioctl failed\n");
+ ioctl(dlfd, MPIORESETBOARD, 0L);
+ return (-1);
+ }
+ /* download configuration information */
+ if (config(dlfd) == -1) {
+ ioctl(dlfd, MPIORESETBOARD, 0L);
+ return (-1);
+ }
+ /* write port/protocol map */
+ ppmap = (char *)&cf.protoports[0];
+ tknzmap(ppmap);
+ if (ioctl(dlfd, MPIOPORTMAP, ppmap) == MP_DLERROR) {
+ printf("MPIOPORTMAP ioctl failed\n");
+ ioctl(dlfd, MPIORESETBOARD, 0L);
+ return (-1);
+ }
+ /* signal end of download */
+ if (ioctl(dlfd, MPIOENDDL, (char *) 0) == MP_DLERROR) {
+ printf("MPIOENDDL ioctl failed\n");
+ ioctl(dlfd, MPIORESETBOARD, 0L);
+ return (-1);
+ }
+ close(dlfd);
+ close(ldfd);
+ printf("Download Complete and Successful\n");
+ return (0);
+}
+
+dlokay(bdfd, mpccnum)
+ int bdfd, mpccnum;
+{
+ char answer;
+
+ if (resetflg) {
+ printf("Reseting MPCC #%x\n",mpccnum);
+ ioctl(bdfd, MPIORESETBOARD, 0L);
+ sleep(10);
+ }
+ if (ioctl(bdfd, MPIOSTARTDL, 0) == MP_DLERROR) {
+ if (errno == EBUSY) {
+ printf("MPCC #%x has already been downloaded.\n",
+ mpccnum);
+ printf("Do you want to re-download it?: ");
+ fscanf(stdin,"%c",&answer);
+ while (getchar() != '\n')
+ ;
+ if ((answer | 0x60) != 'y')
+ return (MP_DLERROR);
+ ioctl(bdfd, MPIORESETBOARD, 0L);
+ sleep(10);
+ if (ioctl(bdfd, MPIOSTARTDL, (char *) 0) == MP_DLERROR) {
+ printf("Can't download MPCC #%x\n", mpccnum);
+ return (MP_DLERROR);
+ }
+ } else {
+ switch (errno) {
+ case ENODEV:
+ printf("MPCC #%x not in system\n", mpccnum);
+ break;
+ case EACCES:
+ printf("Download area in use, try later\n");
+ break;
+ case ENOSPC:
+ printf("MPCC #%x already being downloaded\n",
+ mpccnum);
+ break;
+ default:
+ printf("Unknown response from MPCC #%x\n",
+ mpccnum);
+ break;
+ }
+ return (MP_DLERROR);
+ }
+ }
+ return (0);
+}
+
+dl(dskfd, bdfd, size)
+ int dskfd, bdfd;
+ long size;
+{
+ int bytes;
+
+ while (size > 0) {
+ bytes = (size < MPDLBUFSIZE) ? (int) size : MPDLBUFSIZE;
+ if ((bytes = read(dskfd, buffer, bytes)) == MP_DLERROR) {
+ close(dskfd);
+ close(bdfd);
+ printf("Download-Can't read buffer\n");
+ return (-1);
+ }
+ if (write(bdfd, buffer, bytes) == MP_DLERROR) {
+ close(dskfd);
+ close(bdfd);
+ printf("Download-Can't write buffer\n");
+ return (-1);
+ }
+ size -= bytes;
+ }
+ return (0);
+}
+
+/*
+ * download each protocol's configuration data
+ * and the configuration data for tboard.
+ */
+config(dlfd)
+ int dlfd;
+{
+ register int i;
+ char *ldname;
+
+ for (ldname = cf.loadname; *ldname; ldname++) {
+ switch (*ldname) {
+ case '3': case 'a':
+ if (ioctl(dlfd, MPIOASYNCNF, &bdasy) == MP_DLERROR) {
+ printf("async ioctl failed\n");
+ return (-1);
+ }
+ break;
+ case 'b':
+ break;
+ case 'x':
+ break;
+
+ case 's':
+ break;
+ }
+ }
+}
+
+/*
+ * tokenize the protoport string,
+ * (change from the letter to the corresponding number).
+ */
+tknzmap(map)
+ char *map;
+{
+ short i;
+
+ for (i = 0; i < MPMAXPORT; i++) {
+ switch (*map) {
+ case '3' : *map = MPPROTO_ASYNC; break;
+ case 'A' : *map = MPPROTO_ASYNC; break;
+ case 'B' : *map = MPPROTO_BISYNC; break;
+ case 'S' : *map = MPPROTO_SNA; break;
+ case 'X' : *map = MPPROTO_X25; break;
+ default: *map = MPPROTO_UNUSED; break;
+ }
+ map++;
+ }
+}