OpenCores
URL https://opencores.org/ocsvn/adv_debug_sys/adv_debug_sys/trunk

Subversion Repositories adv_debug_sys

[/] [adv_debug_sys/] [trunk/] [Software/] [adv_jtag_bridge/] [hwp_server.c] - Blame information for rev 54

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 51 nyawn
/* hwp_server.c -- Server for hardware watchpoint handling
2
   Copyright(C) 2010 Nathan Yawn <nyawn@opencores.org>
3
 
4
   This file is part the advanced debug unit / bridge.  GDB does not
5
   have support for the OR1200's advanced hardware watchpoints.  This
6
   acts as a server for a client program that can read and set them.
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
21
 
22
 
23
#include <stdio.h>
24
#include <sys/unistd.h>
25
#include <sys/types.h>
26
#include <sys/fcntl.h>
27
#include <sys/socket.h>
28
#include <arpa/inet.h>
29 53 nyawn
#include <netinet/in.h>
30
#include <unistd.h>
31 51 nyawn
#include <netdb.h>
32
#include <string.h>
33
#include <pthread.h>
34
#include <errno.h>
35
 
36
#include "spr-defs.h"
37
#include "dbg_api.h"
38
#include "hardware_monitor.h"
39
#include "errcodes.h"
40
 
41
 
42
#define debug(...) // fprintf(stderr, __VA_ARGS__ )
43
 
44
#define HWP_BUF_MAX 256
45
 
46
/*! Data structure for RSP buffers. Can't be null terminated, since it may
47
  include zero bytes */
48
struct rsp_buf
49
{
50
  char  data[HWP_BUF_MAX];
51
  int   len;
52
};
53
 
54
int hwp_server_fd = -1;
55
int hwp_client_fd = -1;
56
int hwp_pipe_fds[2];
57
 
58
/* Some convenient net address info to have around */
59
char hwp_ipstr[INET6_ADDRSTRLEN];
60
char *hwp_ipver;
61
int hwp_portnum;
62
char hwp_hostname[256];
63
 
64
/* Other local data */
65
int hwp_server_running = 0;
66
int hwp_target_is_running = 0;
67
int use_cached_dmr2 = 0;
68
uint32_t cached_dmr2 = 0;
69
 
70
/*! String to map hex digits to chars */
71
static const char hexchars[]="0123456789abcdef";
72
 
73
pthread_t hwp_server_thread;
74
void *hwp_server(void *arg);
75
 
76
void hwp_server_close(void);
77
void hwp_client_close(void);
78
void hwp_client_request(void);
79
 
80
struct rsp_buf *hwp_get_packet(void);
81
void put_hwp_rsp_char(int fd, char c);
82
int get_hwp_rsp_char(int fd);
83
void hwp_read_reg(struct rsp_buf *buf);
84
void hwp_write_reg (struct rsp_buf *buf);
85
void hwp_put_str_packet (int fd, const char *str);
86
void hwp_put_packet (int fd, struct rsp_buf *buf);
87
unsigned long int hwp_hex2reg (char *buf);
88
void hwp_reg2hex (unsigned long int val, char *buf);
89
int hwp_hex(int c);
90
void hwp_report_run(void);
91
void hwp_report_stop(void);
92
 
93
/*----------------------------------------------------------*/
94
/* Public API                                               */
95
/*----------------------------------------------------------*/
96
 
