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] - Diff between revs 4 and 8

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 4 Rev 8
Line 1... Line 1...
 
/* bsdl.c - BSDL file handler for the advanced JTAG bridge
 
   Copyright(C) 2008 Nathan Yawn
 
 
 
   This program is free software; you can redistribute it and/or modify
 
   it under the terms of the GNU General Public License as published by
 
   the Free Software Foundation; either version 2 of the License, or
 
   (at your option) any later version.
 
 
 
   This program is distributed in the hope that it will be useful,
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
   GNU General Public License for more details.
 
 
 
   You should have received a copy of the GNU General Public License
 
   along with this program; if not, write to the Free Software
 
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
*/
 
 
 
#include <sys/types.h>
 
#include <string.h>
 
#include <stdio.h>
 
#include <dirent.h>
 
#include "bsdl.h"
 
#include "bsdl_parse.h"
 
 
 
 
 
#define debug(...) //fprintf(stderr, __VA_ARGS__ ) 
 
 
 
// Globals to deal with directory names
 
#define MAX_BSDL_DIRS 64  // Any more than this would take a looooong time...
 
static char *bsdl_dirs[MAX_BSDL_DIRS];
 
static int bsdl_current_dir = 0;  // We try them in reverse order
 
 
 
// Globals to hold the current, open directory
 
DIR *bsdl_open_dir = NULL;
 
 
 
// Globals to hold BSDL info
 
static bsdlinfo *bsdl_head = NULL;
 
static bsdlinfo *bsdl_tail = NULL;
 
static bsdlinfo *bsdl_last = NULL;  // optimization: pointer to the last struct we used (not necessarily the last in the linked list)
 
 
 
// Prototypes for local functions
 
bsdlinfo *get_bsdl_info(uint32_t idcode);
 
 
 
 
 
 
 
//////////////////////////////////////////////////////////////////////
 
// API for init and config
 
 
 
void bsdl_init(void)
 
{
 
  bsdl_dirs[0] = strdup("/opt/bsdl");
 
  bsdl_dirs[1] = strdup("/usr/share/bsdl");
 
  bsdl_dirs[2] = strdup("~/.bsdl");
 
  bsdl_dirs[3] = strdup(".");
 
  bsdl_current_dir = 3;
 
}
 
 
 
void bsdl_add_directory(const char *dirname)
 
{
 
  if(bsdl_current_dir >= (MAX_BSDL_DIRS-1)) {
 
    printf("Max BSDL dirs (%d) exceeded; failed to add directory %s\n", MAX_BSDL_DIRS, dirname);
 
    return;
 
  }
 
 
 
  bsdl_current_dir++;
 
  bsdl_dirs[bsdl_current_dir] = strdup(dirname);
 
}
 
 
 
 
 
///////////////////////////////////////////////////////////////////
 
// API  to get device info from BSDL files, if available
 
 
 
 
 
const char * bsdl_get_name(uint32_t idcode)
 
{
 
  bsdlinfo *info;
 
  info = get_bsdl_info(idcode);
 
  if(info != NULL)
 
    return info->name;
 
 
 
  return NULL;
 
 
 
 
 
}
 
 
 
// Return the IR length of the device with the given IDCODE,
 
// if its BSDL file is available.  Returns -1 on
 
// error, which is an invalid size.
 
 
 
int bsdl_get_IR_size(uint32_t idcode)
 
{
 
  bsdlinfo *info;
 
  info = get_bsdl_info(idcode);
 
  if(info != NULL)
 
    return info->IR_size;
 
 
 
  return -1;
 
}
 
 
 
 
 
// Returns the DEBUG command for the device with the gived IDCODE,
 
// if its BSDL file is available.  Returns 0xFFFFFFFF on error,
 
// which is as invalid command (because it's the BYPASS command)
 
uint32_t bsdl_get_debug_cmd(uint32_t idcode)
 
{
 
  bsdlinfo *info;
 
  info = get_bsdl_info(idcode);
 
  if(info != NULL)
 
    return info->cmd_debug;
 
  return TAP_CMD_INVALID;
 
}
 
 
 
// Returns the USER1 command for the device with the gived IDCODE,
 
// if its BSDL file is available.  Returns 0xFFFFFFFF on error,
 
// which is as invalid command (because it's the BYPASS command)
 
uint32_t bsdl_get_user1_cmd(uint32_t idcode)
 
