Index: chain_commands.c
===================================================================
--- chain_commands.c	(révision 68)
+++ chain_commands.c	(copie de travail)
@@ -1,7 +1,9 @@
 /* chain_commands.c -- JTAG protocol bridge between GDB and Advanced debug module.
    Copyright(C) 2008 - 2010 Nathan Yawn, nyawn@opencores.net
    based on code from jp2 by Marko Mlinar, markom@opencores.org
-   
+
+   Copyright(C) 2011 - Franck Jullien elec4fun@gmail.com
+
    This file contains functions which perform mid-level transactions
    on a JTAG, such as setting a value in the TAP IR
    or doing a burst write on the JTAG chain.
@@ -26,6 +28,7 @@
 #include <stdio.h>
 #include <stdlib.h>  // for malloc()
 #include <unistd.h>  // for usleep()
+#include <string.h>  // for memset()
 //#include <pthread.h>  // for mutexes
 
 #include "chain_commands.h"  // For the return error codes
@@ -36,6 +39,9 @@
 
 #define debug(...) //fprintf(stderr, __VA_ARGS__ )
 
+// Print SLD scan insformation
+//#define VERBOSE_SLD_NODE
+
 // How many tries before an abort
 #define NUM_SOFT_RETRIES 0
 
@@ -112,6 +118,28 @@
   global_xilinx_bscan = (enable) ? 1:0;
 }
 
+static unsigned char guess_addr_width(unsigned char number_of_nodes)
+{
+  unsigned char width = 0;
+  while(number_of_nodes) {
+    number_of_nodes >>= 1;
+    width ++;
+  }
+  return width;
+}
+
+#ifdef VERBOSE_SLD_NODE
+static char * id_to_string(unsigned char id)
+{
+  switch(id) {
+    case VJTAG_NODE_ID          : return "Virtual JTAG";
+    case JTAG_TO_AVALON_NODE_ID : return "JTAG to avalon bridge";
+    case SIGNAL_TAP_NODE_ID     : return "Signal TAP";
+  }
+  return "unknown";
+}
+#endif
+
 //////////////////////////////////////////////////////////////////////
 // Functions which operate on the JTAG TAP
 
@@ -147,18 +175,119 @@
 int tap_enable_debug_module(void)
 {
   uint32_t data;
- int err = APP_ERR_NONE;
+  int err = APP_ERR_NONE;
 
+  int i;
+  int node_index;
+  int vjtag_node_address = 0;
+  union hub_info hub;
+  union node_info node;
+
+  uint32_t zero[2];
+
+  hub.dword = 0;
+  node.dword = 0;
+  memset(zero, 0, 8);
+
   if(global_altera_virtual_jtag) {
+
+    err |= tap_set_ir(vjtag_cmd_vir);  /* This is the altera virtual IR scan command */
+    err |= jtag_write_bit(TMS);        /* SELECT_DR SCAN */
+    err |= jtag_write_bit(0);          /* CAPTURE_DR */
+    err |= jtag_write_bit(0);          /* SHIFT_DR */
+
+    /* The SLD hub contains the HUB IP Configuration Register and SLD_NODE_INFO
+     * register for each SLD node in the design. The HUB IP configuration register provides
+     * information needed to determine the dimensions of the USER1 DR chain. The
+     * SLD_NODE_INFO register is used to determine the address mapping for Virtual
+     * JTAG instance in your design. This register set is shifted out by issuing the
+     * HUB_INFO instruction. Both the ADDR bits for the SLD hub and the HUB_INFO
+     * instruction is 0 × 0.
+     * Because m and n are unknown at this point, the DR register
+     * (ADDR bits + VIR_VALUE) must be filled with zeros. Shifting a sequence of 64 zeroes
+     * into the USER1 DR is sufficient to cover the most conservative case for m and n.
+     */
+
+    err |= jtag_write_stream(zero, 64, 1);  /* EXIT1_DR */
+    err |= jtag_write_bit(TMS);             /* UPDATE_DR */
+    err |= jtag_write_bit(0);               /* IDLE */ 
+
+    /* Read the HUB IP Configuration Register */
+    err |= tap_set_ir(vjtag_cmd_vdr);
+
+    err |= jtag_write_bit(TMS); /* SELECT_DR SCAN */
+    err |= jtag_write_bit(0);   /* CAPTURE_DR */
+    err |= jtag_write_bit(0);   /* SHIFT_DR */
+
+    /* The HUB IP configuration register is shifted out using eight four-bit nibble
+     * scans of the DR register. Each four-bit scan must pass through the UPDATE_DR
+     * state before the next four-bit scan.
+     */
+
+    for(i=0;i<8;i++) {
+      err |= jtag_read_write_stream(zero, &data, 4, 1, 1); /* EXIT1_DR */
+      hub.dword = ((hub.dword >> 4) | (data << 28));
+      err |= jtag_write_bit(TMS);                               /* UPDATE_DR */
+      err |= jtag_write_bit(TMS);                               /* SELECT_DR SCAN */
+      err |= jtag_write_bit(0);                                 /* CAPTURE_DR */
+      err |= jtag_write_bit(0);                                 /* SHIFT_DR */
+    }
+
+#ifdef VERBOSE_SLD_NODE
+    printf("\nSLD HUB Configuration register\n");
+    printf("------------------------------\n");
+    printf("m_width         = %d\n", hub.m_width);
+    printf("manufacturer_id = 0x%02x\n", hub.manufacturer_id);
+    printf("nb_of_node      = %d\n", hub.nb_of_node);
+    printf("version         = %d\n\n", hub.version);
+
+    printf("VIR length = %d\n", guess_addr_width(hub.nb_of_node) + hub.m_width);
+#endif
+    data = 0;
+
+    /* Because the number of SLD nodes is now known, the Nodes on the hub can be
+     * enumerated by repeating the 8 four-bit nibble scans, once for each Node,
+     * to yield the SLD_NODE_INFO register of each Node. The DR nibble shifts
+     * are a continuation of the HUB_INFO DR shift used to shift out the Hub IP
+     * Configuration register.
+     */
+
+    for(node_index = 0;node_index < hub.nb_of_node;node_index++) {
+
+      for(i=0;i<8;i++) {
+        err |= jtag_read_write_stream(zero, &data, 4, 1, 1); /* EXIT1_DR */
+        node.dword = ((node.dword >> 4) | (data << 28));
+        err |= jtag_write_bit(TMS);                          /* UPDATE_DR */
+        err |= jtag_write_bit(TMS);                          /* SELECT_DR SCAN */
+        err |= jtag_write_bit(0);                            /* CAPTURE_DR */
+        err |= jtag_write_bit(0);                            /* SHIFT_DR */
+      }
+#ifdef VERBOSE_SLD_NODE
+      printf("\nNode info register\n");
+      printf("--------------------\n");
+      printf("instance_id     = %d\n",node.instance_id);
+      printf("manufacturer_id = 0x%02x\n", node.manufacturer_id);
+      printf("node_id         = %d (%s)\n", node.node_id, id_to_string(node.node_id));
+      printf("version         = %d\n\n", node.version);
+#endif
+      if(node.node_id == VJTAG_NODE_ID) vjtag_node_address = node_index + 1;
+    }
+
+    err |= jtag_write_bit(TMS); /* EXIT1_DR */
+    err |= jtag_write_bit(TMS); /* UPDATE_DR */
+    err |= jtag_write_bit(0);   /* IDLE */ 
+
+    data = 0;
+
     /* Set for virtual IR shift */