97
void hwp_init(int portNum)
98
{
99
  int status;
100
  struct addrinfo hints;
101
  struct addrinfo *servinfo;  // will point to the results of getaddrinfo
102
  int optval; /* Socket options */
103
  char portnum[6];  /* portNum as a string */
104
  void *addr;
105
 
106
  debug("HWP Server initializing\n");
107
 
108
  hwp_server_fd      = -1;
109
  hwp_client_fd      = -1;
110
  hwp_portnum = portNum;
111
 
112
  memset(portnum, '\0', sizeof(portnum));
113
  snprintf(portnum, 5, "%i", portNum);
114
 
115
  /* Get the address info for the local host */
116
  memset(&hints, 0, sizeof hints); // make sure the struct is empty
117
  hints.ai_family = AF_UNSPEC;     // don't care IPv4 or IPv6
118
  hints.ai_socktype = SOCK_STREAM; // TCP stream sockets
119
  hints.ai_flags = AI_PASSIVE;     // fill in my IP for me
120
 
121
  if ((status = getaddrinfo(NULL, portnum, &hints, &servinfo)) != 0) {
122
    fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
123
    return;
124
  }
125
 
126
 
127
  /* *** TODO: Select the appropriate servinfo in the linked list
128
   * For now, we just use the first entry in servinfo.
129
     struct addrinfo *servinfo, *p;
130
     for(p = servinfo;p != NULL; p = p->ai_next) {
131
     if (p->ai_family == AF_INET) { // IPv4
132
     } else { // IPv6
133
     }
134
     }
135
  */
136
 
137
 
138
  /* Save the IP address, for convenience (different fields in IPv4 and IPv6) */
139
  if (servinfo->ai_family == AF_INET) { // IPv4
140
    struct sockaddr_in *ipv4 = (struct sockaddr_in *)servinfo->ai_addr;
141
    addr = &(ipv4->sin_addr);
142
    hwp_ipver = "IPv4";
143
  } else { // IPv6
144
    struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)servinfo->ai_addr;
145
    addr = &(ipv6->sin6_addr);
146
    hwp_ipver = "IPv6";
147
  }
148
 
149
  /* convert the IP to a string */
150
  inet_ntop(servinfo->ai_family, addr, hwp_ipstr, sizeof(hwp_ipstr));
151
 
152
  /* Find out what our name is, save for convenience */
153
  if (gethostname (hwp_hostname, sizeof(hwp_hostname)) < 0)
154
    {
155
      fprintf (stderr, "Warning: Unable to get hostname for HWP server: %s\n", strerror(errno));
156
      hwp_hostname[0] = '\0';  /* This is not a fatal error. */
157
    }
158
 
159
  /* Create the socket */
160
  hwp_server_fd = socket (servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol);
161
  if (hwp_server_fd < 0)
162
    {
163
      fprintf (stderr, "Error: HWP could not create server socket: %s\n", strerror(errno));
164
      return;
165
    }
166
 
167
  /* Set this socket to reuse its address. */
168
  optval = 1;
169
  if (setsockopt(hwp_server_fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof (optval)) == -1)
170
    {
171
      fprintf (stderr, "Cannot set SO_REUSEADDR option on server socket %d: %s\n", hwp_server_fd, strerror(errno));
172
      hwp_server_close();
173
      return;
174
    }
175
 
176
  /* Bind the socket to the local address */
177
  if (bind (hwp_server_fd, servinfo->ai_addr, servinfo->ai_addrlen) < 0)
178
    {
179
      fprintf (stderr, "Error: Unable to bind HWP server socket %d to port %d: %s\n", hwp_server_fd, portNum, strerror(errno));
180
      hwp_server_close();
181
      return;
182
    }
183
 
184
  /* Set us up as a server, with a maximum backlog of 1 connection */
185
  if (listen (hwp_server_fd, 1) < 0)
186
    {
187
      fprintf (stderr, "Warning: Unable to set HWP backlog on server socket %d to %d: %s\n", hwp_server_fd, 1, strerror(errno));
188
      hwp_server_close();
189
      return;
190
    }
191
 
192
  fprintf(stderr, "HWP server listening on host %s (%s), port %i, address family %s\n",
193
          hwp_hostname, hwp_ipstr, hwp_portnum, hwp_ipver);
194
 
195
  /* Register for stall/unstall events from the target monitor thread. Also creates pipe
196
   * for sending stall/unstall command to the target monitor, unused by us. */
197
  if(0 > register_with_monitor_thread(hwp_pipe_fds)) {  // pipe_fds[0] is for writing to monitor, [1] is to read from it
198
    fprintf(stderr, "HWP server failed to register with monitor thread, exiting");
199
    hwp_server_close();
200
    return;
201
  }
202
 
203
}
204
 
205
 