{
 
  bsdlinfo *info;
 
  info = get_bsdl_info(idcode);
 
  if(info != NULL)
 
    return info->cmd_user1;
 
  return TAP_CMD_INVALID;
 
}
 
 
 
// Returns the IDCODE command for the device with the gived IDCODE,
 
// if its BSDL file is available.  Returns 0xFFFFFFFF on error,
 
// which is as invalid command (because it's the BYPASS command)
 
uint32_t bsdl_get_idcode_cmd(uint32_t idcode)
 
{
 
  bsdlinfo *info;
 
  info = get_bsdl_info(idcode);
 
  if(info != NULL)
 
    return info->cmd_idcode;
 
  return TAP_CMD_INVALID;
 
}
 
 
 
/////////////////////////////////////////////////////////////////////////////
 
// Internal routines
 
 
 
 
 
// This uses a lazy algorithm...first, search data we already have.
 
// Then, parse new files (storing all data) only until we find
 
// the data we want.
 
bsdlinfo *get_bsdl_info(uint32_t idcode)
 
{
 
  struct dirent *direntry = NULL;
 
  bsdlinfo *ptr = bsdl_head;
 
  char *c;
 
 
 
  // Check the last place we looked
 
  if(bsdl_last != NULL)
 
      if((bsdl_last->idcode & bsdl_last->idcode_mask) == (idcode & bsdl_last->idcode_mask))
 
        return bsdl_last;
 
 
 
  // First, search through the info already parsed
 
  while(ptr != NULL)
 
    {
 
      if((ptr->idcode & ptr->idcode_mask) == (idcode & ptr->idcode_mask))
 
        {
 
          bsdl_last = ptr;
 
          return ptr;
 
        }
 
      ptr = ptr->next;
 
    }
 
 
 
  // Parse files until we get the IDCODE we want
 
  while(1)
 
    {
 
      // Find and open a valid directory 
 
      while(bsdl_open_dir == NULL)
 
        {
 
          if(bsdl_current_dir < 0)
 
            return NULL;  // There are no more directories to check
 
          debug("Trying BSDL dir \'%s\'\n", bsdl_dirs[bsdl_current_dir]);
 
          bsdl_open_dir = opendir(bsdl_dirs[bsdl_current_dir]);
 
          if((bsdl_open_dir == NULL) && (bsdl_current_dir > 2))  // Don't warn if default dirs not found
 
            printf("Warning: unable to open BSDL directory \'%s\'\n", bsdl_dirs[bsdl_current_dir]);
 
          bsdl_current_dir--;
 
          direntry = NULL;
 
        }
 
 
 
      // Find a BSDL file
 
      do
 
        {
 
          direntry = readdir(bsdl_open_dir);
 
          if(direntry == NULL)
 
            {  // We've exhausted this directory
 
              closedir(bsdl_open_dir);
 
              bsdl_open_dir = NULL;
 
              break;
 
            }
 
 
 
          // *** If a subdirectory, continue!!
 
 
 
          // Check if it's a BSDL file: .bsd, .bsdl, .BSD, .BSDL
 
          debug("Checking file \'%s\'\n", direntry->d_name);
 
          c = strrchr(direntry->d_name, '.');
 
          debug("File extension is \'%s\'\n", c);
 
          if(c == NULL)
 
            continue;
 
          if(!strcmp(c, ".bsd") || !strcmp(c, ".bsdl") || !strcmp(c, ".BSD") || !strcmp(c, ".BSDL"))
 
            break;
 
 
 
        }
 
      while(1);
 
 
 
      if(direntry == NULL)  // We need a new directory
 
        continue;
 
 
 
      // Parse the BSDL file we found
 
      debug("Parsing file \'%s\'\n", direntry->d_name);
 
      ptr = parse_extract_values(direntry->d_name);
 
 
 
      // If we got good data...
 
      if(ptr != NULL)
 
        {
 
          // Store the values...
 
          if(bsdl_head == NULL) {
 
            bsdl_head = ptr;
 
            bsdl_tail = ptr;
 
          } else {
 
            bsdl_tail->next = ptr;
 
            bsdl_tail = ptr;
 
          }
 
 
 
          // ...and return if we got an IDCODE match
 
          if((ptr->idcode & ptr->idcode_mask) == (idcode & ptr->idcode_mask)) {
 
            bsdl_last = ptr;
 
            return ptr;
 
          }
 
        }
 
    } // while(1), parse files until we find a match or run out of dirs / files
 
 
 
 
 
  // If no more files to parse and not found, return NULL
 
  return NULL;
 
}
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

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