usr.sbin - Include some missing programs in x86_64.
[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.4 2007/02/03 23:13:19 swildner 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
103 usage(void)
104 {
105         fprintf(stderr, "%s\n%s\n",
106 "usage: stlload [-vhVR] [-i image-file] [-c control-device] [-r rx-buf-size]",
107 "               [-t tx-buf-size] [-B boot-banner] [-b unit-number]");
108         exit(0);
109 }
110
111 /*****************************************************************************/
112
113 /*
114  *      Given a boards signature determine how many ports it has. We need to
115  *      know this to setup the slave feature arguments. This function is for
116  *      ECP boards only.
117  */
118
119 int
120 ecpfindports(cdkecpsig_t *sigp)
121 {
122         unsigned int    id;
123         int             bank, nrports;
124
125         nrports = 0;
126         for (bank = 0; (bank < 8); bank++) {
127                 id = (unsigned int) sigp->panelid[bank];
128                 if (id == 0xff)
129                         break;
130                 if ((id & 0x07) != bank)
131                         break;
132                 if (id & 0x20) {
133                         nrports += 16;
134                         bank++;
135                 } else {
136                         nrports += 8;
137                 }
138         }
139
140         return(nrports);
141 }
142
143 /*****************************************************************************/
144
145 /*
146  *      Given a boards signature determine how many ports it has. We need to
147  *      know this to setup the slave feature arguments. This function is for
148  *      ONboards and Brumbys.
149  */
150
151 int
152 onbfindports(cdkonbsig_t *sigp)
153 {
154         int     i, nrports;
155
156         if (sigp->amask1) {
157                 nrports = 32;
158         } else {
159                 for (i = 0; (i < 16); i++) {
160                         if (((sigp->amask0 << i) & 0x8000) == 0)
161                                 break;
162                 }
163                 nrports = i;
164         }
165
166         return(nrports);
167 }
168
169 /*****************************************************************************/
170
171 /*
172  *      Download an image to the slave board. There is a long sequence of
173  *      things to do to get the slave running, but it is basically a simple
174  *      process. Main things to do are: copy slave image into shared memory,
175  *      start slave running and then read shared memory map.
176  */
177
178 int
179 download(void)
180 {
181         unsigned char   alivemarker;
182         time_t          strttime;
183         int             memfd, ifd;
184         int             nrdevs, sigok, n;
185
186         if (verbose)
187                 printf("Opening shared memory device %s\n", memdevice);
188         if ((memfd = open(memdevice, O_RDWR)) < 0) {
189                 warn("failed to open memory device %s", memdevice);
190                 return(-1);
191         }
192
193 /*
194  *      Before starting the download must tell driver that we are about to
195  *      stop its slave. This is only important if it is already running.
196  *      Once we have told the driver its stopped then do a hardware reset
197  *      on it, to get it into a known state.
198  */
199         if (verbose)
200                 printf("Stoping any current slave\n");
201         if (ioctl(memfd, STL_BSTOP, 0) < 0) {
202                 warn("ioctl(STL_BSTOP)");
203                 printf(" (Perhaps you're trying to download firmware to a PCI card that\n doesn't require this?)\n");
204                 return(-1);
205         }
206
207         if (verbose)
208                 printf("Reseting the board\n");
209         if (ioctl(memfd, STL_BRESET, 0) < 0) {
210                 warn("ioctl(STL_BRESET)");
211                 return(-1);
212         }
213         if (reset)
214                 return(0);
215
216 /*
217  *      After reseting the board we need to send an interrupt to the older
218  *      board types to get them to become active. Do that now.
219  */
220         if (verbose)
221                 printf("Interrupting board to activate shared memory\n");
222         if (ioctl(memfd, STL_BINTR, 0) < 0) {
223                 warn("ioctl(STL_BINTR)");
224                 return(-1);
225         }
226         /*sleep(1);*/
227
228         if (verbose)
229                 printf("Opening slave image file %s\n", image);
230         if ((ifd = open(image, O_RDONLY)) < 0) {
231                 warn("failed to open image file %s", image);
232                 return(-1);
233         }
234
235 /*
236  *      At this point get the signature of the board from the shared memory.
237  *      Do a double check that it is a board we know about. We will also need
238  *      to calculate the number of ports on this board (to use later).
239  */
240         sigok = 0;
241         if (verbose)
242                 printf("Reading ROM signature from board\n");
243
244         if (lseek(memfd, CDK_SIGADDR, SEEK_SET) != CDK_SIGADDR) {
245                 warn("lseek(%x) failed on memory file", CDK_FEATADDR);
246                 return(-1);
247         }
248         if (read(memfd, &ecpsig, sizeof(cdkecpsig_t)) < 0) {
249                 warn("read of ROM signature failed");
250                 return(-1);
251         }
252         if (ecpsig.magic == ECP_MAGIC) {
253                 nrdevs = ecpfindports(&ecpsig);
254                 if (nrdevs < 0)
255                         return(-1);
256                 sigok++;
257         }
258
259         if (lseek(memfd, CDK_SIGADDR, SEEK_SET) != CDK_SIGADDR) {
260                 warn("lseek(%x) failed on memory file", CDK_FEATADDR);
261                 return(-1);
262         }
263         if (read(memfd, &onbsig, sizeof(cdkonbsig_t)) < 0) {
264                 warn("read of ROM signature failed");
265                 return(-1);
266         }
267         if ((onbsig.magic0 == ONB_MAGIC0) && (onbsig.magic1 == ONB_MAGIC1) &&
268                         (onbsig.magic2 == ONB_MAGIC2) &&
269                         (onbsig.magic3 == ONB_MAGIC3)) {
270                 nrdevs = onbfindports(&onbsig);
271                 if (nrdevs < 0)
272                         return(-1);
273                 sigok++;
274         }
275
276         if (! sigok) {
277                 warnx("unknown signature from board");
278                 return(-1);
279         }
280
281         if (verbose)
282                 printf("Board signature reports %d ports\n", nrdevs);
283
284 /*
285  *      Start to copy the image file into shared memory. The first thing to
286  *      do is copy the vector region in from shared memory address 0. We will
287  *      then skip over the signature and feature area and start copying the
288  *      actual image data and code from 4k upwards.
289  */
290         if (verbose)
291                 printf("Copying vector table into shared memory\n");
292         if ((n = read(ifd, buf, CDK_SIGADDR)) < 0) {
293                 warn("read of image file failed");
294                 return(-1);
295         }
296         if (lseek(memfd, 0, SEEK_SET) != 0) {
297                 warn("lseek(%x) failed on memory file", CDK_FEATADDR);
298                 return(-1);
299         }
300         if (write(memfd, buf, n) < 0) {
301                 warn("write to memory device failed");
302                 return(-1);
303         }
304
305         if (lseek(ifd, 0x1000, SEEK_SET) != 0x1000) {
306                 warn("lseek(%x) failed on image file", CDK_FEATADDR);
307                 return(-1);
308         }
309         if (lseek(memfd, 0x1000, SEEK_SET) != 0x1000) {
310                 warn("lseek(%x) failed on memory device", CDK_FEATADDR);
311                 return(-1);
312         }
313
314 /*
315  *      Copy buffer size chunks of data from the image file into shared memory.
316  */
317         do {
318                 if ((n = read(ifd, buf, BUFSIZE)) < 0) {
319                         warn("read of image file failed");
320                         return(-1);
321                 }
322                 if (write(memfd, buf, n) < 0) {
323                         warn("write to memory device failed");
324                         return(-1);
325                 }
326         } while (n == BUFSIZE);
327
328         close(ifd);
329
330 /*
331  *      We need to down load the start up parameters for the slave. This is
332  *      done via the feature area of shared memory. Think of the feature area
333  *      as a way of passing "command line" arguments to the slave.
334  *      FIX: should do something here to load "brdspec" as well...
335  */
336         feature.nrdevs = nrdevs;
337         if (verbose)
338                 printf("Loading features into shared memory\n");
339         if (lseek(memfd, CDK_FEATADDR, SEEK_SET) != CDK_FEATADDR) {
340                 warn("lseek(%x) failed on memory device", CDK_FEATADDR);
341                 return(-1);
342         }
343         if (write(memfd, &feature, sizeof(cdkfeature_t)) < 0) {
344                 warn("write to memory device failed");
345                 return(-1);
346         }
347
348 /*
349  *      Wait for board alive marker to be set. The slave image will set the
350  *      byte at address CDK_RDYADDR to 0x13 after it has successfully started.
351  *      If this doesn't happen we timeout and fail.
352  */
353         if (verbose)
354                 printf("Setting alive marker to 0\n");
355         if (lseek(memfd, CDK_RDYADDR, SEEK_SET) != CDK_RDYADDR) {
356                 warn("lseek(%x) failed on memory device", CDK_RDYADDR);
357                 return(-1);
358         }
359         alivemarker = 0;
360         if (write(memfd, &alivemarker, 1) < 0) {
361                 warn("write to memory device failed");
362                 return(-1);
363         }
364
365 /*
366  *      At this point the entire image is loaded into shared memory. To start
367  *      it executiong we poke the board with an interrupt.
368  */
369         if (verbose)
370                 printf("Interrupting board to start slave image\n");
371         if (ioctl(memfd, STL_BINTR, 0) < 0) {
372                 warn("ioctl(STL_BINTR) failed");
373                 return(-1);
374         }
375
376         strttime = time(NULL);
377         if (verbose)
378                 printf("Waiting for slave alive marker, time=%lx timeout=%d\n",
379                         strttime, TIMEOUT);
380         while (time(NULL) < (strttime + TIMEOUT)) {
381                 if (lseek(memfd, CDK_RDYADDR, SEEK_SET) != CDK_RDYADDR) {
382                         warn("lseek(%x) failed on memory device", CDK_RDYADDR);
383                         return(-1);
384                 }
385                 if (read(memfd, &alivemarker, 1) < 0){
386                         warn("read of image file failed");
387                         return(-1);
388                 }
389                 if (alivemarker == CDK_ALIVEMARKER)
390                         break;
391         }
392
393         if (alivemarker != CDK_ALIVEMARKER) {
394                 warnx("slave image failed to start");
395                 return(-1);
396         }
397
398         if (lseek(memfd, CDK_RDYADDR, SEEK_SET) != CDK_RDYADDR) {
399                 warn("lseek(%x) failed on memory device", CDK_RDYADDR);
400                 return(-1);
401         }
402         alivemarker = 0;
403         if (write(memfd, &alivemarker, 1) < 0) {
404                 warn("write to memory device failed");
405                 return(-1);
406         }
407
408         if (verbose)
409                 printf("Slave image started successfully\n");
410
411 /*
412  *      The last thing to do now is to get the driver started. Now that the
413  *      slave is operational it must read in the memory map and gets its
414  *      internal tables initialized.
415  */
416         if (verbose)
417                 printf("Driver initializing host shared memory interface\n");
418         if (ioctl(memfd, STL_BSTART, 0) < 0) {
419                 warn("ioctl(STL_BSTART) failed");
420                 return(-1);
421         }
422
423         close(memfd);
424         return(0);
425 }
426
427 /*****************************************************************************/
428
429 int
430 main(int argc, char *argv[])
431 {
432         struct stat     statinfo;
433         int             c;
434
435         while ((c = getopt(argc, argv, "hvVRB:i:b:c:t:r:")) != -1) {
436                 switch (c) {
437                 case 'V':
438                         printf("stlload version %s\n", version);
439                         exit(0);
440                         break;
441                 case 'B':
442                         feature.banner = atol(optarg);
443                         break;
444                 case 'h':
445                         usage();
446                         break;
447                 case 'v':
448                         verbose++;
449                         break;
450                 case 'i':
451                         image = optarg;
452                         break;
453                 case 'R':
454                         reset++;
455                         break;
456                 case 'b':
457                         brdnr = atoi(optarg);
458                         break;
459                 case 'c':
460                         memdevice = optarg;
461                         break;
462                 case 't':
463                         feature.txrqsize = atol(optarg);
464                         break;
465                 case 'r':
466                         feature.rxrqsize = atol(optarg);
467                         break;
468                 case '?':
469                 default:
470                         usage();
471                         break;
472                 }
473         }
474
475         if (memdevice == NULL) {
476                 if ((brdnr < 0) || (brdnr >= 8))
477                         errx(1, "invalid board number %d specified", brdnr);
478                 sprintf(devstr, defdevice, brdnr);
479                 memdevice = &devstr[0];
480                 if (verbose)
481                         printf("Using shared memory device %s\n", memdevice);
482         }
483
484         if (verbose)
485                 printf("Downloading image %s to board %d\n", image, brdnr);
486
487 /*
488  *      Check that the shared memory device exits and is a character device.
489  */
490         if (stat(memdevice, &statinfo) < 0)
491                 errx(1, "memory device %s does not exist", memdevice);
492         if ((statinfo.st_mode & S_IFMT) != S_IFCHR)
493                 errx(1, "memory device %s is not a char device", memdevice);
494
495         if (stat(image, &statinfo) < 0)
496                 errx(1, "image file %s does not exist", image);
497
498 /*
499  *      All argument checking is now done. So lets get this show on the road.
500  */
501         if (download() < 0)
502                 exit(1);
503         exit(0);
504 }
505
506 /*****************************************************************************/