206
int hwp_server_start(void)
207
{
208
 
209
  hwp_server_running = 1;
210
 
211
  debug("Starting HWP server\n");
212
 
213
  // Create the HWP server thread
214
  if(pthread_create(&hwp_server_thread, NULL, hwp_server, NULL))
215
    {
216
      fprintf(stderr, "Failed to create HWP server thread!\n");
217
      return 0;
218
    }
219
 
220
  return 1;
221
}
222
 
223
 
224
int hwp_server_stop(void)
225
{
226
  /*** NOTE: Since we currently don't use select() in front of the accept()
227
   *** in the server thread, this won't actually work unless/until a client
228
   *** is connected.  Otherwise, the server thread will be blocked on the
229
   *** accept() (though closing the server socket may break it out.)
230
   ***/
231
 
232
  hwp_server_running = 0;
233
  hwp_server_close();
234
  return 1;
235
}
236
 
237
/*--------------------------------------------------------------------*/
238
/* Main server thread                                                 */
239
/*--------------------------------------------------------------------*/
240
 
241
 
242
void *hwp_server(void *arg)
243
{
244
  struct sockaddr_storage their_addr;
245
  struct timeval *tvp;
246
  fd_set  readset;
247
  socklen_t addr_size;
248
  int nfds, flags;
249
  int ret;
250
  char cmd;
251
 
252
  fprintf(stderr, "HWP server thread running!\n");
253
 
254
  while(hwp_server_running)
255
    {
256
      /* Listen for an incoming connection */
257
      addr_size = sizeof their_addr;
258
      hwp_client_fd = accept(hwp_server_fd, (struct sockaddr *)&their_addr, &addr_size);
259
 
260
      if(hwp_client_fd == -1)
261
        {
262
          perror("Error in accept() in HWP server thread");
263
        }
264
      else
265
        {
266
          debug("HWP server got connection!\n");
267
 
268
          /* Do new client init stuff here */
269
          use_cached_dmr2 = 0;
270
 
271
          /* New client should be non-blocking. */
272
          flags = fcntl (hwp_client_fd, F_GETFL);
273
          if (flags < 0)
274
            {
275
              fprintf (stderr, "Warning: Unable to get flags for HWP client socket %d: %s\n", hwp_client_fd, strerror(errno));
276
              // Not really fatal.
277
            }
278
          else {
279
            flags |= O_NONBLOCK;
280
            if (fcntl (hwp_client_fd, F_SETFL, flags) < 0)
281
              {
282
                fprintf (stderr, "Warning: Unable to set flags for HWP client socket %d to 0x%08x: %s\n", hwp_client_fd, flags, strerror(errno));
283
                // Also not really fatal.
284
              }
285
          }
286
        }
287
 
288
      /* Send/receive data on the new connection for as long as it's valid */
289
      while(hwp_server_running && (hwp_client_fd != -1))
290
        {
291
          /* if target not running, block on data from client or monitor thread */
292
          /* if target running, just poll (don't block) */
293
          // if(hwp_target_is_running) {
294
          //  tv.tv_sec = 0;  // Set this each loop, it may be changed by the select() call
295
          //  tv.tv_usec = 0;  // instant timeout when polling
296
          //  tvp = &tv;
297
          //} else {
298
            tvp = NULL;
299
            //}
300
 
301
          FD_ZERO(&readset);
302
          FD_SET(hwp_client_fd, &readset);
303
          FD_SET(hwp_pipe_fds[1], &readset);
304
          nfds = hwp_client_fd;
305
          if(hwp_pipe_fds[1] > nfds) nfds = hwp_pipe_fds[1];
306
          nfds++;
307
 
308
          ret = select(nfds, &readset, NULL, NULL, tvp);
309
 
310
          if(ret == -1)  // error
311
            {
312
                perror("select()");
313
            }
314
          else if(ret != 0)  // fd ready (ret == 0 on timeout)
315
            {
316
              debug("HWP thread got data\n");
317
 
318
              if(FD_ISSET(hwp_pipe_fds[1], &readset))
319
                {
320
                  ret = read(hwp_pipe_fds[1], &cmd, 1);
321
                  debug("HWP server got monitor status \'%c\' (0x%X)\n", cmd, cmd);
322
                  if(ret == 1)
323
                    {
324
                      if(cmd == 'H')
325
                        {
326
                          // Save state so we can tell client on request
327
                          hwp_target_is_running = 0;
328
                        }
329
                      else if(cmd == 'R')
330
                        {
331
                          // Save state so we can tell client on request
332
                          hwp_target_is_running = 1;
333
                          use_cached_dmr2 = 0;
334
                        }
335
                      else
336
                        {
337
                          fprintf(stderr, "HWP server got unknown monitor status \'%c\' (0x%X)\n", cmd, cmd);
338
                        }
339
                    }
340
                  else
341
                    {
342
                      fprintf(stderr, "HWP server failed to read from ready monitor pipe!\n");
343
                    }
344
                }  // if FD_ISSET(hwp_pipe_fds[1])
345
 
346
              if(FD_ISSET(hwp_client_fd, &readset))
347
                {
348
                  hwp_client_request();
349
                }
350
            }   // else if (ret != 0)
351
 
352
        }  /* while client connection is valid */
353
 
354
    } /* while(hwp_server_running) */
355
 
356
  hwp_client_close();
357
 
358
  return arg;  // unused
359
}
360
 
