nvi - Work around problem with git
[dragonfly.git] / sbin / atm / fore_dnld / fore_dnld.c
blobd7d13c0241db0197c8d4a5dd46141bdf09d3eb85
1 /*
3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
8 * This Host ATM Research Platform ("HARP") file (the "Software") is
9 * made available by Network Computing Services, Inc. ("NetworkCS")
10 * "AS IS". NetworkCS does not provide maintenance, improvements or
11 * support of any kind.
13 * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14 * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15 * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16 * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17 * In no event shall NetworkCS be responsible for any damages, including
18 * but not limited to consequential damages, arising from or relating to
19 * any use of the Software or related support.
21 * Copyright 1994-1998 Network Computing Services, Inc.
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
26 * @(#) $FreeBSD: src/sbin/atm/fore_dnld/fore_dnld.c,v 1.6.2.2 2000/12/11 01:03:24 obrien Exp $
27 * @(#) $DragonFly: src/sbin/atm/fore_dnld/fore_dnld.c,v 1.8 2006/10/16 00:15:35 pavalos Exp $
31 * User utilities
32 * --------------
34 * Download (pre)processed microcode into Fore Series-200 host adapter
35 * Interact with i960 uart on Fore Series-200 host adapter
39 #include <sys/param.h>
40 #include <sys/mman.h>
41 #include <sys/socket.h>
42 #include <sys/stat.h>
43 #include <net/if.h>
44 #include <netatm/atm.h>
45 #include <netatm/atm_if.h>
46 #include <netatm/atm_sap.h>
47 #include <netatm/atm_sys.h>
48 #include <netatm/atm_ioctl.h>
49 #include <dev/atm/hfa/fore.h>
50 #include <dev/atm/hfa/fore_aali.h>
51 #include <dev/atm/hfa/fore_slave.h>
53 #include <ctype.h>
54 #include <fcntl.h>
55 #include <paths.h>
56 #include <stdio.h>
57 #include <stdlib.h>
58 #include <string.h>
59 #if (defined(BSD) && (BSD >= 199103))
60 #include <termios.h>
61 #else
62 #include <termio.h>
63 #endif /* !BSD */
64 #include <unistd.h>
66 extern u_char pca200e_microcode[];
67 extern int pca200e_microcode_size;
69 #ifdef sun
70 #define DEV_NAME "/dev/sbus%d"
71 #endif /* sun */
72 #if (defined(BSD) && (BSD >= 199103))
73 #define DEV_NAME _PATH_KMEM
74 #endif /* BSD */
76 #define MAX_CHECK 60
78 int comm_mode = 0;
79 char *progname;
81 int tty;
82 cc_t vmin, vtime;
83 #if (defined(BSD) && (BSD >= 199103))
84 struct termios sgtty;
85 #define TCSETA TIOCSETA
86 #define TCGETA TIOCGETA
87 #else
88 struct termio sgtty;
89 #endif /* !BSD */
91 int endian = 0;
92 int verbose = 0;
93 int reset = 0;
95 char line[132];
96 unsigned int lineptr = 0;
98 Mon960 *Uart;
101 static void
102 delay(int cnt)
104 usleep(cnt);
107 static unsigned long
108 CP_READ ( unsigned long val )
110 if ( endian )
111 return ( ntohl ( val ) );
112 else
113 return ( val );
116 static unsigned long
117 CP_WRITE ( unsigned long val )
119 if ( endian )
120 return ( htonl ( val ) );
121 else
122 return ( val );
126 * Print an error message and exit.
128 * Arguments:
129 * none
131 * Returns:
132 * none
134 static void
135 error ( const char *msg )
137 printf ( "%s\n", msg );
138 exit (1);
142 * Get a byte for the uart and if printing, display it.
144 * Returns:
145 * c Character from uart
147 static char
148 getbyte ( void )
150 int c;
152 while ( ! ( CP_READ(Uart->mon_xmithost) & UART_VALID ) )
153 delay(10);
155 c = ( CP_READ(Uart->mon_xmithost) & UART_DATAMASK );
156 Uart->mon_xmithost = CP_WRITE(UART_READY);
159 * We need to introduce a delay in here or things tend to hang...
161 delay(10000);
163 if ( lineptr >= sizeof(line) )
164 lineptr = 0;
167 * Save character into line
169 line[lineptr++] = c;
171 if (verbose) {
172 if (isprint(c) || (c == '\n') || (c == '\r'))
173 putc(c, stdout);
175 return ( c & 0xff );
179 * Loop getting characters from uart into static string until eol. If printing,
180 * display the line retrieved.
182 * Arguments:
183 * prn Are we displaying characters
185 * Returns:
186 * none Line in global string 'line[]'
188 static void
189 getline ( int prn )
191 char c = '\0';
192 unsigned int i = 0;
194 while ( c != '>' && c != '\n' && c != '\r' )
196 c = getbyte();
197 if ( ++i >= sizeof(line) )
199 if ( prn )
200 printf ( "%s", line );
201 i = 0;
206 * Terminate line
208 line[lineptr] = 0;
209 lineptr = 0;
214 * Send a byte to the i960
216 * Arguments:
217 * c Character to send
219 * Returns:
220 * none
222 static void
223 xmit_byte ( unsigned char c, int dn )
225 int val;
227 while ( CP_READ(Uart->mon_xmitmon) != UART_READY )
229 if ( CP_READ(Uart->mon_xmithost) & UART_VALID )
230 getbyte ();
231 if ( !dn ) delay ( 10000 );
233 val = ( c | UART_VALID );
234 Uart->mon_xmitmon = CP_WRITE( val );
235 if ( !dn ) delay ( 10000 );
236 if ( CP_READ(Uart->mon_xmithost) & UART_VALID )
237 getbyte();
242 * Transmit a line to the i960. Eol must be included as part of text to transmit.
244 * Arguments:
245 * str Character string to transmit
246 * len len of string. This allows us to include NULL's
247 * in the string/block to be transmitted.
249 * Returns:
250 * none
252 static void
253 xmit_to_i960 ( const char *str, int len, int dn )
255 int i;
257 for ( i = 0; i < len; i++ )
258 xmit_byte ( str[i], dn );
262 * Send autobaud sequence to i960 monitor
264 * Arguments:
265 * none
267 * Returns:
268 * none
270 static void
271 autobaud(void)
273 if ( strncmp ( line, "Mon960", 6 ) == 0 )
274 xmit_to_i960 ( "\r\n\r\n\r\n\r\n", 8, 0 );
278 * Reset tty to initial state
280 * Arguments:
281 * ret error code for exit()
283 * Returns:
284 * none
287 static void
288 finish ( int ret )
290 sgtty.c_lflag |= ( ICANON | ECHO );
291 sgtty.c_cc[VMIN] = vmin;
292 sgtty.c_cc[VTIME] = vtime;
293 ioctl ( tty, TCSETA, &sgtty );
294 exit ( ret );
298 * Utility to strip off any leading path information from a filename
300 * Arguments:
301 * path pathname to strip
303 * Returns:
304 * fname striped filename
307 static char *
308 basename ( char *path )
310 char *fname;
312 if ( ( fname = strrchr ( path, '/' ) ) != NULL )
313 fname++;
314 else
315 fname = path;
317 return ( fname );
321 * ASCII constants
323 #define SOH 001
324 #define STX 002
325 #define ETX 003
326 #define EOT 004
327 #define ENQ 005
328 #define ACK 006
329 #define LF 012
330 #define CR 015
331 #define NAK 025
332 #define SYN 026
333 #define CAN 030
334 #define ESC 033
336 #define NAKMAX 2
337 #define ERRORMAX 10
338 #define RETRYMAX 5
340 #define CRCCHR 'C'
341 #define CTRLZ 032
343 #define BUFSIZE 128
345 #define W 16
346 #define B 8
349 * crctab - CRC-16 constant array...
350 * from Usenet contribution by Mark G. Mendel, Network Systems Corp.
351 * (ihnp4!umn-cs!hyper!mark)
353 unsigned short crctab[1<<B] = {
354 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
355 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
356 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
357 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
358 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
359 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
360 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
361 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
362 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
363 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
364 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
365 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
366 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
367 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
368 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
369 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
370 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
371 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
372 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
373 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
374 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
375 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
376 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
377 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
378 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
379 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
380 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
381 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
382 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
383 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
384 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
385 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
389 * Hacked up xmodem protocol. Transmits the file 'filename' down to the i960
390 * using the xmodem protocol.
392 * Arguments:
393 * filename name of file to transmit
395 * Returns:
396 * 0 file transmitted
397 * -1 unable to send file
399 static int
400 xmitfile ( char *filename )
402 int fd;
403 int numsect;
404 int sectnum;
405 struct stat stb;
406 char c;
407 char sendresp;
408 int crcmode = 0;
409 int attempts = 0;
410 int errors;
411 int sendfin;
412 int extrachr;
413 char buf[BUFSIZE + 6];
414 char blockbuf[BUFSIZE + 6];
415 int bufcntr;
416 int bbufcntr;
417 int bufsize = BUFSIZE;
418 int checksum;
421 * Try opening file
423 if ( ( fd = open ( filename, O_RDONLY ) ) < 0 )
425 return -1;
427 stat ( filename, &stb );
430 * Determine number of 128 bytes sectors to transmit
432 numsect = ( stb.st_size / 128 ) + 1;
434 if ( verbose )
435 fprintf ( stderr, "Downloading %d sectors from %s\n",
436 numsect, filename );
439 * Send DO'wnload' command to i960
441 xmit_to_i960 ( "do\r\n", 4, 0 );
443 * Wait for response from i960 indicating download in progress
445 while ( strncmp ( line, "Downloading", 11 ) != 0 )
446 getline ( verbose );
450 * Get startup character from i960
452 do {
453 while ( ( c = getbyte() ) != NAK && c != CRCCHR )
454 if ( ++attempts > NAKMAX )
455 error ( "Remote system not responding" );
457 if ( c == CRCCHR )
458 crcmode = 1;
460 } while ( c != NAK && c != CRCCHR );
462 sectnum = 1;
463 attempts = errors = sendfin = extrachr = 0;
466 * Loop over each sector to be sent
468 do {
469 if ( extrachr >= 128 )
471 extrachr = 0;
472 numsect++;
475 if ( sectnum > 0 )
478 * Read a sectors worth of data from the file into
479 * an internal buffer.
481 for ( bufcntr = 0; bufcntr < bufsize; )
483 int n;
485 * Check for EOF
487 if ( ( n = read ( fd, &c, 1 ) ) == 0 )
489 sendfin = 1;
490 if ( !bufcntr )
491 break;
492 buf[bufcntr++] = CTRLZ;
493 continue;
495 buf[bufcntr++] = c;
497 if ( !bufcntr )
498 break;
502 * Fill in xmodem protocol values. Block size and sector number
504 bbufcntr = 0;
505 blockbuf[bbufcntr++] = (bufsize == 1024) ? STX : SOH;
506 blockbuf[bbufcntr++] = sectnum;
507 blockbuf[bbufcntr++] = ~sectnum;
509 checksum = 0;
512 * Loop over the internal buffer computing the checksum of the
513 * sector
515 for ( bufcntr = 0; bufcntr < bufsize; bufcntr++ )
517 blockbuf[bbufcntr++] = buf[bufcntr];
519 if ( crcmode )
520 checksum = (checksum<<B) ^ crctab[(checksum>>(W-B)) ^ buf[bufcntr]];
521 else
522 checksum = ((checksum + buf[bufcntr]) & 0xff);
527 * Place the checksum at the end of the transmit buffer
529 if ( crcmode )
531 checksum &= 0xffff;
532 blockbuf[bbufcntr++] = ((checksum >> 8) & 0xff);
533 blockbuf[bbufcntr++] = (checksum & 0xff);
534 } else
535 blockbuf[bbufcntr++] = checksum;
537 attempts = 0;
540 * Make several attempts to send the data to the i960
545 * Transmit the sector + protocol to the i960
547 xmit_to_i960 ( blockbuf, bbufcntr, 1 );
550 * Inform user where we're at
552 if ( verbose )
553 printf ( "Sector %3d %3dk\r",
554 sectnum, (sectnum * bufsize) / 1024 );
556 attempts++;
558 * Get response from i960
560 sendresp = getbyte();
563 * If i960 didn't like the sector
565 if ( sendresp != ACK )
567 errors++;
570 * Are we supposed to cancel the transfer?
572 if ( ( sendresp & 0x7f ) == CAN )
573 if ( getbyte() == CAN )
574 error ( "Send canceled at user's request" );
577 } while ( ( sendresp != ACK ) && ( attempts < RETRYMAX ) && ( errors < ERRORMAX ) );
580 * Next sector
582 sectnum++;
584 } while ( !sendfin && ( attempts < RETRYMAX ) && ( errors < ERRORMAX ) );
587 * Did we expire all our allows attempts?
589 if ( attempts >= RETRYMAX )
591 xmit_byte ( CAN, 1 ), xmit_byte ( CAN, 1 ), xmit_byte ( CAN, 1 );
592 error ( "Remote system not responding" );
596 * Check for too many transmission errors
598 if ( errors >= ERRORMAX )
600 xmit_byte ( CAN, 1 ), xmit_byte ( CAN, 1 ), xmit_byte ( CAN, 1 );
601 error ( "Too many errors in transmission" );
604 attempts = 0;
607 * Indicate the transfer is complete
609 xmit_byte ( EOT, 1 );
612 * Wait until i960 acknowledges us
614 while ( ( c = getbyte() ) != ACK && ( ++attempts < RETRYMAX ) )
615 xmit_byte ( EOT, 1 );
617 if ( attempts >= RETRYMAX )
618 error ( "Remote system not responding on completion" );
621 * After download, we'll see a few more command
622 * prompts as the CP does its stuff. Ignore them.
624 while ( strncmp ( line, "=>", 2 ) != 0 )
625 getline ( verbose );
627 while ( strncmp ( line, "=>", 2 ) != 0 )
628 getline ( verbose );
630 while ( strncmp ( line, "=>", 2 ) != 0 )
631 getline ( verbose );
634 * Tell the i960 to start executing the downloaded code
636 xmit_to_i960 ( "go\r\n", 4, 0 );
639 * Get the messages the CP will spit out
640 * after the GO command.
642 getline ( verbose );
643 getline ( verbose );
645 close ( fd );
647 return ( 0 );
651 static int
652 loadmicrocode ( u_char *ucode, int size, u_char *ram )
654 struct {
655 u_long Id;
656 u_long fver;
657 u_long start;
658 u_long entry;
659 } binhdr;
660 #ifdef sun
661 union {
662 u_long w;
663 char c[4];
664 } w1, w2;
665 #endif
666 u_char *bufp;
667 u_long *lp;
671 * Check that we understand this header
673 memcpy(&binhdr, ucode, sizeof(binhdr));
674 if ( strncmp ( (caddr_t)&binhdr.Id, "fore", 4 ) != 0 ) {
675 fprintf ( stderr, "Unrecognized format in micorcode file." );
676 return ( -1 );
679 #ifdef sun
681 * We always swap the SunOS microcode file...
683 endian = 1;
686 * We need to swap the header start/entry words...
688 w1.w = binhdr.start;
689 for ( n = 0; n < sizeof(u_long); n++ )
690 w2.c[3-n] = w1.c[n];
691 binhdr.start = w2.w;
692 w1.w = binhdr.entry;
693 for ( n = 0; n < sizeof(u_long); n++ )
694 w2.c[3-n] = w1.c[n];
695 binhdr.entry = w2.w;
696 #endif /* sun */
699 * Set pointer to RAM load location
701 bufp = (ram + binhdr.start);
704 * Load file
706 if ( endian ) {
707 unsigned int i;
709 lp = (u_long *) ucode;
710 /* Swap buffer */
711 for ( i = 0; i < size / sizeof(long); i++ )
712 #ifndef sun
713 lp[i] = CP_WRITE(lp[i]);
714 #else
716 int j;
718 w1.w = lp[i];
719 for ( j = 0; j < 4; j++ )
720 w2.c[3-j] = w1.c[j];
721 lp[i] = w2.w;
723 #endif
725 bcopy ( (caddr_t)ucode, bufp, size );
728 * With .bin extension, we need to specify start address on 'go'
729 * command.
732 char cmd[80];
734 sprintf ( cmd, "go %lx\r\n", binhdr.entry );
736 xmit_to_i960 ( cmd, strlen ( cmd ), 0 );
738 while ( strncmp ( line, cmd, strlen(cmd) - 3 ) != 0 )
739 getline ( verbose );
741 if ( verbose )
742 printf("\n");
744 return ( 0 );
747 static int
748 sendbinfile ( char *fname, u_char *ram )
750 struct {
751 u_long Id;
752 u_long fver;
753 u_long start;
754 u_long entry;
755 } binhdr;
756 #ifdef sun
757 union {
758 u_long w;
759 char c[4];
760 } w1, w2;
761 #endif
762 int fd;
763 int n;
764 int cnt = 0;
765 u_char *bufp;
766 long buffer[1024];
769 * Try opening file
771 if ( ( fd = open ( fname, O_RDONLY ) ) < 0 )
772 return ( -1 );
775 * Read the .bin header from the file
777 if ( ( read ( fd, &binhdr, sizeof(binhdr) ) ) != sizeof(binhdr) )
779 close ( fd );
780 return ( -1 );
784 * Check that we understand this header
786 if ( strncmp ( (caddr_t)&binhdr.Id, "fore", 4 ) != 0 ) {
787 fprintf ( stderr, "Unrecognized format in micorcode file." );
788 close ( fd );
789 return ( -1 );
792 #ifdef sun
794 * We always swap the SunOS microcode file...
796 endian = 1;
799 * We need to swap the header start/entry words...
801 w1.w = binhdr.start;
802 for ( n = 0; n < sizeof(u_long); n++ )
803 w2.c[3-n] = w1.c[n];
804 binhdr.start = w2.w;
805 w1.w = binhdr.entry;
806 for ( n = 0; n < sizeof(u_long); n++ )
807 w2.c[3-n] = w1.c[n];
808 binhdr.entry = w2.w;
809 #endif /* sun */
812 * Rewind the file
814 lseek ( fd, 0, 0 );
817 * Set pointer to RAM load location
819 bufp = (ram + binhdr.start);
822 * Load file
824 if ( endian ) {
826 * Need to swap longs - copy file into temp buffer
828 while ( ( n = read ( fd, (char *)buffer, sizeof(buffer))) > 0 )
830 unsigned int i;
832 /* Swap buffer */
833 for ( i = 0; i < sizeof(buffer) / sizeof(long); i++ )
834 #ifndef sun
835 buffer[i] = CP_WRITE(buffer[i]);
836 #else
838 int j;
840 w1.w = buffer[i];
841 for ( j = 0; j < 4; j++ )
842 w2.c[3-j] = w1.c[j];
843 buffer[i] = w2.w;
845 #endif
848 * Copy swapped buffer into CP RAM
850 cnt++;
851 bcopy ( (caddr_t)buffer, bufp, n );
852 if ( verbose )
853 printf ( "%d\r", cnt );
854 bufp += n;
856 } else {
857 while ( ( n = read ( fd, bufp, 128 ) ) > 0 )
859 cnt++;
860 if ( verbose )
861 printf ( "%d\r", cnt );
862 bufp += n;
867 * With .bin extension, we need to specify start address on 'go'
868 * command.
871 char cmd[80];
873 sprintf ( cmd, "go %lx\r\n", binhdr.entry );
875 xmit_to_i960 ( cmd, strlen ( cmd ), 0 );
877 while ( strncmp ( line, cmd, strlen(cmd) - 3 ) != 0 )
878 getline ( verbose );
880 if ( verbose )
881 printf("\n");
884 close ( fd );
885 return ( 0 );
890 * Program to download previously processed microcode to series-200 host adapter
893 main( int argc, char **argv )
895 int fd; /* mmap for Uart */
896 u_char *ram; /* pointer to RAM */
897 Mon960 *Mon; /* Uart */
898 Aali *aap;
899 char c;
900 int i, err;
901 int binary = 0; /* Send binary file */
902 caddr_t buf; /* Ioctl buffer */
903 char bus_dev[80]; /* Bus device to mmap on */
904 struct atminfreq req;
905 struct air_cfg_rsp *air; /* Config info response structure */
906 int buf_len; /* Size of ioctl buffer */
907 const char *dev = "\0"; /* Device to download */
908 char *dirname = NULL; /* Directory path to objd files */
909 char *objfile = NULL; /* Command line object filename */
910 u_char *ucode = NULL; /* Pointer to microcode */
911 int ucode_size = 0; /* Length of microcode */
912 char *sndfile = NULL; /* Object filename to download */
913 char filename[64]; /* Constructed object filename */
914 char base[64]; /* sba200/sba200e/pca200e basename */
915 int ext = 0; /* 0 == bin 1 == objd */
916 struct stat sbuf; /* Used to find if .bin or .objd */
918 progname = (char *)basename(argv[0]);
919 comm_mode = strcmp ( progname, "fore_comm" ) == 0;
921 while ( ( c = getopt ( argc, argv, "i:d:f:berv" ) ) != -1 )
922 switch ( c ) {
923 case 'b':
924 binary++;
925 break;
926 case 'd':
927 dirname = (char *)strdup ( optarg );
928 break;
929 case 'e':
930 endian++;
931 break;
932 case 'i':
933 dev = (char *)strdup ( optarg );
934 break;
935 case 'f':
936 objfile = (char *)strdup ( optarg );
937 break;
938 case 'v':
939 verbose++;
940 break;
941 case 'r':
942 reset++;
943 break;
944 case '?':
945 printf ( "usage: %s [-v] [-i intf] [-d dirname] [-f objfile]\n", argv[0] );
946 exit ( 2 );
950 * Unbuffer stdout
952 setbuf ( stdout, NULL );
954 if ( ( fd = socket ( AF_ATM, SOCK_DGRAM, 0 ) ) < 0 )
956 perror ( "Cannot create ATM socket" );
957 exit ( 1 );
960 * Over allocate memory for returned data. This allows
961 * space for IOCTL reply info as well as config info.
963 buf_len = 4 * sizeof(struct air_cfg_rsp);
964 if ( ( buf = (caddr_t)malloc(buf_len) ) == NULL )
966 perror ( "Cannot allocate memory for reply" );
967 exit ( 1 );
970 * Fill in request paramaters
972 req.air_opcode = AIOCS_INF_CFG;
973 req.air_buf_addr = buf;
974 req.air_buf_len = buf_len;
977 * Copy interface name into ioctl request
979 strcpy ( req.air_cfg_intf, dev );
982 * Issue ioctl
984 if ( ( ioctl ( fd, AIOCINFO, (caddr_t)&req ) ) ) {
985 perror ( "ioctl (AIOCSINFO)" );
986 exit ( 1 );
989 * Reset buffer pointer
991 req.air_buf_addr = buf;
994 * Close socket
996 close ( fd );
999 * Loop through all attached adapters
1001 for (; (size_t)req.air_buf_len >= sizeof(struct air_cfg_rsp);
1002 buf += sizeof(struct air_cfg_rsp),
1003 req.air_buf_len -= sizeof(struct air_cfg_rsp)) {
1006 * Point to vendor info
1008 air = (struct air_cfg_rsp *)buf;
1010 if (air->acp_vendor == VENDOR_FORE )
1013 * Create /dev name
1015 #ifdef sun
1016 sprintf ( bus_dev, DEV_NAME, air->acp_busslot );
1017 #else
1018 sprintf ( bus_dev, DEV_NAME );
1019 #endif
1022 * Setup signal handlers
1024 signal ( SIGINT, SIG_IGN );
1025 signal ( SIGQUIT, SIG_IGN );
1028 * If comm_mode, setup terminal for single char I/O
1030 if ( comm_mode ) {
1031 tty = open ( _PATH_TTY, O_RDWR );
1032 ioctl ( tty, TCGETA, &sgtty );
1033 sgtty.c_lflag &= ~( ICANON | ECHO );
1034 vmin = sgtty.c_cc[VMIN];
1035 vtime = sgtty.c_cc[VTIME];
1036 sgtty.c_cc[VMIN] = 0;
1037 sgtty.c_cc[VTIME] = 0;
1038 ioctl ( tty, TCSETA, &sgtty );
1042 * Open bus for memory access
1044 if ( ( fd = open ( bus_dev, O_RDWR ) ) < 0 )
1046 perror ( "open bus_dev" );
1047 fprintf(stderr, "%s download failed (%s)\n",
1048 air->acp_intf, bus_dev);
1049 continue;
1053 * Map in the RAM memory to get access to the Uart
1055 #ifdef __FreeBSD__ /*XXX*/
1056 ram = (u_char *) mmap(0, PCA200E_MMAP_SIZE,
1057 #else
1058 ram = (u_char *) mmap(0, air->acp_ramsize,
1059 #endif
1060 PROT_READ | PROT_WRITE, MAP_SHARED | MAP_HASSEMAPHORE,
1061 fd, air->acp_ram);
1062 if (ram == (u_char *)-1) {
1063 perror ( "mmap ram" );
1064 fprintf(stderr, "%s download failed\n",
1065 air->acp_intf);
1066 close(fd);
1067 continue;
1069 Mon = (Mon960 *)(ram + MON960_BASE);
1070 Uart = (Mon960 *)&(Mon->mon_xmitmon);
1073 * Determine endianess
1075 switch ( Mon->mon_bstat ) {
1076 case BOOT_COLDSTART:
1077 case BOOT_MONREADY:
1078 case BOOT_FAILTEST:
1079 case BOOT_RUNNING:
1080 break;
1082 default:
1083 switch (ntohl(Mon->mon_bstat)) {
1084 case BOOT_COLDSTART:
1085 case BOOT_MONREADY:
1086 case BOOT_FAILTEST:
1087 case BOOT_RUNNING:
1088 endian++;
1089 break;
1091 default:
1092 fprintf(stderr, "%s unknown status\n",
1093 air->acp_intf);
1094 close(fd);
1095 continue;
1097 break;
1100 #ifdef __FreeBSD__
1101 if (reset) {
1102 u_int *hcr = (u_int *)(ram + PCA200E_HCR_OFFSET);
1103 PCA200E_HCR_INIT(*hcr, PCA200E_RESET_BD);
1104 delay(10000);
1105 PCA200E_HCR_CLR(*hcr, PCA200E_RESET_BD);
1106 delay(10000);
1108 #endif
1110 if ( comm_mode ) {
1111 static struct timeval timeout = { 0, 0 };
1112 int esc_seen = 0;
1115 * We want to talk with the i960 monitor
1119 * Loop forever accepting characters
1121 for ( ; ; ) {
1122 fd_set fdr;
1123 int ns;
1126 * Check for data from the terminal
1128 FD_ZERO ( &fdr );
1129 FD_SET ( fileno(stdin), &fdr );
1131 if ( ( ns = select ( FD_SETSIZE, &fdr, NULL, NULL,
1132 &timeout ) ) < 0 ) {
1133 perror ( "select" );
1134 finish( -1 );
1137 if ( ns ) {
1138 int c1;
1139 int nr;
1141 nr = read ( fileno(stdin), &c1, 1 );
1142 c1 &= 0xff;
1143 if ( !esc_seen ) {
1144 if ( c1 == 27 )
1145 esc_seen++;
1146 else
1147 xmit_byte ( c1, 0 );
1148 } else {
1149 if ( c1 == 27 )
1150 finish( -1 );
1151 else {
1152 xmit_byte ( 27, 0 );
1153 esc_seen = 0;
1155 xmit_byte ( c1, 0 );
1160 * Check for data from the i960
1162 if ( CP_READ(Uart->mon_xmithost) & UART_VALID ) {
1163 c = getbyte();
1164 putchar ( c );
1166 if ( strcmp ( line, "Mon960" ) == 0 )
1167 autobaud();
1170 } else {
1172 * Make sure the driver is loaded and that the CP
1173 * is ready for commands
1175 if ( CP_READ(Mon->mon_bstat) == BOOT_RUNNING )
1177 fprintf ( stderr,
1178 "%s is up and running - no download allowed.\n",
1179 air->acp_intf );
1180 close(fd);
1181 continue;
1184 if ( CP_READ(Mon->mon_bstat) != BOOT_MONREADY )
1186 fprintf ( stderr,
1187 "%s is not ready for downloading.\n",
1188 air->acp_intf );
1189 close(fd);
1190 continue;
1194 * Indicate who we're downloading
1196 if ( verbose )
1197 printf ( "Downloading code for %s\n",
1198 air->acp_intf );
1201 * Look for the i960 monitor message.
1202 * We should see this after a board reset.
1204 while ( strncmp ( line, "Mon960", 6 ) != 0 &&
1205 strncmp ( line, "=>", 2 ) != 0 )
1206 getline( verbose ); /* Verbose */
1209 * Autobaud fakery
1211 if ( strncmp ( line, "Mon960", 6 ) == 0 ) {
1212 xmit_to_i960 ( "\r\n\r\n\r\n\r\n", 8, 0 );
1213 delay ( 10000 );
1217 * Keep reading until we get a command prompt
1219 while ( strncmp ( line, "=>", 2 ) != 0 )
1220 getline( verbose ); /* Verbose */
1223 * Choose the correct microcode file based on the
1224 * adapter type the card claims to be.
1226 switch ( air->acp_device )
1228 case DEV_FORE_SBA200:
1229 sprintf ( base, "sba200" );
1230 break;
1232 case DEV_FORE_SBA200E:
1233 sprintf ( base, "sba200e" );
1234 break;
1236 case DEV_FORE_PCA200E:
1237 sprintf ( base, "pca200e" );
1238 break;
1240 default:
1241 err = 1;
1242 fprintf(stderr, "Unknown adapter type: %d\n",
1243 air->acp_device );
1246 sndfile = NULL;
1248 if ( objfile == NULL ) {
1249 switch ( air->acp_device ) {
1250 case DEV_FORE_SBA200:
1251 case DEV_FORE_SBA200E:
1252 sprintf ( filename, "%s.bin%d", base,
1253 air->acp_bustype );
1254 if ( stat ( filename, &sbuf ) == -1 ) {
1255 sprintf ( filename, "%s/%s.bin%d",
1256 dirname, base,
1257 air->acp_bustype );
1258 if ( stat ( filename, &sbuf ) == -1 ) {
1259 ext = 1;
1260 sprintf ( filename, "%s.objd%d",
1261 base, air->acp_bustype );
1262 if ( stat(filename, &sbuf) == -1 ) {
1263 sprintf ( filename,
1264 "%s/%s.objd%d", dirname,
1265 base,
1266 air->acp_bustype );
1267 if ( stat ( filename, &sbuf ) != -1 )
1268 sndfile = filename;
1269 } else
1270 sndfile = filename;
1271 } else
1272 sndfile = filename;
1273 } else
1274 sndfile = filename;
1275 break;
1276 case DEV_FORE_PCA200E:
1277 /* Use compiled in microcode */
1278 ucode = pca200e_microcode;
1279 ucode_size = pca200e_microcode_size;
1280 break;
1281 default:
1282 break;
1284 } else
1285 sndfile = objfile;
1287 if ( ext && !binary )
1288 err = xmitfile ( sndfile );
1289 else if (sndfile != NULL)
1290 err = sendbinfile ( sndfile, ram );
1291 else
1292 err = loadmicrocode( ucode, ucode_size, ram );
1294 if ( err ) {
1295 fprintf(stderr, "%s download failed\n",
1296 air->acp_intf);
1297 close(fd);
1298 continue;
1302 * Download completed - wait around a while for
1303 * the driver to initialize the adapter
1305 aap = (Aali *)(ram + CP_READ(Mon->mon_appl));
1306 for (i = 0; i < MAX_CHECK; i++, sleep(1)) {
1307 u_long hb1, hb2, hb3;
1309 hb3 = CP_READ(Mon->mon_bstat);
1310 if (hb3 != BOOT_RUNNING) {
1311 if (verbose)
1312 printf("bstat %lx\n", hb3);
1313 continue;
1316 hb1 = CP_READ(aap->aali_heartbeat);
1317 delay(1);
1318 hb2 = CP_READ(aap->aali_heartbeat);
1319 if (verbose)
1320 printf("hb %lx %lx\n", hb1, hb2);
1321 if (hb1 < hb2)
1322 break;
1326 close ( fd );
1331 * Exit
1333 exit (0);