Rev 2697 Rev 2933
1 // MLAB Xilinx Virtual Cable Network Server 1 // MLAB Xilinx Virtual Cable Network Server
2 // ---------------------------------------- 2 // ----------------------------------------
3 // 3 //
4 // (c) miho 2012 http://www.mlab.cz/PermaLink/XVC_SOFTWARE 4 // (c) miho 2012 http://www.mlab.cz/PermaLink/XVC_SOFTWARE
5 // 5 //
6 // This program if free. 6 // This program if free.
7 // 7 //
8 // 8 //
9 // History: 9 // History:
10 // 10 //
11 // 1.00 2012_09 Proof of concept (no configuration, not for public release) 11 // 1.00 2012_09 Proof of concept (no configuration, not for public release)
12 // 1.01 2012_09 Added parameter for device selection 12 // 1.01 2012_09 Added parameter for device selection
13 // 1.02 2012_12 Error handling and debugged 13 // 1.02 2012_12 Error handling and debugged
14 // 1.03 2012_12 Release version ready to publish 14 // 1.03 2012_12 Release version ready to publish
-   15 // 1.04 2013_04 Socket Bind Error with eplanation (multiple instance of XVC Server)
15 // 16 //
16 // 17 //
17 // Purpose: 18 // Purpose:
18 // 19 //
19 // XILINX development software (ISE, WebPack) supports several types of JTAG programming 20 // XILINX development software (ISE, WebPack) supports several types of JTAG programming
20 // cables. Among them there is one particularly interesting. It is Xilinx Virtual Cable 21 // cables. Among them there is one particularly interesting. It is Xilinx Virtual Cable
21 // which uses (documented) XVC network protocol to send JTAG commands across TCP/IP network. 22 // which uses (documented) XVC network protocol to send JTAG commands across TCP/IP network.
22 // So it is possible to realize own hardware/software and have it directly supported by 23 // So it is possible to realize own hardware/software and have it directly supported by
23 // XILINX development software (both IMPACT and ChipScope). 24 // XILINX development software (both IMPACT and ChipScope).
24 // 25 //
25 // This program listens TCP data send by XILINX ISE IMAPACT (or ChipScope) and sends it 26 // This program listens TCP data send by XILINX ISE IMAPACT (or ChipScope) and sends it
26 // to the JTAG device (typically FPGA) connected to FTDI USB Chip. You can use ordinary 27 // to the JTAG device (typically FPGA) connected to FTDI USB Chip. You can use ordinary
27 // USB/RS232 translator based on FT232R chip or you can use our own module from 28 // USB/RS232 translator based on FT232R chip or you can use our own module from
28 // http://www.mlab.cz/PermaLink/XVC_FT220X 29 // http://www.mlab.cz/PermaLink/XVC_FT220X
29 // 30 //
30 // Target device JTAG port is connected to pins on FTDI USB chip. Program writes to standard 31 // Target device JTAG port is connected to pins on FTDI USB chip. Program writes to standard
31 // output Which pins are used. Program writes what to set in ISE to enable XVC plugin. 32 // output Which pins are used. Program writes what to set in ISE to enable XVC plugin.
32 // 33 //
33 // 34 //
34 // Environment: 35 // Environment:
35 // 36 //
36 // This is Win32 Console Application and run in WinXP / Win7 / Win8 both 32 and 64 bit. 37 // This is Win32 Console Application and run in WinXP / Win7 / Win8 both 32 and 64 bit.
37 // 38 //
38 // Program needs to listen to the network so it is necessary to allow doing so. In Windows 39 // Program needs to listen to the network so it is necessary to allow doing so. In Windows
39 // firewall configuration enable networking for the exe file. 40 // firewall configuration enable networking for the exe file.
40 // WinXP: run as Administrator c:\WINDOWS\System32\firewall.cpl and add the exe file 41 // WinXP: run as Administrator c:\WINDOWS\System32\firewall.cpl and add the exe file
41 // Win7: the system asks directly to do so 42 // Win7: the system asks directly to do so
42 // 43 //
43 // 44 //
44 // Technology: 45 // Technology:
45 // 46 //
46 // The program uses Windows WINSOCK2 library for network communication 47 // The program uses Windows WINSOCK2 library for network communication
47 // and FTDI ftd2xx library for communication with FTDI USB chip. 48 // and FTDI ftd2xx library for communication with FTDI USB chip.
48 // It can be staticly linked to minimize dependencies on libraries. 49 // It can be staticly linked to minimize dependencies on libraries.
49 // Program requires FTDI drivers installed. 50 // Program requires FTDI drivers installed.
50 // Because of the usage of standard libraries you don't need to solve how to sign drivers. 51 // Because of the usage of standard libraries you don't need to solve how to sign drivers.
51 // 52 //
52 // The program was debug with FT232R and FT220X device. 53 // The program was debug with FT232R and FT220X device.
53 // It should work with any similar FTDI USB chip. 54 // It should work with any similar FTDI USB chip.
54 // 55 //
55 // XVC protocol is documented (you have to ask XILINX support to gain access). 56 // XVC protocol is documented (you have to ask XILINX support to gain access).
56 // The program is inspired by the work http://debugmo.de/2012/02/xvcd-the-xilinx-virtual-cable-daemon/ 57 // The program is inspired by the work http://debugmo.de/2012/02/xvcd-the-xilinx-virtual-cable-daemon/
57 // Ask Google about Xilinx Virtual Cable. 58 // Ask Google about Xilinx Virtual Cable.
58 // 59 //
59 // 60 //
60 // Translation: 61 // Translation:
61 // 62 //
62 // MS Visual C++ 2010 Express (free, registration required) 63 // MS Visual C++ 2010 Express (free, registration required)
63 // Create new empty project for Win32 Console Application and name project mlab_xvcd (to build mlab_xvcd.exe) 64 // Create new empty project for Win32 Console Application and name project mlab_xvcd (to build mlab_xvcd.exe)
64 // Header Files / Add / Existing Items - all .h files 65 // Header Files / Add / Existing Items - all .h files
65 // Resource Files / Add / Existing Items - all .lib files 66 // Resource Files / Add / Existing Items - all .lib files
66 // Source Files / Add / Existing Items - all .cpp files 67 // Source Files / Add / Existing Items - all .cpp files
67 // Select Release version (no debug info) 68 // Select Release version (no debug info)
68 // Set static linkage Project Properties / Configuration Release / Configuration Properties 69 // Set static linkage Project Properties / Configuration Release / Configuration Properties
69 // / Code Generation / Runtime Library = Multithreaded (/MT) 70 // / Code Generation / Runtime Library = Multithreaded (/MT)
70 // 71 //
71 // 72 //
72 // Problems: 73 // Problems:
73 // 74 //
74 // Programming of SPI FLASH configuration memory connected to FPGA does not work. No idea why. 75 // Programming of SPI FLASH configuration memory connected to FPGA does not work. No idea why.
75 // It does not work for internal FLASH of Spartan XC3SxxAN either. 76 // It does not work for internal FLASH of Spartan XC3SxxAN either.
76 // 77 //
77 // 78 //
78 // Possible improvements: 79 // Possible improvements:
79 // 80 //
80 // Linux version (Winsock library differs). 81 // Linux version (Winsock library differs).
81 // External definition of JTAG pins. 82 // External definition of JTAG pins.
-   83 // Enable Socket Number (to be able to run multiple XVC Servers), now it is constant XVC_TCP_PORT (should be only a default)
82   84  
83   85  
84 // Library Definitions 86 // Library Definitions
85 // ------------------- 87 // -------------------
86   88  
87 #undef UNICODE 89 #undef UNICODE
88 #define WIN32_LEAN_AND_MEAN 90 #define WIN32_LEAN_AND_MEAN
89   91  
90 #include "mlab_xvcd.h" // Program Configuration 92 #include "mlab_xvcd.h" // Program Configuration
91 #include <windows.h> // Windows Console Application 93 #include <windows.h> // Windows Console Application
92 #include <winsock2.h> // Windows WinSock2 94 #include <winsock2.h> // Windows WinSock2
93 #include <ws2tcpip.h> // Windows WinSock2 95 #include <ws2tcpip.h> // Windows WinSock2
94 #include <stdlib.h> // Standard Library (exit, atoi, ...) 96 #include <stdlib.h> // Standard Library (exit, atoi, ...)
95 #include <stdio.h> // Standard IO (printf, ...) 97 #include <stdio.h> // Standard IO (printf, ...)
96 #include <signal.h> // CTRL+C handling 98 #include <signal.h> // CTRL+C handling
97   99  
98 // Link with library 100 // Link with library
99 #pragma comment (lib, "Ws2_32.lib") 101 #pragma comment (lib, "Ws2_32.lib")
100   102  
101 #define XVC_RX_BUFLEN (XVC_JTAG_LEN/8*2+20) // Length of receive buffer in bytes (command+length+TMSbuffer+TDIbuffer) 103 #define XVC_RX_BUFLEN (XVC_JTAG_LEN/8*2+20) // Length of receive buffer in bytes (command+length+TMSbuffer+TDIbuffer)
102 #define XVC_TX_BUFLEN (XVC_JTAG_LEN/8) // Length of transmit buffer in bytes (TDObuffer) 104 #define XVC_TX_BUFLEN (XVC_JTAG_LEN/8) // Length of transmit buffer in bytes (TDObuffer)
103   105  
104   106  
105 // JTAG state machine 107 // JTAG state machine
106 // ------------------ 108 // ------------------
107   109  
108 // JTAG States 110 // JTAG States
109 enum 111 enum
110 { 112 {
111 test_logic_reset, run_test_idle, // Starts from 0 113 test_logic_reset, run_test_idle, // Starts from 0
112   114  
113 select_dr_scan, capture_dr, shift_dr, 115 select_dr_scan, capture_dr, shift_dr,
114 exit1_dr, pause_dr, exit2_dr, update_dr, 116 exit1_dr, pause_dr, exit2_dr, update_dr,
115   117  
116 select_ir_scan, capture_ir, shift_ir, 118 select_ir_scan, capture_ir, shift_ir,
117 exit1_ir, pause_ir, exit2_ir, update_ir, 119 exit1_ir, pause_ir, exit2_ir, update_ir,
118   120  
119 num_states 121 num_states
120 }; 122 };
121   123  
122   124  
123 // JTAG State Machine transfer Function 125 // JTAG State Machine transfer Function
124 static int jtagStep(int state, int tms) 126 static int jtagStep(int state, int tms)
125 { 127 {
126 static const int next_state[num_states][2] = 128 static const int next_state[num_states][2] =
127 { 129 {
128 /* JTAG State -->> New State */ 130 /* JTAG State -->> New State */
129 /* -------------------------------------------------------------*/ 131 /* -------------------------------------------------------------*/
130 /* | TMS=0 | TMS=1 */ 132 /* | TMS=0 | TMS=1 */
131 /* -------------------------------------------------------------*/ 133 /* -------------------------------------------------------------*/
132 /* [test_logic_reset] -> */ { run_test_idle, test_logic_reset }, 134 /* [test_logic_reset] -> */ { run_test_idle, test_logic_reset },
133 /* [run_test_idle] -> */ { run_test_idle, select_dr_scan }, 135 /* [run_test_idle] -> */ { run_test_idle, select_dr_scan },
134 /* [select_dr_scan] -> */ { capture_dr, select_ir_scan }, 136 /* [select_dr_scan] -> */ { capture_dr, select_ir_scan },
135 /* [capture_dr] -> */ { shift_dr, exit1_dr }, 137 /* [capture_dr] -> */ { shift_dr, exit1_dr },
136 /* [shift_dr] -> */ { shift_dr, exit1_dr }, 138 /* [shift_dr] -> */ { shift_dr, exit1_dr },
137 /* [exit1_dr] -> */ { pause_dr, update_dr }, 139 /* [exit1_dr] -> */ { pause_dr, update_dr },
138 /* [pause_dr] -> */ { pause_dr, exit2_dr }, 140 /* [pause_dr] -> */ { pause_dr, exit2_dr },
139 /* [exit2_dr] -> */ { shift_dr, update_dr }, 141 /* [exit2_dr] -> */ { shift_dr, update_dr },
140 /* [update_dr] -> */ { run_test_idle, select_dr_scan }, 142 /* [update_dr] -> */ { run_test_idle, select_dr_scan },
141 /* [select_ir_scan] -> */ { capture_ir, test_logic_reset }, 143 /* [select_ir_scan] -> */ { capture_ir, test_logic_reset },
142 /* [capture_ir] -> */ { shift_ir, exit1_ir }, 144 /* [capture_ir] -> */ { shift_ir, exit1_ir },
143 /* [shift_ir] -> */ { shift_ir, exit1_ir }, 145 /* [shift_ir] -> */ { shift_ir, exit1_ir },
144 /* [exit1_ir] -> */ { pause_ir, update_ir }, 146 /* [exit1_ir] -> */ { pause_ir, update_ir },
145 /* [pause_ir] -> */ { pause_ir, exit2_ir }, 147 /* [pause_ir] -> */ { pause_ir, exit2_ir },
146 /* [exit2_ir] -> */ { shift_ir, update_ir }, 148 /* [exit2_ir] -> */ { shift_ir, update_ir },
147 /* [update_ir] -> */ { run_test_idle, select_dr_scan } 149 /* [update_ir] -> */ { run_test_idle, select_dr_scan }
148 }; 150 };
149   151  
150 return next_state[state][tms]; 152 return next_state[state][tms];
151 } 153 }
152   154  
153   155  
154 int handleData(SOCKET ClientSocket) 156 int handleData(SOCKET ClientSocket)
155 { 157 {
156   158  
157 bool seen_tlr = false; 159 bool seen_tlr = false;
158 bool jtagError = false; 160 bool jtagError = false;
159   161  
160 static int jtag_state; 162 static int jtag_state;
161   163  
162 do 164 do
163 { 165 {
164 int iResult; 166 int iResult;
165   167  
166 // Read Command 168 // Read Command
167 char command[16]; 169 char command[16];
168 int commandLen = 0; 170 int commandLen = 0;
169   171  
170 // Read String terminated by ':' 172 // Read String terminated by ':'
171 do 173 do
172 { 174 {
173 iResult = recv(ClientSocket, command+commandLen, 1, 0); 175 iResult = recv(ClientSocket, command+commandLen, 1, 0);
174 if (iResult==0) 176 if (iResult==0)
175 { 177 {
176 printf("\n Connection Closed\n\n"); 178 printf("\n Connection Closed\n\n");
177 return -1; 179 return -1;
178 } 180 }
179 else if (iResult==1) 181 else if (iResult==1)
180 { 182 {
181 commandLen++; 183 commandLen++;
182 } 184 }
183 else 185 else
184 { 186 {
185 fprintf(stderr, "Error Reading Command\n"); 187 fprintf(stderr, "Error Reading Command\n");
186 return -2; 188 return -2;
187 } 189 }
188 } 190 }
189 while (command[commandLen-1]!=':' && commandLen<sizeof(command)-1 ); 191 while (command[commandLen-1]!=':' && commandLen<sizeof(command)-1 );
190 command[commandLen] = char(0); 192 command[commandLen] = char(0);
191   193  
192 if (0==strncmp(command, "shift:", sizeof(command))) 194 if (0==strncmp(command, "shift:", sizeof(command)))
193 { 195 {
194 196
195 } 197 }
196 else 198 else
197 { 199 {
198 fprintf(stderr, "Invalid Command '%s'\n", command); 200 fprintf(stderr, "Invalid Command '%s'\n", command);
199 return -2; 201 return -2;
200 } 202 }
201   203  
202 // Read Length (in bits, 32bit integer) 204 // Read Length (in bits, 32bit integer)
203 int len; 205 int len;
204   206  
205 iResult = recv(ClientSocket, (char *)&len, 4, 0); // pøepsat pøenositelnì 207 iResult = recv(ClientSocket, (char *)&len, 4, 0); // pøepsat pøenositelnì
206 if (iResult==0) 208 if (iResult==0)
207 { 209 {
208 printf("\n Connection Closed\n\n"); 210 printf("\n Connection Closed\n\n");
209 return -1; 211 return -1;
210 } 212 }
211 if (iResult != 4) 213 if (iResult != 4)
212 { 214 {
213 fprintf(stderr, "Reading Length Failed\n"); 215 fprintf(stderr, "Reading Length Failed\n");
214 return -2; 216 return -2;
215 } 217 }
216   218  
217 char buffer[2048]; 219 char buffer[2048];
218   220  
219 // Read Data (data string for TMS and TDI) 221 // Read Data (data string for TMS and TDI)
220 int nr_bytes = (len + 7) / 8; 222 int nr_bytes = (len + 7) / 8;
221 if (nr_bytes * 2 > sizeof(buffer)) 223 if (nr_bytes * 2 > sizeof(buffer))
222 { 224 {
223 fprintf(stderr, "Buffer Size Exceeded\n"); 225 fprintf(stderr, "Buffer Size Exceeded\n");
224 return -2; 226 return -2;
225 } 227 }
226   228  
227 int iReceivedBytes=0; 229 int iReceivedBytes=0;
228 while (iReceivedBytes<nr_bytes * 2) 230 while (iReceivedBytes<nr_bytes * 2)
229 { 231 {
230 iResult = recv(ClientSocket, buffer+iReceivedBytes, nr_bytes * 2 - iReceivedBytes, 0); 232 iResult = recv(ClientSocket, buffer+iReceivedBytes, nr_bytes * 2 - iReceivedBytes, 0);
231 if (iResult==0) 233 if (iResult==0)
232 { 234 {
233 printf("\n Connection Closed\n\n"); 235 printf("\n Connection Closed\n\n");
234 return -1; 236 return -1;
235 } 237 }
236 if (iResult<=0) 238 if (iResult<=0)
237 { 239 {
238 fprintf(stderr, "Reading Data Failed %d %d\n", iResult, nr_bytes * 2); 240 fprintf(stderr, "Reading Data Failed %d %d\n", iResult, nr_bytes * 2);
239 return -2; 241 return -2;
240 } 242 }
241 iReceivedBytes += iResult; 243 iReceivedBytes += iResult;
242 } 244 }
243   245  
244 char result[1024]; 246 char result[1024];
245 memset(result, 0, nr_bytes); 247 memset(result, 0, nr_bytes);
246   248  
247 // Deal with JTAG 249 // Deal with JTAG
248   250  
249 // Only allow exiting if the state is rti and the IR 251 // Only allow exiting if the state is rti and the IR
250 // has the default value (IDCODE) by going through test_logic_reset. 252 // has the default value (IDCODE) by going through test_logic_reset.
251 // As soon as going through capture_dr or capture_ir no exit is 253 // As soon as going through capture_dr or capture_ir no exit is
252 // allowed as this will change DR/IR. 254 // allowed as this will change DR/IR.
253 seen_tlr = (seen_tlr || jtag_state == test_logic_reset) && (jtag_state != capture_dr) && (jtag_state != capture_ir); 255 seen_tlr = (seen_tlr || jtag_state == test_logic_reset) && (jtag_state != capture_dr) && (jtag_state != capture_ir);
254 256
255 // Due to a weird bug(??) xilinx impacts goes through another "capture_ir"/"capture_dr" cycle after 257 // Due to a weird bug(??) xilinx impacts goes through another "capture_ir"/"capture_dr" cycle after
256 // reading IR/DR which unfortunately sets IR to the read-out IR value. 258 // reading IR/DR which unfortunately sets IR to the read-out IR value.
257 // Just ignore these transactions. 259 // Just ignore these transactions.
258 if ((jtag_state == exit1_ir && len == 5 && buffer[0] == 0x17) || (jtag_state == exit1_dr && len == 4 && buffer[0] == 0x0b)) 260 if ((jtag_state == exit1_ir && len == 5 && buffer[0] == 0x17) || (jtag_state == exit1_dr && len == 4 && buffer[0] == 0x0b))
259 { 261 {
260 // printf("Ignoring Bogus jtag State movement at jtag_state %d\n", jtag_state); 262 // printf("Ignoring Bogus jtag State movement at jtag_state %d\n", jtag_state);
261 } 263 }
262 else 264 else
263 { 265 {
264 for (int i = 0; i < len; ++i) 266 for (int i = 0; i < len; ++i)
265 { 267 {
266 // 268 //
267 // Do the actual cycle. 269 // Do the actual cycle.
268 // 270 //
269 int tms = !!(buffer[i/8] & (1<<(i&7))); 271 int tms = !!(buffer[i/8] & (1<<(i&7)));
270 // 272 //
271 // Track the state. 273 // Track the state.
272 // 274 //
273 jtag_state = jtagStep(jtag_state, tms); 275 jtag_state = jtagStep(jtag_state, tms);
274 } 276 }
275 if (jtagScan((unsigned char *) buffer, (unsigned char *) buffer + nr_bytes, (unsigned char *) result, len) < 0) 277 if (jtagScan((unsigned char *) buffer, (unsigned char *) buffer + nr_bytes, (unsigned char *) result, len) < 0)
276 { 278 {
277 //fprintf(stderr, "jtagScan failed\n"); 279 //fprintf(stderr, "jtagScan failed\n");
278 // Can't stop now, have to sent (any) answer not to hung the IMPACT 280 // Can't stop now, have to sent (any) answer not to hung the IMPACT
279 jtagError = true; 281 jtagError = true;
280 } 282 }
281 } 283 }
282   284  
283 // Send the Ansver 285 // Send the Ansver
284 iResult = send(ClientSocket, result, nr_bytes, 0 ); 286 iResult = send(ClientSocket, result, nr_bytes, 0 );
285 if (iResult == SOCKET_ERROR) 287 if (iResult == SOCKET_ERROR)
286 { 288 {
287 printf("Send Failed with Error: %d\n", WSAGetLastError()); 289 printf("Send Failed with Error: %d\n", WSAGetLastError());
288 closesocket(ClientSocket); 290 closesocket(ClientSocket);
289 WSACleanup(); 291 WSACleanup();
290 return -2; 292 return -2;
291 } 293 }
292 // printf("Bytes Sent: %d\n", iSendResult); 294 // printf("Bytes Sent: %d\n", iSendResult);
293 // printf("jtag state %d\n", jtag_state); 295 // printf("jtag state %d\n", jtag_state);
294 } 296 }
295 while (!(seen_tlr && jtag_state == run_test_idle)); 297 while (!(seen_tlr && jtag_state == run_test_idle));
296   298  
297 return jtagError ? -2 : 0; 299 return jtagError ? -2 : 0;
298 } 300 }
299   301  
300   302  
301 // Stop Handler - switch JTAG port off and stop program 303 // Stop Handler - switch JTAG port off and stop program
302 void stopHandler(int sig) 304 void stopHandler(int sig)
303 { 305 {
304 jtagClosePort(); 306 jtagClosePort();
305 exit(1); 307 exit(1);
306 } 308 }
307   309  
308   310  
309 // Print help and stop program with error 311 // Print help and stop program with error
310 void Help(char *progName) 312 void Help(char *progName)
311 { 313 {
312 fprintf(stderr, "Bad Parameters\n"); 314 fprintf(stderr, "Bad Parameters\n");
313 fprintf(stderr, "\n"); 315 fprintf(stderr, "\n");
314 fprintf(stderr, "Usage: %s [arg]\n", progName); 316 fprintf(stderr, "Usage: %s [arg]\n", progName);
315 fprintf(stderr, "\n"); 317 fprintf(stderr, "\n");
316 fprintf(stderr, " Where [arg] is one of: \n"); 318 fprintf(stderr, " Where [arg] is one of: \n");
317 fprintf(stderr, " -d Description Fing FTDI device by Description\n"); 319 fprintf(stderr, " -d Description Fing FTDI device by Description\n");
318 fprintf(stderr, " -l Location Fing FTDI device by Loaction\n"); 320 fprintf(stderr, " -l Location Fing FTDI device by Loaction\n");
319 fprintf(stderr, " -s Serial_number Fing FTDI device by it's SN\n"); 321 fprintf(stderr, " -s Serial_number Fing FTDI device by it's SN\n");
320 fprintf(stderr, " -n Number Use N-th FTDI device\n"); 322 fprintf(stderr, " -n Number Use N-th FTDI device\n");
321 fprintf(stderr, " The first FTDI device is used if no argument\n"); 323 fprintf(stderr, " The first FTDI device is used if no argument\n");
322 exit(2); 324 exit(2);
323 } 325 }
324   326  
325   327  
326 int __cdecl main(int argc, char *argv[]) 328 int __cdecl main(int argc, char *argv[])
327 { 329 {
328 // Variables 330 // Variables
329 bool verbose = true; 331 bool verbose = true;
330   332  
331 // Program Info 333 // Program Info
332 printf("\n"); 334 printf("\n");
333 printf("Xilinx Virtual Cable Network Server\n"); 335 printf("Xilinx Virtual Cable Network Server\n");
334 printf("===================================\n"); 336 printf("===================================\n");
335 printf("(c) miho 2012 v " VERSION "\n\n"); 337 printf("(c) miho 2012 v " VERSION "\n\n");
336   338  
337 // Get program name 339 // Get program name
338 char *cp; 340 char *cp;
339 char *progName; 341 char *progName;
340 cp = argv[0]; 342 cp = argv[0];
341 progName=cp; 343 progName=cp;
342 while (cp[0]!='\0') 344 while (cp[0]!='\0')
343 { 345 {
344 if (cp[0]=='/' || cp[0]=='\\') 346 if (cp[0]=='/' || cp[0]=='\\')
345 progName=cp+1; 347 progName=cp+1;
346 cp++; 348 cp++;
347 } 349 }
348   350  
349 // Process command line params 351 // Process command line params
350 char *findDeviceByStr = 0; // String parameter 352 char *findDeviceByStr = 0; // String parameter
351 int findDeviceBy = 0; // What does the string means 353 int findDeviceBy = 0; // What does the string means
352   354  
353 if (argc>1) 355 if (argc>1)
354 { 356 {
355 if (argc==3) 357 if (argc==3)
356 { 358 {
357 findDeviceByStr = argv[2]; 359 findDeviceByStr = argv[2];
358 if (strcmp(argv[1], "-d")==0) 360 if (strcmp(argv[1], "-d")==0)
359 { 361 {
360 findDeviceBy = OPEN_BY_DESCRIPTION; 362 findDeviceBy = OPEN_BY_DESCRIPTION;
361 } 363 }
362 else if (strcmp(argv[1], "-l")==0) 364 else if (strcmp(argv[1], "-l")==0)
363 { 365 {
364 findDeviceBy = OPEN_BY_LOCATION; 366 findDeviceBy = OPEN_BY_LOCATION;
365 } 367 }
366 else if (strcmp(argv[1], "-s")==0) 368 else if (strcmp(argv[1], "-s")==0)
367 { 369 {
368 findDeviceBy = OPEN_BY_SERIAL_NUMBER; 370 findDeviceBy = OPEN_BY_SERIAL_NUMBER;
369 } 371 }
370 else if (strcmp(argv[1], "-n")==0) 372 else if (strcmp(argv[1], "-n")==0)
371 { 373 {
372 findDeviceBy = 0; 374 findDeviceBy = 0;
373 } 375 }
374 else 376 else
375 { 377 {
376 Help(progName); 378 Help(progName);
377 } 379 }
378 } 380 }
379 else 381 else
380 { 382 {
381 Help(progName); 383 Help(progName);
382 } 384 }
383 } 385 }
384 else 386 else
385 { 387 {
386 // Empty String - find device by number and number is empty 388 // Empty String - find device by number and number is empty
387 findDeviceBy = 0; 389 findDeviceBy = 0;
388 findDeviceByStr = ""; 390 findDeviceByStr = "";
389 } 391 }
390   392  
391 // Find, Init and Open FTDI USB Chip 393 // Find, Init and Open FTDI USB Chip
392 if (jtagOpenPort(findDeviceBy, findDeviceByStr)<0) { 394 if (jtagOpenPort(findDeviceBy, findDeviceByStr)<0) {
393 // No Device Found 395 // No Device Found
394 fprintf(stderr, "ERROR: No Device Found\n"); 396 fprintf(stderr, "ERROR: No Device Found\n");
395 return -1; 397 return -1;
396 } 398 }
397   399  
398 // Signal Handler (for CRTL+C) 400 // Signal Handler (for CRTL+C)
399 signal(SIGINT, &stopHandler); 401 signal(SIGINT, &stopHandler);
400   402  
401 printf("Starting Network Server\n"); 403 printf("Starting Network Server\n");
402 WSADATA wsaData; 404 WSADATA wsaData;
403 int iResult; 405 int iResult;
404   406  
405 SOCKET ListenSocket = INVALID_SOCKET; 407 SOCKET ListenSocket = INVALID_SOCKET;
406 SOCKET ClientSocket = INVALID_SOCKET; 408 SOCKET ClientSocket = INVALID_SOCKET;
407   409  
408 // Initialize Winsock 410 // Initialize Winsock
409 iResult = WSAStartup(MAKEWORD(2,2), &wsaData); 411 iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
410 if (iResult != 0) 412 if (iResult != 0)
411 { 413 {
412 fprintf(stderr, "WSAStartup failed with error: %d\n", iResult); 414 fprintf(stderr, "WSAStartup failed with error: %d\n", iResult);
413 jtagClosePort(); 415 jtagClosePort();
414 return -2; 416 return -2;
415 } 417 }
416   418  
417 // Display HostName and Address 419 // Display HostName and Address
418 char sMyName[255]; 420 char sMyName[255];
419 gethostname(sMyName, sizeof(sMyName)); 421 gethostname(sMyName, sizeof(sMyName));
420 printf(" Host Name %s\n", sMyName); 422 printf(" Host Name %s\n", sMyName);
421 hostent * pHostInfo; 423 hostent * pHostInfo;
422 pHostInfo = gethostbyname(sMyName); 424 pHostInfo = gethostbyname(sMyName);
423 printf(" Network Name %s\n", pHostInfo->h_name); 425 printf(" Network Name %s\n", pHostInfo->h_name);
424 if (pHostInfo->h_length>0 && pHostInfo->h_length<=16) 426 if (pHostInfo->h_length>0 && pHostInfo->h_length<=16)
425 { 427 {
426 printf(" Host Address "); 428 printf(" Host Address ");
427 for (int i=0; i<pHostInfo->h_length-1; i++) 429 for (int i=0; i<pHostInfo->h_length-1; i++)
428 { 430 {
429 printf("%d.", (unsigned char)pHostInfo->h_addr_list[0][i]); 431 printf("%d.", (unsigned char)pHostInfo->h_addr_list[0][i]);
430 } 432 }
431 printf("%d\n", (unsigned char)pHostInfo->h_addr_list[0][pHostInfo->h_length-1]); 433 printf("%d\n", (unsigned char)pHostInfo->h_addr_list[0][pHostInfo->h_length-1]);
432 } 434 }
433   435  
434 // Create Protocol Structure 436 // Create Protocol Structure
435 struct addrinfo hints; 437 struct addrinfo hints;
436 ZeroMemory(&hints, sizeof(hints)); 438 ZeroMemory(&hints, sizeof(hints));
437 hints.ai_family = AF_INET; // IP6 439 hints.ai_family = AF_INET; // IP6
438 hints.ai_socktype = SOCK_STREAM; // Reliable two-way connection 440 hints.ai_socktype = SOCK_STREAM; // Reliable two-way connection
439 hints.ai_protocol = IPPROTO_TCP; // Protocol TCP 441 hints.ai_protocol = IPPROTO_TCP; // Protocol TCP
440 hints.ai_flags = AI_PASSIVE; 442 hints.ai_flags = AI_PASSIVE;
441   443  
442 // Resolve the server address and port (allocate structure "result") 444 // Resolve the server address and port (allocate structure "result")
443 struct addrinfo *result = NULL; 445 struct addrinfo *result = NULL;
444 iResult = getaddrinfo(NULL, XVC_TCP_PORT, &hints, &result); 446 iResult = getaddrinfo(NULL, XVC_TCP_PORT, &hints, &result);
445 if ( iResult != 0 ) 447 if ( iResult != 0 )
446 { 448 {
447 fprintf(stderr, "getaddrinfo failed with error: %d\n", iResult); 449 fprintf(stderr, "getaddrinfo failed with error: %d\n", iResult);
448 WSACleanup(); 450 WSACleanup();
449 jtagClosePort(); 451 jtagClosePort();
450 return -2; 452 return -2;
451 } 453 }
452   454  
453 // Create a SOCKET 455 // Create a SOCKET
454 ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); 456 ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
455 if (ListenSocket == INVALID_SOCKET) 457 if (ListenSocket == INVALID_SOCKET)
456 { 458 {
457 fprintf(stderr, "socket failed with error: %ld\n", WSAGetLastError()); 459 fprintf(stderr, "socket failed with error: %ld\n", WSAGetLastError());
458 freeaddrinfo(result); 460 freeaddrinfo(result);
459 WSACleanup(); 461 WSACleanup();
460 jtagClosePort(); 462 jtagClosePort();
461 return -2; 463 return -2;
462 } 464 }
463   465  
464 // Bind the SOCKED (assign the address) 466 // Bind the SOCKED (assign the address)
465 iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen); 467 iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
466 if (iResult == SOCKET_ERROR) 468 if (iResult == SOCKET_ERROR)
467 { 469 {
-   470 int LastError=WSAGetLastError();
468 fprintf(stderr, "Bind failed with error: %d\n", WSAGetLastError()); 471 fprintf(stderr, "Bind failed with error: %d\n", LastError);
-   472 if (LastError==10048) fprintf(stderr, "Trying to start second instance of XVC Server?\n");
469 freeaddrinfo(result); 473 freeaddrinfo(result);
470 closesocket(ListenSocket); 474 closesocket(ListenSocket);
471 WSACleanup(); 475 WSACleanup();
472 jtagClosePort(); 476 jtagClosePort();
473 return -2; 477 return -2;
474 } 478 }
475   479  
476 if (verbose) 480 if (verbose)
477 { 481 {
478 printf(" Bound Socket %s\n", XVC_TCP_PORT); 482 printf(" Bound Socket %s\n", XVC_TCP_PORT);
479 } 483 }
480   484  
481 // Help for user 485 // Help for user
482 printf(" Set in IMPACT xilinx_xvc host=%s:%s disableversioncheck=true\n", sMyName, XVC_TCP_PORT); 486 printf(" Set in IMPACT xilinx_xvc host=%s:%s disableversioncheck=true\n", sMyName, XVC_TCP_PORT);
483   487  
484 freeaddrinfo(result); 488 freeaddrinfo(result);
485   489  
486 // Listen SOCKET 490 // Listen SOCKET
487 iResult = listen(ListenSocket, SOMAXCONN); 491 iResult = listen(ListenSocket, SOMAXCONN);
488 if (iResult == SOCKET_ERROR) 492 if (iResult == SOCKET_ERROR)
489 { 493 {
490 printf("listen failed with error: %d\n", WSAGetLastError()); 494 fprintf(stderr, "listen failed with error: %d\n", WSAGetLastError());
491 closesocket(ListenSocket); 495 closesocket(ListenSocket);
492 WSACleanup(); 496 WSACleanup();
493 jtagClosePort(); 497 jtagClosePort();
494 return -2; 498 return -2;
495 } 499 }
496   500  
497 printf("\n"); 501 printf("\n");
498   502  
499 do 503 do
500 { 504 {
501 printf(" Listen\n"); 505 printf(" Listen\n");
502 jtagSetLED(true); 506 jtagSetLED(true);
503   507  
504 // Accept a client SOCKET 508 // Accept a client SOCKET
505 sockaddr ClientSocetAddr; 509 sockaddr ClientSocetAddr;
506 int ClientSocetAddrLen = sizeof(sockaddr); 510 int ClientSocetAddrLen = sizeof(sockaddr);
507 ClientSocket = accept(ListenSocket, &ClientSocetAddr, &ClientSocetAddrLen); 511 ClientSocket = accept(ListenSocket, &ClientSocetAddr, &ClientSocetAddrLen);
508 if (ClientSocket == INVALID_SOCKET) 512 if (ClientSocket == INVALID_SOCKET)
509 { 513 {
510 printf("accept failed with error: %d\n", WSAGetLastError()); 514 fprintf(stderr, "accept failed with error: %d\n", WSAGetLastError());
511 closesocket(ListenSocket); 515 closesocket(ListenSocket);
512 WSACleanup(); 516 WSACleanup();
513 jtagClosePort(); 517 jtagClosePort();
514 return -2; 518 return -2;
515 } 519 }
516   520  
517 // Print Accepted + Address 521 // Print Accepted + Address
518 printf(" Accepted "); 522 printf(" Accepted ");
519 jtagSetLED(false); 523 jtagSetLED(false);
520 for (int i=2; i<2+4-1; i++) 524 for (int i=2; i<2+4-1; i++)
521 { 525 {
522 printf("%d.", (unsigned char)ClientSocetAddr.sa_data[i]); 526 printf("%d.", (unsigned char)ClientSocetAddr.sa_data[i]);
523 } 527 }
524 printf("%d:%d\n", (unsigned char)ClientSocetAddr.sa_data[2+4-1], (unsigned char)ClientSocetAddr.sa_data[0]*256+(unsigned char)ClientSocetAddr.sa_data[1]); 528 printf("%d:%d\n", (unsigned char)ClientSocetAddr.sa_data[2+4-1], (unsigned char)ClientSocetAddr.sa_data[0]*256+(unsigned char)ClientSocetAddr.sa_data[1]);
525   529  
526 // Process Data until the peer shuts down the connection 530 // Process Data until the peer shuts down the connection
527 int Cnt = 0; 531 int Cnt = 0;
528 printf(" Handle Data "); 532 printf(" Handle Data ");
529 do 533 do
530 { 534 {
531 iResult = handleData(ClientSocket); 535 iResult = handleData(ClientSocket);
532 if (iResult>=0) 536 if (iResult>=0)
533 { 537 {
534 printf("."); 538 printf(".");
535 Cnt++; 539 Cnt++;
536 if (Cnt>40) 540 if (Cnt>40)
537 { 541 {
538 Cnt = 0; 542 Cnt = 0;
539 printf("\n "); 543 printf("\n ");
540 } 544 }
541 } 545 }
542 } 546 }
543 while (iResult >= 0); 547 while (iResult >= 0);
544   548  
545 // Connection Closed by peer 549 // Connection Closed by peer
546 if (iResult==-1) 550 if (iResult==-1)
547 { 551 {
548 // JTAG port 552 // JTAG port
549 jtagSetIdle(); 553 jtagSetIdle();
550 } 554 }
551   555  
552 // Error - shutdown the connection 556 // Error - shutdown the connection
553 if (iResult==-2) 557 if (iResult==-2)
554 { 558 {
555 fprintf(stderr, " Disconnect\n"); 559 fprintf(stderr, " Disconnect\n");
556 iResult = shutdown(ClientSocket, SD_SEND); 560 iResult = shutdown(ClientSocket, SD_SEND);
557 if (iResult == SOCKET_ERROR) 561 if (iResult == SOCKET_ERROR)
558 { 562 {
559 fprintf(stderr, "shutdown failed with error: %d\n", WSAGetLastError()); 563 fprintf(stderr, "shutdown failed with error: %d\n", WSAGetLastError());
560 } 564 }
561 iResult=-2; // Error 565 iResult=-2; // Error
562 } 566 }
563   567  
564 // cleanup 568 // cleanup
565 closesocket(ClientSocket); 569 closesocket(ClientSocket);
566   570  
567 } 571 }
568 // If not Error Listen Again 572 // If not Error Listen Again
569 while (iResult!=-2); 573 while (iResult!=-2);
570   574  
571 // cleanup 575 // cleanup
572 closesocket(ListenSocket); 576 closesocket(ListenSocket);
573 WSACleanup(); 577 WSACleanup();
574 jtagClosePort(); 578 jtagClosePort();
575   579  
576 return 1; 580 return 1;
577 } 581 }