361
/*--------------------------------------------------------------------*/
362
/* Helper functions                                                   */
363
/*--------------------------------------------------------------------*/
364
 
365
void hwp_server_close(void)
366
{
367
  if (hwp_server_fd != -1)
368
    {
369
      close(hwp_server_fd);
370
      hwp_server_fd = -1;
371
    }
372
}
373
 
374
 
375
void hwp_client_close(void)
376
{
377
  if (hwp_client_fd != -1)
378
    {
379
      close (hwp_client_fd);
380
      hwp_client_fd = -1;
381
    }
382
}       /* hwp_client_close () */
383
 
384
 
385
void hwp_client_request(void)
386
{
387
  struct rsp_buf *buf = hwp_get_packet ();      /* Message sent to us */
388
 
389
  // Null packet means we hit EOF or the link was closed for some other
390
  // reason. Close the client and return
391
  if (NULL == buf)
392
    {
393
      hwp_client_close ();
394
      return;
395
    }
396
 
397
  debug("HWP Packet received %s: %d chars\n", buf->data, buf->len );
398
 
399
  switch (buf->data[0])
400
    {
401
 
402
    case '?':
403
      // Different meaning than RSP: in RSP, this always returns an 'S' packet.
404
      // here, we want to know running / stopped.
405
      if(hwp_target_is_running) {
406
        hwp_report_run();
407
      } else {
408
        hwp_report_stop();
409
      }
410
      return;
411
 
412
 
413
      /*
414
        case 'g':
415
        rsp_read_all_regs ();
416
        return;
417
 
418
        case 'G':
419
        rsp_write_all_regs (buf);
420
        return;
421
      */
422
 
423
 
424
    case 'p':
425
      /* Read a register */
426
      hwp_read_reg(buf);
427
      return;
428
 
429
    case 'P':
430
      /* Write a register */
431
      hwp_write_reg(buf);
432
      return;
433
 
434
      /*
435
        case 'q':
436
        // Any one of a number of query packets
437
        rsp_query (buf);
438
        return;
439
 
440
        case 'Q':
441
        // Any one of a number of set packets
442
        rsp_set (buf);
443
        return;
444
      */
445
 
446
    default:
447
      /* Unknown commands are ignored */
448
      fprintf (stderr, "Warning: Unknown HWP request %s\n", buf->data);
449
      return;
450
    }
451
}       /* hwp_client_request () */
452
 
453
 
454
/*---------------------------------------------------------------------------*/
455
/*!Get a packet from the GDB client
456
 
457
   Modeled on the stub version supplied with GDB. The data is in a static
458
   buffer. The data should be copied elsewhere if it is to be preserved across
459
   a subsequent call to get_packet().
460
 
461
   Unlike the reference implementation, we don't deal with sequence
462
   numbers. GDB has never used them, and this implementation is only intended
463
   for use with GDB 6.8 or later. Sequence numbers were removed from the RSP
464
   standard at GDB 5.0.
465
 
466
   @return  A pointer to the static buffer containing the data                */
