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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 nyawn
/* bsdl.c - BSDL file handler for the advanced JTAG bridge
2 32 nyawn
   Copyright(C) 2008 - 2010 Nathan Yawn
3 4 nyawn
 
4
   This program is free software; you can redistribute it and/or modify
5
   it under the terms of the GNU General Public License as published by
6
   the Free Software Foundation; either version 2 of the License, or
7
   (at your option) any later version.
8
 
9
   This program is distributed in the hope that it will be useful,
10
   but WITHOUT ANY WARRANTY; without even the implied warranty of
11
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
   GNU General Public License for more details.
13
 
14
   You should have received a copy of the GNU General Public License
15
   along with this program; if not, write to the Free Software
16
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
*/
18
 
19
#include <sys/types.h>
20
#include <string.h>
21
#include <stdio.h>
22
#include <dirent.h>
23 32 nyawn
#include <stdlib.h>
24
#include <errno.h>
25 4 nyawn
#include "bsdl.h"
26
#include "bsdl_parse.h"
27
 
28
 
29
#define debug(...) //fprintf(stderr, __VA_ARGS__ ) 
30
 
31
// Globals to deal with directory names
32
#define MAX_BSDL_DIRS 64  // Any more than this would take a looooong time...
33
static char *bsdl_dirs[MAX_BSDL_DIRS];
34
static int bsdl_current_dir = 0;  // We try them in reverse order
35
 
36
// Globals to hold the current, open directory
37
DIR *bsdl_open_dir = NULL;
38
 
39
// Globals to hold BSDL info
40
static bsdlinfo *bsdl_head = NULL;
41
static bsdlinfo *bsdl_tail = NULL;
42
static bsdlinfo *bsdl_last = NULL;  // optimization: pointer to the last struct we used (not necessarily the last in the linked list)
43
 
44 32 nyawn
// Scratchpad for full pathname
45
int bsdl_scratchpad_size = 0;
46
char *bsdl_scratchpad = NULL;
47
 
48 4 nyawn
// Prototypes for local functions
49
bsdlinfo *get_bsdl_info(uint32_t idcode);
50
 
51
 
52
 
53
//////////////////////////////////////////////////////////////////////
54
// API for init and config
55
 
56
void bsdl_init(void)
57
{
58
  bsdl_dirs[0] = strdup("/opt/bsdl");
59
  bsdl_dirs[1] = strdup("/usr/share/bsdl");
60
  bsdl_dirs[2] = strdup("~/.bsdl");
61
  bsdl_dirs[3] = strdup(".");
62
  bsdl_current_dir = 3;
63 32 nyawn
  bsdl_scratchpad = (char *) malloc(64);
64
  bsdl_scratchpad_size = 64;
65 4 nyawn
}
66
 
67
void bsdl_add_directory(const char *dirname)
68
{
69
  if(bsdl_current_dir >= (MAX_BSDL_DIRS-1)) {
70
    printf("Max BSDL dirs (%d) exceeded; failed to add directory %s\n", MAX_BSDL_DIRS, dirname);
71
    return;
72
  }
73
 
74
  bsdl_current_dir++;
75
  bsdl_dirs[bsdl_current_dir] = strdup(dirname);
76
}
77
 
78
 
79
///////////////////////////////////////////////////////////////////
80
// API  to get device info from BSDL files, if available
81
 
82
 
83
const char * bsdl_get_name(uint32_t idcode)
84
{
85
  bsdlinfo *info;
86
  info = get_bsdl_info(idcode);
87
  if(info != NULL)
88
    return info->name;
89
 
90
  return NULL;
91
 
92
 
93
}
94
 
95
// Return the IR length of the device with the given IDCODE,
96
// if its BSDL file is available.  Returns -1 on
97
// error, which is an invalid size.
98
 
99
int bsdl_get_IR_size(uint32_t idcode)
100
{
101
  bsdlinfo *info;
102
  info = get_bsdl_info(idcode);
103
  if(info != NULL)
104
    return info->IR_size;
105
 
106
  return -1;
107
}
108
 
109
 
110
// Returns the DEBUG command for the device with the gived IDCODE,
111
// if its BSDL file is available.  Returns 0xFFFFFFFF on error,
112
// which is as invalid command (because it's the BYPASS command)
113
uint32_t bsdl_get_debug_cmd(uint32_t idcode)
114
{
115
  bsdlinfo *info;
116
  info = get_bsdl_info(idcode);
117
  if(info != NULL)
118
    return info->cmd_debug;
119
  return TAP_CMD_INVALID;
120
}
121
 
122
// Returns the USER1 command for the device with the gived IDCODE,
123
// if its BSDL file is available.  Returns 0xFFFFFFFF on error,
124
// which is as invalid command (because it's the BYPASS command)
125
uint32_t bsdl_get_user1_cmd(uint32_t idcode)
126
{
127
  bsdlinfo *info;
128
  info = get_bsdl_info(idcode);
129
  if(info != NULL)
130
    return info->cmd_user1;
131
  return TAP_CMD_INVALID;
132
}
133
 
134
// Returns the IDCODE command for the device with the gived IDCODE,
135
// if its BSDL file is available.  Returns 0xFFFFFFFF on error,
136
// which is as invalid command (because it's the BYPASS command)
137
uint32_t bsdl_get_idcode_cmd(uint32_t idcode)
138
{
139
  bsdlinfo *info;
140
  info = get_bsdl_info(idcode);
141
  if(info != NULL)
142
    return info->cmd_idcode;
143
  return TAP_CMD_INVALID;
144
}
145
 
