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