467
/*---------------------------------------------------------------------------*/
468
struct rsp_buf *hwp_get_packet(void)
469
{
470
  static struct rsp_buf  buf;           /* Survives the return */
471
 
472
  /* Keep getting packets, until one is found with a valid checksum */
473
  while (1)
474
    {
475
      unsigned char  checksum;          /* The checksum we have computed */
476
      int            count;             /* Index into the buffer */
477
      int            ch;                /* Current character */
478
 
479
      /* Wait around for the start character ('$'). Ignore all other
480
         characters */
481
      ch = get_hwp_rsp_char(hwp_client_fd);
482
      while (ch != '$')
483
        {
484
          if (-1 == ch)
485
            {
486
              return  NULL;             /* Connection failed */
487
            }
488
 
489
          ch = get_hwp_rsp_char(hwp_client_fd);
490
        }
491
 
492
      /* Read until a '#' or end of buffer is found */
493
      checksum =  0;
494
      count    =  0;
495
      while (count < HWP_BUF_MAX - 1)
496
        {
497
          ch = get_hwp_rsp_char(hwp_client_fd);
498
 
499
          /* Check for connection failure */
500
          if (-1 == ch)
501
            {
502
              return  NULL;
503
            }
504
 
505
          /* If we hit a start of line char begin all over again */
506
          if ('$' == ch)
507
            {
508
              checksum =  0;
509
              count    =  0;
510
 
511
              continue;
512
            }
513
 
514
          /* Break out if we get the end of line char */
515
          if ('#' == ch)
516
            {
517
              break;
518
            }
519
 
520
          /* Update the checksum and add the char to the buffer */
521
 
522
          checksum        = checksum + (unsigned char)ch;
523
          buf.data[count] = (char)ch;
524
          count           = count + 1;
525
        }
526
 
527
      /* Mark the end of the buffer with EOS - it's convenient for non-binary
528
         data to be valid strings. */
529
      buf.data[count] = 0;
530
      buf.len         = count;
531
 
532
      /* If we have a valid end of packet char, validate the checksum */
533
      if ('#' == ch)
534
        {
535
          unsigned char  xmitcsum;      /* The checksum in the packet */
536
 
537
          ch = get_hwp_rsp_char(hwp_client_fd);
538
          if (-1 == ch)
539
            {
540
              return  NULL;             /* Connection failed */
541
            }
542
          xmitcsum = hwp_hex(ch) << 4;
543
 
544
          ch = get_hwp_rsp_char(hwp_client_fd);
545
          if (-1 == ch)
546
            {
547
              return  NULL;             /* Connection failed */
548
            }
549
 
550
          xmitcsum += hwp_hex(ch);
551
 
552
          /* If the checksums don't match print a warning, and put the
553
             negative ack back to the client. Otherwise put a positive ack. */
554
          if (checksum != xmitcsum)
555
            {
556
              fprintf (stderr, "Warning: Bad HWP RSP checksum: Computed "
557
                       "0x%02x, received 0x%02x\n", checksum, xmitcsum);
558
 
559
              put_hwp_rsp_char (hwp_client_fd, '-');    /* Failed checksum */
560
            }
561
          else
562
            {
563
              put_hwp_rsp_char (hwp_client_fd, '+');    /* successful transfer */
564
              break;
565
            }
566
        }
567
      else
568
        {
569
          fprintf (stderr, "Warning: HWP RSP packet overran buffer\n");
570
        }
571
    }
572
 
573
  return &buf;                          /* Success */
574
 
575
}       /* hwp_get_packet () */
576
 
577
 
