ce2c4a0d7f5a32589339f12c977ddf212b9bded5
[external/binutils.git] / sim / cris / rvdummy.c
1 /* Test-driver for the remote-virtual-component simulator framework
2    for GDB, the GNU Debugger.
3
4    Copyright 2006, 2007 Free Software Foundation, Inc.
5
6    This file is part of GDB.
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 59 Temple Place - Suite 330,
21    Boston, MA 02111-1307, USA.  */
22
23 /* Avoid any problems whatsoever building this program if we're not
24    also building hardware support.  */
25
26 #if !WITH_HW
27 int
28 main (int argc, char *argv[])
29 {
30   return 2;
31 }
32 #else
33
34 #ifdef HAVE_CONFIG_H
35 #include "cconfig.h"
36 #include "tconfig.h"
37 #endif
38
39 #include "getopt.h"
40 #include "libiberty.h"
41
42 #define _GNU_SOURCE
43 #include <stdio.h>
44
45 #ifdef HAVE_UNISTD_H
46 #include <unistd.h>
47 #endif
48 #ifdef HAVE_STDLIB_H
49 #include <stdlib.h>
50 #endif
51 #ifdef HAVE_STRING_H
52 #include <string.h>
53 #endif
54
55 #ifdef HAVE_SYS_TYPES_H
56 #include <sys/types.h>
57 #endif
58
59 #ifdef HAVE_SYS_TIME_H
60 #include <sys/time.h>
61 #endif
62
63 #ifdef HAVE_SYS_SELECT_H
64 #include <sys/select.h>
65 #endif
66
67 #ifdef HAVE_ERRNO_H
68 #include <errno.h>
69 #endif
70
71 /* Not guarded in dv-sockser.c, so why here.  */
72 #include <netinet/in.h>
73 #include <arpa/inet.h>
74 #include <netdb.h>
75 #include <sys/socket.h>
76
77 enum rv_command {
78   RV_READ_CMD = 0,
79   RV_WRITE_CMD = 1,
80   RV_IRQ_CMD = 2,
81   RV_MEM_RD_CMD = 3,
82   RV_MEM_WR_CMD = 4,
83   RV_MBOX_HANDLE_CMD = 5,
84   RV_MBOX_PUT_CMD = 6,
85   RV_WATCHDOG_CMD = 7
86 };
87
88 enum opts { OPT_PORT = 1, OPT_TIMEOUT, OPT_VERBOSE };
89
90 struct option longopts[] =
91   {
92     {"port", required_argument, NULL, OPT_PORT},
93     {"timeout", required_argument, NULL, OPT_TIMEOUT},
94     {"verbose", no_argument, NULL, OPT_VERBOSE},
95     {NULL, 0, NULL, 0}
96   };
97
98 int port = 10000;
99 time_t timeout = 30000;
100 char *progname = "(unknown)";
101 int verbose = 0;
102
103 /* Required forward-declarations.  */
104 static void handle_input_file (int, char *);
105
106 /* Set up a "server" listening to the port in PORT for a raw TCP
107    connection.  Return a file descriptor for the connection or -1 on
108    error.  */
109
110 int setupsocket (void)
111 {
112   int s;
113   socklen_t len;
114   int reuse = 1;
115   struct sockaddr_in sa_in;
116   struct sockaddr_in from;
117
118   len = sizeof (from);
119   memset (&from, 0, len);
120   memset (&sa_in, 0, sizeof (sa_in));
121
122   s = socket (AF_INET, SOCK_STREAM, 0);
123   if (s < 0)
124     return -1;
125
126   if (setsockopt (s, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof reuse) != 0)
127     return -1;
128
129   sa_in.sin_port = htons (port);
130   sa_in.sin_family = AF_INET;
131
132   if (bind (s, (struct sockaddr *) & sa_in, sizeof sa_in) < 0)
133     return -1;
134
135   if (listen (s, 1) < 0)
136     return -1;
137
138   return accept (s, (struct sockaddr *) &from, &len);
139 }
140
141 /* Basic host-to-little-endian 32-bit value.  Could use the BFD
142    machinery, but let's avoid it for this only dependency.  */
143
144 static void
145 h2le32 (unsigned char *dest, unsigned int val)
146 {
147   dest[0] = val & 255;
148   dest[1] = (val >> 8) & 255;
149   dest[2] = (val >> 16) & 255;
150   dest[3] = (val >> 24) & 255;
151 }
152
153 /* Send a blob of data.  */
154
155 static void
156 send_output (int fd, unsigned char *buf, int nbytes)
157 {
158   while (nbytes > 0)
159     {
160       ssize_t written = write (fd, buf, nbytes);
161       if (written < 0)
162         {
163           fprintf (stderr, "%s: write to socket failed: %s\n",
164                   progname, strerror (errno));
165           exit (2);
166         }
167       nbytes -= written;
168     }
169 }
170
171 /* Receive a blob of data, NBYTES large.  Compare to the first NCOMP
172    bytes of BUF; if not a match, write error message to stderr and
173    exit (2).  Else put it in buf.  */
174
175 static void
176 expect_input (int fd, unsigned char *buf, int nbytes, int ncomp)
177 {
178   unsigned char byt;
179   int i;
180
181   for (i = 0; i < nbytes; i++)
182     {
183       int r;
184
185       do
186         {
187           errno = 0;
188           r = read (fd, &byt, 1);
189         }
190       while (r <= 0 && (r == 0 || errno == EAGAIN));
191
192       if (r != 1)
193         {
194           fprintf (stderr, "%s: read from socket failed: %s",
195                   progname, strerror (errno));
196           exit (2);
197         }
198
199       if (i < ncomp && byt != buf[i])
200         {
201           int j;
202           fprintf (stderr, "%s: unexpected input,\n ", progname);
203           if (i == 0)
204             fprintf (stderr, "nothing,");
205           else
206             for (j = 0; j < i; j++)
207               fprintf (stderr, "%02x", buf[j]);
208           fprintf (stderr, "\nthen %02x instead of %02x\n", byt, buf[i]);
209           exit (2);
210         }
211       else
212         buf[i] = byt;
213     }
214 }
215
216 /* Handle everything about a nil-terminated line of input.
217    Call exit (2) on error with error text on stderr.  */
218
219 static void
220 handle_input (int fd, char *buf, char *fname, int lineno)
221 {
222   int nbytes = 0;
223   int n = -1;
224   char *s = buf + 2;
225   unsigned int data;
226   static unsigned char bytes[1024];
227   int i;
228
229   memset (bytes, 0, sizeof bytes);
230   lineno++;
231
232   if (buf[1] != ',')
233     goto syntax_error;
234
235   switch (buf[0])
236     {
237       /* Comment characters and empty lines.  */
238     case 0: case '!': case '#':
239       break;
240
241       /* Include another file.  */
242     case '@':
243       handle_input_file (fd, s);
244       break;
245
246       /* Raw input (to be expected).  */
247     case 'i':
248       do
249         {
250           n = -1;
251           sscanf (s, "%02x%n", &data, &n);
252           s += n;
253           if (n > 0)
254             bytes[nbytes++] = data;
255         }
256       while (n > 0);
257       expect_input (fd, bytes, nbytes, nbytes);
258       if (verbose)
259         {
260           printf ("i,");
261           for (i = 0; i < nbytes; i++)
262             printf ("%02x", bytes[i]);
263           printf ("\n");
264         }
265       break;
266
267       /* Raw output (to be written).  */
268     case 'o':
269       do
270         {
271           n = -1;
272           sscanf (s, "%02x%n", &data, &n);
273           if (n > 0)
274             {
275               s += n;
276               bytes[nbytes++] = data;
277             }
278         }
279       while (n > 0);
280       if (*s != 0)
281         goto syntax_error;
282       send_output (fd, bytes, nbytes);
283       if (verbose)
284         {
285           printf ("o,");
286           for (i = 0; i < nbytes; i++)
287             printf ("%02x", bytes[i]);
288           printf ("\n");
289         }
290       break;
291
292       /* Read a register.  */
293     case 'r':
294       {
295         unsigned int addr;
296         sscanf (s, "%x,%x%n", &addr, &data, &n);
297         if (n < 0 || s[n] != 0)
298           goto syntax_error;
299         bytes[0] = 11;
300         bytes[1] = 0;
301         bytes[2] = RV_READ_CMD;
302         h2le32 (bytes + 3, addr);
303         expect_input (fd, bytes, 11, 7);
304         h2le32 (bytes + 7, data);
305         send_output (fd, bytes, 11);
306         if (verbose)
307           printf ("r,%x,%x\n", addr, data);
308       }
309       break;
310
311       /* Write a register.  */
312     case 'w':
313       {
314         unsigned int addr;
315         sscanf (s, "%x,%x%n", &addr, &data, &n);
316         if (n < 0 || s[n] != 0)
317           goto syntax_error;
318         bytes[0] = 11;
319         bytes[1] = 0;
320         bytes[2] = RV_WRITE_CMD;
321         h2le32 (bytes + 3, addr);
322         h2le32 (bytes + 7, data);
323         expect_input (fd, bytes, 11, 11);
324         send_output (fd, bytes, 11);
325         if (verbose)
326           printf ("w,%x,%x\n", addr, data);
327       }
328       break;
329
330       /* Wait for some milliseconds.  */
331     case 't':
332       {
333         int del = 0;
334         struct timeval to;
335         sscanf (s, "%d%n", &del, &n);
336         if (n < 0 || s[n] != 0 || del == 0)
337           goto syntax_error;
338
339         to.tv_sec = del / 1000;
340         to.tv_usec = (del % 1000) * 1000;
341
342         if (select (0, NULL, NULL, NULL, &to) != 0)
343           {
344             fprintf (stderr, "%s: problem waiting for %d ms:\n %s\n",
345                      progname, del, strerror (errno));
346             exit (2);
347           }
348         if (verbose)
349           printf ("t,%d\n", del);
350       }
351       break;
352
353       /* Expect a watchdog command.  */
354     case 'W':
355       if (*s != 0)
356         goto syntax_error;
357       bytes[0] = 3;
358       bytes[1] = 0;
359       bytes[2] = RV_WATCHDOG_CMD;
360       expect_input (fd, bytes, 3, 3);
361       if (verbose)
362         printf ("W\n");
363       break;
364
365       /* Send an IRQ notification.  */
366     case 'I':
367       sscanf (s, "%x%n", &data, &n);
368       if (n < 0 || s[n] != 0)
369         goto syntax_error;
370       bytes[0] = 7;
371       bytes[1] = 0;
372       bytes[2] = RV_IRQ_CMD;
373       h2le32 (bytes + 3, data);
374       send_output (fd, bytes, 7);
375       if (verbose)
376         printf ("I,%x\n", data);
377       break;
378
379       /* DMA store (to CPU).  */
380     case 's':
381       {
382         unsigned int addr;
383         sscanf (s, "%x,%n", &addr, &n);
384
385         if (n < 0 || s[n] == 0)
386           goto syntax_error;
387         s += n;
388         do
389           {
390             n = -1;
391             sscanf (s, "%02x%n", &data, &n);
392             if (n > 0)
393               {
394                 s += n;
395                 bytes[11 + nbytes++] = data;
396               }
397           }
398         while (n > 0);
399
400         if (*s != 0)
401           goto syntax_error;
402         h2le32 (bytes, nbytes + 11);
403         bytes[2] = RV_MEM_WR_CMD;
404         h2le32 (bytes + 3, addr);
405         h2le32 (bytes + 7, nbytes);
406         send_output (fd, bytes, nbytes + 11);
407         if (verbose)
408           {
409             printf ("s,%x,", addr);
410             for (i = 0; i < nbytes; i++)
411               printf ("%02x", bytes[i]);
412             printf ("\n");
413           }
414       }
415       break;
416
417       /* DMA load (from CPU).  */
418     case 'l':
419       {
420         unsigned int addr;
421         sscanf (s, "%x,%n", &addr, &n);
422
423         if (n < 0 || s[n] == 0)
424           goto syntax_error;
425         s += n;
426         do
427           {
428             n = -1;
429             sscanf (s, "%02x%n", &data, &n);
430             if (n > 0)
431               {
432                 s += n;
433                 bytes[11 + nbytes++] = data;
434               }
435           }
436         while (n > 0);
437
438         if (*s != 0)
439           goto syntax_error;
440         h2le32 (bytes, nbytes + 11);
441         bytes[0] = 11;
442         bytes[1] = 0;
443         bytes[2] = RV_MEM_RD_CMD;
444         h2le32 (bytes + 3, addr);
445         h2le32 (bytes + 7, nbytes);
446         send_output (fd, bytes, 11);
447         bytes[0] = (nbytes + 11) & 255;
448         bytes[1] = ((nbytes + 11) >> 8) & 255;
449         expect_input (fd, bytes, nbytes + 11, nbytes + 11);
450         if (verbose)
451           {
452             printf ("l,%x,", addr);
453             for (i = 0; i < nbytes; i++)
454               printf ("%02x", bytes[i]);
455             printf ("\n");
456           }
457       }
458       break;
459
460     syntax_error:
461     default:
462       fprintf (stderr, "%s: invalid command line in %s:%d:\n %s",
463                progname, fname, lineno, strerror (errno));
464       exit (2);
465     }
466 }
467
468 /* Loop over the contents of FNAME, using handle_input to parse each line.
469    Errors to stderr, exit (2).  */
470
471 static void
472 handle_input_file (int fd, char *fname)
473 {
474   static char buf[2048] = {0};
475   int lineno = 0;
476   FILE *f = fopen (fname, "r");
477
478   if (f == NULL)
479     {
480       fprintf (stderr, "%s: problem opening %s: %s\n",
481                progname, fname, strerror (errno));
482       exit (2);
483     }
484
485   /* Let's cut the buffer short, so we always get a newline.  */
486   while (fgets (buf, sizeof (buf) - 1, f) != NULL)
487     {
488       buf[strlen (buf) - 1] = 0;
489       lineno++;
490       handle_input (fd, buf, fname, lineno);
491     }
492
493   fclose (f);
494 }
495
496 int
497 main (int argc, char *argv[])
498 {
499   int optc;
500   int fd;
501   FILE *f;
502   int i;
503
504   progname = argv[0];
505   while ((optc = getopt_long (argc, argv, "", longopts, NULL)) != -1)
506     switch (optc)
507       {
508       case OPT_PORT:
509         port = atoi (optarg);
510         break;
511
512       case OPT_TIMEOUT:
513         timeout = (time_t) atoi (optarg);
514         break;
515
516       case OPT_VERBOSE:
517         verbose = 1;
518         break;
519       }
520
521   fd = setupsocket ();
522   if (fd < 0)
523     {
524       fprintf (stderr, "%s: problem setting up the connection: %s\n",
525                progname, strerror (errno));
526       exit (2);
527     }
528
529   for (i = optind; i < argc; i++)
530     handle_input_file (fd, argv[i]);
531
532   /* FIXME: option-controlled test for remaining input?  */
533   close (fd);
534   return 1;
535 }
536 #endif