jtag

commandline jtag stuff
git clone http://frotz.net/git/jtag.git
Log | Files | Refs | README

jtag-virtual.c (3530B)


      1 /* Copyright 2012 Brian Swetland <swetland@frotz.net>
      2  *
      3  * Licensed under the Apache License, Version 2.0 (the "License");
      4  * you may not use this file except in compliance with the License.
      5  * You may obtain a copy of the License at
      6  *
      7  *     http://www.apache.org/licenses/LICENSE-2.0
      8  *
      9  * Unless required by applicable law or agreed to in writing, software
     10  * distributed under the License is distributed on an "AS IS" BASIS,
     11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12  * See the License for the specific language governing permissions and
     13  * limitations under the License.
     14  */
     15 
     16 #include <stdio.h>
     17 #include <stdlib.h>
     18 
     19 #include "jtag.h"
     20 
     21 int jtag_dr_8x4(unsigned *out) {
     22 	unsigned bits = 0;
     23 	unsigned tmp;
     24 	int n, r;
     25 
     26 	for (n = 0; n < 8; n++) {
     27 		if ((r = jtag_dr(4, 0, &tmp)) < 0) return r;
     28 		bits |= (tmp <<= (n * 4));
     29 	}
     30 	*out = bits;
     31 	return 0;
     32 }
     33 
     34 /* number of bits needed given a max value 1-255 */
     35 unsigned needbits(unsigned max) {
     36 	if (max > 127) return 8;
     37 	if (max > 63) return 7;
     38 	if (max > 31) return 6;
     39 	if (max > 15) return 5;
     40 	if (max > 7) return 4;
     41 	if (max > 3) return 3;
     42 	if (max > 1) return 2;
     43 	return 1;
     44 }
     45 
     46 static unsigned ir_width = 10;
     47 
     48 static unsigned hub_version = 0;
     49 static unsigned hub_nodecount = 0;
     50 static unsigned hub_mfg = 0;
     51 
     52 static unsigned vir_width = 0;
     53 static unsigned vir_width_addr = 0;
     54 static unsigned vir_width_ir = 0;
     55 static unsigned vir_addr = 0;
     56 
     57 
     58 int jtag_vir(unsigned vir) {
     59 	int r;
     60 	if ((r = jtag_ir(ir_width, 14)) < 0) return r;
     61 	if ((r = jtag_dr(vir_width, vir_addr | vir, 0)) < 0) return r;
     62 	return 0;
     63 }
     64 
     65 int jtag_vdr(unsigned sz, unsigned bits, unsigned *out) {
     66 	int r;
     67 	if ((r = jtag_ir(ir_width, 12)) < 0) return r;
     68 	if ((r = jtag_dr(sz, bits, out)) < 0) return r;
     69 	return 0;
     70 }
     71 
     72 int jtag_open_virtual_device(unsigned iid) {
     73 	unsigned n, bits;
     74 	int r;
     75 
     76 	if ((r = jtag_open()) < 0) return r;
     77 
     78 	if ((r = jtag_reset()) < 0) return r;
     79 
     80 	/* select empty node_addr + node_vir -- all zeros */
     81 	if ((r = jtag_ir(ir_width, 14)) < 0) return r;
     82 	if ((r = jtag_dr(32, 0, 0)) < 0) return r;
     83 
     84 	/* select vdr - this will be the hub info (addr=0,vir=0) */
     85 	if ((r = jtag_ir(ir_width, 12)) < 0) return r;
     86 
     87 	/* read hub info */
     88 	if ((r = jtag_dr_8x4(&bits)) < 0) return r;
     89 	hub_version = (bits >> 27) & 0x1F;
     90 	hub_nodecount = (bits >> 19) & 0xFF;
     91 	hub_mfg = (bits >> 8) & 0x7FF;
     92 
     93 	if (hub_mfg != 0x06e) {
     94 		fprintf(stderr,"HUB:    Cannot Find Virtual JTAG HUB\n");
     95 		return -1;
     96 	}
     97 
     98 	/* altera docs claim this field is the sum of M bits (VIR field) and
     99 	 * N bits (ADDR field), but empirical evidence suggests it is actually
    100 	 * just the width of the ADDR field and the docs are wrong...
    101 	 */
    102 	vir_width_ir = bits & 0xFF;
    103 	vir_width_addr = needbits(hub_nodecount);
    104 	vir_width = vir_width_ir + vir_width_addr;
    105 
    106 	fprintf(stderr,"HUB:    Mfg=0x%03x, Ver=0x%02x, Nodes=%d, VIR=%d+%d bits\n",
    107 		hub_mfg, hub_version, hub_nodecount, vir_width_addr, vir_width_ir);
    108 
    109 	for (n = 0; n < hub_nodecount; n++) {
    110 		unsigned node_ver, node_id, node_mfg, node_iid;
    111 		if ((r = jtag_dr_8x4(&bits)) < 0) return r;
    112 		node_ver = (bits >> 27) & 0x1F;
    113 		node_id = (bits >> 19) & 0xFF;
    114 		node_mfg = (bits >> 8) & 0x7FF;
    115 		node_iid = bits & 0xFF;
    116 
    117 		fprintf(stderr,"NODE:   Mfg=0x%03x, Ver=0x%02x, ID=0x%02x, IID=0x%02x\n",
    118 			node_mfg, node_ver, node_id, node_iid);
    119 
    120 		if ((node_id == 0x08) && (node_iid) == iid) {
    121 			vir_addr = (n + 1) << vir_width_ir;
    122 		}
    123 	}
    124 
    125 	if ((vir_addr == 0) && (iid < 256)) {
    126 		fprintf(stderr,"ERROR: IID 0x%02x not found\n", iid);
    127 		return -1;
    128 	}
    129 	return 0;
    130 }
    131 
    132