578
/*---------------------------------------------------------------------------*/
579
/*Single character get/set routines                                          */
580
/*---------------------------------------------------------------------------*/
581
void put_hwp_rsp_char(int fd, char  c)
582
{
583
  if (-1 == fd)
584
    {
585
      fprintf (stderr, "Warning: Attempt to write '%c' to unopened HWP RSP client: Ignored\n", c);
586
      return;
587
    }
588
 
589
  /* Write until successful (we retry after interrupts) or catastrophic
590
     failure. */
591
  while (1)
592
    {
593
      switch (write(fd, &c, sizeof (c)))
594
        {
595
        case -1:
596
          /* Error: only allow interrupts or would block */
597
          if ((EAGAIN != errno) && (EINTR != errno))
598
            {
599
              fprintf (stderr, "Warning: Failed to write to HWP RSP client: Closing client connection: %s\n",
600
                       strerror (errno));
601
              hwp_client_close();
602
              return;
603
            }
604
 
605
          break;
606
 
607
        case 0:
608
          break;                /* Nothing written! Try again */
609
 
610
        default:
611
          return;               /* Success, we can return */
612
        }
613
    }
614
}       /* put_hwp_rsp_char() */
615
 
616
 
617
 
618
int get_hwp_rsp_char(int fd)
619
{
620
  unsigned char  c;             /* The character read */
621
 
622
  if (-1 == fd)
623
    {
624
      fprintf (stderr, "Warning: Attempt to read from unopened HWP RSP client: Ignored\n");
625
      return  -1;
626
    }
627
 
628
  /* Read until successful (we retry after interrupts) or catastrophic
629
     failure. */
630
  while (1)
631
    {
632
      switch (read (fd, &c, sizeof (c)))
633
        {
634
        case -1:
635
          /* Error: only allow interrupts or would block */
636
          if ((EAGAIN != errno) && (EINTR != errno))
637
            {
638
              fprintf (stderr, "Warning: Failed to read from HWP RSP client: Closing client connection: %s\n",
639
                       strerror (errno));
640
              hwp_client_close();
641
              return  -1;
642
            }
643
 
644
          break;
645
 
646
        case 0:
647
          // EOF
648
          hwp_client_close();
649
          return  -1;
650
 
651
        default:
652
          return  c & 0xff;     /* Success, we can return (no sign extend!) */
653
        }
654
    }
655
}       /* get_hwp_rsp_char() */
656
 
657
 
658
/*---------------------------------------------------------------------------*/
659
/*!Read a single register
660
 
661
   The registers follow the GDB sequence for OR1K: GPR0 through GPR31, PC
662
   (i.e. SPR NPC) and SR (i.e. SPR SR). The register is returned as a
663
   sequence of bytes in target endian order.
664
 
665
   Each byte is packed as a pair of hex digits.
666
 
667
   @param[in] buf  The original packet request. Reused for the reply.        */
668
/*---------------------------------------------------------------------------*/
669
void hwp_read_reg(struct rsp_buf *buf)
670
{
671
  unsigned int  regnum;
672
  uint32_t tmp;
673
  unsigned int errcode = APP_ERR_NONE;
674
 
675
  /* Break out the fields from the data */
676
  if (1 != sscanf (buf->data, "p%x", &regnum))
677
    {
678
      fprintf (stderr, "Warning: Failed to recognize HWP RSP read register command: \'%s\'\n", buf->data);
679
      hwp_put_str_packet (hwp_client_fd, "E01");
680
      return;
681
    }
682
 
683
  if((regnum == SPR_DMR2) && use_cached_dmr2)  // Should we use the cached DMR2 value?
684
    {
685
      tmp = cached_dmr2;
686
      errcode = APP_ERR_NONE;
687
      fprintf(stderr, "Using cached DMR2 value 0x%X\n", tmp);
688
    }
689
  else
690
    {
691
      /* Get the relevant register.  We assume the client is not GDB,
692
       * and that no register number translation is needed.
693
       */
694
      errcode = dbg_cpu0_read(regnum, &tmp);
695
    }
696
 
697
  if(errcode == APP_ERR_NONE) {
698
    hwp_reg2hex(tmp, buf->data);
699
    buf->len = strlen (buf->data);
700
    debug("Read reg 0x%x, got %s (0x%X), len %i\n", regnum, buf->data, tmp, buf->len);
701
    hwp_put_packet (hwp_client_fd, buf);
702
  }
703
  else {
704
    fprintf(stderr, "Error reading HWP register: %s\n", get_err_string(errcode));
705
    hwp_put_str_packet(hwp_client_fd, "E01");
706
  }
707
 
708
}       /* hwp_read_reg() */
709
 