146
/////////////////////////////////////////////////////////////////////////////
147
// Internal routines
148
 
149
 
150
// This uses a lazy algorithm...first, search data we already have.
151
// Then, parse new files (storing all data) only until we find
152
// the data we want.
153
bsdlinfo *get_bsdl_info(uint32_t idcode)
154
{
155
  struct dirent *direntry = NULL;
156
  bsdlinfo *ptr = bsdl_head;
157
  char *c;
158
 
159
  // Check the last place we looked
160
  if(bsdl_last != NULL)
161
      if((bsdl_last->idcode & bsdl_last->idcode_mask) == (idcode & bsdl_last->idcode_mask))
162
        return bsdl_last;
163
 
164
  // First, search through the info already parsed
165
  while(ptr != NULL)
166
    {
167
      if((ptr->idcode & ptr->idcode_mask) == (idcode & ptr->idcode_mask))
168
        {
169
          bsdl_last = ptr;
170
          return ptr;
171
        }
172
      ptr = ptr->next;
173
    }
174
 
175
  // Parse files until we get the IDCODE we want
176
  while(1)
177
    {
178
      // Find and open a valid directory 
179
      while(bsdl_open_dir == NULL)
180
        {
181
          if(bsdl_current_dir < 0)
182
            return NULL;  // There are no more directories to check
183
          debug("Trying BSDL dir \'%s\'\n", bsdl_dirs[bsdl_current_dir]);
184
          bsdl_open_dir = opendir(bsdl_dirs[bsdl_current_dir]);
185
          if((bsdl_open_dir == NULL) && (bsdl_current_dir > 2))  // Don't warn if default dirs not found
186 32 nyawn
            printf("Warning: unable to open BSDL directory \'%s\': %s\n", bsdl_dirs[bsdl_current_dir], strerror(errno));
187 4 nyawn
          bsdl_current_dir--;
188
          direntry = NULL;
189
        }
190
 
191
      // Find a BSDL file
192
      do
193
        {
194
          direntry = readdir(bsdl_open_dir);
195
          if(direntry == NULL)
196
            {  // We've exhausted this directory
197 32 nyawn
              debug("Next bsdl directory\n");
198 4 nyawn
              closedir(bsdl_open_dir);
199
              bsdl_open_dir = NULL;
200
              break;
201
            }
202
 
203
          // *** If a subdirectory, continue!!
204
 
205
          // Check if it's a BSDL file: .bsd, .bsdl, .BSD, .BSDL
206
          debug("Checking file \'%s\'\n", direntry->d_name);
207
          c = strrchr(direntry->d_name, '.');
208
          debug("File extension is \'%s\'\n", c);
209
          if(c == NULL)
210
            continue;
211
          if(!strcmp(c, ".bsd") || !strcmp(c, ".bsdl") || !strcmp(c, ".BSD") || !strcmp(c, ".BSDL"))
212
            break;
213
 
214
        }
215
      while(1);
216
 
217
      if(direntry == NULL)  // We need a new directory
218
        continue;
219
 
220 57 nyawn
      // Make sure we can hold the full path (+2 for a '/' and the trailing NULL)
221
      if((strlen(direntry->d_name) + strlen(bsdl_dirs[bsdl_current_dir+1])+2) >= bsdl_scratchpad_size)
222 32 nyawn
        {
223
          char *tmp = (char *) realloc(bsdl_scratchpad, (bsdl_scratchpad_size*2));
224
          if(tmp != NULL)
225
            {
226
              debug("Extending bsdl scratchpad to size %i", bsdl_scratchpad_size);
227
              bsdl_scratchpad_size *= 2;
228
              bsdl_scratchpad = tmp;
229
            }
230
          else
231
            {
232
              fprintf(stderr, "Warning: failed to reallocate BSDL scratchpad to size %i", bsdl_scratchpad_size*2);
233
              continue;
234
            }
235
        }
236
 
237
      strcpy(bsdl_scratchpad, bsdl_dirs[bsdl_current_dir+1]);
238
      strcat(bsdl_scratchpad, "/");
239
      strcat(bsdl_scratchpad, direntry->d_name);
240
 
241 4 nyawn
      // Parse the BSDL file we found
242 32 nyawn
      debug("Parsing file \'%s\'\n", bsdl_scratchpad);
243
      ptr = parse_extract_values(bsdl_scratchpad);
244 4 nyawn
 
245
      // If we got good data...
246
      if(ptr != NULL)
247
        {
248
          // Store the values...
249
          if(bsdl_head == NULL) {
250
            bsdl_head = ptr;
251
            bsdl_tail = ptr;
252
          } else {
253
            bsdl_tail->next = ptr;
254
            bsdl_tail = ptr;
255
          }
256
 
257
          // ...and return if we got an IDCODE match
258
          if((ptr->idcode & ptr->idcode_mask) == (idcode & ptr->idcode_mask)) {
259
            bsdl_last = ptr;
260
            return ptr;
261
          }
262
        }
263
    } // while(1), parse files until we find a match or run out of dirs / files
264
 
265
 
266
  // If no more files to parse and not found, return NULL
267
  return NULL;
268
}

powered by: WebSVN 2.1.0

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