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

4.104.114.84.95
Last change on this file since cfefaa6e was c6fb8e90, checked in by Joel Sherrill <joel.sherrill@…>, on 08/01/95 at 15:33:39

updated mvme162 code from Misha (mms@…)

  • Property mode set to 100644
File size: 15.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')) || (islower(str[0]) && (str[0] == 's')))
89  {
90  /* check for valid header number */
91    switch (str[1]) {
92      case '0' : return 0;    /* header record */
93      case '1' : return 1;    /* data record, 2byte addr */
94      case '2' : return 2;    /*  "     "   , 3byte addr */
95      case '3' : return 3;    /*  "     "   , 4byte addr */
96      case '5' : return 5;    /* number of S1,S2,S3 blocks */
97      case '7' : return 7;    /* S3 terminator */
98      case '8' : return 8;    /* S2 terminator */
99      case '9' : return 9;    /* S1 terminator */
100      default  : return -2;   /* all others are invalid */
101    }
102  }
103  return(-1);
104}
105
106int validrec(char *str)
107/*  Tests for a valid srecord. tests checksum & for nondigit characters
108 *  doesn't rely on any other srecord routines.
109 * 
110 *    entry   : str   =  pointer to null terminated string
111 *    returns : -1        =  srecord contains invalid characters
112 *                        : -2    =  srecord checksum is invalid
113 *                    : -3    =  srecord record length is invalid
114 *            : 0     =  srecord is valid
115 */
116{
117  int         cn = 1, rlen=0;
118  int         mchksum=0, rchksum=0;
119
120/* first check if there are any non-digit characters except S */
121  while (str[cn]!=0)
122    if (!isxdigit(str[cn++]))
123      return(-1);
124
125/* test number of data bytes */
126  rlen = ahdtoi(str[2])* 0x10 + ahdtoi(str[3]);
127  if (((strlen(str)-4)/2U) != rlen) return(-3);
128
129/* get checksum from string */
130  rchksum = ahdtoi(str[rlen*2+2])*0x10 + ahdtoi(str[rlen*2+3]); /* string chksum */
131
132/* now calculate my own checksum */
133  for (cn=2; cn <= rlen*2; )
134    mchksum += ahdtoi(str[cn++])*0x10 + ahdtoi(str[cn++]);
135  mchksum = ~mchksum & 0xFF;
136  if (mchksum != rchksum) return(-2); /* return -2 in not equal */
137
138/* return OK if we didn't fail any of these tests */
139  return(0);
140}
141
142void hdr2str(char *sstr, char *pstr)
143/*  converts header record (S0) string into a plain string
144 * 
145 *  entry        : sstr = pointer to S0 string record
146 *  exit         : pstr = pointer to string long enough to hold string
147 *                                (caller must allocate enough space for string)
148 */
149{
150  int     rlen, cn, pn=0;
151
152  rlen = ahdtoi(sstr[2])*0x10 + ahdtoi(sstr[3]);
153  for (cn=8; cn <= rlen*2; )
154    pstr[pn++] = ahdtoi(sstr[cn++])*0x10 + ahdtoi(sstr[cn++]);
155  pstr[pn]=0;
156}
157
158unsigned long getaddr(char *str)
159/*  returns the address of the srecord in str. assumes record is valid.
160 * 
161 *  entry        : str = pointer to srecord string
162 *  exit         : address of data, word or long.
163 */
164{
165  unsigned long addr=0;
166
167  switch (issrec(str)) {
168    case 0 :
169    case 1 :
170    case 5 :
171    case 9 :  addr = ahdtoi(str[4])*0x1000 + ahdtoi(str[5])*0x100
172              + ahdtoi(str[6])*0x10 + ahdtoi(str[7]);
173              return(addr);
174    case 2 :
175    case 8 :  addr = ahdtoi(str[4])*0x100000 + ahdtoi(str[5])*0x10000
176              + ahdtoi(str[6])*0x1000 + ahdtoi(str[7])*0x100
177              + ahdtoi(str[8])*0x10 + ahdtoi(str[9]);
178              return(addr);
179    case 3 :
180    case 7 :  addr = ahdtoi(str[4])*0x10000000 + ahdtoi(str[5])*0x1000000
181              + ahdtoi(str[6])*0x100000 + ahdtoi(str[7])*0x10000
182              + ahdtoi(str[8])*0x1000 + ahdtoi(str[9])*0x100
183              + ahdtoi(str[10])*0x10 + ahdtoi(str[11]);
184              return(addr);
185    default : return(-1);
186  }
187}
188
189unsigned int datasize(char *str)
190/*
191 *  returns the number of data bytes in the srecord. assumes record is valid.
192 * 
193 *  entry        : str = pointer to srecord string
194 *  exit         : number of bytes of data in the data field.
195 */
196{
197  unsigned int size=0;
198
199  switch (issrec(str)) {
200    case 0  :
201    case 1  :
202    case 5  :
203    case 7  :
204    case 8  :
205    case 9  : size = ahdtoi(str[2])*0x10 + ahdtoi(str[3]);
206              return(size-3);
207    case 2  : size = ahdtoi(str[2])*0x10 + ahdtoi(str[3]);
208              return(size-4);
209    case 3  : size = ahdtoi(str[2])*0x10 + ahdtoi(str[3]);
210              return(size-5);
211    default : return(-1);
212  }
213}
214
215void usage (void)
216/*
217 *  prints correct usage on stdout
218 */
219{
220   printf("\nUSAGE :  sload [-v][-g][-r] [file]\n");
221   printf("  file is an s-record file\n");
222   printf("  -v for verbose summary of s-records loaded\n");
223   printf("  -g to start execution\n");
224   printf("  -r to reset MVME162\n\n");
225}
226
227int MVMEControl(u_long entry, int reset, int go)
228/*  Controls MVME-162 from other VME master:
229 *  if entry != 0, loads it as start address
230 *  if go != 0, starts program execution from entry
231 *  if reset != 0, resets mvme162's local bus 
232 *  Depends upon #define'ed GROUP_BASE_ADDRESS and BOARD_BASE_ADDRESS
233 *  which in turn are set by the 162-BUG's ENV command.
234 */
235{
236  int         vme;
237  char        vmedev[32] = "/dev/vme16d32";   /* d32 is important !!!  */
238  u_long      pagesize;
239  struct gcsr *gcsr_map;
240
241  pagesize = sysconf(_SC_PAGESIZE);   /* mmap likes to be page-aligned */
242 
243  if ((vme = open(vmedev, O_RDWR)) == -1) {
244    perror("open");
245    fprintf(stderr, "Cannot open vme as %s to access GCSR\n", vmedev);
246    return 1;
247  }
248
249/* "MAP_SHARED" is important here */
250  gcsr_map = (struct gcsr *) mmap(0, 0x1000, PROT_WRITE|PROT_READ, MAP_SHARED,
251                          vme, (u_long)gcsr_vme / pagesize * pagesize);
252  if (gcsr_map == (struct gcsr *) - 1) {
253    perror("mmap");
254    fprintf(stderr, "Cannot mmap() to remote bus address 0x%08X\n",
255                 (u_long)gcsr_vme / pagesize * pagesize);
256    return 1;
257  }
258
259/*
260 * use GCSR to start execution in MVME162
261 * adjust pointer to compensate for page alignement
262 */
263  gcsr_map = (struct gcsr *)((u_long)gcsr_map + (u_long)gcsr_vme % pagesize);
264
265  if (reset) {                /* reset the local bus... */
266    gcsr_map->board_scr |= 0x80;
267  }
268  if (entry) {                /* ...load start address... */
269    gcsr_map->gpr[0] = entry >> 16U;
270    gcsr_map->gpr[1] = entry & 0x0000FFFF;
271  }
272  if (go) {                   /* ... and kick it in the ass! */
273    gcsr_map->lmsig = 0x1;
274  }
275}
276
277/*=================================================================== */
278main(int argc, char *argv[])
279{
280  char        inpstr[256];
281  u_char      image[256];
282  char        hdrstr[64];
283  int         i, j, k, result, size, line=0, lastrec=0;
284  long        addr, tsize=0, naddr=0, blksize=0, blknum=1;
285  FILE        *in;
286  char        infile[256] = "";
287  char        vmedev[32] = "/dev/vme32d32";   /* Assume "/dev/vme32d32"  */
288  int         vme, verbose = 0, go = 0, reset = 0, havefile = 0;
289 
290/*  Parse the command line */
291
292  --argc;
293
294  while (argv++, argc--) {
295    if (**argv != '-') {
296      strcpy(infile, *argv);
297      havefile = 1;
298    } else if (!strcmp(*argv, "-v")) {
299      verbose = 1;
300    } else if (!strcmp(*argv, "-g")) {
301      go = 1;
302    } else if (!strcmp(*argv, "-r")) {
303      reset = 1;
304/*    } else if (!strcmp(*argv, "-vme32")) { */
305/*      strcpy(vmedev, "/dev/vme32d32"); */
306/*    } else if (!strcmp(*argv, "-vme24")) { */
307/*      strcpy(vmedev, "/dev/vme24d32"); */
308/*    } else if (!strcmp(*argv, "-vme16")) { */
309/*      strcpy(vmedev, "/dev/vme16d32"); */
310    } else if (!strcmp(*argv, "-")) {
311        usage();
312        exit(0);
313    } else {
314        usage();
315        exit(0);
316    }
317  }
318
319  if (!havefile) {
320    if (!reset && !go) {
321        usage();
322    }
323    else {
324      MVMEControl(0, reset, go);
325    }
326    exit(0);
327  }
328 
329  if ((in = fopen(infile, "r")) == NULL) {
330    perror("open");
331    fprintf(stderr, "Cannot open input file %s\n", infile);
332    exit(1);
333  }
334
335  if ((vme = open(vmedev, O_RDWR)) == -1) {
336    fprintf(stderr, "Cannot open vme as %s\n", vmedev);
337  }
338
339  while (fscanf(in, "%s", &inpstr) != EOF) {
340    line++;
341    if (validrec(inpstr) == 0) {
342      switch (issrec(inpstr)) {
343      case 0 :
344        hdr2str(inpstr, hdrstr);
345        if (verbose) printf("HEADER string = `%s'\n", hdrstr);
346        lastrec=HEADER;
347        break;
348      case 1 :
349        addr = getaddr(inpstr);
350        size = datasize(inpstr);
351        if (blksize == 0) {
352          blksize+=size;
353          naddr=addr+size;
354          if (verbose) printf("DATA\tS19\t$%04lX", addr);
355          lastrec=DATA19;
356        }
357        else if ((blksize!=0) && (addr==naddr)) {
358          blksize+=size;
359          naddr=addr+size;
360        }
361        else {
362          if (verbose) printf("\t$%04lX\t%lu", naddr-1, blksize);
363          if (verbose) printf("\t%d\n", blknum);
364          blknum+=1;
365          naddr=addr+size;
366          blksize=size;
367          if (verbose) printf("DATA\tS19\t$%04lX", addr);
368          lastrec=DATA19;
369        }
370        tsize += size;
371        if (vme == -1) break;
372        for (i = 0, j = 8, k = size; k-- > 0; i += 1, j += 2) {
373          image[i] = ahdtoi(inpstr[j])*0x10 + ahdtoi(inpstr[j+1]);
374        }
375        if (lseek(vme, addr, SEEK_SET) == -1) {
376          fprintf(stderr, "lseek() to vme address %08X failed\n", addr);
377        }
378        else {
379          if (write(vme, (u_char *)image, size) != size) {
380            fprintf(stderr, "Write to vme address %08X failed\n", addr);
381          }
382        }
383        break;
384      case 2 :
385        addr = getaddr(inpstr);
386        size = datasize(inpstr);
387        if (blksize == 0) {
388          blksize+=size;
389          naddr=addr+size;
390          if (verbose) printf("DATA\tS28\t$%06lX",addr);
391          lastrec=DATA28;
392        }
393        else if ((blksize!=0) && (addr==naddr)) {
394          blksize+=size;
395          naddr=addr+size;
396        }
397        else {
398          if (verbose) printf("\t$%06lX\t%lu",naddr-1,blksize);
399          if (verbose) printf("\t%d\n",blknum);
400          blknum+=1;
401          naddr=addr+size;
402          blksize=size;
403          if (verbose) printf("DATA\tS28\t$%06lX",addr);
404          lastrec=DATA28;
405        }
406        tsize += size;
407        if (vme == -1) break;
408        for (i = 0, j = 10, k = size; k-- > 0; i += 1, j += 2) {
409          image[i] = ahdtoi(inpstr[j])*0x10 + ahdtoi(inpstr[j+1]);
410        }
411        if (lseek(vme, addr, SEEK_SET) == -1) {
412          fprintf(stderr, "lseek() to vme address %08X failed\n", addr);
413        }
414        else {
415          if (write(vme, (u_char *)image, size) != size) {
416            fprintf(stderr, "Write to vme address %08X failed\n", addr);
417          }
418        }
419        break;
420      case 3 :
421        addr = getaddr(inpstr);
422        size = datasize(inpstr);
423        if (blksize == 0) {
424          blksize+=size;
425          naddr=addr+size;
426          if (verbose) printf("DATA\tS37\t$%08lX",addr);
427          lastrec=DATA37;
428        }
429        else if ((blksize!=0) && (addr==naddr)) {
430          blksize+=size;
431          naddr=addr+size;
432        }
433        else {
434          if (verbose) printf("\t$%08lX\t%lu",naddr-1,blksize);
435          if (verbose) printf("\t%d\n",blknum);
436          blknum+=1;
437          naddr=addr+size;
438          blksize=size;
439          if (verbose) printf("DATA\tS37\t$%08lX",addr);
440          lastrec=DATA37;
441        }
442        tsize += size;
443        if (vme == -1) break;
444        for (i = 0, j = 12, k = size; k-- > 0; i += 1, j += 2) {
445          image[i] = ahdtoi(inpstr[j])*0x10 + ahdtoi(inpstr[j+1]);
446        }
447        if (lseek(vme, addr, SEEK_SET) == -1) {
448          fprintf(stderr, "lseek() to vme address %08X failed\n", addr);
449        }
450        else {
451          if (write(vme, (u_char *)image, size) != size) {
452            fprintf(stderr, "Write to vme address %08X failed\n", addr);
453          }
454        }
455        break;
456      case 7 :
457        if (lastrec==DATA19){if (verbose) printf("\t$%04lX\t%lu",naddr-1,blksize);}
458        if (lastrec==DATA28){if (verbose) printf("\t$%06lX\t%lu",naddr-1,blksize);}
459        if (lastrec==DATA37){if (verbose) printf("\t$%08lX\t%lu",naddr-1,blksize);}
460        if (verbose) printf("\t%d\n",blknum);
461        addr = getaddr(inpstr);
462        if (verbose) printf("TERM\tS37");
463        printf("\nExecution address = $%08lX\n", addr);
464        lastrec=TERMINATOR;
465        break;
466      case 8 :
467        if (lastrec==DATA19){if (verbose) printf("\t$%04lX\t%lu",naddr-1,blksize);}
468        if (lastrec==DATA28){if (verbose) printf("\t$%06lX\t%lu",naddr-1,blksize);}
469        if (lastrec==DATA37){if (verbose) printf("\t$%08lX\t%lu",naddr-1,blksize);}
470        if (verbose) printf("\t%d\n",blknum);
471        addr = getaddr(inpstr);
472        if (verbose) printf("TERM\tS28");
473        printf("\nExecution address = $%06lX\n", addr);
474        lastrec=TERMINATOR;
475        break;
476      case 9 :
477        if (lastrec==DATA19){if (verbose) printf("\t$%04lX\t%lu",naddr-1,blksize);}
478        if (lastrec==DATA28){if (verbose) printf("\t$%06lX\t%lu",naddr-1,blksize);}
479        if (lastrec==DATA37){if (verbose) printf("\t$%08lX\t%lu",naddr-1,blksize);}
480        if (verbose) printf("\t%d\n",blknum);
481        addr = getaddr(inpstr);
482        if (verbose) printf("TERM\tS19");
483        printf("\nExecution address = $%04lX\n", addr);
484        lastrec=TERMINATOR;
485        break;
486      }
487    }
488    else {
489      printf("\nError on line %d. ",line);
490      switch (validrec(inpstr)) {
491      case -1 : {printf("SRecord contains invalid characters.\n"); break; }
492      case -2 : {printf("SRecord checksum is invalid.\n"); break;}
493      case -3 : {printf("SRecord length is invalid.\n"); break;}
494      }
495      exit(1);
496    }
497  }
498
499  if ((lastrec==DATA19) || (lastrec==DATA28) || (lastrec==DATA37)) {
500    if (lastrec==DATA19){if (verbose) printf("\t$%04lX\t%lu",naddr-1,blksize);}
501    if (lastrec==DATA28){if (verbose) printf("\t$%06lX\t%lu",naddr-1,blksize);}
502    if (lastrec==DATA37){if (verbose) printf("\t$%08lX\t%lu",naddr-1,blksize);}
503    if (verbose) printf("\t%d\n",blknum);
504    printf("ERROR: terminator record not found.\n");
505  }
506  else {
507    for (i = 0x000FFFF; i-- > 0;) ;           /* mystique delay... */
508    MVMEControl(addr, reset, go);
509  }
510  if (verbose) printf("total data size = %lu bytes\n", tsize);
511}
Note: See TracBrowser for help on using the repository browser.