]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/nindy-share/Onindy.c
Initial creation of sourceware repository
[thirdparty/binutils-gdb.git] / gdb / nindy-share / Onindy.c
1 /* This file is part of GDB.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
16
17 /* This started out life as code shared between the nindy monitor and
18 GDB. For various reasons, this is no longer true. Eventually, it
19 probably should be merged into remote-nindy.c. */
20
21 /******************************************************************************
22 *
23 * NINDY INTERFACE ROUTINES
24 *
25 * This version of the NINDY interface routines supports NINDY versions
26 * 2.13 and older. The older versions used a hex communication protocol,
27 * instead of the (faster) current binary protocol. These routines have
28 * been renamed by prepending the letter 'O' to their names, to avoid
29 * conflict with the current version. The old versions are kept only for
30 * backward compatibility, and well disappear in a future release.
31 *
32 **************************************************************************/
33
34 /* Having these in a separate file from nindy.c is really ugly, and should
35 be merged with nindy.c. */
36
37 #include <stdio.h>
38 #if 0
39 #include <sys/ioctl.h>
40 #include <sys/types.h> /* Needed by file.h on Sys V */
41 #include <sys/file.h>
42 #include <signal.h>
43 #include <sys/stat.h>
44 #include <fcntl.h> /* Needed on Sys V */
45 #include "ttycntl.h"
46 #endif
47 #include "defs.h"
48 #include "serial.h"
49
50 #include "block_io.h"
51 #include "wait.h"
52 #include "env.h"
53
54 /* Number of bytes that we send to nindy. I believe this is defined by
55 the protocol (it does not agree with REGISTER_BYTES). */
56 #define OLD_NINDY_REGISTER_BYTES ((36*4) + (4*8))
57
58 extern int quiet; /* 1 => stifle unnecessary messages */
59
60 /* tty connected to 960/NINDY board. */
61 extern serial_t nindy_serial;
62
63 static OninStrGet();
64 \f
65 /****************************
66 * *
67 * MISCELLANEOUS UTILTIES *
68 * *
69 ****************************/
70
71
72 /******************************************************************************
73 * fromhex:
74 * Convert a hex ascii digit h to a binary integer
75 ******************************************************************************/
76 static
77 int
78 fromhex( h )
79 int h;
80 {
81 if (h >= '0' && h <= '9'){
82 h -= '0';
83 } else if (h >= 'a' && h <= 'f'){
84 h -= 'a' - 10;
85 } else {
86 h = 0;
87 }
88 return (h & 0xff);
89 }
90
91
92 /******************************************************************************
93 * hexbin:
94 * Convert a string of ASCII hex digits to a string of binary bytes.
95 ******************************************************************************/
96 static
97 hexbin( n, hexp, binp )
98 int n; /* Number of bytes to convert (twice this many digits)*/
99 char *hexp; /* Get hex from here */
100 char *binp; /* Put binary here */
101 {
102 while ( n-- ){
103 *binp++ = (fromhex(*hexp) << 4) | fromhex(*(hexp+1));
104 hexp += 2;
105 }
106 }
107
108
109 /******************************************************************************
110 * binhex:
111 * Convert a string of binary bytes to a string of ASCII hex digits
112 ******************************************************************************/
113 static
114 binhex( n, binp, hexp )
115 int n; /* Number of bytes to convert */
116 char *binp; /* Get binary from here */
117 char *hexp; /* Place hex here */
118 {
119 static char tohex[] = "0123456789abcdef";
120
121 while ( n-- ){
122 *hexp++ = tohex[ (*binp >> 4) & 0xf ];
123 *hexp++ = tohex[ *binp & 0xf ];
124 binp++;
125 }
126 }
127
128 /******************************************************************************
129 * byte_order:
130 * If the host byte order is different from 960 byte order (i.e., the
131 * host is big-endian), reverse the bytes in the passed value; otherwise,
132 * return the passed value unchanged.
133 *
134 ******************************************************************************/
135 static
136 long
137 byte_order( n )
138 long n;
139 {
140 long rev;
141 int i;
142 static short test = 0x1234;
143
144 if (*((char *) &test) == 0x12) {
145 /*
146 * Big-endian host, swap the bytes.
147 */
148 rev = 0;
149 for ( i = 0; i < sizeof(n); i++ ){
150 rev <<= 8;
151 rev |= n & 0xff;
152 n >>= 8;
153 }
154 n = rev;
155 }
156 return n;
157 }
158
159 /******************************************************************************
160 * say:
161 * This is a printf that takes at most two arguments (in addition to the
162 * format string) and that outputs nothing if verbose output has been
163 * suppressed.
164 ******************************************************************************/
165 static
166 say( fmt, arg1, arg2 )
167 char *fmt;
168 int arg1, arg2;
169 {
170 if ( !quiet ){
171 printf( fmt, arg1, arg2 );
172 fflush( stdout );
173 }
174 }
175 \f
176 /*****************************
177 * *
178 * LOW-LEVEL COMMUNICATION *
179 * *
180 *****************************/
181
182 /* Read a single character from the remote end. */
183
184 static int
185 readchar()
186 {
187 /* FIXME: Do we really want to be reading without a timeout? */
188 return SERIAL_READCHAR (nindy_serial, -1);
189 }
190
191 /******************************************************************************
192 * getpkt:
193 * Read a packet from a remote NINDY, with error checking, and return
194 * it in the indicated buffer.
195 ******************************************************************************/
196 static
197 getpkt (buf)
198 char *buf;
199 {
200 unsigned char recv; /* Checksum received */
201 unsigned char csum; /* Checksum calculated */
202 char *bp; /* Poointer into the buffer */
203 int c;
204
205 while (1){
206 csum = 0;
207 bp = buf;
208 /* FIXME: check for error from readchar (). */
209 while ( (c = readchar()) != '#' ){
210 *bp++ = c;
211 csum += c;
212 }
213 *bp = 0;
214
215 /* FIXME: check for error from readchar (). */
216 recv = fromhex(readchar()) << 4;
217 recv |= fromhex(readchar());
218 if ( csum == recv ){
219 break;
220 }
221
222 fprintf(stderr,
223 "Bad checksum (recv=0x%02x; calc=0x%02x); retrying\r\n",
224 recv, csum );
225 SERIAL_WRITE (nindy_serial, "-", 1);
226 }
227
228 SERIAL_WRITE (nindy_serial, "+", 1);
229 }
230
231
232 /******************************************************************************
233 * putpkt:
234 * Checksum and send a gdb command to a remote NINDY, and wait for
235 * positive acknowledgement.
236 *
237 ******************************************************************************/
238 static
239 putpkt( cmd )
240 char *cmd; /* Command to be sent, without lead ^P (\020)
241 * or trailing checksum
242 */
243 {
244 char ack; /* Response received from NINDY */
245 char checksum[4];
246 char *p;
247 unsigned int s;
248 char resend;
249
250 for ( s='\020', p=cmd; *p; p++ ){
251 s += *p;
252 }
253 sprintf( checksum, "#%02x", s & 0xff );
254
255 /* Send checksummed message over and over until we get a positive ack
256 */
257 resend = 1;
258 do {
259 if ( resend ) {
260 SERIAL_WRITE ( nindy_serial, "\020", 1 );
261 SERIAL_WRITE( nindy_serial, cmd, strlen(cmd) );
262 SERIAL_WRITE( nindy_serial, checksum, strlen(checksum) );
263 }
264 /* FIXME: do we really want to be reading without timeout? */
265 ack = SERIAL_READCHAR (nindy_serial, -1);
266 if (ack < 0)
267 {
268 fprintf (stderr, "error reading from serial port\n");
269 }
270 if ( ack == '-' ){
271 fprintf( stderr, "Remote NAK, resending\r\n" );
272 resend = 1;
273 } else if ( ack != '+' ){
274 fprintf( stderr, "Bad ACK, ignored: <%c>\r\n", ack );
275 resend = 0;
276 }
277 } while ( ack != '+' );
278 }
279
280
281
282 /******************************************************************************
283 * send:
284 * Send a message to a remote NINDY and return the reply in the same
285 * buffer (clobbers the input message). Check for error responses
286 * as indicated by the second argument.
287 *
288 ******************************************************************************/
289 static
290 send( buf, ack_required )
291 char *buf; /* Message to be sent to NINDY; replaced by
292 * NINDY's response.
293 */
294 int ack_required; /* 1 means NINDY's response MUST be either "X00" (no
295 * error) or an error code "Xnn".
296 * 0 means the it's OK as long as it doesn't
297 * begin with "Xnn".
298 */
299 {
300 int errnum;
301 static char *errmsg[] = {
302 "", /* X00 */
303 "Buffer overflow", /* X01 */
304 "Unknown command", /* X02 */
305 "Wrong amount of data to load register(s)", /* X03 */
306 "Missing command argument(s)", /* X04 */
307 "Odd number of digits sent to load memory", /* X05 */
308 "Unknown register name", /* X06 */
309 "No such memory segment", /* X07 */
310 "No breakpoint available", /* X08 */
311 "Can't set requested baud rate", /* X09 */
312 };
313 # define NUMERRS ( sizeof(errmsg) / sizeof(errmsg[0]) )
314
315 static char err0[] = "NINDY failed to acknowledge command: <%s>\r\n";
316 static char err1[] = "Unknown error response from NINDY: <%s>\r\n";
317 static char err2[] = "Error response %s from NINDY: %s\r\n";
318
319 putpkt (buf);
320 getpkt (buf);
321
322 if ( buf[0] != 'X' ){
323 if ( ack_required ){
324 fprintf( stderr, err0, buf );
325 abort();
326 }
327
328 } else if ( strcmp(buf,"X00") ){
329 sscanf( &buf[1], "%x", &errnum );
330 if ( errnum > NUMERRS ){
331 fprintf( stderr, err1, buf );
332 } else{
333 fprintf( stderr, err2, buf, errmsg[errnum] );
334 }
335 abort();
336 }
337 }
338 \f
339 /**********************************
340 * *
341 * NINDY INTERFACE ROUTINES *
342 * *
343 * ninConnect *MUST* be the first *
344 * one of these routines called. *
345 **********************************/
346
347 /******************************************************************************
348 * ninBptDel:
349 * Ask NINDY to delete the specified type of *hardware* breakpoint at
350 * the specified address. If the 'addr' is -1, all breakpoints of
351 * the specified type are deleted.
352 ******************************************************************************/
353 OninBptDel( addr, data )
354 long addr; /* Address in 960 memory */
355 int data; /* '1' => data bkpt, '0' => instruction breakpoint */
356 {
357 char buf[100];
358
359 if ( addr == -1 ){
360 sprintf( buf, "b%c", data ? '1' : '0' );
361 } else {
362 sprintf( buf, "b%c%x", data ? '1' : '0', addr );
363 }
364 return send( buf, 0 );
365 }
366
367
368 /******************************************************************************
369 * ninBptSet:
370 * Ask NINDY to set the specified type of *hardware* breakpoint at
371 * the specified address.
372 ******************************************************************************/
373 OninBptSet( addr, data )
374 long addr; /* Address in 960 memory */
375 int data; /* '1' => data bkpt, '0' => instruction breakpoint */
376 {
377 char buf[100];
378
379 sprintf( buf, "B%c%x", data ? '1' : '0', addr );
380 return send( buf, 0 );
381 }
382
383 /******************************************************************************
384 * ninGdbExit:
385 * Ask NINDY to leave GDB mode and print a NINDY prompt.
386 * Since it'll no longer be in GDB mode, don't wait for a response.
387 ******************************************************************************/
388 OninGdbExit()
389 {
390 putpkt( "E" );
391 }
392
393 /******************************************************************************
394 * ninGo:
395 * Ask NINDY to start or continue execution of an application program
396 * in it's memory at the current ip.
397 ******************************************************************************/
398 OninGo( step_flag )
399 int step_flag; /* 1 => run in single-step mode */
400 {
401 putpkt( step_flag ? "s" : "c" );
402 }
403
404
405 /******************************************************************************
406 * ninMemGet:
407 * Read a string of bytes from NINDY's address space (960 memory).
408 ******************************************************************************/
409 OninMemGet(ninaddr, hostaddr, len)
410 long ninaddr; /* Source address, in the 960 memory space */
411 char *hostaddr; /* Destination address, in our memory space */
412 int len; /* Number of bytes to read */
413 {
414 /* How much do we send at a time? */
415 #define OLD_NINDY_MEMBYTES 1024
416 /* Buffer: hex in, binary out */
417 char buf[2*OLD_NINDY_MEMBYTES+20];
418
419 int cnt; /* Number of bytes in next transfer */
420
421 for ( ; len > 0; len -= OLD_NINDY_MEMBYTES ){
422 cnt = len > OLD_NINDY_MEMBYTES ? OLD_NINDY_MEMBYTES : len;
423
424 sprintf( buf, "m%x,%x", ninaddr, cnt );
425 send( buf, 0 );
426 hexbin( cnt, buf, hostaddr );
427
428 ninaddr += cnt;
429 hostaddr += cnt;
430 }
431 }
432
433
434 /******************************************************************************
435 * ninMemPut:
436 * Write a string of bytes into NINDY's address space (960 memory).
437 ******************************************************************************/
438 OninMemPut( destaddr, srcaddr, len )
439 long destaddr; /* Destination address, in NINDY memory space */
440 char *srcaddr; /* Source address, in our memory space */
441 int len; /* Number of bytes to write */
442 {
443 char buf[2*OLD_NINDY_MEMBYTES+20]; /* Buffer: binary in, hex out */
444 char *p; /* Pointer into buffer */
445 int cnt; /* Number of bytes in next transfer */
446
447 for ( ; len > 0; len -= OLD_NINDY_MEMBYTES ){
448 cnt = len > OLD_NINDY_MEMBYTES ? OLD_NINDY_MEMBYTES : len;
449
450 sprintf( buf, "M%x,", destaddr );
451 p = buf + strlen(buf);
452 binhex( cnt, srcaddr, p );
453 *(p+(2*cnt)) = '\0';
454 send( buf, 1 );
455
456 srcaddr += cnt;
457 destaddr += cnt;
458 }
459 }
460
461 /******************************************************************************
462 * ninRegGet:
463 * Retrieve the contents of a 960 register, and return them as a long
464 * in host byte order.
465 *
466 * THIS ROUTINE CAN ONLY BE USED TO READ THE LOCAL, GLOBAL, AND
467 * ip/ac/pc/tc REGISTERS.
468 *
469 ******************************************************************************/
470 long
471 OninRegGet( regname )
472 char *regname; /* Register name recognized by NINDY, subject to the
473 * above limitations.
474 */
475 {
476 char buf[200];
477 long val;
478
479 sprintf( buf, "u%s", regname );
480 send( buf, 0 );
481 hexbin( 4, buf, (char *)&val );
482 return byte_order(val);
483 }
484
485 /******************************************************************************
486 * ninRegPut:
487 * Set the contents of a 960 register.
488 *
489 * THIS ROUTINE CAN ONLY BE USED TO SET THE LOCAL, GLOBAL, AND
490 * ip/ac/pc/tc REGISTERS.
491 *
492 ******************************************************************************/
493 OninRegPut( regname, val )
494 char *regname; /* Register name recognized by NINDY, subject to the
495 * above limitations.
496 */
497 long val; /* New contents of register, in host byte-order */
498 {
499 char buf[200];
500
501 sprintf( buf, "U%s,%08x", regname, byte_order(val) );
502 send( buf, 1 );
503 }
504
505 /******************************************************************************
506 * ninRegsGet:
507 * Get a dump of the contents of the entire 960 register set. The
508 * individual registers appear in the dump in the following order:
509 *
510 * pfp sp rip r3 r4 r5 r6 r7
511 * r8 r9 r10 r11 r12 r13 r14 r15
512 * g0 g1 g2 g3 g4 g5 g6 g7
513 * g8 g9 g10 g11 g12 g13 g14 fp
514 * pc ac ip tc fp0 fp1 fp2 fp3
515 *
516 * Each individual register comprises exactly 4 bytes, except for
517 * fp0-fp3, which are 8 bytes.
518 *
519 * WARNING:
520 * Each register value is in 960 (little-endian) byte order.
521 *
522 ******************************************************************************/
523 OninRegsGet( regp )
524 char *regp; /* Where to place the register dump */
525 {
526 char buf[(2*OLD_NINDY_REGISTER_BYTES)+10]; /* Registers in ASCII hex */
527
528 strcpy( buf, "r" );
529 send( buf, 0 );
530 hexbin( OLD_NINDY_REGISTER_BYTES, buf, regp );
531 }
532
533 /******************************************************************************
534 * ninRegsPut:
535 * Initialize the entire 960 register set to a specified set of values.
536 * The format of the register value data should be the same as that
537 * returned by ninRegsGet.
538 *
539 * WARNING:
540 * Each register value should be in 960 (little-endian) byte order.
541 *
542 ******************************************************************************/
543 OninRegsPut( regp )
544 char *regp; /* Pointer to desired values of registers */
545 {
546 char buf[(2*OLD_NINDY_REGISTER_BYTES)+10]; /* Registers in ASCII hex */
547
548 buf[0] = 'R';
549 binhex( OLD_NINDY_REGISTER_BYTES, regp, buf+1 );
550 buf[ (2*OLD_NINDY_REGISTER_BYTES)+1 ] = '\0';
551
552 send( buf, 1 );
553 }
554
555
556 /******************************************************************************
557 * ninReset:
558 * Ask NINDY to perform a soft reset; wait for the reset to complete.
559 ******************************************************************************/
560 OninReset()
561 {
562
563 putpkt( "X" );
564 /* FIXME: check for error from readchar (). */
565 while ( readchar() != '+' ){
566 ;
567 }
568 }
569
570
571 /******************************************************************************
572 * ninSrq:
573 * Assume NINDY has stopped execution of the 960 application program in
574 * order to process a host service request (srq). Ask NINDY for the
575 * srq arguments, perform the requested service, and send an "srq
576 * complete" message so NINDY will return control to the application.
577 *
578 ******************************************************************************/
579 OninSrq()
580 {
581 /* FIXME: Imposes arbitrary limits on lengths of pathnames and such. */
582 char buf[BUFSIZE];
583 int retcode;
584 unsigned char srqnum;
585 char *p;
586 char *argp;
587 int nargs;
588 int arg[MAX_SRQ_ARGS];
589
590
591 /* Get srq number and arguments
592 */
593 strcpy( buf, "!" );
594 send( buf, 0 );
595 hexbin( 1, buf, (char *)&srqnum );
596
597 /* Set up array of pointers the each of the individual
598 * comma-separated args
599 */
600 nargs=0;
601 argp = p = buf+2;
602 while ( 1 ){
603 while ( *p != ',' && *p != '\0' ){
604 p++;
605 }
606 sscanf( argp, "%x", &arg[nargs++] );
607 if ( *p == '\0' || nargs == MAX_SRQ_ARGS ){
608 break;
609 }
610 argp = ++p;
611 }
612
613 /* Process Srq
614 */
615 switch( srqnum ){
616 case BS_CLOSE:
617 /* args: file descriptor */
618 if ( arg[0] > 2 ){
619 retcode = close( arg[0] );
620 } else {
621 retcode = 0;
622 }
623 break;
624 case BS_CREAT:
625 /* args: filename, mode */
626 OninStrGet( arg[0], buf );
627 retcode = creat(buf,arg[1]);
628 break;
629 case BS_OPEN:
630 /* args: filename, flags, mode */
631 OninStrGet( arg[0], buf );
632 retcode = open(buf,arg[1],arg[2]);
633 break;
634 case BS_READ:
635 /* args: file descriptor, buffer, count */
636 retcode = read(arg[0],buf,arg[2]);
637 if ( retcode > 0 ){
638 OninMemPut( arg[1], buf, retcode );
639 }
640 break;
641 case BS_SEEK:
642 /* args: file descriptor, offset, whence */
643 retcode = lseek(arg[0],arg[1],arg[2]);
644 break;
645 case BS_WRITE:
646 /* args: file descriptor, buffer, count */
647 OninMemGet( arg[1], buf, arg[2] );
648 retcode = write(arg[0],buf,arg[2]);
649 break;
650 default:
651 retcode = -1;
652 break;
653 }
654
655 /* Tell NINDY to continue
656 */
657 sprintf( buf, "e%x", retcode );
658 send( buf, 1 );
659 }
660
661
662 /******************************************************************************
663 * ninStopWhy:
664 * Assume the application program has stopped (i.e., a DLE was received
665 * from NINDY). Ask NINDY for status information describing the
666 * reason for the halt.
667 *
668 * Returns a non-zero value if the user program has exited, 0 otherwise.
669 * Also returns the following information, through passed pointers:
670 * - why: an exit code if program the exited; otherwise the reason
671 * why the program halted (see stop.h for values).
672 * - contents of register ip (little-endian byte order)
673 * - contents of register sp (little-endian byte order)
674 * - contents of register fp (little-endian byte order)
675 ******************************************************************************/
676 char
677 OninStopWhy( whyp, ipp, fpp, spp )
678 char *whyp; /* Return the 'why' code through this pointer */
679 char *ipp; /* Return contents of register ip through this pointer */
680 char *fpp; /* Return contents of register fp through this pointer */
681 char *spp; /* Return contents of register sp through this pointer */
682 {
683 char buf[30];
684 char stop_exit;
685
686 strcpy( buf, "?" );
687 send( buf, 0 );
688 hexbin( 1, buf, &stop_exit );
689 hexbin( 1, buf+2, whyp );
690 hexbin( 4, buf+4, ipp );
691 hexbin( 4, buf+12, fpp );
692 hexbin( 4, buf+20, spp );
693 return stop_exit;
694 }
695
696 /******************************************************************************
697 * ninStrGet:
698 * Read a '\0'-terminated string of data out of the 960 memory space.
699 *
700 ******************************************************************************/
701 static
702 OninStrGet( ninaddr, hostaddr )
703 unsigned long ninaddr; /* Address of string in NINDY memory space */
704 char *hostaddr; /* Address of the buffer to which string should
705 * be copied.
706 */
707 {
708 /* FIXME: seems to be an arbitrary limit on the length of the string. */
709 char buf[BUFSIZE]; /* String as 2 ASCII hex digits per byte */
710 int numchars; /* Length of string in bytes. */
711
712 sprintf( buf, "\"%x", ninaddr );
713 send( buf, 0 );
714 numchars = strlen(buf)/2;
715 hexbin( numchars, buf, hostaddr );
716 hostaddr[numchars] = '\0';
717 }
718
719 #if 0
720 /* never used. */
721
722 /******************************************************************************
723 * ninVersion:
724 * Ask NINDY for version information about itself.
725 * The information is sent as an ascii string in the form "x.xx,<arch>",
726 * where,
727 * x.xx is the version number
728 * <arch> is the processor architecture: "KA", "KB", "MC", "CA" *
729 *
730 ******************************************************************************/
731 int
732 OninVersion( p )
733 char *p; /* Where to place version string */
734 {
735 /* FIXME: this is an arbitrary limit on the length of version string. */
736 char buf[BUFSIZE];
737
738 strcpy( buf, "v" );
739 send( buf, 0 );
740 strcpy( p, buf );
741 return strlen( buf );
742 }
743 #endif