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