Commit | Line | Data |
---|---|---|
f6458c6a C |
1 | #include <a.out.h> |
2 | #include <fcntl.h> | |
3 | #include <stdio.h> | |
4 | ||
5 | #define mkioctl(type,value) (0x20000000|('type'<<8)|value) | |
6 | ||
7 | #define ENPIOGO mkioctl( S,1 ) /* start the enp */ | |
8 | #define ENPIORESET mkioctl( S,2 ) /* reset the enp */ | |
9 | ||
10 | #define ENP0 0x0 /* Enp's 0 Memory */ | |
11 | #define ENP1 0x0 /* Enp's 1 Memory */ | |
12 | #define ENP2 0x0 /* Enp's 2 Memory */ | |
13 | #define ENP3 0x0 /* Enp's 3 Memory */ | |
14 | ||
15 | #define RELO 0x03FFFF /* ENP->Kernel Mask */ | |
16 | ||
17 | #define BUTTON 0x1000 /* Addr to "push" for startup */ | |
18 | #define JADDR 0x1004 /* Start vector goes here */ | |
19 | #define JUMP 0x8080 /* "jump" command */ | |
20 | ||
21 | /* | |
22 | * ENP "device" table (so we can load multiple ENPs) | |
23 | * See ENP/30 User Guide | |
24 | */ | |
25 | ||
26 | typedef struct enp | |
27 | { | |
28 | char name[8]; /* Device's "name" */ | |
29 | long mstart; /* Host's idea of enp mem org */ | |
30 | long button; /* Addr of "go" button */ | |
31 | long jaddr; /* Addr of "jump" command */ | |
32 | } ENP; | |
33 | ||
34 | ENP enp_tab[] = | |
35 | { | |
36 | { "enp0", ENP0, ENP0 + BUTTON, ENP0 + JADDR, }, | |
37 | { "enp1", ENP1, ENP1 + BUTTON, ENP1 + JADDR, }, | |
38 | { "enp2", ENP2, ENP2 + BUTTON, ENP2 + JADDR, }, | |
39 | { "enp3", ENP3, ENP3 + BUTTON, ENP3 + JADDR, }, | |
40 | }; | |
41 | short num_enp = sizeof(enp_tab) / sizeof(enp_tab[0]); | |
42 | ||
43 | ENP *getenp(); | |
44 | short enpfid = -1; /* dev "enpram" fid */ | |
45 | ||
46 | ||
47 | /* | |
48 | * For loading from a.out files ... | |
49 | */ | |
50 | ||
51 | #define BSIZE 512 /* Size buffer we use */ | |
52 | #define MAXFILE 4 /* Max of 4 a.outs */ | |
53 | #define MAXBIN 4 /* bin files on command line */ | |
54 | ||
55 | typedef struct bins | |
56 | { | |
57 | short b_fid; | |
58 | char *b_name; | |
59 | } BINS; | |
60 | ||
61 | BINS file_tab[ MAXFILE ]; /* fid/name of a.outs */ | |
62 | ||
63 | char enpdev[] = "/dev/enpXram"; | |
64 | char buff[ BSIZE ]; /* I/O Buffer */ | |
65 | char zbuf[ BSIZE ]; /* For quick clearing */ | |
66 | ||
67 | int nostart; | |
68 | int noload; | |
69 | ||
70 | main( argc,argv ) | |
71 | int argc; | |
72 | char **argv; | |
73 | { | |
74 | register BINS *fp; /* File params */ | |
75 | register short fcnt,i; /* Files to load */ | |
76 | struct exec hdr; /* a.out header */ | |
77 | int cnt; /* I/O count */ | |
78 | long f_size,bss_size; /* text + data & bss */ | |
79 | ||
80 | register ENP *ep; /* enp_tab pointer */ | |
81 | unsigned long enp_go; /* Start up vector */ | |
82 | short enp_jump = JUMP; /* "jump" command */ | |
83 | long lstart; /* Start loading at */ | |
84 | long cstart; /* Clear from */ | |
85 | ||
86 | ||
87 | if( (argc < 3) || (argc > 3 + MAXBIN) ) | |
88 | { | |
89 | printf( "usage: enpload dev file_1 [ file_2 ... file_4 ]\n" ); | |
90 | exit( 1 ); | |
91 | } | |
92 | argv++; | |
93 | if( (ep = getenp( *argv++ )) == 0 ) | |
94 | { | |
95 | printf( "Bad ENP device name!\n" ); | |
96 | exit( 1 ); | |
97 | } | |
98 | ||
99 | enpdev[8] = ep->name[3]; | |
100 | dup2(1,2); /* redirect sdterr to stdout */ | |
101 | if( (enpfid = open(enpdev,O_RDWR)) == -1 ) | |
102 | { | |
103 | sprintf(zbuf, "enpload: Can't open %s ram", ep->name); | |
104 | perror( zbuf ); | |
105 | exit( 1 ); | |
106 | } | |
107 | ||
108 | /* Collect file names and compute number of them */ | |
109 | ||
110 | fp = file_tab; fcnt = 0; | |
111 | while( *argv ) | |
112 | { | |
113 | if( argv[0][0] == '-' ) | |
114 | { | |
115 | if( argv[0][1] == 'L' ) | |
116 | noload = 1; | |
117 | else | |
118 | if( argv[0][1] == 'S' ) | |
119 | nostart = 1; | |
120 | argv++; | |
121 | } | |
122 | else | |
123 | { | |
124 | fp->b_name = *argv++; | |
125 | fp++; fcnt++; | |
126 | } | |
127 | } | |
128 | ||
129 | /* Zero buffer used to clear bss storage in ENP */ | |
130 | ||
131 | for( i = 0; i < BSIZE; i++ ) | |
132 | { | |
133 | zbuf[i] = 0; | |
134 | } | |
135 | ||
136 | if( noload ) | |
137 | { | |
138 | printf("Restart %s at 0xf02000\n", ep->name); | |
139 | ioctl( enpfid,ENPIOGO,0xf02000 ); | |
140 | exit( 0 ); | |
141 | } | |
142 | ioctl( enpfid,ENPIORESET,0 ); | |
143 | ||
144 | /* Open, validate, and load each file_tab[] file */ | |
145 | ||
146 | for( i = 0; i < fcnt; i++ ) | |
147 | { | |
148 | fp = &file_tab[i]; | |
149 | if( (fp->b_fid = open( fp->b_name,O_RDONLY )) == -1 ) | |
150 | { | |
151 | printf( "enpload: Can't open %s!\n",fp->b_name ); | |
152 | closem( i-1 ); | |
153 | exit( 1 ); | |
154 | } | |
155 | ||
156 | if( read( fp->b_fid,&hdr,sizeof( hdr ) ) != sizeof( hdr) ) | |
157 | { | |
158 | printf( "enpload: %s Bad header!\n",fp->b_name ); | |
159 | closem( i ); | |
160 | exit( 1 ); | |
161 | } | |
162 | ||
163 | if( N_BADMAG( hdr ) ) | |
164 | { | |
165 | printf( "enpload: %s Bad magic!\n",fp->b_name ); | |
166 | closem( i ); | |
167 | exit( 1 ); | |
168 | } | |
169 | ||
170 | f_size = hdr.a_text + hdr.a_data; | |
171 | bss_size = hdr.a_bss; | |
172 | lstart = (ep->mstart + (hdr.a_entry & RELO)) - 0x1000; | |
173 | cstart = lstart + f_size; | |
174 | ||
175 | printf("Loading %s --- ", enpdev); | |
176 | printf( "with file: %s --- ",fp->b_name ); | |
177 | /* | |
178 | printf( "text + data: %d bss: %d\n",f_size,bss_size ); | |
179 | printf( "ENP's a_entry addr: %06X\n",hdr.a_entry ); | |
180 | printf( "load start:%06X bss start:%06X\n",lstart,cstart ); | |
181 | ||
182 | printf( "Clearing bss ... " ); | |
183 | */ | |
184 | lseek( enpfid,cstart,0 ); | |
185 | while( bss_size >= BSIZE ) | |
186 | { | |
187 | if( write( enpfid,zbuf,BSIZE ) != BSIZE ) | |
188 | printf("enpload: bss write error\n"); | |
189 | bss_size -= BSIZE; | |
190 | } | |
191 | if( bss_size > 0 ) | |
192 | { | |
193 | write( enpfid,zbuf,bss_size ); | |
194 | } | |
195 | /* | |
196 | printf( "DONE!\n" ); | |
197 | */ | |
198 | ||
199 | /* | |
200 | printf( "Loading ... " ); | |
201 | */ | |
202 | lseek( enpfid,lstart,0 ); | |
203 | while( f_size > BSIZE ) | |
204 | { | |
205 | cnt = read( fp->b_fid,buff,BSIZE ); | |
206 | f_size -= cnt; | |
207 | if( write( enpfid,buff,cnt ) != cnt ) | |
208 | perror("enpload: write"); | |
209 | } | |
210 | if( f_size > 0 ) | |
211 | { | |
212 | cnt = read( fp->b_fid,buff,f_size ); | |
213 | write( enpfid,buff,cnt ); | |
214 | } | |
215 | printf( "DONE!\n" ); | |
216 | } | |
217 | ||
218 | /* Last file, we exec this one */ | |
219 | ||
220 | if( nostart == 0 ) | |
221 | { | |
222 | enp_go = hdr.a_entry; | |
223 | /* | |
224 | printf( "Starting ENP execution at %X ... ",enp_go ); | |
225 | */ | |
226 | ioctl( enpfid,ENPIOGO, enp_go ); | |
227 | /* | |
228 | printf( "DONE!\n" ); | |
229 | */ | |
230 | } | |
231 | } | |
232 | ||
233 | ||
234 | ENP * | |
235 | getenp( np ) | |
236 | register char *np; | |
237 | { | |
238 | register ENP *ep; | |
239 | ||
240 | for( ep = enp_tab; ep < &enp_tab[num_enp]; ep++ ) | |
241 | if( strcmp( np,ep->name ) == 0 ) | |
242 | { | |
243 | return( ep ); | |
244 | } | |
245 | return( 0 ); | |
246 | } | |
247 | ||
248 | ||
249 | closem( cnt ) | |
250 | register short cnt; | |
251 | { | |
252 | register BINS *fp; | |
253 | ||
254 | for( fp = file_tab; fp < &file_tab[cnt]; fp++ ) | |
255 | { | |
256 | close( fp->b_fid ); | |
257 | } | |
258 | if( enpfid != -1 ) | |
259 | { | |
260 | close( enpfid ); | |
261 | } | |
262 | } |