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 51

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

powered by: WebSVN 2.1.0

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