710
 
711
/*---------------------------------------------------------------------------*/
712
/*!Write a single register
713
 
714
   The registers follow the GDB sequence for OR1K: GPR0 through GPR31, PC
715
   (i.e. SPR NPC) and SR (i.e. SPR SR). The register is specified as a
716
   sequence of bytes in target endian order.
717
 
718
   Each byte is packed as a pair of hex digits.
719
 
720
   @param[in] buf  The original packet request.                              */
721
/*---------------------------------------------------------------------------*/
722
void hwp_write_reg (struct rsp_buf *buf)
723
{
724
  unsigned int  regnum;
725
  char          valstr[9];              /* Allow for EOS on the string */
726
  unsigned int  errcode = APP_ERR_NONE;
727
 
728
  /* Break out the fields from the data */
729
  if (2 != sscanf (buf->data, "P%x=%8s", &regnum, valstr))
730
    {
731
      fprintf (stderr, "Warning: Failed to recognize RSP write register command: %s\n", buf->data);
732
      hwp_put_str_packet (hwp_client_fd, "E01");
733
      return;
734
    }
735
 
736
  /* Set the relevant register.  We assume that the client is not
737
   * GDB, and no register number translation is needed. */
738
  errcode = dbg_cpu0_write(regnum, hwp_hex2reg(valstr));
739
 
740
  if(errcode == APP_ERR_NONE) {
741
    debug("Wrote reg 0x%X with val 0x%X (%s)\n", regnum, hwp_hex2reg(valstr), valstr);
742
    hwp_put_str_packet (hwp_client_fd, "OK");
743
  }
744
  else {
745
    fprintf(stderr, "Error writing register: %s\n", get_err_string(errcode));
746
    hwp_put_str_packet(hwp_client_fd, "E01");
747
  }
748
 
749
}       /* hwp_write_reg() */
750
 
751
/*---------------------------------------------------------------------------*/
752
/*!Convenience to put a constant string packet
753
 
754
   param[in] str  The text of the packet                                     */
755
/*---------------------------------------------------------------------------*/
756
void hwp_put_str_packet (int fd, const char *str)
757
{
758
  struct rsp_buf  buf;
759
  int             len = strlen (str);
760
 
761
  /* Construct the packet to send, so long as string is not too big,
762
     otherwise truncate. Add EOS at the end for convenient debug printout */
763
 
764
  if (len >= HWP_BUF_MAX)
765
    {
766
      fprintf (stderr, "Warning: String %s too large for HWP RSP packet: truncated\n", str);
767
      len = HWP_BUF_MAX - 1;
768
    }
769
 
770
  strncpy (buf.data, str, len);
771
  buf.data[len] = 0;
772
  buf.len       = len;
773
 
774
  hwp_put_packet (fd, &buf);
775
 
776
}       /* hwp_put_str_packet () */
777
 
778
/*---------------------------------------------------------------------------*/
779
/*!Send a packet to the GDB client
780
 
781
   Modeled on the stub version supplied with GDB. Put out the data preceded by
782
   a '$', followed by a '#' and a one byte checksum. '$', '#', '*' and '}' are
783
   escaped by preceding them with '}' and then XORing the character with
784
   0x20.
785
 
786
   @param[in] buf  The data to send                                          */
