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/] [adv_jtag_bridge.c] - Blame information for rev 51

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

Line No. Rev Author Line
1 4 nyawn
/* adv_jtag_bridge.c -- JTAG protocol bridge between GDB and Advanced debug module.
2
   Copyright(C) 2001 Marko Mlinar, markom@opencores.org
3
   Code for TCP/IP copied from gdb, by Chris Ziomkowski
4 32 nyawn
   Refactoring by Nathan Yawn <nyawn@opencores.org> (C) 2008 - 2010
5 4 nyawn
 
6
   This file was part of the OpenRISC 1000 Architectural Simulator.
7
   It is now also used to connect GDB to a running hardware OpenCores / OR1200
8
   advanced debug unit.
9
 
10
   This program is free software; you can redistribute it and/or modify
11
   it under the terms of the GNU General Public License as published by
12
   the Free Software Foundation; either version 2 of the License, or
13
   (at your option) any later version.
14
 
15
   This program is distributed in the hope that it will be useful,
16
   but WITHOUT ANY WARRANTY; without even the implied warranty of
17
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
   GNU General Public License for more details.
19
 
20
   You should have received a copy of the GNU General Public License
21
   along with this program; if not, write to the Free Software
22
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
23
 
24
/* Establishes jtag proxy server and communicates with parallel
25
   port directly.  Requires root access. */
26
 
27
#include <stdio.h>
28
#include <stdlib.h>  // for exit(), atoi(), strtoul()
29
#include <unistd.h>
30
#include <stdarg.h>
31
#include <string.h>  // for strstr()
32
#include <sys/types.h>
33
 
34
 
35
#include "adv_jtag_bridge.h"
36
#include "rsp-server.h"
37
#include "chain_commands.h"
38
#include "cable_common.h"
39
#include "or32_selftest.h"
40
#include "bsdl.h"
41
#include "errcodes.h"
42 42 nyawn
#include "hardware_monitor.h"
43
#include "jsp_server.h"
44 51 nyawn
#include "hwp_server.h"
45 4 nyawn
 
46
#define debug(...) //fprintf(stderr, __VA_ARGS__ )
47
 
48
// How many command-line IR length settings to create by default
49
#define IR_START_SETS 16
50
 
51
//////////////////////////////////////////////////
52
// Command line option flags / values
53
 
54
/* Which device in the scan chain we want to target.
55
 * 0 is the first device we find, which is nearest the data input of the cable.
56
 */
57
unsigned int target_dev_pos = 0;
58
 
59
// Do test before setting up server?
60
unsigned char do_selftest = 0;
61
 
62
// IR register length in TAP of 
63
// Can override autoprobe, or set if IDCODE not supported
64
typedef struct {
65
  int dev_index;
66
  int ir_length;
67
} irset;
68
 
69
#define START_IR_SETS 16
70
int reallocs = 0;
71
int num_ir_sets = 0;
72
irset * cmd_line_ir_sizes = NULL;
73
 
74
// DEBUG command for target device TAP
75
// May actually be USER1, for Xilinx devices using internal BSCAN modules
76
// Can override autoprobe, or set if unable to find in BSDL files
77
int cmd_line_cmd_debug = -1;  // 0 is a valid debug command, so use -1
78
 
79
// TCP port to set up the server for GDB on
80 42 nyawn
char *port = NULL;
81 4 nyawn
char default_port[] = "9999";
82
 
83 42 nyawn
#ifdef ENABLE_JSP
84
char *jspport = NULL;
85
char default_jspport[] = "9944";
86
#endif
87
 
88 51 nyawn
char *hwpport = NULL;
89
char default_hwpport[] = "9928";
90
 
91 4 nyawn
// Force altera virtual jtag mode on(1) or off(-1)
92
int force_alt_vjtag = 0;
93
 
94
 
95
// Pointer to the command line arg used as the cable name
96
char * cable_name = NULL;
97
 
98
////////////////////////////////////////////////////////
99
// List of IDCODES of devices on the JTAG scan chain
100
// The array is dynamically allocated in chain_commands/jtag_enumerate_chain()
101
 
102
uint32_t *idcodes = NULL;
103
int num_devices = 0;
104
 
105
 
106
const char *name_not_found = "(unknown)";
107
 