-    err |= tap_set_ir(vjtag_cmd_vir);  // This is the altera virtual IR scan command
-    err |= jtag_write_bit(TMS); /* SELECT_DR SCAN */
-    err |= jtag_write_bit(0); /* CAPTURE_DR */
-    err |= jtag_write_bit(0); /* SHIFT_DR */
+    err |= tap_set_ir(vjtag_cmd_vir);  /* This is the altera virtual IR scan command */
+    err |= jtag_write_bit(TMS);        /* SELECT_DR SCAN */
+    err |= jtag_write_bit(0);          /* CAPTURE_DR */
+    err |= jtag_write_bit(0);          /* SHIFT_DR */
     
     /* Select debug scan chain in  virtual IR */
-    data = (0x1<<ALT_VJTAG_IR_SIZE)|ALT_VJTAG_CMD_DEBUG;
-    err |= jtag_write_stream(&data, (ALT_VJTAG_IR_SIZE+1), 1);  // EXIT1_DR
+    data = (vjtag_node_address << hub.m_width) | ALT_VJTAG_CMD_DEBUG;
+    err |= jtag_write_stream(&data, guess_addr_width(hub.nb_of_node) + hub.m_width, 1); /* EXIT1_DR */
     err |= jtag_write_bit(TMS); /* UPDATE_DR */
     err |= jtag_write_bit(0); /* IDLE */ 
 
Index: altera_virtual_jtag.h
===================================================================
--- altera_virtual_jtag.h	(révision 68)
+++ altera_virtual_jtag.h	(copie de travail)
@@ -16,4 +16,29 @@
 #define ALT_VJTAG_IR_SIZE    4
 #define ALT_VJTAG_CMD_DEBUG  0x8
 
+// SLD node ID
+#define JTAG_TO_AVALON_NODE_ID	0x84
+#define VJTAG_NODE_ID		0x08
+#define SIGNAL_TAP_NODE_ID	0x00
+
+union hub_info {
+	struct {
+		unsigned m_width :8;
+		unsigned manufacturer_id :11;
+		unsigned nb_of_node :8;
+		unsigned version :5;
+	};
+	uint32_t dword;
+};
+
+union node_info {
+	struct {
+		unsigned instance_id :8;
+		unsigned manufacturer_id :11;
+		unsigned node_id :8;
+		unsigned version :5;
+	};
+	uint32_t dword;
+};
+
 #endif