787
/*---------------------------------------------------------------------------*/
788
void hwp_put_packet (int fd, struct rsp_buf *buf)
789
{
790
  int  ch;                              /* Ack char */
791
 
792
  /* Construct $<packet info>#<checksum>. Repeat until the GDB client
793
     acknowledges satisfactory receipt. */
794
  do
795
    {
796
      unsigned char checksum = 0;        /* Computed checksum */
797
      int           count    = 0;        /* Index into the buffer */
798
 
799
      debug("Putting %s\n", buf->data);
800
 
801
      put_hwp_rsp_char (fd, '$');               /* Start char */
802
 
803
      /* Body of the packet */
804
      for (count = 0; count < buf->len; count++)
805
        {
806
          unsigned char  ch = buf->data[count];
807
 
808
          /* Check for escaped chars */
809
          if (('$' == ch) || ('#' == ch) || ('*' == ch) || ('}' == ch))
810
            {
811
              ch       ^= 0x20;
812
              checksum += (unsigned char)'}';
813
              put_hwp_rsp_char (fd, '}');
814
            }
815
 
816
          checksum += ch;
817
          put_hwp_rsp_char (fd, ch);
818
        }
819
 
820
      put_hwp_rsp_char (fd, '#');               /* End char */
821
 
822
      /* Computed checksum */
823
      put_hwp_rsp_char (fd, hexchars[checksum >> 4]);
824
      put_hwp_rsp_char (fd, hexchars[checksum % 16]);
825
 
826
      /* Check for ack or connection failure */
827
      ch = get_hwp_rsp_char (fd);
828
      if (-1 == ch)
829
        {
830
          return;                       /* Fail the put silently. */
831
        }
832
    }
833
  while ('+' != ch);
834
 
835
}       /* hwp_put_packet() */
836
 
837
 
838
unsigned long int hwp_hex2reg (char *buf)
839
{
840
  int                n;         /* Counter for digits */
841
  unsigned long int  val = 0;    /* The result */
842
 
843
  for (n = 0; n < 8; n++)
844
    {
845
#ifdef WORDSBIGENDIAN
846
      int  nyb_shift = n * 4;
847
#else
848
      int  nyb_shift = 28 - (n * 4);
849
#endif
850
      val |= hwp_hex(buf[n]) << nyb_shift;
851
    }
852
 
853
  return val;
854
 
855
}       /* hwp_hex2reg() */
856
 
857
 
858
void hwp_reg2hex(unsigned long int val, char *buf)
859
{
860
  int  n;                       /* Counter for digits */
861
 
862
  for (n = 0; n < 8; n++)
863
    {
864
#ifdef WORDSBIGENDIAN
865
      int  nyb_shift = n * 4;
866
#else
867
      int  nyb_shift = 28 - (n * 4);
868
#endif
869
      buf[n] = hexchars[(val >> nyb_shift) & 0xf];
870
    }
871
 
872
  buf[8] = 0;                    /* Useful to terminate as string */
873
 
874
}       /* hwp_reg2hex() */
875
 
876
 
877
int hwp_hex(int c)
878
{
879
  return  ((c >= 'a') && (c <= 'f')) ? c - 'a' + 10 :
880
          ((c >= '0') && (c <= '9')) ? c - '0' :
881
          ((c >= 'A') && (c <= 'F')) ? c - 'A' + 10 : -1;
882
 
883
}       /* hwp_hex() */
884
 
885
/* ---------------------------------------------------------------------- */
886
/* Functions to report stop and start to the client.                      */
887
/* Not strictly correct RSP protocol.                                     */
888
/*------------------------------------------------------------------------*/
889
 
890
void hwp_report_stop(void)
891
{
892
  struct rsp_buf  buf;
893
  uint32_t ppcval;
894
 
895
  // Read the PPC
896
  dbg_cpu0_read(SPR_PPC, &ppcval);
897
 
898
  debug("HWP reporting stop, PPC = 0x%X\n", ppcval);
899
 
900
  /* Construct a signal received packet */
901
  buf.data[0] = 'S';
902
  buf.data[1] = hexchars[ppcval >> 4];
903
  buf.data[2] = hexchars[ppcval % 16];
904
  buf.data[3] = 0;
905
  buf.len     = strlen (buf.data);
906
 
907
  hwp_put_packet(hwp_client_fd, &buf);
908
 
909
}       /* rsp_report_exception () */
910
 
911
 
912
void hwp_report_run(void)
913
{
914
  struct rsp_buf  buf;
915
 
916
  // Construct a 'run' packet.  This is completely non-standard, non-RSP, made up.
917
  buf.data[0] = 'R';
918
  buf.data[1] = 'U';
919
  buf.data[2] = 'N';
920
  buf.data[3] = 0;
921
  buf.len     = strlen (buf.data);
922
 
923
  hwp_put_packet(hwp_client_fd, &buf);
924
 
925
}  /* hwp_report_run() */
926
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.