source: rtems/c/src/lib/libbsp/m68k/mvme162/tools/sload.c @ 88d594a

4.104.114.84.95
Last change on this file since 88d594a was ac7d5ef0, checked in by Joel Sherrill <joel.sherrill@…>, on 05/11/95 at 17:39:37

Initial revision

  • Property mode set to 100644
File size: 17.6 KB
Line 
1/*
2 *
3 *        Copyright (c) 1994 by EISCAT Scientific Association.
4 *                        All Rights Reserved.
5 *                             M.Savitski
6 *
7 *     S-record code - courtesy of Kym Newbery
8 *     8918927y@lux.levels.unisa.edu.au
9 *
10 *     Loading S-records into the VMEbus memory.
11 *
12 *  Loads an executable in s-record format into the MVME dual-ported
13 *  memory and directs the MVME CPU to start execution.
14 *  VMEbus access is done via the FORCE CPU-2CE vmeplus driver in
15 *  read/write mode for loading and in mmap mode for accessing MVME registers.
16 *  See mvme162.h for #define's dependent on the MVME162 setup.
17 *
18 *  $Id$
19 *
20 */
21
22#include <stdio.h>
23#include <string.h>
24#include <ctype.h>
25
26
27#include <sys/types.h>
28#include <sys/fcntl.h>
29#include <sys/resource.h>
30#include <unistd.h>
31#include <sys/vme.h>
32#include <sys/mman.h>
33
34#include "../include/bsp.h"
35
36#define FALSE 0
37#define TRUE 1
38
39#define DATA19 0
40#define DATA28 1
41#define DATA37 3
42#define HEADER 4
43#define TERMINATOR 5
44#define NONE 6
45
46unsigned int ahdtoi(unsigned char digit);
47int issrec(char *str);
48int validrec(char *str);
49void hdr2str(char *sstr, char *pstr);
50unsigned long getaddr(char *str);
51unsigned int datasize(char *str);
52void usage (void);
53int MVMEControl(u_long entry, int reset, int go);
54
55unsigned int ahdtoi(unsigned char digit)
56/*       converts a hexadecimal char to an integer
57 *
58 *       entry        : digit = character to convert
59 *                    : 0..15 = result
60 *                    : -1    = char is not a digit
61 */
62{
63/* check digit */
64        if (!isxdigit(digit))
65                return(-1);
66
67        switch (toupper(digit)) {
68                case 'A' : return(0xA);
69                case 'B' : return(0xB);
70                case 'C' : return(0xC);
71                case 'D' : return(0xD);
72                case 'E' : return(0xE);
73                case 'F' : return(0xF);
74                default  : return(digit - 0x30);
75        }
76}
77
78int issrec(char *str)
79/*      attempts to identify the type of Srecord string passed
80 *
81 *       entry   : str =  pointer to null terminated string
82 *       returns : 0,1,2,3,5,7,8,9 for S0..S9 except S6 & S4
83 *               : -1 = invalid header or header not found
84 *                       : -2 = invalid header number
85 */
86{
87/* Check first character for S */
88        if ((isupper(str[0]) && (str[0] == 'S')) ||
89            (islower(str[0]) && (str[0] == 's')))
90        {
91        /* check for valid header number */
92                switch (str[1]) {
93                        case '0' : return 0;    /* header record */
94                        case '1' : return 1;    /* data record, 2byte addr */
95                        case '2' : return 2;    /*  "     "   , 3byte addr */
96                        case '3' : return 3;    /*  "     "   , 4byte addr */
97                        case '5' : return 5;    /* number of S1,S2,S3 blocks */
98                        case '7' : return 7;    /* S3 terminator */
99                        case '8' : return 8;    /* S2 terminator */
100                        case '9' : return 9;    /* S1 terminator */
101                        default  : return -2;   /* all others are invalid */
102                }
103        }
104        return(-1);
105}
106
107int validrec(char *str)
108/*      Tests for a valid srecord. tests checksum & for nondigit characters
109 *      doesn't rely on any other srecord routines.
110 *
111 *        entry   : str   =  pointer to null terminated string
112 *        returns : -1        =  srecord contains invalid characters
113 *                            : -2    =  srecord checksum is invalid
114 *                        : -3    =  srecord record length is invalid
115 *                : 0     =  srecord is valid
116 */
117{
118        int                                     cn = 1, rlen=0;
119        int                                     mchksum=0, rchksum=0;
120
121/* first check if there are any non-digit characters except S */
122        while (str[cn]!=0)
123                if (!isxdigit(str[cn++]))
124                        return(-1);
125
126/* test number of data bytes */
127        rlen = ahdtoi(str[2])* 0x10 + ahdtoi(str[3]);
128        if (((strlen(str)-4)/2U) != rlen) return(-3);
129
130/* get checksum from string */
131        rchksum = ahdtoi(str[rlen*2+2])*0x10 + ahdtoi(str[rlen*2+3]);
132             /* string chksum */
133
134/* now calculate my own checksum */
135        for (cn=2; cn <= rlen*2; )
136                mchksum += ahdtoi(str[cn++])*0x10 + ahdtoi(str[cn++]);
137        mchksum = ~mchksum & 0xFF;
138        if (mchksum != rchksum) return(-2); /* return -2 in not equal */
139
140/* return OK if we didn't fail any of these tests */
141        return(0);
142}
143
144void hdr2str(char *sstr, char *pstr)
145/*      converts header record (S0) string into a plain string
146 *
147 *      entry        : sstr = pointer to S0 string record
148 *      exit         : pstr = pointer to string long enough to hold string
149 *                              (caller must allocate enough space for string)
150 */
151{
152        int                     rlen, cn, pn=0;
153
154        rlen = ahdtoi(sstr[2])*0x10 + ahdtoi(sstr[3]);
155        for (cn=8; cn <= rlen*2; )
156                pstr[pn++] = ahdtoi(sstr[cn++])*0x10 + ahdtoi(sstr[cn++]);
157        pstr[pn]=0;
158}
159
160unsigned long getaddr(char *str)
161/*      returns the address of the srecord in str. assumes record is valid.
162 *
163 *      entry        : str = pointer to srecord string
164 *      exit         : address of data, word or long.
165 */
166{
167        unsigned long addr=0;
168
169        switch (issrec(str)) {
170                case 0 :
171                case 1 :
172                case 5 :
173                case 9 :
174                  addr = ahdtoi(str[4])*0x1000 + ahdtoi(str[5])*0x100
175                         + ahdtoi(str[6])*0x10 + ahdtoi(str[7]);
176                  return(addr);
177                case 2 :
178                case 8 :
179                  addr = ahdtoi(str[4])*0x100000 + ahdtoi(str[5])*0x10000
180                         + ahdtoi(str[6])*0x1000 + ahdtoi(str[7])*0x100
181                         + ahdtoi(str[8])*0x10 + ahdtoi(str[9]);
182                  return(addr);
183                case 3 :
184                case 7 :
185                  addr = ahdtoi(str[4])*0x10000000 + ahdtoi(str[5])*0x1000000
186                         + ahdtoi(str[6])*0x100000 + ahdtoi(str[7])*0x10000
187                         + ahdtoi(str[8])*0x1000 + ahdtoi(str[9])*0x100
188                         + ahdtoi(str[10])*0x10 + ahdtoi(str[11]);
189                  return(addr);
190                default : return(-1);
191        }
192}
193
194unsigned int datasize(char *str)
195/*
196 *    returns the number of data bytes in the srecord. assumes record is valid.
197 *
198 *      entry        : str = pointer to srecord string
199 *      exit         : number of bytes of data in the data field.
200 */
201{
202        unsigned int size=0;
203
204        switch (issrec(str)) {
205                case 0  :
206                case 1  :
207                case 5  :
208                case 7  :
209                case 8  :
210                case 9  : size = ahdtoi(str[2])*0x10 + ahdtoi(str[3]);
211                                                        return(size-3);
212                case 2  : size = ahdtoi(str[2])*0x10 + ahdtoi(str[3]);
213                                                        return(size-4);
214                case 3  : size = ahdtoi(str[2])*0x10 + ahdtoi(str[3]);
215                                                        return(size-5);
216                default : return(-1);
217        }
218}
219
220void usage (void)
221/*
222 *      prints correct usage on stdout
223 */
224{
225         printf("\nUSAGE :  sload [-v][-g][-r] [file]\n");
226         printf("  file is an s-record file\n");
227         printf("  -v for verbose summary of s-records loaded\n");
228         printf("  -g to start execution\n");
229         printf("  -r to reset MVME162\n\n");
230}
231
232int MVMEControl(u_long entry, int reset, int go)
233/*      Controls MVME-162 from other VME master:
234 *  if entry != 0, loads it as start address
235 *      if go != 0, starts program execution from entry
236 *      if reset != 0, resets mvme162's local bus
237 *  Depends upon #define'ed GROUP_BASE_ADDRESS and BOARD_BASE_ADDRESS
238 *      which in turn are set by the 162-BUG's ENV command.
239 */
240{
241        int          vme;
242        char         vmedev[32] = "/dev/vme16d32"; /* d32 is important !!!  */
243        u_long       pagesize;
244        struct gcsr *gcsr_map;
245
246        pagesize = sysconf(_SC_PAGESIZE);  /* mmap likes to be page-aligned */
247
248        if ((vme = open(vmedev, O_RDWR)) == -1) {
249          perror("open");
250          fprintf(stderr, "Cannot open vme as %s to access GCSR\n", vmedev);
251          return 1;
252        }
253
254/* "MAP_SHARED" is important here */
255        gcsr_map = (struct gcsr *)
256          mmap(0, 0x1000, PROT_WRITE|PROT_READ, MAP_SHARED,
257               vme, (u_long)gcsr_vme / pagesize * pagesize);
258        if (gcsr_map == (struct gcsr *) - 1) {
259          perror("mmap");
260          fprintf(stderr, "Cannot mmap() to remote bus address 0x%08X\n",
261                           (u_long)gcsr_vme / pagesize * pagesize);
262                return 1;
263        }
264
265/*
266 * use GCSR to start execution in MVME162
267 * adjust pointer to compensate for page alignement
268 */
269        gcsr_map = (struct gcsr *)((u_long)gcsr_map +
270                       (u_long)gcsr_vme % pagesize);
271
272        if (reset) {                           /* reset the local bus... */
273                gcsr_map->board_scr |= 0x80;
274        }
275        if (entry) {                           /* ...load start address... */
276                gcsr_map->gpr[0] = entry >> 16U;
277                gcsr_map->gpr[1] = entry & 0x0000FFFF;
278        }
279        if (go) {                              /* ... and kick it in the ass! */
280                gcsr_map->lmsig = 0x1;
281        }
282}
283
284/*=================================================================== */
285main(int argc, char *argv[])
286{
287        char       inpstr[256];
288        u_char     image[256];
289        char       hdrstr[64];
290        int        i, j, k, result, size, line=0, lastrec=0;
291        long       addr, tsize=0, naddr=0, blksize=0, blknum=1;
292        FILE       *in;
293        char       infile[256] = "";
294        char       vmedev[32] = "/dev/vme32d32";  /* Assume "/dev/vme32d32"  */
295        int        vme, verbose = 0, go = 0, reset = 0, havefile = 0;
296
297/*      Parse the command line */
298
299  --argc;
300
301  while (argv++, argc--) {
302        if (**argv != '-') {
303                strcpy(infile, *argv);
304                havefile = 1;
305    } else if (!strcmp(*argv, "-v")) {
306      verbose = 1;
307    } else if (!strcmp(*argv, "-g")) {
308      go = 1;
309    } else if (!strcmp(*argv, "-r")) {
310      reset = 1;
311/*    } else if (!strcmp(*argv, "-vme32")) { */
312/*      strcpy(vmedev, "/dev/vme32d32"); */
313/*    } else if (!strcmp(*argv, "-vme24")) { */
314/*      strcpy(vmedev, "/dev/vme24d32"); */
315/*    } else if (!strcmp(*argv, "-vme16")) { */
316/*      strcpy(vmedev, "/dev/vme16d32"); */
317    } else if (!strcmp(*argv, "-")) {
318        usage();
319        exit(0);
320    } else {
321        usage();
322        exit(0);
323    }
324  }
325
326  if (!havefile) {
327    if (!reset && !go) {
328      usage();
329    }
330    else {
331      MVMEControl(0, reset, go);
332    }
333    exit(0);
334  }
335
336  if ((in = fopen(infile, "r")) == NULL) {
337    perror("open");
338    fprintf(stderr, "Cannot open input file %s\n", infile);
339    exit(1);
340  }
341
342  if ((vme = open(vmedev, O_RDWR)) == -1) {
343    fprintf(stderr, "Cannot open vme as %s\n", vmedev);
344  }
345
346  while (fscanf(in, "%s", &inpstr) != EOF) {
347    line++;
348    if (validrec(inpstr) == 0) {
349      switch (issrec(inpstr)) {
350        case 0 :
351          hdr2str(inpstr, hdrstr);
352          if (verbose) printf("HEADER string = `%s'\n", hdrstr);
353          lastrec=HEADER;
354          break;
355        case 1 :
356          addr = getaddr(inpstr);
357          size = datasize(inpstr);
358          if (blksize == 0) {
359            blksize+=size;
360            naddr=addr+size;
361            if (verbose) printf("DATA\tS19\t$%04lX", addr);
362            lastrec=DATA19;
363          }
364          else if ((blksize!=0) && (addr==naddr)) {
365            blksize+=size;
366            naddr=addr+size;
367          }
368          else {
369            if (verbose) printf("\t$%04lX\t%lu", naddr-1, blksize);
370            if (verbose) printf("\t%d\n", blknum);
371            blknum+=1;
372            naddr=addr+size;
373            blksize=size;
374            if (verbose) printf("DATA\tS19\t$%04lX", addr);
375            lastrec=DATA19;
376          }
377          tsize += size;
378          if (vme == -1) break;
379          for (i = 0, j = 8, k = size; k-- > 0; i += 1, j += 2) {
380            image[i] = ahdtoi(inpstr[j])*0x10 + ahdtoi(inpstr[j+1]);
381          }
382          if (lseek(vme, addr, SEEK_SET) == -1) {
383            fprintf(stderr, "lseek() to vme address %08X failed\n", addr);
384          }
385          else {
386            if (write(vme, (u_char *)image, size) != size) {
387              fprintf(stderr, "Write to vme address %08X failed\n", addr);
388            }
389          }
390          break;
391        case 2 :
392          addr = getaddr(inpstr);
393          size = datasize(inpstr);
394          if (blksize == 0) {
395            blksize+=size;
396            naddr=addr+size;
397            if (verbose) printf("DATA\tS28\t$%06lX",addr);
398            lastrec=DATA28;
399          }
400          else if ((blksize!=0) && (addr==naddr)) {
401            blksize+=size;
402            naddr=addr+size;
403          }
404          else {
405            if (verbose) printf("\t$%06lX\t%lu",naddr-1,blksize);
406            if (verbose) printf("\t%d\n",blknum);
407            blknum+=1;
408            naddr=addr+size;
409            blksize=size;
410            if (verbose) printf("DATA\tS28\t$%06lX",addr);
411            lastrec=DATA28;
412          }
413          tsize += size;
414          if (vme == -1) break;
415          for (i = 0, j = 10, k = size; k-- > 0; i += 1, j += 2) {
416            image[i] = ahdtoi(inpstr[j])*0x10 + ahdtoi(inpstr[j+1]);
417          }
418          if (lseek(vme, addr, SEEK_SET) == -1) {
419            fprintf(stderr, "lseek() to vme address %08X failed\n", addr);
420          }
421          else {
422            if (write(vme, (u_char *)image, size) != size) {
423              fprintf(stderr, "Write to vme address %08X failed\n", addr);
424            }
425          }
426          break;
427        case 3 :
428          addr = getaddr(inpstr);
429          size = datasize(inpstr);
430          if (blksize == 0) {
431            blksize+=size;
432            naddr=addr+size;
433            if (verbose) printf("DATA\tS37\t$%08lX",addr);
434            lastrec=DATA37;
435          }
436          else if ((blksize!=0) && (addr==naddr)) {
437            blksize+=size;
438            naddr=addr+size;
439          }
440          else {
441            if (verbose) printf("\t$%08lX\t%lu",naddr-1,blksize);
442            if (verbose) printf("\t%d\n",blknum);
443            blknum+=1;
444            naddr=addr+size;
445            blksize=size;
446            if (verbose) printf("DATA\tS37\t$%08lX",addr);
447            lastrec=DATA37;
448          }
449          tsize += size;
450          if (vme == -1) break;
451          for (i = 0, j = 12, k = size; k-- > 0; i += 1, j += 2) {
452            image[i] = ahdtoi(inpstr[j])*0x10 + ahdtoi(inpstr[j+1]);
453          }
454          if (lseek(vme, addr, SEEK_SET) == -1) {
455            fprintf(stderr, "lseek() to vme address %08X failed\n", addr);
456          }
457          else {
458            if (write(vme, (u_char *)image, size) != size) {
459              fprintf(stderr, "Write to vme address %08X failed\n", addr);
460            }
461          }
462          break;
463        case 7 :
464          if (lastrec==DATA19){
465            if (verbose) printf("\t$%04lX\t%lu",naddr-1,blksize);
466          }
467          if (lastrec==DATA28){
468            if (verbose) printf("\t$%06lX\t%lu",naddr-1,blksize);
469          }
470          if (lastrec==DATA37){
471            if (verbose) printf("\t$%08lX\t%lu",naddr-1,blksize);
472          }
473          if (verbose) printf("\t%d\n",blknum);
474          addr = getaddr(inpstr);
475          if (verbose) printf("TERM\tS37");
476          printf("\nExecution address = $%08lX\n", addr);
477          lastrec=TERMINATOR;
478          break;
479        case 8 :
480          if (lastrec==DATA19){
481            if (verbose) printf("\t$%04lX\t%lu",naddr-1,blksize);
482          }
483          if (lastrec==DATA28){
484            if (verbose) printf("\t$%06lX\t%lu",naddr-1,blksize);
485          }
486          if (lastrec==DATA37){
487            if (verbose) printf("\t$%08lX\t%lu",naddr-1,blksize);
488          }
489          if (verbose) printf("\t%d\n",blknum);
490          addr = getaddr(inpstr);
491          if (verbose) printf("TERM\tS28");
492          printf("\nExecution address = $%06lX\n", addr);
493          lastrec=TERMINATOR;
494          break;
495        case 9 :
496          if (lastrec==DATA19){
497            if (verbose) printf("\t$%04lX\t%lu",naddr-1,blksize);
498          }
499          if (lastrec==DATA28){
500            if (verbose) printf("\t$%06lX\t%lu",naddr-1,blksize);
501          }
502          if (lastrec==DATA37){
503            if (verbose) printf("\t$%08lX\t%lu",naddr-1,blksize);
504          }
505          if (verbose) printf("\t%d\n",blknum);
506          addr = getaddr(inpstr);
507          if (verbose) printf("TERM\tS19");
508          printf("\nExecution address = $%04lX\n", addr);
509          lastrec=TERMINATOR;
510          break;
511        }
512      }
513      else {
514        printf("\nError on line %d. ",line);
515        switch (validrec(inpstr)) {
516          case -1 : {printf("SRecord contains invalid characters.\n"); break; }
517          case -2 : {printf("SRecord checksum is invalid.\n"); break;}
518          case -3 : {printf("SRecord length is invalid.\n"); break;}
519        }
520       exit(1);
521     }
522   }
523
524   if ((lastrec==DATA19) || (lastrec==DATA28) || (lastrec==DATA37)) {
525     if (lastrec==DATA19){
526       if (verbose) printf("\t$%04lX\t%lu",naddr-1,blksize);
527     }
528     if (lastrec==DATA28){
529       if (verbose) printf("\t$%06lX\t%lu",naddr-1,blksize);
530     }
531     if (lastrec==DATA37){
532       if (verbose) printf("\t$%08lX\t%lu",naddr-1,blksize);
533     }
534     if (verbose) printf("\t%d\n",blknum);
535     printf("ERROR: terminator record not found.\n");
536   }
537   else {
538     for (i = 0x000FFFF; i-- > 0;) ; /* mystique delay... */
539       MVMEControl(addr, reset, go);
540     }
541   if (verbose) printf("total data size = %lu bytes\n", tsize);
542}
Note: See TracBrowser for help on using the repository browser.