BSD 4_3_Tahoe development
[unix-history] / usr / src / cci / enpload.c
#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 );
}
}