108
///////////////////////////////////////////////////////////
109
// JTAG constants
110
 
111
// Defines for Altera JTAG constants
112
#define ALTERA_MANUFACTURER_ID   0x6E
113
 
114
// Defines for Xilinx JTAG constants
115
#define XILINX_MANUFACTURER_ID   0x49
116
 
117
 
118
///////////////////////////////////////////////////
119
// Prototypes for local / helper functions
120
int get_IR_size(int devidx);
121
uint32_t get_debug_cmd(int devidx);
122
void configure_chain(void);
123
void print_usage(char *func);
124
void parse_args(int argc, char **argv);
125
void get_ir_opts(char *optstr, int *idx, int *val);
126
 
127
 
128
//////////////////////////////////////////////////////////////////////////////////////
129
/*----------------------------------------------------------------------------------*/
130
// Functions
131
/////////////////////////////////////////////////////////////////////////////////////
132
 
133
// Resets JTAG, and sets up DEBUG scan chain
134
void configure_chain(void)
135
{
136
  int i;
137
  unsigned int manuf_id;
138
  uint32_t cmd;
139
  const char *name;
140
  int irlen;
141
  int err = APP_ERR_NONE;
142
 
143
  err |= tap_reset();
144
  err |= jtag_enumerate_chain(&idcodes, &num_devices);
145
 
146
  if(err != APP_ERR_NONE) {
147
    printf("Error %s enumerating JTAG chain, aborting.\n", get_err_string(err));
148
    exit(1);
149
  }
150
 
151
  printf("\nDevices on JTAG chain:\n");
152
  printf("Index\tName\t\tID Code\t\tIR Length\n");
153
  printf("----------------------------------------------------------------\n");
154
  for(i = 0; i < num_devices; i++)
155
    {
156
      if(idcodes[i] != IDCODE_INVALID) {
157
        name = bsdl_get_name(idcodes[i]);
158
        irlen = bsdl_get_IR_size(idcodes[i]);
159
        if(name == NULL)
160
          name = name_not_found;
161
      } else {
162
        name = name_not_found;
163
        irlen = -1;
164
      }
165 14 nyawn
      printf("%d: \t%s \t0x%08X \t%d\n", i, name, idcodes[i], irlen);
166 4 nyawn
    }
167
  printf("\n");
168
 
169 14 nyawn
#ifdef __LEGACY__
170
// The legacy debug interface cannot support multi-device chains.  If there is more than
171
// one device on this chain, pull the cord.
172
if(num_devices > 1) {
173
        fprintf(stderr, "\n*** ERROR: The legacy debug hardware cannot support JTAG chains with\n");
174
        fprintf(stderr, "*** more than one device.  Reconnect the JTAG cable to ONLY the legacy\n");
175
        fprintf(stderr, "*** debug unit, or change your SoC to use the Advanced Debug Unit.\n");
176
        exit(0);
177
}
178
#endif
179
 
180
 
181 4 nyawn
  if(target_dev_pos >= num_devices) {
182
    printf("ERROR:  Requested target device (%i) beyond highest device index (%i).\n", target_dev_pos, num_devices-1);
183
    exit(1);
184
  } else {
185 14 nyawn
    printf("Target device %i, JTAG ID = 0x%08x\n", target_dev_pos, idcodes[target_dev_pos]);
186 4 nyawn
  }
187
 
188
  manuf_id = (idcodes[target_dev_pos] >> 1) & 0x7FF;
189
 
190
  // Use BSDL files to determine prefix bits, postfix bits, debug command, IR length
191
  config_set_IR_size(get_IR_size(target_dev_pos));
192
 
193
  // Set the IR prefix / postfix bits
194
  int total = 0;
195
  for(i = 0; i < num_devices; i++) {
196
    if(i == target_dev_pos) {
197
      config_set_IR_postfix_bits(total);
198
      //debug("Postfix bits: %d\n", total);
199
      total = 0;
200
      continue;
201
    }
202
 
203
    total += get_IR_size(i);
204
    debug("Adding %i to total for devidx %i\n", get_IR_size(i), i);
205
  }
206
  config_set_IR_prefix_bits(total);
207
  debug("Prefix bits: %d\n", total);
208
 
209
 
210
  // Note that there's a little translation here, since device index 0 is actually closest to the cable data input
211
  config_set_DR_prefix_bits(num_devices - target_dev_pos - 1);  // number of devices between cable data out and target device
212
  config_set_DR_postfix_bits(target_dev_pos);  // number of devices between target device and cable data in
213
 
214
  // Set the DEBUG command for the IR of the target device.
215
  // If this is a Xilinx device, use USER1 instead of DEBUG
216
  // If we Altera Virtual JTAG mode, we don't care.
217
  if((force_alt_vjtag == -1) || ((force_alt_vjtag == 0) &&  (manuf_id != ALTERA_MANUFACTURER_ID))) {
218
    cmd = get_debug_cmd(target_dev_pos);
219
    if(cmd == TAP_CMD_INVALID) {
220
      printf("Unable to find DEBUG command, aborting.\n");
221
      exit(1);
222
    }
223
    config_set_debug_cmd(cmd);  // This may have to be USER1 if this is a Xilinx device   
224
  }
225
 
226
  // Enable the kludge for Xilinx BSCAN, if necessary.
227
  // Safe, but slower, for non-BSCAN TAPs.
228
  if(manuf_id == XILINX_MANUFACTURER_ID) {
229
    config_set_xilinx_bscan(1);
230
  }
231
 
232
  // Set Altera Virtual JTAG mode on or off.  If not forced, then enable
233
  // if the target device has an Altera manufacturer IDCODE
234
  if(force_alt_vjtag == 1) {
235
    config_set_alt_vjtag(1);
236
  } else if(force_alt_vjtag == -1) {
237
    config_set_alt_vjtag(0);
238
  } else {
239
    if(manuf_id == ALTERA_MANUFACTURER_ID) {
240
      config_set_alt_vjtag(1);
241
    } else {
242
      config_set_alt_vjtag(0);
243
    }
244
  }
245
 
246
  // Do a sanity test
247
  cmd = bsdl_get_idcode_cmd(idcodes[target_dev_pos]);
248
  if(cmd != TAP_CMD_INVALID) {
249
       uint32_t id_read;
250
       err |= jtag_get_idcode(cmd, &id_read);
251
 
252
       if(err != APP_ERR_NONE) {
253
         printf("Error %s checking IDCODE, aborting.\n", get_err_string(err));
254
         exit(1);
255
       }
256
 
257
       if(id_read == idcodes[target_dev_pos]) {
258
         printf("IDCODE sanity test passed, chain OK!\n");
259
       } else {
260 14 nyawn
         printf("Warning: IDCODE sanity test failed.  Read IDCODE 0x%08X, expected 0x%08X\n", id_read, idcodes[target_dev_pos]);
261 4 nyawn
       }
262
     }
263
 
264
  if(err |= tap_enable_debug_module()) {  // Select the debug unit in the TAP.
265
    printf("Error %s enabling debug module, aborting.\n", get_err_string(err));
266
    exit(1);
267
  }
268
}
269
 
