Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / usr.sbin / stallion / stlload / stlload.c
1 /*****************************************************************************/
2
3 /*
4  * stlload.c  -- stallion intelligent multiport down loader.
5  *
6  * Copyright (c) 1994-1998 Greg Ungerer (gerg@stallion.oz.au).
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *      This product includes software developed by Greg Ungerer.
20  * 4. Neither the name of the author nor the names of any co-contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  * $FreeBSD: src/usr.sbin/stallion/stlload/stlload.c,v 1.10.2.2 2002/02/13 22:55:45 dbaker Exp $
37  * $DragonFly: src/usr.sbin/stallion/stlload/stlload.c,v 1.2 2003/06/17 04:30:03 dillon Exp $
38  */
39
40 /*****************************************************************************/
41
42 #include <err.h>
43 #include <fcntl.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <time.h>
47 #include <unistd.h>
48 #include <sys/stat.h>
49 #include <sys/ioctl.h>
50
51 #include <machine/cdk.h>
52
53 /*****************************************************************************/
54
55 char    *version = "2.0.0";
56 char    *defdevice = "/dev/staliomem%d";
57 char    *image = BOOTDIR "/cdk.sys";
58 char    *oldimage = BOOTDIR "/2681.sys";
59
60 char    *memdevice;
61 char    devstr[128];
62 int     brdnr = 0;
63 int     verbose = 0;
64 int     reset = 0;
65
66 /*
67  *      Define a local buffer for copying the image into the shared memory.
68  */
69 #define BUFSIZE         4096
70
71 char    buf[BUFSIZE];
72
73 /*
74  *      Define the timeout length when waiting for slave to start up.
75  *      The quantity is measured in seconds.
76  */
77 #define TIMEOUT         5
78
79 /*
80  *      Set up a default feature area structure.
81  */
82 cdkfeature_t    feature = { 0, 0, ETYP_CDK, 0, 0, 0, 0, 0 };
83
84 /*
85  *      Have local copies of the board signatures ready.
86  */
87 cdkecpsig_t     ecpsig;
88 cdkonbsig_t     onbsig;
89
90 /*****************************************************************************/
91
92 /*
93  *      Declare internal function prototypes here.
94  */
95 static void     usage(void);
96 int     ecpfindports(cdkecpsig_t *sigp);
97 int     onbfindports(cdkonbsig_t *sigp);
98 int     download(void);
99
100 /*****************************************************************************/
101
102 static void usage()
103 {
104         fprintf(stderr, "%s\n%s\n",
105 "usage: stlload [-vhVR] [-i image-file] [-c control-device] [-r rx-buf-size]",
106 "               [-t tx-buf-size] [-B boot-banner] [-b unit-number]");
107         exit(0);
108 }
109
110 /*****************************************************************************/
111
112 /*
113  *      Given a boards signature determine how many ports it has. We need to
114  *      know this to setup the slave feature arguments. This function is for
115  *      ECP boards only.
116  */
117
118 int ecpfindports(cdkecpsig_t *sigp)
119 {
120         unsigned int    id;
121         int             bank, nrports;
122
123         nrports = 0;
124         for (bank = 0; (bank < 8); bank++) {
125                 id = (unsigned int) sigp->panelid[bank];
126                 if (id == 0xff)
127                         break;
128                 if ((id & 0x07) != bank)
129                         break;
130                 if (id & 0x20) {
131                         nrports += 16;
132                         bank++;
133                 } else {
134                         nrports += 8;
135                 }
136         }
137
138         return(nrports);
139 }
140
141 /*****************************************************************************/
142
143 /*
144  *      Given a boards signature determine how many ports it has. We need to
145  *      know this to setup the slave feature arguments. This function is for
146  *      ONboards and Brumbys.
147  */
148
149 int onbfindports(cdkonbsig_t *sigp)
150 {
151         int     i, nrports;
152
153         if (sigp->amask1) {
154                 nrports = 32;
155         } else {
156                 for (i = 0; (i < 16); i++) {
157                         if (((sigp->amask0 << i) & 0x8000) == 0)
158                                 break;
159                 }
160                 nrports = i;
161         }
162
163         return(nrports);
164 }
165
166 /*****************************************************************************/
167
168 /*
169  *      Download an image to the slave board. There is a long sequence of
170  *      things to do to get the slave running, but it is basically a simple
171  *      process. Main things to do are: copy slave image into shared memory,
172  *      start slave running and then read shared memory map.
173  */
174
175 int download()
176 {
177         unsigned char   alivemarker;
178         time_t          strttime;
179         int             memfd, ifd;
180         int             nrdevs, sigok, n;
181
182         if (verbose)
183                 printf("Opening shared memory device %s\n", memdevice);
184         if ((memfd = open(memdevice, O_RDWR)) < 0) {
185                 warn("failed to open memory device %s", memdevice);
186                 return(-1);
187         }
188
189 /*
190  *      Before starting the download must tell driver that we are about to
191  *      stop its slave. This is only important if it is already running.
192  *      Once we have told the driver its stopped then do a hardware reset
193  *      on it, to get it into a known state.
194  */
195         if (verbose)
196                 printf("Stoping any current slave\n");
197         if (ioctl(memfd, STL_BSTOP, 0) < 0) {
198                 warn("ioctl(STL_BSTOP)");
199                 printf(" (Perhaps you're trying to download firmare to a PCI card that\n doesn't require this?)\n");
200                 return(-1);
201         }
202
203         if (verbose)
204                 printf("Reseting the board\n");
205         if (ioctl(memfd, STL_BRESET, 0) < 0) {
206                 warn("ioctl(STL_BRESET)");
207                 return(-1);
208         }
209         if (reset)
210                 return(0);
211
212 /*
213  *      After reseting the board we need to send an interrupt to the older
214  *      board types to get them to become active. Do that now.
215  */
216         if (verbose)
217                 printf("Interrupting board to activate shared memory\n");
218         if (ioctl(memfd, STL_BINTR, 0) < 0) {
219                 warn("ioctl(STL_BINTR)");
220                 return(-1);
221         }
222         /*sleep(1);*/
223
224         if (verbose)
225                 printf("Opening slave image file %s\n", image);
226         if ((ifd = open(image, O_RDONLY)) < 0) {
227                 warn("failed to open image file %s", image);
228                 return(-1);
229         }
230
231 /*
232  *      At this point get the signature of the board from the shared memory.
233  *      Do a double check that it is a board we know about. We will also need
234  *      to calculate the number of ports on this board (to use later).
235  */
236         sigok = 0;
237         if (verbose)
238                 printf("Reading ROM signature from board\n");
239
240         if (lseek(memfd, CDK_SIGADDR, SEEK_SET) != CDK_SIGADDR) {
241                 warn("lseek(%x) failed on memory file", CDK_FEATADDR);
242                 return(-1);
243         }
244         if (read(memfd, &ecpsig, sizeof(cdkecpsig_t)) < 0) {
245                 warn("read of ROM signature failed");
246                 return(-1);
247         }
248         if (ecpsig.magic == ECP_MAGIC) {
249                 nrdevs = ecpfindports(&ecpsig);
250                 if (nrdevs < 0)
251                         return(-1);
252                 sigok++;
253         }
254
255         if (lseek(memfd, CDK_SIGADDR, SEEK_SET) != CDK_SIGADDR) {
256                 warn("lseek(%x) failed on memory file", CDK_FEATADDR);
257                 return(-1);
258         }
259         if (read(memfd, &onbsig, sizeof(cdkonbsig_t)) < 0) {
260                 warn("read of ROM signature failed");
261                 return(-1);
262         }
263         if ((onbsig.magic0 == ONB_MAGIC0) && (onbsig.magic1 == ONB_MAGIC1) &&
264                         (onbsig.magic2 == ONB_MAGIC2) &&
265                         (onbsig.magic3 == ONB_MAGIC3)) {
266                 nrdevs = onbfindports(&onbsig);
267                 if (nrdevs < 0)
268                         return(-1);
269                 sigok++;
270         }
271
272         if (! sigok) {
273                 warnx("unknown signature from board");
274                 return(-1);
275         }
276
277         if (verbose)
278                 printf("Board signature reports %d ports\n", nrdevs);
279
280 /*
281  *      Start to copy the image file into shared memory. The first thing to
282  *      do is copy the vector region in from shared memory address 0. We will
283  *      then skip over the signature and feature area and start copying the
284  *      actual image data and code from 4k upwards.
285  */
286         if (verbose)
287                 printf("Copying vector table into shared memory\n");
288         if ((n = read(ifd, buf, CDK_SIGADDR)) < 0) {
289                 warn("read of image file failed");
290                 return(-1);
291         }
292         if (lseek(memfd, 0, SEEK_SET) != 0) {
293                 warn("lseek(%x) failed on memory file", CDK_FEATADDR);
294                 return(-1);
295         }
296         if (write(memfd, buf, n) < 0) {
297                 warn("write to memory device failed");
298                 return(-1);
299         }
300
301         if (lseek(ifd, 0x1000, SEEK_SET) != 0x1000) {
302                 warn("lseek(%x) failed on image file", CDK_FEATADDR);
303                 return(-1);
304         }
305         if (lseek(memfd, 0x1000, SEEK_SET) != 0x1000) {
306                 warn("lseek(%x) failed on memory device", CDK_FEATADDR);
307                 return(-1);
308         }
309
310 /*
311  *      Copy buffer size chunks of data from the image file into shared memory.
312  */
313         do {
314                 if ((n = read(ifd, buf, BUFSIZE)) < 0) {
315                         warn("read of image file failed");
316                         return(-1);
317                 }
318                 if (write(memfd, buf, n) < 0) {
319                         warn("write to memory device failed");
320                         return(-1);
321                 }
322         } while (n == BUFSIZE);
323
324         close(ifd);
325
326 /*
327  *      We need to down load the start up parameters for the slave. This is
328  *      done via the feature area of shared memory. Think of the feature area
329  *      as a way of passing "command line" arguments to the slave.
330  *      FIX: should do something here to load "brdspec" as well...
331  */
332         feature.nrdevs = nrdevs;
333         if (verbose)
334                 printf("Loading features into shared memory\n");
335         if (lseek(memfd, CDK_FEATADDR, SEEK_SET) != CDK_FEATADDR) {
336                 warn("lseek(%x) failed on memory device", CDK_FEATADDR);
337                 return(-1);
338         }
339         if (write(memfd, &feature, sizeof(cdkfeature_t)) < 0) {
340                 warn("write to memory device failed");
341                 return(-1);
342         }
343
344 /*
345  *      Wait for board alive marker to be set. The slave image will set the
346  *      byte at address CDK_RDYADDR to 0x13 after it has successfully started.
347  *      If this doesn't happen we timeout and fail.
348  */
349         if (verbose)
350                 printf("Setting alive marker to 0\n");
351         if (lseek(memfd, CDK_RDYADDR, SEEK_SET) != CDK_RDYADDR) {
352                 warn("lseek(%x) failed on memory device", CDK_RDYADDR);
353                 return(-1);
354         }
355         alivemarker = 0;
356         if (write(memfd, &alivemarker, 1) < 0) {
357                 warn("write to memory device failed");
358                 return(-1);
359         }
360
361 /*
362  *      At this point the entire image is loaded into shared memory. To start
363  *      it executiong we poke the board with an interrupt.
364  */
365         if (verbose)
366                 printf("Interrupting board to start slave image\n");
367         if (ioctl(memfd, STL_BINTR, 0) < 0) {
368                 warn("ioctl(STL_BINTR) failed");
369                 return(-1);
370         }
371
372         strttime = time((time_t *) NULL);
373         if (verbose)
374                 printf("Waiting for slave alive marker, time=%x timeout=%d\n",
375                         strttime, TIMEOUT);
376         while (time((time_t *) NULL) < (strttime + TIMEOUT)) {
377                 if (lseek(memfd, CDK_RDYADDR, SEEK_SET) != CDK_RDYADDR) {
378                         warn("lseek(%x) failed on memory device", CDK_RDYADDR);
379                         return(-1);
380                 }
381                 if (read(memfd, &alivemarker, 1) < 0){
382                         warn("read of image file failed");
383                         return(-1);
384                 }
385                 if (alivemarker == CDK_ALIVEMARKER)
386                         break;
387         }
388
389         if (alivemarker != CDK_ALIVEMARKER) {
390                 warnx("slave image failed to start");
391                 return(-1);
392         }
393
394         if (lseek(memfd, CDK_RDYADDR, SEEK_SET) != CDK_RDYADDR) {
395                 warn("lseek(%x) failed on memory device", CDK_RDYADDR);
396                 return(-1);
397         }
398         alivemarker = 0;
399         if (write(memfd, &alivemarker, 1) < 0) {
400                 warn("write to memory device failed");
401                 return(-1);
402         }
403
404         if (verbose)
405                 printf("Slave image started successfully\n");
406
407 /*
408  *      The last thing to do now is to get the driver started. Now that the
409  *      slave is operational it must read in the memory map and gets its
410  *      internal tables initialized.
411  */
412         if (verbose)
413                 printf("Driver initializing host shared memory interface\n");
414         if (ioctl(memfd, STL_BSTART, 0) < 0) {
415                 warn("ioctl(STL_BSTART) failed");
416                 return(-1);
417         }
418
419         close(memfd);
420         return(0);
421 }
422
423 /*****************************************************************************/
424
425 int main(int argc, char *argv[])
426 {
427         struct stat     statinfo;
428         int             c;
429
430         while ((c = getopt(argc, argv, "hvVRB:i:b:c:t:r:")) != -1) {
431                 switch (c) {
432                 case 'V':
433                         printf("stlload version %s\n", version);
434                         exit(0);
435                         break;
436                 case 'B':
437                         feature.banner = atol(optarg);
438                         break;
439                 case 'h':
440                         usage();
441                         break;
442                 case 'v':
443                         verbose++;
444                         break;
445                 case 'i':
446                         image = optarg;
447                         break;
448                 case 'R':
449                         reset++;
450                         break;
451                 case 'b':
452                         brdnr = atoi(optarg);
453                         break;
454                 case 'c':
455                         memdevice = optarg;
456                         break;
457                 case 't':
458                         feature.txrqsize = atol(optarg);
459                         break;
460                 case 'r':
461                         feature.rxrqsize = atol(optarg);
462                         break;
463                 case '?':
464                 default:
465                         usage();
466                         break;
467                 }
468         }
469
470         if (memdevice == (char *) NULL) {
471                 if ((brdnr < 0) || (brdnr >= 8))
472                         errx(1, "invalid board number %d specified", brdnr);
473                 sprintf(devstr, defdevice, brdnr);
474                 memdevice = &devstr[0];
475                 if (verbose)
476                         printf("Using shared memory device %s\n", memdevice);
477         }
478
479         if (verbose)
480                 printf("Downloading image %s to board %d\n", image, brdnr);
481
482 /*
483  *      Check that the shared memory device exits and is a character device.
484  */
485         if (stat(memdevice, &statinfo) < 0)
486                 errx(1, "memory device %s does not exist", memdevice);
487         if ((statinfo.st_mode & S_IFMT) != S_IFCHR)
488                 errx(1, "memory device %s is not a char device", memdevice);
489
490         if (stat(image, &statinfo) < 0)
491                 errx(1, "image file %s does not exist", image);
492
493 /*
494  *      All argument checking is now done. So lets get this show on the road.
495  */
496         if (download() < 0)
497                 exit(1);
498         exit(0);
499 }
500
501 /*****************************************************************************/