+#include <a.out.h>
+#include <fcntl.h>
+#include <stdio.h>
+
+#define mkioctl(type,value) (0x20000000|('type'<<8)|value)
+
+#define ENPIOGO mkioctl( S,1 ) /* start the enp */
+#define ENPIORESET mkioctl( S,2 ) /* reset the enp */
+
+#define ENP0 0x0 /* Enp's 0 Memory */
+#define ENP1 0x0 /* Enp's 1 Memory */
+#define ENP2 0x0 /* Enp's 2 Memory */
+#define ENP3 0x0 /* Enp's 3 Memory */
+
+#define RELO 0x03FFFF /* ENP->Kernel Mask */
+
+#define BUTTON 0x1000 /* Addr to "push" for startup */
+#define JADDR 0x1004 /* Start vector goes here */
+#define JUMP 0x8080 /* "jump" command */
+
+/*
+ * ENP "device" table (so we can load multiple ENPs)
+ * See ENP/30 User Guide
+*/
+
+typedef struct enp
+{
+ char name[8]; /* Device's "name" */
+ long mstart; /* Host's idea of enp mem org */
+ long button; /* Addr of "go" button */
+ long jaddr; /* Addr of "jump" command */
+} ENP;
+
+ENP enp_tab[] =
+{
+ { "enp0", ENP0, ENP0 + BUTTON, ENP0 + JADDR, },
+ { "enp1", ENP1, ENP1 + BUTTON, ENP1 + JADDR, },
+ { "enp2", ENP2, ENP2 + BUTTON, ENP2 + JADDR, },
+ { "enp3", ENP3, ENP3 + BUTTON, ENP3 + JADDR, },
+};
+short num_enp = sizeof(enp_tab) / sizeof(enp_tab[0]);
+
+ENP *getenp();
+short enpfid = -1; /* dev "enpram" fid */
+
+
+/*
+ * For loading from a.out files ...
+*/
+
+#define BSIZE 512 /* Size buffer we use */
+#define MAXFILE 4 /* Max of 4 a.outs */
+#define MAXBIN 4 /* bin files on command line */
+
+typedef struct bins
+{
+ short b_fid;
+ char *b_name;
+} BINS;
+
+BINS file_tab[ MAXFILE ]; /* fid/name of a.outs */
+
+char enpdev[] = "/dev/enpXram";
+char buff[ BSIZE ]; /* I/O Buffer */
+char zbuf[ BSIZE ]; /* For quick clearing */
+
+int nostart;
+int noload;
+
+main( argc,argv )
+int argc;
+char **argv;
+{
+ register BINS *fp; /* File params */
+ register short fcnt,i; /* Files to load */
+ struct exec hdr; /* a.out header */
+ int cnt; /* I/O count */
+ long f_size,bss_size; /* text + data & bss */
+
+ register ENP *ep; /* enp_tab pointer */
+ unsigned long enp_go; /* Start up vector */
+ short enp_jump = JUMP; /* "jump" command */
+ long lstart; /* Start loading at */
+ long cstart; /* Clear from */
+
+
+ if( (argc < 3) || (argc > 3 + MAXBIN) )
+ {
+ printf( "usage: enpload dev file_1 [ file_2 ... file_4 ]\n" );
+ exit( 1 );
+ }
+ argv++;
+ if( (ep = getenp( *argv++ )) == 0 )
+ {
+ printf( "Bad ENP device name!\n" );
+ exit( 1 );
+ }
+
+ enpdev[8] = ep->name[3];
+ dup2(1,2); /* redirect sdterr to stdout */
+ if( (enpfid = open(enpdev,O_RDWR)) == -1 )
+ {
+ sprintf(zbuf, "enpload: Can't open %s ram", ep->name);
+ perror( zbuf );
+ exit( 1 );
+ }
+
+/* Collect file names and compute number of them */
+
+ fp = file_tab; fcnt = 0;
+ while( *argv )
+ {
+ if( argv[0][0] == '-' )
+ {
+ if( argv[0][1] == 'L' )
+ noload = 1;
+ else
+ if( argv[0][1] == 'S' )
+ nostart = 1;
+ argv++;
+ }
+ else
+ {
+ fp->b_name = *argv++;
+ fp++; fcnt++;
+ }
+ }
+
+/* Zero buffer used to clear bss storage in ENP */
+
+ for( i = 0; i < BSIZE; i++ )
+ {
+ zbuf[i] = 0;
+ }
+
+ if( noload )
+ {
+ printf("Restart %s at 0xf02000\n", ep->name);
+ ioctl( enpfid,ENPIOGO,0xf02000 );
+ exit( 0 );
+ }
+ ioctl( enpfid,ENPIORESET,0 );
+
+/* Open, validate, and load each file_tab[] file */
+
+ for( i = 0; i < fcnt; i++ )
+ {
+ fp = &file_tab[i];
+ if( (fp->b_fid = open( fp->b_name,O_RDONLY )) == -1 )
+ {
+ printf( "enpload: Can't open %s!\n",fp->b_name );
+ closem( i-1 );
+ exit( 1 );
+ }
+
+ if( read( fp->b_fid,&hdr,sizeof( hdr ) ) != sizeof( hdr) )
+ {
+ printf( "enpload: %s Bad header!\n",fp->b_name );
+ closem( i );
+ exit( 1 );
+ }
+
+ if( N_BADMAG( hdr ) )
+ {
+ printf( "enpload: %s Bad magic!\n",fp->b_name );
+ closem( i );
+ exit( 1 );
+ }
+
+ f_size = hdr.a_text + hdr.a_data;
+ bss_size = hdr.a_bss;
+ lstart = (ep->mstart + (hdr.a_entry & RELO)) - 0x1000;
+ cstart = lstart + f_size;
+
+ printf("Loading %s --- ", enpdev);
+ printf( "with file: %s --- ",fp->b_name );
+/*
+ printf( "text + data: %d bss: %d\n",f_size,bss_size );
+ printf( "ENP's a_entry addr: %06X\n",hdr.a_entry );
+ printf( "load start:%06X bss start:%06X\n",lstart,cstart );
+
+ printf( "Clearing bss ... " );
+*/
+ lseek( enpfid,cstart,0 );
+ while( bss_size >= BSIZE )
+ {
+ if( write( enpfid,zbuf,BSIZE ) != BSIZE )
+ printf("enpload: bss write error\n");
+ bss_size -= BSIZE;
+ }
+ if( bss_size > 0 )
+ {
+ write( enpfid,zbuf,bss_size );
+ }
+/*
+ printf( "DONE!\n" );
+*/
+
+/*
+ printf( "Loading ... " );
+*/
+ lseek( enpfid,lstart,0 );
+ while( f_size > BSIZE )
+ {
+ cnt = read( fp->b_fid,buff,BSIZE );
+ f_size -= cnt;
+ if( write( enpfid,buff,cnt ) != cnt )
+ perror("enpload: write");
+ }
+ if( f_size > 0 )
+ {
+ cnt = read( fp->b_fid,buff,f_size );
+ write( enpfid,buff,cnt );
+ }
+ printf( "DONE!\n" );
+ }
+
+/* Last file, we exec this one */
+
+ if( nostart == 0 )
+ {
+ enp_go = hdr.a_entry;
+/*
+ printf( "Starting ENP execution at %X ... ",enp_go );
+*/
+ ioctl( enpfid,ENPIOGO, enp_go );
+/*
+ printf( "DONE!\n" );
+*/
+ }
+}
+
+
+ENP *
+getenp( np )
+register char *np;
+{
+ register ENP *ep;
+
+ for( ep = enp_tab; ep < &enp_tab[num_enp]; ep++ )
+ if( strcmp( np,ep->name ) == 0 )
+ {
+ return( ep );
+ }
+ return( 0 );
+}
+
+
+closem( cnt )
+register short cnt;
+{
+ register BINS *fp;
+
+ for( fp = file_tab; fp < &file_tab[cnt]; fp++ )
+ {
+ close( fp->b_fid );
+ }
+ if( enpfid != -1 )
+ {
+ close( enpfid );
+ }
+}