/* * Morrow's S record down loader * Len Edmondson * May 1984 * * S record types */ #include #define until(a) while(!(a)) #define XON 17 #define XOFF 19 #define BUFSIZE 512 #define START '0' #define SHIP2 '1' #define SHIP3 '2' #define TERM3 '8' #define TERM2 '9' #define YES 1 #define NO 0 #define IBUFSIZE 256 #define REMOTE (1 << 10) #define REMTTY 1 #define LOCTTY 0 char sum = 0; char db = NO; char lbuf [BUFSIZE], rbuf [BUFSIZE]; char *lp, *rp; char buf [BUFSIZE]; char *ip, *op; int icount = 0; long lineno = 0; int baud = 9600; main (ac, av) char **av; { extern char *sbrk(); static char srec = NO; static lcommand = NO; static char c; int i; int b; /* * Example mon 1200 */ if (ac != 1) baud = atoi (av[1]); sinit (); /* Hardward initialize */ lp = lbuf; rp = rbuf; for (;;) { i = sread (); /* read a character */ c = i & 0177; if (i & REMOTE) { if (c == 'S' && rp == rbuf) srec = YES; if (c != '\r') *rp++ = c; if (!srec) swrite (c, LOCTTY); if (c == '\n') { if (srec) { *rp = 0; process (rbuf); srec = NO; } rp = rbuf; } } else /* from local */ { swrite (c, REMTTY); } } } /* * <1 byte data count> * <1 byte data count><2 byte address> * <1 byte data count><3 byte address> * <1 byte data count><3 byte address> * <1 byte data count><3 byte address> */ process (a) char *a; { static char *oldaddress; static char type, *olda, *address; static char namebuf [BUFSIZE]; static long count, x; static (*f)(); sum = 0; olda = a; a++; /* skip S */ type = *a++; if (!index ("01289", type)) { complain ("Unknown S-record type\n"); return; } count = htoi (a); a += 2; if (count * 2 + 5 != strlen (olda)) { complain ("Byte data count error.\n"); return; } /* * address */ if (type == START) { x = (long) namebuf; } else { x = htoi (a); a += 2; x *= 256; x += htoi (a); a += 2; if (type == SHIP3 || type == TERM3) { x *= 256; x += htoi (a); a += 2; } } address = (char *) x; /* * data */ switch (type) { case SHIP2: { count -= 3; break; } case SHIP3: { count -= 4; break; } case TERM2: case TERM3: { count = 0; break; } case START: { count--; break; } } while (count--) { if (db && type != START) { htoi (a); } else { *address++ = htoi (a); } a +=2; } /* * checksum */ htoi (a); a += 2; sum++; if (sum) { complain ("Checksum error.\n"); return; } if (*a != '\n') { complain ("Missing NEWLINE\n"); return; } switch (type) { case START: { prs (namebuf); prs ("\n"); break; } case TERM2: case TERM3: { prs ("\nSuccessful download\n"); prs ("Execution starts at "); prhex (address); prs ("\n"); if (!db) { f = address; (*f)(); } break; } } } complain (a) char *a; { prs (buf); sprintf (buf, "line %ld: %s\n", lineno, a); prs (buf); } /* * Bits. */ #define OUTREADY (1 << 0) #define INREADY (1 << 1) /* * Modes. */ #define REG1 0x6e #define REG2_9600 0x7d /* 9600 baud */ #define REG2_1200 0x78 /* 1200 baud */ #define REG3 0x27 /* * Hardware initialization. */ sinit () { sopen (LOCTTY, 9600); sopen (REMTTY, baud); } htoi (a) char *a; { char i; i = hval (*a++); i *= 16; i += hval (*a); sum += i; return 0377 & i; } hval (a) char a; { if (isdigit (a)) { a += (0 - '0'); } else if (isupper (a)) { a += (10 - 'A'); } else if (islower (a)) { a += (10 - 'a'); } return a; } isdigit (a) { return '0' <= a && a <= '9'; } isupper (a) { return 'A' <= a && a <= 'Z'; } islower (a) { return 'a' <= a && a <= 'z'; } prs (a) char *a; { for (; *a; a++) { if (*a == '\n') swrite ('\r', LOCTTY); swrite (*a, LOCTTY); } } prhex (a) long a; { static char b [16]; sprintf (b, "%lx", a); prs (b); }