00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 #if !defined(OS_LINUX) && !defined(OS_WINDOWS)
00045 #define OS_LINUX 1
00046 #endif
00047
00048 #ifdef OS_LINUX
00049 #include <assert.h>
00050 #include <unistd.h>
00051 #include <sys/io.h>
00052 #include <stdio.h>
00053 #endif // OS_LINUX
00054
00055 #ifdef OS_WINDOWS
00056 #include <windows.h>
00057 #endif // OS_WINDOWS
00058
00059 #include "altera_jtag.h"
00060
00061
00062
00063
00064
00065
00066
00067 #define JTAG_TMS (1<<1) // Mode Select (D1)
00068 #define JTAG_CLK (1<<0) // Clock (D0)
00069 #define JTAG_TDI (1<<6) // Data In of the IC (D6)
00070
00071 #define BBMV_WLB_OUT (1<<5) // Wired Loopback (D5)
00072 #define BBMV_BLB_OUT (1<<7) // Buffered Loopback (D7)
00073 #define BBMV_BUF_EN (1<<1) // Buffer Enable* (AUTO_FEED*)
00074
00075
00076 #define JTAG_TDO (1<<7) // Data Out of the IC (BUSY*)
00077
00078 #define BBMV_WLB_IN (1<<6) // Wired Loopback (ACK*)
00079 #define BBMV_BLB_IN (1<<5) // Buffered Loopback (PE)
00080
00081 #ifdef OS_WINDOWS
00082
00083 #define PGDC_IOCTL_GET_DEVICE_INFO_PP 0x00166A00L
00084 #define PGDC_IOCTL_READ_PORT_PP 0x00166A04L
00085 #define PGDC_IOCTL_WRITE_PORT_PP 0x0016AA08L
00086 #define PGDC_IOCTL_PROCESS_LIST_PP 0x0016AA1CL
00087 #define PGDC_WRITE_PORT 0x0a82
00088 #define PGDC_HDLC_NTDRIVER_VERSION 2
00089 #endif // OS_WINDOWS
00090
00091
00092
00093
00094
00095 bool AlteraByteBlasterJTAG::init( int argc , char **argv )
00096 {
00097
00098 if (!open_port())
00099 return false;
00100
00101
00102 if (!detect())
00103 return false;
00104
00105 dataVal = 0;
00106 ctrlVal = 0;
00107
00108
00109 ctrlVal |= BBMV_BUF_EN;
00110 if (!write_port( 2 , ctrlVal , true ))
00111 return false;
00112
00113
00114 return true;
00115 }
00116
00117 bool AlteraByteBlasterJTAG::drive_signal( int signal ,
00118 bool value ,
00119 bool clock ,
00120 bool test )
00121 {
00122 unsigned char mask = 0;
00123
00124 if ( signal != SIGNAL_TMS &&
00125 signal != SIGNAL_TDI )
00126 return false;
00127
00128 if (signal == SIGNAL_TMS)
00129 mask = JTAG_TMS;
00130 else
00131 mask = JTAG_TDI;
00132
00133 if (!value) {
00134 mask = ~mask;
00135 dataVal &= mask;
00136 }
00137 else {
00138 dataVal |= mask;
00139 }
00140
00141 write_port( 0 , dataVal , test );
00142
00143 if (clock) {
00144 dataVal |= JTAG_CLK;
00145 write_port( 0 , dataVal , test);
00146
00147 dataVal &= ~JTAG_CLK;
00148 write_port( 0 , dataVal, test);
00149 }
00150 return true;
00151 }
00152
00153 unsigned long AlteraByteBlasterJTAG::transfer_data( int bit_count ,
00154 unsigned long data ,
00155 bool instruction )
00156 {
00157 int n = ( instruction ? ( bit_count - 1 ) : ( bit_count ) );
00158 unsigned long tdo=0;
00159 unsigned char t;
00160
00161 if (n>32) n = 32;
00162
00163 for (int i=0; i<n; i++) {
00164
00165 read_port( 1 , t );
00166
00167
00168 if ((t & JTAG_TDO)==0)
00169 tdo |= (1<<i);
00170
00171 drive_signal( SIGNAL_TDI ,
00172 ((data & (1<<i))?true:false) ,
00173 true ,
00174 true );
00175 }
00176 return tdo;
00177 }
00178
00179 void AlteraByteBlasterJTAG::flush()
00180 {
00181 flush_ports();
00182 }
00183
00184
00185 const char * AlteraByteBlasterJTAG::getName() const
00186 {
00187 return "altera_bbmv";
00188 }
00189
00190
00191
00192
00193
00194
00195 AlteraByteBlasterJTAG::AlteraByteBlasterJTAG()
00196 {
00197 #ifdef OS_LINUX
00198 base_port = 0x378;
00199 #endif // OS_LINUX
00200
00201 #ifdef OS_WINDOWS
00202 nt_device_handle = INVALID_HANDLE_VALUE;
00203 port_io_buffer_count = 0;
00204 #endif // OS_WINDOWS
00205 }
00206
00207 AlteraByteBlasterJTAG::~AlteraByteBlasterJTAG()
00208 {
00209 close_port();
00210 }
00211
00212
00213 bool AlteraByteBlasterJTAG::open_port()
00214 {
00215 #ifdef OS_LINUX
00216 return ( ioperm( base_port , 3 , 1 ) == 0 );
00217 #endif // OS_LINUX
00218
00219 #ifdef OS_WINDOWS
00220 bool init_ok = false;
00221 ULONG ulVersion, ulLength;
00222 char nt_lpt_str[] = "\\\\.\\ALTLPT1";
00223
00224 nt_device_handle = CreateFile(
00225 nt_lpt_str ,
00226 GENERIC_READ | GENERIC_WRITE ,
00227 0 ,
00228 NULL ,
00229 OPEN_EXISTING ,
00230 FILE_ATTRIBUTE_NORMAL ,
00231 NULL );
00232
00233 if ( nt_device_handle == INVALID_HANDLE_VALUE )
00234 return false;
00235
00236 if ( DeviceIoControl(
00237 nt_device_handle ,
00238 PGDC_IOCTL_GET_DEVICE_INFO_PP ,
00239 (ULONG *) NULL ,
00240 0 ,
00241 &ulVersion ,
00242 sizeof(ULONG) ,
00243 &ulLength ,
00244 NULL )) {
00245
00246 if ( ( ulLength == sizeof( ULONG ) ) &&
00247 ( ulVersion == PGDC_HDLC_NTDRIVER_VERSION ) )
00248 return true;
00249 }
00250
00251 CloseHandle( nt_device_handle );
00252 nt_device_handle = INVALID_HANDLE_VALUE;
00253 return false;
00254
00255 #endif // OS_WINDOWS
00256 }
00257
00258 void AlteraByteBlasterJTAG::close_port()
00259 {
00260 dataVal = 0x00;
00261 ctrlVal = 0x00;
00262
00263 write_port( 0 , dataVal , true );
00264 write_port( 2 , ctrlVal , true );
00265
00266 #ifdef OS_WINDOWS
00267 if ( nt_device_handle != INVALID_HANDLE_VALUE ) {
00268 CloseHandle( nt_device_handle );
00269 nt_device_handle = INVALID_HANDLE_VALUE;
00270 }
00271 #endif // OS_WINDOWS;
00272 }
00273
00274
00275 bool AlteraByteBlasterJTAG::read_port( unsigned int port ,
00276 unsigned char &data)
00277 {
00278 #ifdef OS_LINUX
00279 data = inb(base_port + (port%3));
00280 return true;
00281 #endif // OS_LINUX
00282
00283 #ifdef OS_WINDOWS
00284 BOOL rc;
00285 ULONG ulPort = port, ulData, ulLength = 0;
00286
00287 rc = DeviceIoControl(
00288 nt_device_handle ,
00289 PGDC_IOCTL_READ_PORT_PP ,
00290 (ULONG *)&ulPort ,
00291 sizeof(ULONG) ,
00292 (ULONG *)&ulData ,
00293 sizeof(ULONG) ,
00294 (ULONG *)&ulLength ,
00295 NULL );
00296
00297 if ((!rc) || ulLength!= sizeof(ULONG))
00298 return false;
00299 data = (unsigned char)(ulData & 0xff);
00300 return true;
00301 #endif // OS_WINDOWS
00302
00303 }
00304
00305 bool AlteraByteBlasterJTAG::write_port( unsigned int port ,
00306 unsigned char data ,
00307 bool test )
00308 {
00309 #ifdef OS_LINUX
00310 outb(data, base_port + (port%3));
00311 return true;
00312 #endif // OS_LINUX
00313
00314 #ifdef OS_WINDOWS
00315 BOOL rc;
00316 ULONG ulBuf[2], ulLength = 0;
00317
00318 if ( port == 0 && !test ) {
00319 port_io_buffer[port_io_buffer_count].data = (unsigned short)data;
00320 port_io_buffer[port_io_buffer_count].command = PGDC_WRITE_PORT;
00321 port_io_buffer_count++;
00322
00323 if (port_io_buffer_count >= PORT_IO_BUFFER_SIZE)
00324 flush_ports();
00325
00326 return true;
00327 }
00328 else {
00329
00330 ulBuf[0] = port;
00331 ulBuf[1] = data;
00332
00333 rc = DeviceIoControl(
00334 nt_device_handle ,
00335 PGDC_IOCTL_WRITE_PORT_PP ,
00336 (ULONG *)&ulBuf ,
00337 2 * sizeof(ULONG) ,
00338 (ULONG *)NULL ,
00339 0 ,
00340 (ULONG *)&ulLength ,
00341 NULL );
00342
00343 return (rc==TRUE);
00344 }
00345 #endif // OS_WINDOWS
00346 }
00347
00348 void AlteraByteBlasterJTAG::flush_ports()
00349 {
00350 #ifdef OS_WINDOWS
00351 ULONG ulLen = 0;
00352 BOOL rc;
00353
00354 rc = DeviceIoControl(
00355 nt_device_handle ,
00356 PGDC_IOCTL_PROCESS_LIST_PP ,
00357 (LPVOID)port_io_buffer ,
00358 port_io_buffer_count * 2 * sizeof(unsigned short),
00359 (LPVOID)port_io_buffer ,
00360 port_io_buffer_count * 2 * sizeof(unsigned short),
00361 &ulLen,
00362 NULL );
00363
00364 port_io_buffer_count = 0;
00365
00366 #endif // OS_WINDOWS
00367 }
00368
00369
00370 bool AlteraByteBlasterJTAG::detect()
00371 {
00372 unsigned char t;
00373
00374
00375 write_port( 0 , ( BBMV_WLB_OUT | BBMV_BLB_OUT ) , true );
00376 read_port( 1 , t );
00377
00378 if ((t&(BBMV_BLB_IN|BBMV_WLB_IN))!=(BBMV_BLB_IN|BBMV_WLB_IN))
00379 return false;
00380
00381 write_port( 0 , 0 , true );
00382 read_port( 1 , t );
00383
00384 if ((t&0x60)!=0x00)
00385 return false;
00386
00387 return true;
00388 }
00389