--- /dev/null	2009-08-02 22:44:47.000000000 +0200
+++ ft245r.c	2009-08-02 21:56:45.000000000 +0200
@@ -0,0 +1,762 @@
+/*
+ * avrdude - A Downloader/Uploader for AVR device programmers
+ * Copyright (C) 2003-2004  Theodore A. Roth  <troth@openavr.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* $Id$ */
+
+/* ft245r -- FT245R/FT232R Synchronous BitBangMode Programmer
+  default pin assign 
+               FT232R / FT245R
+  miso  = 1;  # RxD   / D1
+  sck   = 0;  # RTS   / D0
+  mosi  = 2;  # TxD   / D2
+  reset = 4;  # DTR   / D4
+*/
+
+#include "ac_cfg.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#include "avr.h"
+#include "pindefs.h"
+#include "pgm.h"
+#include "bitbang.h"
+#include "ft245r.h"
+
+#if defined(_WIN32) || defined(SUPPORT_FT245R)
+#if defined(_WIN32)
+#include <windows.h>
+#include "ftd2xx.h"
+#else
+#include "ftd2xx.h"
+#endif
+
+#define FT245R_CYCLES	2
+#define FT245R_FRAGMENT_SIZE  512
+#define REQ_OUTSTANDINGS	10
+//#define USE_INLINE_WRITE_PAGE
+
+#define FT245R_DEBUG	1
+
+extern char * progname;
+extern int do_cycles;
+extern int ovsigck;
+extern int verbose;
+
+static FT_HANDLE handle;
+
+static unsigned char ft245r_ddr;
+static unsigned char ft245r_sck;
+static unsigned char ft245r_mosi;
+static unsigned char ft245r_reset;
+static unsigned char ft245r_miso;
+
+static inline void setbit(UCHAR *data, int pinno, int v)
+{
+	if (v) {
+		*data |= (1 << (pinno));
+	} else {
+		*data &= ~(1 <<(pinno));
+	}
+}
+
+static int ft245r_send(PROGRAMMER * pgm, char * buf, size_t len)
+{
+  FT_STATUS r;
+  DWORD rlen;
+  r = FT_Write(handle, buf, len, &rlen);
+  if (r == FT_OK) return 0;
+  if (len != rlen) return -1;
+  return -1;
+}
+
+
+static int ft245r_recv(PROGRAMMER * pgm, char * buf, size_t len)
+{
+  FT_STATUS r;
+  DWORD rlen;
+
+  r = FT_Read(handle, buf, len, &rlen);
+
+  if (r != FT_OK || len != rlen) {
+    fprintf(stderr,
+	    "%s: ft245r_recv(): programmer is not responding\n",
+	    progname);
+    exit(1);
+  }
+  return 0;
+}
+
+
+static int ft245r_drain(PROGRAMMER * pgm, int display)
+{
+  FT_STATUS r;
+  DWORD n;
+  r = FT_SetBitMode(handle, 0, 0x0); 	// reset 
+  if (r != FT_OK) return -1;
+  r = FT_SetBitMode(handle, ft245r_ddr, 0x4); // set Synchronuse BitBang
+  if (r != FT_OK) return -1;
+
+  r = FT_GetQueueStatus(handle, &n);
+  if (r != FT_OK) return -1;
+  if (n) {
+	fprintf(stderr, "ft245r_drain called but queue is not empty %d \n",
+		(int)n);
+  }
+  return 0;
+}
+
+static inline int ft245r_sync(PROGRAMMER * pgm)
+{
+  FT_STATUS r;
+  UCHAR ch;
+  r = FT_GetBitMode(handle, &ch);
+  if (r != FT_OK) return -1;
+  return 0;
+}
+
+static int ft245r_chip_erase(PROGRAMMER * pgm, AVRPART * p)
+{
+  unsigned char cmd[4];
+  unsigned char res[4];
+
+  if (p->op[AVR_OP_CHIP_ERASE] == NULL) {
+    fprintf(stderr, "chip erase instruction not defined for part \"%s\"\n",
+            p->desc);
+    return -1;
+  }
+
+  memset(cmd, 0, sizeof(cmd));
+
+  avr_set_bits(p->op[AVR_OP_CHIP_ERASE], cmd);
+  pgm->cmd(pgm, cmd, res);
+  usleep(p->chip_erase_delay);
+  pgm->initialize(pgm, p);
+
+  return 0;
+}
+
+static unsigned char saved_signature[3];
+
+static int valid_rates[] = {
+   2400, 4800, 9600, 14400, 19200, 38400, 57600, 
+   115200, 230400, 460800, 921600, 3000000
+};
+
+static void ft245r_set_bitclock(PROGRAMMER * pgm) {
+  FT_STATUS r;
+  int rate = 0;
+  int i;
+
+  if (pgm->bitclock == 0.0) { // using default
+	  rate = 235000.0 /2; 
+  } else if (pgm->bitclock >= 0.50 ) {
+	  rate = 500000.0 /2;
+  } else if (pgm->bitclock <  0.01) {
+	  rate =   1000.0 /2;
+  } else {
+	  rate = pgm->bitclock * 1000000.0 /2;
+  }
+  for (i= sizeof(valid_rates)/sizeof(valid_rates[0]) -1; i>=0; --i) 
+  {
+    if (valid_rates[i] <= rate) {
+		rate = valid_rates[i];
+		break;
+    }
+  }
+  if (i<0) rate = valid_rates[0];
+
+  r = FT_SetBaudRate(handle, rate);
+  if ((verbose>=1) || FT245R_DEBUG) {
+	fprintf(stderr," ft245r:  bitclk %d -> ft baud %d\n", 
+			rate * 2, rate);
+  }
+}
+
+static int set_reset(PROGRAMMER * pgm, int val)
+{
+  unsigned char buf[1];
+
+  buf[0] = 0;
+  if (val) buf[0] |= ft245r_reset;
+
+  ft245r_send (pgm, buf, 1);
+  ft245r_recv (pgm, buf, 1);
+  return 0;
+}
+
+static int ft245r_cmd(PROGRAMMER * pgm, unsigned char cmd[4], 
+                      unsigned char res[4]);
+/*
+ * issue the 'program enable' command to the AVR device
+ */
+static int ft245r_program_enable(PROGRAMMER * pgm, AVRPART * p)
+{
+  int retry_count = 0;
+  unsigned char cmd[4];
+  unsigned char res[4];
+  int i,reset_ok;
+
+  ft245r_set_bitclock(pgm);
+
+retry:
+  reset_ok = 0;
+  set_reset(pgm, 0);
+  usleep(5000); // 5ms
+  set_reset(pgm, 1);
+  usleep(5000); // 5ms
+  set_reset(pgm, 0);
+  usleep(5000); // 5ms
+
+  cmd[0] = 0xAC;
+  cmd[1] = 0x53;
+  cmd[2] = 0;
+  cmd[3] = 0;
+  ft245r_cmd(pgm, cmd, res); 
+  if (res[2] == 0x53 ) reset_ok = 1;
+  for (i=0; i<3; i++) {
+     cmd[0] = 0x30;
+     cmd[1] = 0;
+     cmd[2] = i;
+     cmd[3] = 0;
+     ft245r_cmd(pgm, cmd, res); 
+     saved_signature[i] = res[3];
+  }
+
+  if (reset_ok && (saved_signature[0] == 0x1e)) // success
+     return 0;
+
+  if (retry_count < 5) {
+	  retry_count++;
+	  goto retry;
+  }
+  if ((verbose>=1) || FT245R_DEBUG) {
+     fprintf(stderr,
+	    "%s: ft245r_program_enable: failed\n", progname);
+     fflush(stderr);
+  }
+  return -1;
+}
+
+static int ft245r_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m)
+{
+   m->buf[0] = saved_signature[0];
+   m->buf[1] = saved_signature[1];
+   m->buf[2] = saved_signature[2];
+   return 3;
+}
+
+/*
+ * initialize the AVR device and prepare it to accept commands
+ */
+static int ft245r_initialize(PROGRAMMER * pgm, AVRPART * p)
+{
+  return ft245r_program_enable(pgm, p);
+}
+
+static void ft245r_disable(PROGRAMMER * pgm)
+{
+  return;
+}
+
+
+static void ft245r_enable(PROGRAMMER * pgm)
+{
+  /* Do nothing. */
+
+  return;
+}
+
+static inline int set_data(unsigned char *buf, unsigned char data)
+{
+    int j;
+    int buf_pos = 0;
+    unsigned char bit = 0x80;
+
+    for (j=0; j<8; j++) {
+    	buf[buf_pos] = 0;
+	if (data & bit) buf[buf_pos] |= ft245r_mosi;
+	buf_pos++;
+
+    	buf[buf_pos] = 0;
+	if (data & bit) buf[buf_pos] |= ft245r_mosi;
+    	buf[buf_pos] |= ft245r_sck;
+	buf_pos++;
+
+	bit >>= 1;
+    }
+    return buf_pos;
+}
+
+static inline unsigned char extract_data(unsigned char *buf, int offset)
+{
+    int j;
+    int buf_pos = 1;
+    unsigned char bit = 0x80;
+    unsigned char r = 0;
+
+    buf += offset * (8 * FT245R_CYCLES);
+    for (j=0; j<8; j++) {
+	if (buf[buf_pos] & ft245r_miso) {
+		  r |= bit;
+	}
+	buf_pos += FT245R_CYCLES;
+	bit >>= 1;
+    }
+    return r;
+}
+
+/* to check data */
+static inline unsigned char extract_data_out(unsigned char *buf, int offset)
+{
+    int j;
+    int buf_pos = 1;
+    unsigned char bit = 0x80;
+    unsigned char r = 0;
+
+    buf += offset * (8 * FT245R_CYCLES);
+    for (j=0; j<8; j++) {
+	if (buf[buf_pos] & ft245r_mosi) {
+		  r |= bit;
+	}
+	buf_pos += FT245R_CYCLES;
+	bit >>= 1;
+    }
+    return r;
+}
+
+ 
+/*
+ * transmit an AVR device command and return the results; 'cmd' and
+ * 'res' must point to at least a 4 byte data buffer
+ */
+static int ft245r_cmd(PROGRAMMER * pgm, unsigned char cmd[4], 
+                      unsigned char res[4])
+{
+  int i,buf_pos;
+  unsigned char buf[128];
+
+  buf_pos = 0;
+  for (i=0; i<4; i++) {
+     buf_pos += set_data(buf+buf_pos, cmd[i]);
+  }
+  buf[buf_pos] = 0;
+  buf_pos++;
+
+  ft245r_send (pgm, buf, buf_pos);
+  ft245r_recv (pgm, buf, buf_pos);
+  res[0] = extract_data(buf, 0);
+  res[1] = extract_data(buf, 1);
+  res[2] = extract_data(buf, 2);
+  res[3] = extract_data(buf, 3);
+
+  return 0;
+}
+
+static int ft245r_open(PROGRAMMER * pgm, char * port)
+{
+  FT_STATUS r;
+  int devnum = -1;
+  strcpy(pgm->port, port);
+
+#ifdef _WIN32
+  if (!strncasecmp("ft", port, 2) && '0' <= port[2] && port[2] <= '9') {
+     devnum = port[2] - '0';
+  } else {
+    fprintf(stderr,
+	    "%s: invalid portname  %s: use ft0 - ft9\n",
+	    progname,port);
+    exit(1);
+  }
+  r = FT_Open(devnum, &handle);
+#else
+  for (devnum=0; devnum<9; devnum++) {
+     r = FT_Open(devnum, &handle);
+     if (r == FT_OK) break;
+  }
+#endif
+  if (r != FT_OK) {
+    fprintf(stderr,
+	    "%s: %s open failed \n",
+	    progname, port);
+    exit(1);
+  }
+  r = FT_SetBitMode(handle, 0, 0x4); // set Synchronuse BitBang
+  if (r != FT_OK) {
+    fprintf(stderr,
+	    "%s: Synchronuse BitBangMode is not supported\n",
+	    progname);
+     exit(1);
+  }
+#if FT245R_DEBUG
+  fprintf(stderr, "%s: BitBang OK \n", progname);
+  fflush(stderr);
+#endif
+
+  ft245r_ddr = 0;
+  setbit(&ft245r_ddr, pgm->pinno[PIN_AVR_SCK], 1);
+  setbit(&ft245r_ddr, pgm->pinno[PIN_AVR_MOSI], 1);
+  setbit(&ft245r_ddr, pgm->pinno[PIN_AVR_RESET], 1);
+  ft245r_sck = 0;
+  setbit(&ft245r_sck, pgm->pinno[PIN_AVR_SCK], 1);
+  ft245r_mosi = 0;
+  setbit(&ft245r_mosi, pgm->pinno[PIN_AVR_MOSI], 1);
+  ft245r_reset = 0;
+  setbit(&ft245r_reset, pgm->pinno[PIN_AVR_RESET], 1);
+  ft245r_miso = 0;
+  setbit(&ft245r_miso, pgm->pinno[PIN_AVR_MISO], 1);
+  if ((verbose>=1) || FT245R_DEBUG) {
+    fprintf(stderr,
+	    "%s: pin assign miso %d sck %d mosi %d reset %d\n",
+	      progname,
+              pgm->pinno[PIN_AVR_MISO],
+              pgm->pinno[PIN_AVR_SCK],
+              pgm->pinno[PIN_AVR_MOSI],
+              pgm->pinno[PIN_AVR_RESET]);
+  }
+
+  /*
+   * drain any extraneous input
+   */
+  ft245r_drain (pgm, 0);
+#if FT245R_DEBUG
+  fprintf(stderr, "%s: drain OK \n", progname);
+  fflush(stderr);
+#endif
+	
+  return 0;
+}
+
+static void ft245r_close(PROGRAMMER * pgm)
+{
+  FT_Close(handle);  
+}
+
+static void ft245r_display(PROGRAMMER * pgm, char * p)
+{
+  return;
+}
+
+static int ft245r_paged_write_gen(PROGRAMMER * pgm, AVRPART * p,
+                                     AVRMEM * m, int page_size, int n_bytes)
+{
+  unsigned long    i;
+  int rc;
+  for (i=0; i<n_bytes; i++) {
+    report_progress(i, n_bytes, NULL);
+
+    rc = avr_write_byte_default(pgm, p, m, i, m->buf[i]);
+    if (rc != 0) {
+      return -2;
+    }
+
+    if (m->paged) {
+      /*
+       * check to see if it is time to flush the page with a page
+       * write
+       */
+      if (((i % m->page_size) == m->page_size-1) || (i == n_bytes-1)) {
+        rc = avr_write_page(pgm, p, m, i);
+        if (rc != 0) {
+	  return -2;
+        }
+      }
+    }
+  }
+  return i;
+}
+
+static struct ft245r_request {
+	int addr;
+	int bytes;
+	int n;
+	struct ft245r_request *next;
+} *req_head,*req_tail,*req_pool;
+
+static void put_request(int addr, int bytes, int n)
+{
+  struct ft245r_request *p;
+  if (req_pool) {
+     p = req_pool;
+     req_pool = p->next;
+  } else {
+     p = malloc(sizeof(struct ft245r_request));
+     if (!p) {
+       fprintf(stderr, "can't alloc memory\n");
+       exit(1);
+     }
+  }
+  memset(p, 0, sizeof(struct ft245r_request));
+  p->addr = addr;
+  p->bytes = bytes;
+  p->n = n;
+  if (req_tail) {
+     req_tail->next = p;
+     req_tail = p;
+  } else {
+     req_head = req_tail = p;
+  }
+}
+
+static int do_request(PROGRAMMER * pgm, AVRMEM *m)
+{
+  struct ft245r_request *p;
+  int addr, bytes, j, n;
+  char buf[FT245R_FRAGMENT_SIZE+1+128];
+
+  if (!req_head) return 0;
+  p = req_head;
+  req_head = p->next;
+  if (!req_head) req_tail = req_head;
+
+  addr = p->addr;
+  bytes = p->bytes;
+  n = p->n;
+  memset(p, 0, sizeof(struct ft245r_request));
+  p->next = req_pool;
+  req_pool = p;
+
+  ft245r_recv(pgm, buf, bytes);
+  for (j=0; j<n; j++) {
+     m->buf[addr++] = extract_data(buf , (j * 4 + 3));
+  }
+#if 0
+if (n == 0) // paged_write
+fprintf(stderr, "recv addr 0x%04x buf size %d \n",addr, bytes);
+#endif
+  return 1;
+}
+
+static int ft245r_paged_write_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, 
+                                    int page_size, int n_bytes)
+{
+  unsigned int    i,j;
+  int addr,addr_save,buf_pos,do_page_write,req_count;
+  char buf[FT245R_FRAGMENT_SIZE+1+128];
+
+  req_count = 0;
+  addr = 0;
+  for (i=0; i<n_bytes; ) {
+     addr_save = addr;
+     buf_pos = 0;
+     do_page_write = 0;
+     for (j=0; j< FT245R_FRAGMENT_SIZE/8/FT245R_CYCLES/4; j++) {
+        buf_pos += set_data(buf+buf_pos, (addr & 1)?0x48:0x40 ); 
+        buf_pos += set_data(buf+buf_pos, (addr >> 9) & 0xff ); 
+        buf_pos += set_data(buf+buf_pos, (addr >> 1) & 0xff );
+        buf_pos += set_data(buf+buf_pos, m->buf[i]);
+	addr ++;
+	i++;
+	if ( (m->paged) &&
+             (((i % m->page_size) == 0) || (i == n_bytes))) {
+		do_page_write = 1;
+		break;
+	}
+     }
+#if defined(USE_INLINE_WRITE_PAGE)
+     if (do_page_write) {
+        int addr_wk = addr_save - (addr_save % m->page_size);
+        /* If this device has a "load extended address" command, issue it. */
+	if (m->op[AVR_OP_LOAD_EXT_ADDR]) {
+	    unsigned char cmd[4];
+	    OPCODE *lext = m->op[AVR_OP_LOAD_EXT_ADDR];
+
+	    memset(cmd, 0, 4);
+	    avr_set_bits(lext, cmd);
+	    avr_set_addr(lext, cmd, addr_wk/2);
+            buf_pos += set_data(buf+buf_pos, cmd[0]);
+            buf_pos += set_data(buf+buf_pos, cmd[1]);
+            buf_pos += set_data(buf+buf_pos, cmd[2]);
+            buf_pos += set_data(buf+buf_pos, cmd[3]);
+	}
+        buf_pos += set_data(buf+buf_pos, 0x4C); /* Issue Page Write */
+        buf_pos += set_data(buf+buf_pos,(addr_wk >> 9) & 0xff); 
+        buf_pos += set_data(buf+buf_pos,(addr_wk >> 1) & 0xff); 
+        buf_pos += set_data(buf+buf_pos, 0);
+     }
+#endif
+     if (i >= n_bytes) {
+        buf[buf_pos++] = 0; // sck down
+     }
+     ft245r_send(pgm, buf, buf_pos);
+     put_request(addr_save, buf_pos, 0);
+     //ft245r_sync(pgm);
+#if 0
+fprintf(stderr, "send addr 0x%04x bufsize %d [%02x %02x] page_write %d\n",
+		addr_save,buf_pos,
+		extract_data_out(buf , (0*4 + 3) ),
+		extract_data_out(buf , (1*4 + 3) ),
+		do_page_write);
+#endif
+     req_count++;
+     if (req_count > REQ_OUTSTANDINGS)
+        do_request(pgm, m);
+     if (do_page_write) {
+#if defined(USE_INLINE_WRITE_PAGE)
+        while (do_request(pgm, m))
+	     ;
+        usleep(m->max_write_delay);
+#else
+        int addr_wk = addr_save - (addr_save % m->page_size);
+	int rc;
+        while (do_request(pgm, m))
+	     ;
+        rc = avr_write_page(pgm, p, m, addr_wk);
+        if (rc != 0) {
+	  return -2;
+        }
+#endif
+        req_count = 0;
+     }
+     report_progress(i, n_bytes, NULL);
+  }
+  while (do_request(pgm, m))
+	  ;
+  return i;
+}
+
+
+static int ft245r_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
+                              int page_size, int n_bytes)
+{
+  if (strcmp(m->desc, "flash") == 0) {
+    return ft245r_paged_write_flash(pgm, p, m, page_size, n_bytes);
+  }
+  else if (strcmp(m->desc, "eeprom") == 0) {
+    return ft245r_paged_write_gen(pgm, p, m, page_size, n_bytes);
+  }
+  else {
+    return -2;
+  }
+}
+
+static int ft245r_paged_load_gen(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, 
+                             int page_size, int n_bytes)
+{
+  unsigned char    rbyte;
+  unsigned long    i;
+  int rc;
+
+  for (i=0; i<n_bytes; i++) {
+     rc = avr_read_byte_default(pgm, p, m, i, &rbyte);
+     if (rc != 0) {
+       return -2;
+     }
+     m->buf[i] = rbyte;
+     report_progress(i, n_bytes, NULL);
+  }
+  return 0;
+}
+
+
+static int ft245r_paged_load_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, 
+                             int page_size, int n_bytes)
+{
+  unsigned long    i,j,n;
+  //int rc;
+  int addr,addr_save,buf_pos;
+  int req_count = 0;
+  char buf[FT245R_FRAGMENT_SIZE+1];
+
+  addr = 0;
+  for (i=0; i<n_bytes; ) {
+     buf_pos = 0;
+     addr_save = addr;
+     for (j=0; j< FT245R_FRAGMENT_SIZE/8/FT245R_CYCLES/4; j++) {
+	if (i >= n_bytes) break;
+        buf_pos += set_data(buf+buf_pos, (addr & 1)?0x28:0x20 ); 
+        buf_pos += set_data(buf+buf_pos, (addr >> 9) & 0xff ); 
+        buf_pos += set_data(buf+buf_pos, (addr >> 1) & 0xff );
+        buf_pos += set_data(buf+buf_pos, 0);
+	addr ++;
+	i++;
+     }
+     if (i >= n_bytes) {
+        buf[buf_pos++] = 0; // sck down
+     }
+     n = j;
+     ft245r_send(pgm, buf, buf_pos);
+     put_request(addr_save, buf_pos, n);
+     req_count++;
+     if (req_count > REQ_OUTSTANDINGS)
+        do_request(pgm, m);
+     report_progress(i, n_bytes, NULL);
+  }
+  while (do_request(pgm, m))
+	  ;
+  return 0;
+}
+
+static int ft245r_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, 
+                             int page_size, int n_bytes)
+{
+  if (strcmp(m->desc, "flash") == 0) {
+    return ft245r_paged_load_flash(pgm, p, m, page_size, n_bytes);
+  }
+  else if (strcmp(m->desc, "eeprom") == 0) {
+    return ft245r_paged_load_gen(pgm, p, m, page_size, n_bytes);
+  }
+  else {
+    return -2;
+  }
+}
+
+void ft245r_initpgm(PROGRAMMER * pgm)
+{
+  strcpy(pgm->type, "ft245r");
+
+  /*
+   * mandatory functions
+   */
+  pgm->initialize     = ft245r_initialize;
+  pgm->display        = ft245r_display;
+  pgm->enable         = ft245r_enable;
+  pgm->disable        = ft245r_disable;
+  pgm->program_enable = ft245r_program_enable;
+  pgm->chip_erase     = ft245r_chip_erase;
+  pgm->cmd            = ft245r_cmd;
+  pgm->open           = ft245r_open;
+  pgm->close          = ft245r_close;
+  pgm->read_byte      = avr_read_byte_default;
+  pgm->write_byte     = avr_write_byte_default;
+
+  /*
+   * optional functions
+   */
+  pgm->paged_write = ft245r_paged_write;
+  pgm->paged_load = ft245r_paged_load;
+
+  pgm->read_sig_bytes = ft245r_read_sig_bytes;
+}
+#else
+static int ft245r_initialize(PROGRAMMER * pgm, AVRPART * p)
+{
+	return -1;
+}
+
+void ft245r_initpgm(PROGRAMMER * pgm)
+{
+  pgm->initialize     = ft245r_initialize;
+}
+
+#endif
