1 /* This file is part of GDB.
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.
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.
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. */
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. */
21 /******************************************************************************
23 * NINDY INTERFACE ROUTINES
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.
32 **************************************************************************/
34 /* Having these in a separate file from nindy.c is really ugly, and should
35 be merged with nindy.c. */
39 #include <sys/ioctl.h>
40 #include <sys/types.h> /* Needed by file.h on Sys V */
44 #include <fcntl.h> /* Needed on Sys V */
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))
58 extern int quiet
; /* 1 => stifle unnecessary messages */
60 /* tty connected to 960/NINDY board. */
61 extern serial_t nindy_serial
;
65 /****************************
67 * MISCELLANEOUS UTILTIES *
69 ****************************/
72 /******************************************************************************
74 * Convert a hex ascii digit h to a binary integer
75 ******************************************************************************/
81 if (h
>= '0' && h
<= '9'){
83 } else if (h
>= 'a' && h
<= 'f'){
92 /******************************************************************************
94 * Convert a string of ASCII hex digits to a string of binary bytes.
95 ******************************************************************************/
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 */
103 *binp
++ = (fromhex(*hexp
) << 4) | fromhex(*(hexp
+1));
109 /******************************************************************************
111 * Convert a string of binary bytes to a string of ASCII hex digits
112 ******************************************************************************/
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 */
119 static char tohex
[] = "0123456789abcdef";
122 *hexp
++ = tohex
[ (*binp
>> 4) & 0xf ];
123 *hexp
++ = tohex
[ *binp
& 0xf ];
128 /******************************************************************************
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.
134 ******************************************************************************/
142 static short test
= 0x1234;
144 if (*((char *) &test
) == 0x12) {
146 * Big-endian host, swap the bytes.
149 for ( i
= 0; i
< sizeof(n
); i
++ ){
159 /******************************************************************************
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
164 ******************************************************************************/
166 say( fmt
, arg1
, arg2
)
171 printf( fmt
, arg1
, arg2
);
176 /*****************************
178 * LOW-LEVEL COMMUNICATION *
180 *****************************/
182 /* Read a single character from the remote end. */
187 /* FIXME: Do we really want to be reading without a timeout? */
188 return SERIAL_READCHAR (nindy_serial
, -1);
191 /******************************************************************************
193 * Read a packet from a remote NINDY, with error checking, and return
194 * it in the indicated buffer.
195 ******************************************************************************/
200 unsigned char recv
; /* Checksum received */
201 unsigned char csum
; /* Checksum calculated */
202 char *bp
; /* Poointer into the buffer */
208 /* FIXME: check for error from readchar (). */
209 while ( (c
= readchar()) != '#' ){
215 /* FIXME: check for error from readchar (). */
216 recv
= fromhex(readchar()) << 4;
217 recv
|= fromhex(readchar());
223 "Bad checksum (recv=0x%02x; calc=0x%02x); retrying\r\n",
225 SERIAL_WRITE (nindy_serial
, "-", 1);
228 SERIAL_WRITE (nindy_serial
, "+", 1);
232 /******************************************************************************
234 * Checksum and send a gdb command to a remote NINDY, and wait for
235 * positive acknowledgement.
237 ******************************************************************************/
240 char *cmd
; /* Command to be sent, without lead ^P (\020)
241 * or trailing checksum
244 char ack
; /* Response received from NINDY */
250 for ( s
='\020', p
=cmd
; *p
; p
++ ){
253 sprintf( checksum
, "#%02x", s
& 0xff );
255 /* Send checksummed message over and over until we get a positive ack
260 SERIAL_WRITE ( nindy_serial
, "\020", 1 );
261 SERIAL_WRITE( nindy_serial
, cmd
, strlen(cmd
) );
262 SERIAL_WRITE( nindy_serial
, checksum
, strlen(checksum
) );
264 /* FIXME: do we really want to be reading without timeout? */
265 ack
= SERIAL_READCHAR (nindy_serial
, -1);
268 fprintf (stderr
, "error reading from serial port\n");
271 fprintf( stderr
, "Remote NAK, resending\r\n" );
273 } else if ( ack
!= '+' ){
274 fprintf( stderr
, "Bad ACK, ignored: <%c>\r\n", ack
);
277 } while ( ack
!= '+' );
282 /******************************************************************************
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.
288 ******************************************************************************/
290 send( buf
, ack_required
)
291 char *buf
; /* Message to be sent to NINDY; replaced by
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
301 static char *errmsg
[] = {
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 */
313 # define NUMERRS ( sizeof(errmsg) / sizeof(errmsg[0]) )
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";
322 if ( buf
[0] != 'X' ){
324 fprintf( stderr
, err0
, buf
);
328 } else if ( strcmp(buf
,"X00") ){
329 sscanf( &buf
[1], "%x", &errnum
);
330 if ( errnum
> NUMERRS
){
331 fprintf( stderr
, err1
, buf
);
333 fprintf( stderr
, err2
, buf
, errmsg
[errnum
] );
339 /**********************************
341 * NINDY INTERFACE ROUTINES *
343 * ninConnect *MUST* be the first *
344 * one of these routines called. *
345 **********************************/
347 /******************************************************************************
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 */
360 sprintf( buf
, "b%c", data
? '1' : '0' );
362 sprintf( buf
, "b%c%x", data
? '1' : '0', addr
);
364 return send( buf
, 0 );
368 /******************************************************************************
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 */
379 sprintf( buf
, "B%c%x", data
? '1' : '0', addr
);
380 return send( buf
, 0 );
383 /******************************************************************************
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 ******************************************************************************/
393 /******************************************************************************
395 * Ask NINDY to start or continue execution of an application program
396 * in it's memory at the current ip.
397 ******************************************************************************/
399 int step_flag
; /* 1 => run in single-step mode */
401 putpkt( step_flag
? "s" : "c" );
405 /******************************************************************************
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 */
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];
419 int cnt
; /* Number of bytes in next transfer */
421 for ( ; len
> 0; len
-= OLD_NINDY_MEMBYTES
){
422 cnt
= len
> OLD_NINDY_MEMBYTES
? OLD_NINDY_MEMBYTES
: len
;
424 sprintf( buf
, "m%x,%x", ninaddr
, cnt
);
426 hexbin( cnt
, buf
, hostaddr
);
434 /******************************************************************************
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 */
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 */
447 for ( ; len
> 0; len
-= OLD_NINDY_MEMBYTES
){
448 cnt
= len
> OLD_NINDY_MEMBYTES
? OLD_NINDY_MEMBYTES
: len
;
450 sprintf( buf
, "M%x,", destaddr
);
451 p
= buf
+ strlen(buf
);
452 binhex( cnt
, srcaddr
, p
);
461 /******************************************************************************
463 * Retrieve the contents of a 960 register, and return them as a long
464 * in host byte order.
466 * THIS ROUTINE CAN ONLY BE USED TO READ THE LOCAL, GLOBAL, AND
467 * ip/ac/pc/tc REGISTERS.
469 ******************************************************************************/
471 OninRegGet( regname
)
472 char *regname
; /* Register name recognized by NINDY, subject to the
479 sprintf( buf
, "u%s", regname
);
481 hexbin( 4, buf
, (char *)&val
);
482 return byte_order(val
);
485 /******************************************************************************
487 * Set the contents of a 960 register.
489 * THIS ROUTINE CAN ONLY BE USED TO SET THE LOCAL, GLOBAL, AND
490 * ip/ac/pc/tc REGISTERS.
492 ******************************************************************************/
493 OninRegPut( regname
, val
)
494 char *regname
; /* Register name recognized by NINDY, subject to the
497 long val
; /* New contents of register, in host byte-order */
501 sprintf( buf
, "U%s,%08x", regname
, byte_order(val
) );
505 /******************************************************************************
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:
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
516 * Each individual register comprises exactly 4 bytes, except for
517 * fp0-fp3, which are 8 bytes.
520 * Each register value is in 960 (little-endian) byte order.
522 ******************************************************************************/
524 char *regp
; /* Where to place the register dump */
526 char buf
[(2*OLD_NINDY_REGISTER_BYTES
)+10]; /* Registers in ASCII hex */
530 hexbin( OLD_NINDY_REGISTER_BYTES
, buf
, regp
);
533 /******************************************************************************
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.
540 * Each register value should be in 960 (little-endian) byte order.
542 ******************************************************************************/
544 char *regp
; /* Pointer to desired values of registers */
546 char buf
[(2*OLD_NINDY_REGISTER_BYTES
)+10]; /* Registers in ASCII hex */
549 binhex( OLD_NINDY_REGISTER_BYTES
, regp
, buf
+1 );
550 buf
[ (2*OLD_NINDY_REGISTER_BYTES
)+1 ] = '\0';
556 /******************************************************************************
558 * Ask NINDY to perform a soft reset; wait for the reset to complete.
559 ******************************************************************************/
564 /* FIXME: check for error from readchar (). */
565 while ( readchar() != '+' ){
571 /******************************************************************************
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.
578 ******************************************************************************/
581 /* FIXME: Imposes arbitrary limits on lengths of pathnames and such. */
584 unsigned char srqnum
;
588 int arg
[MAX_SRQ_ARGS
];
591 /* Get srq number and arguments
595 hexbin( 1, buf
, (char *)&srqnum
);
597 /* Set up array of pointers the each of the individual
598 * comma-separated args
603 while ( *p
!= ',' && *p
!= '\0' ){
606 sscanf( argp
, "%x", &arg
[nargs
++] );
607 if ( *p
== '\0' || nargs
== MAX_SRQ_ARGS
){
617 /* args: file descriptor */
619 retcode
= close( arg
[0] );
625 /* args: filename, mode */
626 OninStrGet( arg
[0], buf
);
627 retcode
= creat(buf
,arg
[1]);
630 /* args: filename, flags, mode */
631 OninStrGet( arg
[0], buf
);
632 retcode
= open(buf
,arg
[1],arg
[2]);
635 /* args: file descriptor, buffer, count */
636 retcode
= read(arg
[0],buf
,arg
[2]);
638 OninMemPut( arg
[1], buf
, retcode
);
642 /* args: file descriptor, offset, whence */
643 retcode
= lseek(arg
[0],arg
[1],arg
[2]);
646 /* args: file descriptor, buffer, count */
647 OninMemGet( arg
[1], buf
, arg
[2] );
648 retcode
= write(arg
[0],buf
,arg
[2]);
655 /* Tell NINDY to continue
657 sprintf( buf
, "e%x", retcode
);
662 /******************************************************************************
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.
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 ******************************************************************************/
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 */
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
);
696 /******************************************************************************
698 * Read a '\0'-terminated string of data out of the 960 memory space.
700 ******************************************************************************/
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
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. */
712 sprintf( buf
, "\"%x", ninaddr
);
714 numchars
= strlen(buf
)/2;
715 hexbin( numchars
, buf
, hostaddr
);
716 hostaddr
[numchars
] = '\0';
722 /******************************************************************************
724 * Ask NINDY for version information about itself.
725 * The information is sent as an ascii string in the form "x.xx,<arch>",
727 * x.xx is the version number
728 * <arch> is the processor architecture: "KA", "KB", "MC", "CA" *
730 ******************************************************************************/
733 char *p
; /* Where to place version string */
735 /* FIXME: this is an arbitrary limit on the length of version string. */
741 return strlen( buf
);
This page took 0.047371 seconds and 4 git commands to generate.