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