270
 
271
void print_usage(char *func)
272
{
273 14 nyawn
  printf("JTAG connection between GDB and the SoC debug interface.\n");
274
#ifdef __LEGACY__
275
  printf("Compiled with support for the Legacy debug unit (debug_if).\n");
276
#else
277
  printf("Compiled with support for the Advanced Debug Interface (adv_dbg_if).\n");
278
#endif
279 42 nyawn
#ifdef ENABLE_JSP
280
  printf("Compiled with support for the JTAG Serial Port (JSP).\n");
281
#else
282
  printf("Support for the JTAG serial port is NOT compiled in.\n");
283
#endif
284
  printf("Copyright (C) 2010 Nathan Yawn, nathan.yawn@opencores.org\n\n");
285 4 nyawn
  printf("Usage: %s (options) [cable] (cable options)\n", func);
286
  printf("Options:\n");
287 42 nyawn
  printf("\t-g [port]     : port number for GDB (default: %s)\n", default_port);
288
#ifdef ENABLE_JSP
289
  printf("\t-j [port]     : port number for JSP Server (default: %s)\n", default_jspport);
290
#endif
291 51 nyawn
  printf("\t-w [port]     : port number for HWP server (default: %s)\n", default_hwpport);
292 4 nyawn
  printf("\t-x [index]    : Position of the target device in the scan chain\n");
293
  printf("\t-a [0 / 1]    : force Altera virtual JTAG mode off (0) or on (1)\n");
294
  printf("\t-l [<index>:<bits>]     : Specify length of IR register for device\n");
295
  printf("\t                <index>, override autodetect (if any)\n");
296
  printf("\t-c [hex cmd]  : Debug command for target TAP, override autodetect\n");
297
  printf("\t                (ignored for Altera targets)\n");
298
  printf("\t-v [hex cmd]  : VIR command for target TAP, override autodetect\n");
299
  printf("\t                (Altera virtual JTAG targets only)\n");
300
  printf("\t-r [hex cmd]  : VDR for target TAP, override autodetect\n");
301
  printf("\t                (Altera virtual JTAG targets only)\n");
302
  printf("\t-b [dirname]  : Add a directory to search for BSDL files\n");
303
  printf("\t-t            : perform CPU / memory self-test before starting server\n");
304
  printf("\t-h            : show help\n\n");
305
  cable_print_help();
306
}
307
 
