Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

altera_jtag.cpp

00001 /*--------------------------------------------------------------------
00002  * altera_jtag.cpp -- Altera ByteBlasterMV Parallel Port to JTAG 
00003  *                    interface 
00004  *--------------------------------------------------------------------
00005  * $Id: altera_jtag.cpp,v 1.2 2003/03/18 16:50:43 cgaudin Exp $
00006  *--------------------------------------------------------------------
00007  * This file is part of JTAG Framework
00008  * (c) 2002 Julien Pilet <julien.pilet@epfl.ch> and
00009  *          Stephane Magnenat <stephane.magnenat@epfl.ch>
00010  *--------------------------------------------------------------------
00011  * JTAG Framework is free software; you can redistribute it
00012  * and/or modify it under the terms of the GNU General Public License 
00013  * as published by the Free Software Foundation; either version 2 of 
00014  * the License, or (at your option) any later version.
00015  *
00016  * JTAG Framework is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with Foobar; if not, write to: 
00023  * Free Software Foundation, Inc., 
00024  * 59 Temple Place, 
00025  * Suite 330, Boston, MA  02111-1307  USA
00026  *--------------------------------------------------------------------
00027  * OS_LINUX          for Linux
00028  * OS_WINDOWS        for Windows NT/2000/XP
00029  *--------------------------------------------------------------------
00030  *! \file
00031  * \brief Altera ByteBlasterMV Parallel Port-JTAG Low Level Driver.
00032  *
00033  * This file contains support for the Altera ByteBlaster<tm>, 
00034  * connected on a parallel port. 
00035  * 
00036  * Unfortunatly it's for x86/Linux and x86/Windows.
00037  *
00038  * \author Julien Pilet <julien.pilet@epfl.ch>
00039  * \author Stephane Magnenat <stephane.magnenat@epfl.ch>
00040  * \author Cedric Gaudin <cedric.gaudin@epfl.ch> 
00041  */
00042 
00043 // default OS & hardware module 
00044 #if !defined(OS_LINUX) && !defined(OS_WINDOWS)
00045 #define OS_LINUX         1
00046 #endif /* !defined(OS_LINUX) && !defined(OS_WINDOWS) */ 
00047           
00048 #ifdef OS_LINUX
00049 #include <assert.h>
00050 #include <unistd.h> /* for libc5 */
00051 #include <sys/io.h> /* for glibc */
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  * Private Constants 
00064  */
00065 
00066 // Output Pins 
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 // Input Pins 
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 // Device I/O Control Codes (for Windows)
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  * Public Members 
00093  */
00094 
00095 bool AlteraByteBlasterJTAG::init( int argc , char **argv ) 
00096 {
00097   /* open port */
00098   if (!open_port()) 
00099     return false;
00100 
00101   /* try to detect ByteBlasterMV */
00102   if (!detect())
00103     return false;
00104 
00105   dataVal = 0;
00106   ctrlVal = 0;
00107 
00108   /* activate buffer */
00109   ctrlVal |= BBMV_BUF_EN;
00110   if (!write_port( 2 , ctrlVal , true ))
00111     return false;
00112 
00113   /* everything seems ok */
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         /* JTAG_TDO is on BUSY* */
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  * Constructor & destructor
00192  */
00193 
00194 // Constructor
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 // Read on parallel port
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 // Detect Altera ByteBlasterMV
00370 bool AlteraByteBlasterJTAG::detect()
00371 {
00372   unsigned char t;
00373 
00374   /* wired loopback & buffered loopback */
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 

Generated on Fri May 16 13:01:44 2003 for Jelie by doxygen1.2.15