You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

392 lines
7.9 KiB
C

/*
* $Id$
*
* Copyright (C) 2002 ETC s.r.o.
*
* 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., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by Marcel Telka <marcel@telka.sk>, 2002.
*
*/
#include "sysdep.h"
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <cmd.h>
#include <bsdl.h>
#include "register.h"
#include "tap.h"
#include "cable.h"
#include "part.h"
#include "chain.h"
#include "jtag.h"
struct id_record {
char name[20];
char fullname[100];
};
static int
find_record( char *filename, tap_register *key, struct id_record *idr )
{
FILE *file;
tap_register *tr;
int r = 0;
file = fopen( filename, "r" );
if (!file) {
printf( _("Cannot open %s\n"), filename );
return 0;
}
tr = register_alloc( key->len );
for (;;) {
char *p;
char *s;
char line[1024];
if (fgets( line, 1024, file ) == NULL)
break;
/* remove comment and nl from the line */
p = strpbrk( line, "#\n" );
if (p)
*p = '\0';
p = line;
/* skip whitespace */
while (*p && isspace(*p))
p++;
/* remove ending whitespace */
s = strchr( p, '\0' );
while (s != p) {
if (!isspace(*--s))
break;
*s = '\0';
}
/* line is empty? */
if (!*p)
continue;
/* find end of field */
s = p;
while (*s && !isspace(*s))
s++;
if (*s)
*s++ = '\0';
/* test field length */
if (strlen( p ) != key->len)
continue;
/* match */
register_init( tr, p );
if (register_compare( tr, key ))
continue;
/* next field */
p = s;
/* skip whitespace */
while (*p && isspace(*p))
p++;
/* line is empty? */
if (!*p)
continue;
/* find end of field */
s = p;
while (*s && !isspace(*s))
s++;
if (*s)
*s++ = '\0';
/* test field length */
if (strlen( p ) >= sizeof idr->name)
continue;
/* copy name */
strcpy( idr->name, p );
/* next field */
p = s;
/* skip whitespace */
while (*p && isspace(*p))
p++;
/* line is empty? */
if (!*p)
continue;
/* test field length */
if (strlen( p ) >= sizeof idr->fullname)
continue;
/* copy fullname */
strcpy( idr->fullname, p );
r = 1;
break;
}
fclose( file );
register_free( tr );
return r;
}
uint64_t bits_to_uint64(tap_register *t)
{
int i;
uint64_t l,b;
l = 0; b=1;
for(i=0;i < t->len ;i++) {
if(t->data[i] & 1)l |= b;
b <<= 1;
}
return l;
}
int
detect_parts( chain_t *chain, char *db_path )
{
int irlen;
tap_register *ir;
int chlen;
tap_register *one;
tap_register *ones;
tap_register *br;
tap_register *id;
parts_t *ps;
int i;
char data_path[1024];
char *cmd[3] = {"script", data_path, NULL};
char manufacturer[MAXLEN_MANUFACTURER + 1];
char partname[MAXLEN_PART + 1];
char stepping[MAXLEN_STEPPING + 1];
/* Detect IR length */
tap_reset( chain );
tap_capture_ir( chain );
irlen = detect_register_size( chain );
if (irlen < 1)
return 0;
printf( _("IR length: %d\n"), irlen );
/* Allocate IR */
ir = register_fill( register_alloc( irlen ), 1 );
if (ir == NULL) {
printf( _("out of memory\n") );
return 0;
}
tap_shift_register( chain, ir, NULL, 1 );
register_free( ir );
/* Detect chain length */
tap_capture_dr( chain );
chlen = detect_register_size( chain );
if (chlen < 1) {
printf( _("Unable to detect JTAG chain length\n") );
return 0;
}
printf( _("Chain length: %d\n"), chlen );
/* Allocate registers and parts */
one = register_fill( register_alloc( 1 ), 1 );
ones = register_fill( register_alloc( 31 ), 1 );
br = register_alloc( 1 );
id = register_alloc( 32 );
ps = parts_alloc();
if (!one || !ones || !br || !id || !ps) {
printf( _("out of memory\n") );
register_free( one );
register_free( ones );
register_free( br );
register_free( id );
parts_free( ps );
return 0;
}
chain->parts = ps;
chain->active_part = 0;
/* Detect parts */
tap_reset( chain );
tap_capture_dr( chain );
for (i = 0; i < chlen; i++) {
part_t *part;
tap_register *did = br; /* detected id (length is 1 or 32) */
tap_register *key;
struct id_record idr;
char *p;
tap_shift_register( chain, one, br, 0 );
if (register_compare( one, br ) == 0) {
/* part with id */
tap_shift_register( chain, ones, id, 0 );
register_shift_left( id, 1 );
id->data[0] = 1;
did = id;
}
printf( _("Device Id: %s (0x%016lX)\n"), register_get_string( did ), bits_to_uint64(did) );
part = part_alloc( did );
if (part == NULL) {
printf( _("Out of memory\n") );
break;
}
parts_add_part( ps, part );
if (did == br)
continue;
chain->active_part = ps->len - 1;
#ifdef ENABLE_BSDL
if (bsdl_scan_files(register_get_string( did ), 1) <= 0) {
#endif
/* find JTAG declarations for a part with id */
strcpy( data_path, db_path ); /* FIXME: Buffer overrun */
/* manufacturers */
strcat( data_path, "/MANUFACTURERS" );
key = register_alloc( 11 );
memcpy( key->data, &id->data[1], key->len );
if (!find_record( data_path, key, &idr )) {
printf( _(" Unknown manufacturer!\n") );
register_free( key );
continue;
}
register_free( key );
printf( _(" Manufacturer: %s\n"), idr.fullname );
if (strlen( idr.fullname ) > MAXLEN_MANUFACTURER)
printf( _("Warning: Manufacturer too long\n") );
strncpy( manufacturer, idr.fullname, MAXLEN_MANUFACTURER );
manufacturer[MAXLEN_MANUFACTURER] = '\0';
/* parts */
p = strrchr( data_path, '/' );
if (p)
p[1] = '\0';
else
data_path[0] = '\0';
strcat( data_path, idr.name );
strcat( data_path, "/PARTS" );
key = register_alloc( 16 );
memcpy( key->data, &id->data[12], key->len );
if (!find_record( data_path, key, &idr )) {
printf( _(" Unknown part!\n") );
register_free( key );
continue;
}
register_free( key );
printf( _(" Part(%d): %s\n"), chain->active_part, idr.fullname );
if (strlen( idr.fullname ) > MAXLEN_PART)
printf( _("Warning: Part too long\n") );
strncpy( partname, idr.fullname, MAXLEN_PART );
partname[MAXLEN_PART] = '\0';
/* steppings */
p = strrchr( data_path, '/' );
if (p)
p[1] = '\0';
else
data_path[0] = '\0';
strcat( data_path, idr.name );
strcat( data_path, "/STEPPINGS" );
key = register_alloc( 4 );
memcpy( key->data, &id->data[28], key->len );
if (!find_record( data_path, key, &idr )) {
printf( _(" Unknown stepping!\n") );
register_free( key );
continue;
}
register_free( key );
printf( _(" Stepping: %s\n"), idr.fullname );
if (strlen( idr.fullname ) > MAXLEN_STEPPING)
printf( _("Warning: Stepping too long\n") );
strncpy( stepping, idr.fullname, MAXLEN_STEPPING );
stepping[MAXLEN_STEPPING] = '\0';
/* part definition file */
p = strrchr( data_path, '/' );
if (p)
p[1] = '\0';
else
data_path[0] = '\0';
strcat( data_path, idr.name );
printf( _(" Filename: %s\n"), data_path );
/* run JTAG declarations */
strcpy( part->manufacturer, manufacturer );
strcpy( part->part, partname );
strcpy( part->stepping, stepping );
cmd_run( cmd );
#ifdef ENABLE_BSDL
}
#endif
if (part->active_instruction == NULL)
part->active_instruction = part_find_instruction( part, "IDCODE" );
}
for (i = 0; i < 32; i++) {
tap_shift_register( chain, one, br, 0 );
if (register_compare( one, br ) != 0) {
printf( _("Error: Unable to detect JTAG chain end!\n") );
break;
}
}
tap_shift_register( chain, one, NULL, 1 );
register_free( one );
register_free( ones );
register_free( br );
register_free( id );
return ps->len;
}