308
 
309
void parse_args(int argc, char **argv)
310
{
311
  int c;
312
  int i;
313
  int idx, val;
314
  const char *valid_cable_args = NULL;
315
  port = NULL;
316 42 nyawn
#ifdef ENABLE_JSP
317
  jspport = NULL;
318
#endif
319 4 nyawn
  force_alt_vjtag = 0;
320
  cmd_line_cmd_debug = -1;
321
 
322
  /* Parse the global arguments (if-any) */
323 51 nyawn
  while((c = getopt(argc, argv, "+g:j:w:x:a:l:c:v:r:b:th")) != -1) {
324 4 nyawn
    switch(c) {
325
    case 'h':
326
      print_usage(argv[0]);
327
      exit(0);
328
      break;
329
    case 'g':
330
      port = optarg;
331
      break;
332 42 nyawn
#ifdef ENABLE_JSP
333
    case 'j':
334
      jspport = optarg;
335
      break;
336
#endif
337 51 nyawn
    case 'w':
338
      hwpport = optarg;
339
      break;
340 4 nyawn
    case 'x':
341
      target_dev_pos = atoi(optarg);
342
      break;
343
    case 'l':
344
      get_ir_opts(optarg, &idx, &val);        // parse the option
345
      if(num_ir_sets >= (IR_START_SETS<<reallocs)) {
346
        cmd_line_ir_sizes = (irset *) realloc(cmd_line_ir_sizes, (IR_START_SETS<<reallocs)*sizeof(irset));
347
        if(cmd_line_ir_sizes == NULL) {
348
          printf("Error: out of memory while parsing command line.  Aborting.\n");
349
          exit(1);
350
        }
351
      }
352
      cmd_line_ir_sizes[num_ir_sets].dev_index = idx;
353
      cmd_line_ir_sizes[num_ir_sets].ir_length = val;
354
      num_ir_sets++;
355
      break;
356
    case 'c':
357
      cmd_line_cmd_debug = strtoul(optarg, NULL, 16);
358
      break;
359
    case 'v':
360
      config_set_vjtag_cmd_vir(strtoul(optarg, NULL, 16));
361
      break;
362
    case 'r':
363
      config_set_vjtag_cmd_vdr(strtoul(optarg, NULL, 16));
364
      break;
365
    case 't':
366
      do_selftest = 1;
367
      break;
368
     case 'a':
369
       if(atoi(optarg) == 1)
370
        force_alt_vjtag = 1;
371
       else
372
        force_alt_vjtag = -1;
373
       break;
374
    case 'b':
375
       bsdl_add_directory(optarg);
376
      break;
377
    default:
378
      print_usage(argv[0]);
379
      exit(1);
380
    }
381
  }
382
 
383
  if(port == NULL)
384
    port = default_port;
385
 
386 42 nyawn
#ifdef ENABLE_JSP
387
  if(jspport == NULL)
388
    jspport = default_jspport;
389
#endif
390
 
391 51 nyawn
  if(hwpport == NULL)
392
    hwpport = default_hwpport;
393
 
394 4 nyawn
  int found_cable = 0;
395
  char* start_str = argv[optind];
396
  int start_idx = optind;
397
  for(i = optind; i < argc; i++) {
398
    if(cable_select(argv[i]) == APP_ERR_NONE) {
399
      found_cable = 1;
400
      cable_name = argv[i];
401
      argv[optind] = argv[start_idx];  // swap the cable name with the other arg,
402
      argv[start_idx] = start_str;     // keep all cable opts at the end
403
      break;
404
    }
405
  }
406
 
407
 
408
  if(!found_cable) {
409 51 nyawn
    fprintf(stderr, "Error: No valid cable specified.\n");
410
    print_usage(argv[0]);
411 4 nyawn
    exit(1);
412
  }
413
 
414
  optind = start_idx+1;  // reset the parse index
415
 
416
    /* Get the cable-arguments */
417
  valid_cable_args = cable_get_args();
418
 
419
  /* Parse the remaining options for the cable.
420
   * Note that this will include unrecognized option from before the cable name.
421
   */
422
  while((c = getopt(argc, argv, valid_cable_args)) != -1) {
423
    //printf("Got cable opt %c (0x%X)\n", (char)c, c);
424
    if(c == '?') {
425
      printf("\nERROR:  Unknown cable option \'-%c\'\n\n", optopt);
426
      print_usage(argv[0]);
427
      exit(1);
428
    }
429
    else if(cable_parse_opt(c, optarg) != APP_ERR_NONE) {
430
      printf("\nERROR:  Failed to parse cable option \'-%c\' %s\n\n", (char)c, optarg);
431
      print_usage(argv[0]);
432
      exit(1);
433
    }
434
  }
435
}
436
 
437
 
438
 
439
int main(int argc,  char *argv[]) {
440
  char *s;
441
  long int serverPort;
442
 
443
  srand(getpid());
444
  bsdl_init();
445
  cmd_line_ir_sizes = (irset *) malloc(IR_START_SETS * sizeof(irset));
446
  if(cmd_line_ir_sizes == NULL) {
447
    printf("ERROR: out of memory allocating array for IR sizes.\n");
448
    return 1;
449
  }
450
 
451
  parse_args(argc, argv);
452
 
453
  if(cable_init() != APP_ERR_NONE) {
454
    printf("Failed to initialize cable \'%s\', aborting.\n", cable_name);
455
    exit(1);
456
  }
457
 
458
 
459
  /* Initialize a new connection to the or1k board, and make sure we are
460
     really connected.  */
461
  configure_chain();
462
 
463
  if(do_selftest) {
464
    // Test the connection.
465
    printf("*** Doing self-test ***\n");
466
    if(dbg_test() != APP_ERR_NONE) {
467
      printf("Self-test FAILED *** Bailing out!\n");
468
      exit(1);
469
    }
470
    printf("*** Self-test PASSED ***\n");
471
  }
472
 
473
  /* We have a connection.  Establish server.  */
474
  serverPort = strtol(port,&s,10);
475 42 nyawn
  if(*s) {
476
    printf("Failed to get RSP server port \'%s\', using default \'%s\'.\n", port, default_port);
477
    serverPort = strtol(default_port,&s,10);
478
    if(*s) {
479
      printf("Failed to get RSP default port, exiting.\n");
480
      return -1;
481
    }
482
  }
483 4 nyawn
 
484 42 nyawn
  // Start the thread which handle CPU stall/unstall
485
  start_monitor_thread();
486
 
487 4 nyawn
  rsp_init(serverPort);
488
 
489 42 nyawn
#ifdef ENABLE_JSP
490
  long int jspserverport;
491
  jspserverport = strtol(jspport,&s,10);
492
  if(*s) {
493
    printf("Failed to get JSP server port \'%s\', using default \'%s\'.\n", jspport, default_jspport);
494
    serverPort = strtol(default_jspport,&s,10);
495
    if(*s) {
496
      printf("Failed to get default JSP port, exiting.\n");
497
      return -1;
498
    }
499
  }
500
 
501
  jsp_init(jspserverport);
502
  jsp_server_start();
503
#endif
504
 
505 51 nyawn
  long int hwpserverport;
506
  hwpserverport = strtol(hwpport,&s,10);
507
  if(*s) {
508
    printf("Failed to get HWP server port \'%s\', using default \'%s\'.\n", jspport, default_jspport);
509
    serverPort = strtol(default_hwpport,&s,10);
510
    if(*s) {
511
      printf("Failed to get default HWP port, exiting.\n");
512
      return -1;
513
    }
514
  }
515
 
516
  hwp_init(hwpserverport);
517
  hwp_server_start();
518
 
519 4 nyawn
  printf("JTAG bridge ready!\n");
520
 
521
  // This handles requests from GDB.  I'd prefer the while() loop to be in the function
522
  // with the select()/poll(), but the or1ksim rsp code (ported for use here) doesn't work 
523
  // that way, and I don't want to rework that code (to make it easier to import fixes
524
  // written for the or1ksim rsp server).  --NAY
525
  while(handle_rsp());
526
 
527
  return 0;
528
}
529
 
530
//////////////////////////////////////////////////
531
// Helper functions
532
 
533
int get_IR_size(int devidx)
534
{
535
  int retval = -1;
536
  int i;
537
 
538
  if(idcodes[devidx] != IDCODE_INVALID) {
539
    retval = bsdl_get_IR_size(idcodes[devidx]);
540
  }
541
 
542
  // Search for this devices in the array of command line IR sizes
543
  for(i = 0; i < num_ir_sets; i++) {
544
    if(cmd_line_ir_sizes[i].dev_index == devidx) {
545
      if((retval > 0) && (retval != cmd_line_ir_sizes[i].ir_length))
546
        printf("Warning: overriding autoprobed IR length (%i) with command line value (%i) for device %i\n", retval,
547
                            cmd_line_ir_sizes[i].ir_length, devidx);
548
      retval = cmd_line_ir_sizes[i].ir_length;
549
    }
550
  }
551
 
552
  if(retval < 0) {  // Make sure we have a value
553
    printf("ERROR! Unable to autoprobe IR length for device index %i;  Must set IR size on command line. Aborting.\n", devidx);
554
    exit(1);
555
  }
556
 
557
  return retval;
558
}
559
 
560
 
561
uint32_t get_debug_cmd(int devidx)
562
{
563
  int retval = TAP_CMD_INVALID;
564
  uint32_t manuf_id = (idcodes[devidx] >> 1) & 0x7FF;
565
 
566
  if(idcodes[devidx] != IDCODE_INVALID) {
567
    if(manuf_id == XILINX_MANUFACTURER_ID) {
568
      retval = bsdl_get_user1_cmd(idcodes[devidx]);
569
      if(cmd_line_cmd_debug < 0) printf("Xilinx IDCODE, assuming internal BSCAN mode\n\t(using USER1 instead of DEBUG TAP command)\n");
570
    } else {
571
      retval = bsdl_get_debug_cmd(idcodes[devidx]);
572
    }
573
  }
574
 
575
  if(cmd_line_cmd_debug >= 0) {
576
    if(retval != TAP_CMD_INVALID) {
577
      printf("Warning: overriding autoprobe debug command (0x%X) with command line value (0x%X)\n", retval, cmd_line_cmd_debug);
578
    } else {
579
      printf("Using command-line debug command 0x%X\n", cmd_line_cmd_debug);
580
    }
581
    retval = cmd_line_cmd_debug;
582
  }
583
 
584
  if(retval == TAP_CMD_INVALID) {
585 14 nyawn
    printf("ERROR!  Unable to find DEBUG command for device index %i, device ID 0x%0X\n", devidx, idcodes[devidx]);
586 4 nyawn
  }
587
 
588
  return retval;
589
}
590
 
591
 
592
// Extracts two values from an option string
593
// of the form "<index>:<value>", where both args
594
// are in base 10
595
void get_ir_opts(char *optstr, int *idx, int *val)
596
{
597
  char *ptr;
598
 
599
  ptr = strstr(optstr, ":");
600
  if(ptr == NULL) {
601
    printf("Error: badly formatted IR length option.  Use format \'<index>:<value>\', without spaces, where both args are in base 10\n");
602
    exit(1);
603
  }
604
 
605
  *ptr = '\0';
606
  ptr++;  // This now points to the second (value) arg string
607
 
608
  *idx = strtoul(optstr, NULL, 10);
609
  *val = strtoul(ptr, NULL, 10);
610
  // ***CHECK FOR SUCCESS
611
}
612
 

powered by: WebSVN 2.1.0

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