Ticket #20526: patch-ft245r.c.diff

File patch-ft245r.c.diff, 18.1 KB (added by ranauei@…, 15 years ago)
  • new file ft245r.c

    - +  
     1/*
     2 * avrdude - A Downloader/Uploader for AVR device programmers
     3 * Copyright (C) 2003-2004  Theodore A. Roth  <troth@openavr.org>
     4 *
     5 * This program is free software; you can redistribute it and/or modify
     6 * it under the terms of the GNU General Public License as published by
     7 * the Free Software Foundation; either version 2 of the License, or
     8 * (at your option) any later version.
     9 *
     10 * This program is distributed in the hope that it will be useful,
     11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13 * GNU General Public License for more details.
     14 *
     15 * You should have received a copy of the GNU General Public License
     16 * along with this program; if not, write to the Free Software
     17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     18 */
     19
     20/* $Id$ */
     21
     22/* ft245r -- FT245R/FT232R Synchronous BitBangMode Programmer
     23  default pin assign
     24               FT232R / FT245R
     25  miso  = 1;  # RxD   / D1
     26  sck   = 0;  # RTS   / D0
     27  mosi  = 2;  # TxD   / D2
     28  reset = 4;  # DTR   / D4
     29*/
     30
     31#include "ac_cfg.h"
     32
     33#include <stdio.h>
     34#include <stdlib.h>
     35#include <string.h>
     36#include <errno.h>
     37#include <sys/time.h>
     38#include <unistd.h>
     39
     40#include "avr.h"
     41#include "pindefs.h"
     42#include "pgm.h"
     43#include "bitbang.h"
     44#include "ft245r.h"
     45
     46#if defined(_WIN32) || defined(SUPPORT_FT245R)
     47#if defined(_WIN32)
     48#include <windows.h>
     49#include "ftd2xx.h"
     50#else
     51#include "ftd2xx.h"
     52#endif
     53
     54#define FT245R_CYCLES   2
     55#define FT245R_FRAGMENT_SIZE  512
     56#define REQ_OUTSTANDINGS        10
     57//#define USE_INLINE_WRITE_PAGE
     58
     59#define FT245R_DEBUG    1
     60
     61extern char * progname;
     62extern int do_cycles;
     63extern int ovsigck;
     64extern int verbose;
     65
     66static FT_HANDLE handle;
     67
     68static unsigned char ft245r_ddr;
     69static unsigned char ft245r_sck;
     70static unsigned char ft245r_mosi;
     71static unsigned char ft245r_reset;
     72static unsigned char ft245r_miso;
     73
     74static inline void setbit(UCHAR *data, int pinno, int v)
     75{
     76        if (v) {
     77                *data |= (1 << (pinno));
     78        } else {
     79                *data &= ~(1 <<(pinno));
     80        }
     81}
     82
     83static int ft245r_send(PROGRAMMER * pgm, char * buf, size_t len)
     84{
     85  FT_STATUS r;
     86  DWORD rlen;
     87  r = FT_Write(handle, buf, len, &rlen);
     88  if (r == FT_OK) return 0;
     89  if (len != rlen) return -1;
     90  return -1;
     91}
     92
     93
     94static int ft245r_recv(PROGRAMMER * pgm, char * buf, size_t len)
     95{
     96  FT_STATUS r;
     97  DWORD rlen;
     98
     99  r = FT_Read(handle, buf, len, &rlen);
     100
     101  if (r != FT_OK || len != rlen) {
     102    fprintf(stderr,
     103            "%s: ft245r_recv(): programmer is not responding\n",
     104            progname);
     105    exit(1);
     106  }
     107  return 0;
     108}
     109
     110
     111static int ft245r_drain(PROGRAMMER * pgm, int display)
     112{
     113  FT_STATUS r;
     114  DWORD n;
     115  r = FT_SetBitMode(handle, 0, 0x0);    // reset
     116  if (r != FT_OK) return -1;
     117  r = FT_SetBitMode(handle, ft245r_ddr, 0x4); // set Synchronuse BitBang
     118  if (r != FT_OK) return -1;
     119
     120  r = FT_GetQueueStatus(handle, &n);
     121  if (r != FT_OK) return -1;
     122  if (n) {
     123        fprintf(stderr, "ft245r_drain called but queue is not empty %d \n",
     124                (int)n);
     125  }
     126  return 0;
     127}
     128
     129static inline int ft245r_sync(PROGRAMMER * pgm)
     130{
     131  FT_STATUS r;
     132  UCHAR ch;
     133  r = FT_GetBitMode(handle, &ch);
     134  if (r != FT_OK) return -1;
     135  return 0;
     136}
     137
     138static int ft245r_chip_erase(PROGRAMMER * pgm, AVRPART * p)
     139{
     140  unsigned char cmd[4];
     141  unsigned char res[4];
     142
     143  if (p->op[AVR_OP_CHIP_ERASE] == NULL) {
     144    fprintf(stderr, "chip erase instruction not defined for part \"%s\"\n",
     145            p->desc);
     146    return -1;
     147  }
     148
     149  memset(cmd, 0, sizeof(cmd));
     150
     151  avr_set_bits(p->op[AVR_OP_CHIP_ERASE], cmd);
     152  pgm->cmd(pgm, cmd, res);
     153  usleep(p->chip_erase_delay);
     154  pgm->initialize(pgm, p);
     155
     156  return 0;
     157}
     158
     159static unsigned char saved_signature[3];
     160
     161static int valid_rates[] = {
     162   2400, 4800, 9600, 14400, 19200, 38400, 57600,
     163   115200, 230400, 460800, 921600, 3000000
     164};
     165
     166static void ft245r_set_bitclock(PROGRAMMER * pgm) {
     167  FT_STATUS r;
     168  int rate = 0;
     169  int i;
     170
     171  if (pgm->bitclock == 0.0) { // using default
     172          rate = 235000.0 /2;
     173  } else if (pgm->bitclock >= 0.50 ) {
     174          rate = 500000.0 /2;
     175  } else if (pgm->bitclock <  0.01) {
     176          rate =   1000.0 /2;
     177  } else {
     178          rate = pgm->bitclock * 1000000.0 /2;
     179  }
     180  for (i= sizeof(valid_rates)/sizeof(valid_rates[0]) -1; i>=0; --i)
     181  {
     182    if (valid_rates[i] <= rate) {
     183                rate = valid_rates[i];
     184                break;
     185    }
     186  }
     187  if (i<0) rate = valid_rates[0];
     188
     189  r = FT_SetBaudRate(handle, rate);
     190  if ((verbose>=1) || FT245R_DEBUG) {
     191        fprintf(stderr," ft245r:  bitclk %d -> ft baud %d\n",
     192                        rate * 2, rate);
     193  }
     194}
     195
     196static int set_reset(PROGRAMMER * pgm, int val)
     197{
     198  unsigned char buf[1];
     199
     200  buf[0] = 0;
     201  if (val) buf[0] |= ft245r_reset;
     202
     203  ft245r_send (pgm, buf, 1);
     204  ft245r_recv (pgm, buf, 1);
     205  return 0;
     206}
     207
     208static int ft245r_cmd(PROGRAMMER * pgm, unsigned char cmd[4],
     209                      unsigned char res[4]);
     210/*
     211 * issue the 'program enable' command to the AVR device
     212 */
     213static int ft245r_program_enable(PROGRAMMER * pgm, AVRPART * p)
     214{
     215  int retry_count = 0;
     216  unsigned char cmd[4];
     217  unsigned char res[4];
     218  int i,reset_ok;
     219
     220  ft245r_set_bitclock(pgm);
     221
     222retry:
     223  reset_ok = 0;
     224  set_reset(pgm, 0);
     225  usleep(5000); // 5ms
     226  set_reset(pgm, 1);
     227  usleep(5000); // 5ms
     228  set_reset(pgm, 0);
     229  usleep(5000); // 5ms
     230
     231  cmd[0] = 0xAC;
     232  cmd[1] = 0x53;
     233  cmd[2] = 0;
     234  cmd[3] = 0;
     235  ft245r_cmd(pgm, cmd, res);
     236  if (res[2] == 0x53 ) reset_ok = 1;
     237  for (i=0; i<3; i++) {
     238     cmd[0] = 0x30;
     239     cmd[1] = 0;
     240     cmd[2] = i;
     241     cmd[3] = 0;
     242     ft245r_cmd(pgm, cmd, res);
     243     saved_signature[i] = res[3];
     244  }
     245
     246  if (reset_ok && (saved_signature[0] == 0x1e)) // success
     247     return 0;
     248
     249  if (retry_count < 5) {
     250          retry_count++;
     251          goto retry;
     252  }
     253  if ((verbose>=1) || FT245R_DEBUG) {
     254     fprintf(stderr,
     255            "%s: ft245r_program_enable: failed\n", progname);
     256     fflush(stderr);
     257  }
     258  return -1;
     259}
     260
     261static int ft245r_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m)
     262{
     263   m->buf[0] = saved_signature[0];
     264   m->buf[1] = saved_signature[1];
     265   m->buf[2] = saved_signature[2];
     266   return 3;
     267}
     268
     269/*
     270 * initialize the AVR device and prepare it to accept commands
     271 */
     272static int ft245r_initialize(PROGRAMMER * pgm, AVRPART * p)
     273{
     274  return ft245r_program_enable(pgm, p);
     275}
     276
     277static void ft245r_disable(PROGRAMMER * pgm)
     278{
     279  return;
     280}
     281
     282
     283static void ft245r_enable(PROGRAMMER * pgm)
     284{
     285  /* Do nothing. */
     286
     287  return;
     288}
     289
     290static inline int set_data(unsigned char *buf, unsigned char data)
     291{
     292    int j;
     293    int buf_pos = 0;
     294    unsigned char bit = 0x80;
     295
     296    for (j=0; j<8; j++) {
     297        buf[buf_pos] = 0;
     298        if (data & bit) buf[buf_pos] |= ft245r_mosi;
     299        buf_pos++;
     300
     301        buf[buf_pos] = 0;
     302        if (data & bit) buf[buf_pos] |= ft245r_mosi;
     303        buf[buf_pos] |= ft245r_sck;
     304        buf_pos++;
     305
     306        bit >>= 1;
     307    }
     308    return buf_pos;
     309}
     310
     311static inline unsigned char extract_data(unsigned char *buf, int offset)
     312{
     313    int j;
     314    int buf_pos = 1;
     315    unsigned char bit = 0x80;
     316    unsigned char r = 0;
     317
     318    buf += offset * (8 * FT245R_CYCLES);
     319    for (j=0; j<8; j++) {
     320        if (buf[buf_pos] & ft245r_miso) {
     321                  r |= bit;
     322        }
     323        buf_pos += FT245R_CYCLES;
     324        bit >>= 1;
     325    }
     326    return r;
     327}
     328
     329/* to check data */
     330static inline unsigned char extract_data_out(unsigned char *buf, int offset)
     331{
     332    int j;
     333    int buf_pos = 1;
     334    unsigned char bit = 0x80;
     335    unsigned char r = 0;
     336
     337    buf += offset * (8 * FT245R_CYCLES);
     338    for (j=0; j<8; j++) {
     339        if (buf[buf_pos] & ft245r_mosi) {
     340                  r |= bit;
     341        }
     342        buf_pos += FT245R_CYCLES;
     343        bit >>= 1;
     344    }
     345    return r;
     346}
     347
     348 
     349/*
     350 * transmit an AVR device command and return the results; 'cmd' and
     351 * 'res' must point to at least a 4 byte data buffer
     352 */
     353static int ft245r_cmd(PROGRAMMER * pgm, unsigned char cmd[4],
     354                      unsigned char res[4])
     355{
     356  int i,buf_pos;
     357  unsigned char buf[128];
     358
     359  buf_pos = 0;
     360  for (i=0; i<4; i++) {
     361     buf_pos += set_data(buf+buf_pos, cmd[i]);
     362  }
     363  buf[buf_pos] = 0;
     364  buf_pos++;
     365
     366  ft245r_send (pgm, buf, buf_pos);
     367  ft245r_recv (pgm, buf, buf_pos);
     368  res[0] = extract_data(buf, 0);
     369  res[1] = extract_data(buf, 1);
     370  res[2] = extract_data(buf, 2);
     371  res[3] = extract_data(buf, 3);
     372
     373  return 0;
     374}
     375
     376static int ft245r_open(PROGRAMMER * pgm, char * port)
     377{
     378  FT_STATUS r;
     379  int devnum = -1;
     380  strcpy(pgm->port, port);
     381
     382#ifdef _WIN32
     383  if (!strncasecmp("ft", port, 2) && '0' <= port[2] && port[2] <= '9') {
     384     devnum = port[2] - '0';
     385  } else {
     386    fprintf(stderr,
     387            "%s: invalid portname  %s: use ft0 - ft9\n",
     388            progname,port);
     389    exit(1);
     390  }
     391  r = FT_Open(devnum, &handle);
     392#else
     393  for (devnum=0; devnum<9; devnum++) {
     394     r = FT_Open(devnum, &handle);
     395     if (r == FT_OK) break;
     396  }
     397#endif
     398  if (r != FT_OK) {
     399    fprintf(stderr,
     400            "%s: %s open failed \n",
     401            progname, port);
     402    exit(1);
     403  }
     404  r = FT_SetBitMode(handle, 0, 0x4); // set Synchronuse BitBang
     405  if (r != FT_OK) {
     406    fprintf(stderr,
     407            "%s: Synchronuse BitBangMode is not supported\n",
     408            progname);
     409     exit(1);
     410  }
     411#if FT245R_DEBUG
     412  fprintf(stderr, "%s: BitBang OK \n", progname);
     413  fflush(stderr);
     414#endif
     415
     416  ft245r_ddr = 0;
     417  setbit(&ft245r_ddr, pgm->pinno[PIN_AVR_SCK], 1);
     418  setbit(&ft245r_ddr, pgm->pinno[PIN_AVR_MOSI], 1);
     419  setbit(&ft245r_ddr, pgm->pinno[PIN_AVR_RESET], 1);
     420  ft245r_sck = 0;
     421  setbit(&ft245r_sck, pgm->pinno[PIN_AVR_SCK], 1);
     422  ft245r_mosi = 0;
     423  setbit(&ft245r_mosi, pgm->pinno[PIN_AVR_MOSI], 1);
     424  ft245r_reset = 0;
     425  setbit(&ft245r_reset, pgm->pinno[PIN_AVR_RESET], 1);
     426  ft245r_miso = 0;
     427  setbit(&ft245r_miso, pgm->pinno[PIN_AVR_MISO], 1);
     428  if ((verbose>=1) || FT245R_DEBUG) {
     429    fprintf(stderr,
     430            "%s: pin assign miso %d sck %d mosi %d reset %d\n",
     431              progname,
     432              pgm->pinno[PIN_AVR_MISO],
     433              pgm->pinno[PIN_AVR_SCK],
     434              pgm->pinno[PIN_AVR_MOSI],
     435              pgm->pinno[PIN_AVR_RESET]);
     436  }
     437
     438  /*
     439   * drain any extraneous input
     440   */
     441  ft245r_drain (pgm, 0);
     442#if FT245R_DEBUG
     443  fprintf(stderr, "%s: drain OK \n", progname);
     444  fflush(stderr);
     445#endif
     446       
     447  return 0;
     448}
     449
     450static void ft245r_close(PROGRAMMER * pgm)
     451{
     452  FT_Close(handle); 
     453}
     454
     455static void ft245r_display(PROGRAMMER * pgm, char * p)
     456{
     457  return;
     458}
     459
     460static int ft245r_paged_write_gen(PROGRAMMER * pgm, AVRPART * p,
     461                                     AVRMEM * m, int page_size, int n_bytes)
     462{
     463  unsigned long    i;
     464  int rc;
     465  for (i=0; i<n_bytes; i++) {
     466    report_progress(i, n_bytes, NULL);
     467
     468    rc = avr_write_byte_default(pgm, p, m, i, m->buf[i]);
     469    if (rc != 0) {
     470      return -2;
     471    }
     472
     473    if (m->paged) {
     474      /*
     475       * check to see if it is time to flush the page with a page
     476       * write
     477       */
     478      if (((i % m->page_size) == m->page_size-1) || (i == n_bytes-1)) {
     479        rc = avr_write_page(pgm, p, m, i);
     480        if (rc != 0) {
     481          return -2;
     482        }
     483      }
     484    }
     485  }
     486  return i;
     487}
     488
     489static struct ft245r_request {
     490        int addr;
     491        int bytes;
     492        int n;
     493        struct ft245r_request *next;
     494} *req_head,*req_tail,*req_pool;
     495
     496static void put_request(int addr, int bytes, int n)
     497{
     498  struct ft245r_request *p;
     499  if (req_pool) {
     500     p = req_pool;
     501     req_pool = p->next;
     502  } else {
     503     p = malloc(sizeof(struct ft245r_request));
     504     if (!p) {
     505       fprintf(stderr, "can't alloc memory\n");
     506       exit(1);
     507     }
     508  }
     509  memset(p, 0, sizeof(struct ft245r_request));
     510  p->addr = addr;
     511  p->bytes = bytes;
     512  p->n = n;
     513  if (req_tail) {
     514     req_tail->next = p;
     515     req_tail = p;
     516  } else {
     517     req_head = req_tail = p;
     518  }
     519}
     520
     521static int do_request(PROGRAMMER * pgm, AVRMEM *m)
     522{
     523  struct ft245r_request *p;
     524  int addr, bytes, j, n;
     525  char buf[FT245R_FRAGMENT_SIZE+1+128];
     526
     527  if (!req_head) return 0;
     528  p = req_head;
     529  req_head = p->next;
     530  if (!req_head) req_tail = req_head;
     531
     532  addr = p->addr;
     533  bytes = p->bytes;
     534  n = p->n;
     535  memset(p, 0, sizeof(struct ft245r_request));
     536  p->next = req_pool;
     537  req_pool = p;
     538
     539  ft245r_recv(pgm, buf, bytes);
     540  for (j=0; j<n; j++) {
     541     m->buf[addr++] = extract_data(buf , (j * 4 + 3));
     542  }
     543#if 0
     544if (n == 0) // paged_write
     545fprintf(stderr, "recv addr 0x%04x buf size %d \n",addr, bytes);
     546#endif
     547  return 1;
     548}
     549
     550static int ft245r_paged_write_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
     551                                    int page_size, int n_bytes)
     552{
     553  unsigned int    i,j;
     554  int addr,addr_save,buf_pos,do_page_write,req_count;
     555  char buf[FT245R_FRAGMENT_SIZE+1+128];
     556
     557  req_count = 0;
     558  addr = 0;
     559  for (i=0; i<n_bytes; ) {
     560     addr_save = addr;
     561     buf_pos = 0;
     562     do_page_write = 0;
     563     for (j=0; j< FT245R_FRAGMENT_SIZE/8/FT245R_CYCLES/4; j++) {
     564        buf_pos += set_data(buf+buf_pos, (addr & 1)?0x48:0x40 );
     565        buf_pos += set_data(buf+buf_pos, (addr >> 9) & 0xff );
     566        buf_pos += set_data(buf+buf_pos, (addr >> 1) & 0xff );
     567        buf_pos += set_data(buf+buf_pos, m->buf[i]);
     568        addr ++;
     569        i++;
     570        if ( (m->paged) &&
     571             (((i % m->page_size) == 0) || (i == n_bytes))) {
     572                do_page_write = 1;
     573                break;
     574        }
     575     }
     576#if defined(USE_INLINE_WRITE_PAGE)
     577     if (do_page_write) {
     578        int addr_wk = addr_save - (addr_save % m->page_size);
     579        /* If this device has a "load extended address" command, issue it. */
     580        if (m->op[AVR_OP_LOAD_EXT_ADDR]) {
     581            unsigned char cmd[4];
     582            OPCODE *lext = m->op[AVR_OP_LOAD_EXT_ADDR];
     583
     584            memset(cmd, 0, 4);
     585            avr_set_bits(lext, cmd);
     586            avr_set_addr(lext, cmd, addr_wk/2);
     587            buf_pos += set_data(buf+buf_pos, cmd[0]);
     588            buf_pos += set_data(buf+buf_pos, cmd[1]);
     589            buf_pos += set_data(buf+buf_pos, cmd[2]);
     590            buf_pos += set_data(buf+buf_pos, cmd[3]);
     591        }
     592        buf_pos += set_data(buf+buf_pos, 0x4C); /* Issue Page Write */
     593        buf_pos += set_data(buf+buf_pos,(addr_wk >> 9) & 0xff);
     594        buf_pos += set_data(buf+buf_pos,(addr_wk >> 1) & 0xff);
     595        buf_pos += set_data(buf+buf_pos, 0);
     596     }
     597#endif
     598     if (i >= n_bytes) {
     599        buf[buf_pos++] = 0; // sck down
     600     }
     601     ft245r_send(pgm, buf, buf_pos);
     602     put_request(addr_save, buf_pos, 0);
     603     //ft245r_sync(pgm);
     604#if 0
     605fprintf(stderr, "send addr 0x%04x bufsize %d [%02x %02x] page_write %d\n",
     606                addr_save,buf_pos,
     607                extract_data_out(buf , (0*4 + 3) ),
     608                extract_data_out(buf , (1*4 + 3) ),
     609                do_page_write);
     610#endif
     611     req_count++;
     612     if (req_count > REQ_OUTSTANDINGS)
     613        do_request(pgm, m);
     614     if (do_page_write) {
     615#if defined(USE_INLINE_WRITE_PAGE)
     616        while (do_request(pgm, m))
     617             ;
     618        usleep(m->max_write_delay);
     619#else
     620        int addr_wk = addr_save - (addr_save % m->page_size);
     621        int rc;
     622        while (do_request(pgm, m))
     623             ;
     624        rc = avr_write_page(pgm, p, m, addr_wk);
     625        if (rc != 0) {
     626          return -2;
     627        }
     628#endif
     629        req_count = 0;
     630     }
     631     report_progress(i, n_bytes, NULL);
     632  }
     633  while (do_request(pgm, m))
     634          ;
     635  return i;
     636}
     637
     638
     639static int ft245r_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
     640                              int page_size, int n_bytes)
     641{
     642  if (strcmp(m->desc, "flash") == 0) {
     643    return ft245r_paged_write_flash(pgm, p, m, page_size, n_bytes);
     644  }
     645  else if (strcmp(m->desc, "eeprom") == 0) {
     646    return ft245r_paged_write_gen(pgm, p, m, page_size, n_bytes);
     647  }
     648  else {
     649    return -2;
     650  }
     651}
     652
     653static int ft245r_paged_load_gen(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
     654                             int page_size, int n_bytes)
     655{
     656  unsigned char    rbyte;
     657  unsigned long    i;
     658  int rc;
     659
     660  for (i=0; i<n_bytes; i++) {
     661     rc = avr_read_byte_default(pgm, p, m, i, &rbyte);
     662     if (rc != 0) {
     663       return -2;
     664     }
     665     m->buf[i] = rbyte;
     666     report_progress(i, n_bytes, NULL);
     667  }
     668  return 0;
     669}
     670
     671
     672static int ft245r_paged_load_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
     673                             int page_size, int n_bytes)
     674{
     675  unsigned long    i,j,n;
     676  //int rc;
     677  int addr,addr_save,buf_pos;
     678  int req_count = 0;
     679  char buf[FT245R_FRAGMENT_SIZE+1];
     680
     681  addr = 0;
     682  for (i=0; i<n_bytes; ) {
     683     buf_pos = 0;
     684     addr_save = addr;
     685     for (j=0; j< FT245R_FRAGMENT_SIZE/8/FT245R_CYCLES/4; j++) {
     686        if (i >= n_bytes) break;
     687        buf_pos += set_data(buf+buf_pos, (addr & 1)?0x28:0x20 );
     688        buf_pos += set_data(buf+buf_pos, (addr >> 9) & 0xff );
     689        buf_pos += set_data(buf+buf_pos, (addr >> 1) & 0xff );
     690        buf_pos += set_data(buf+buf_pos, 0);
     691        addr ++;
     692        i++;
     693     }
     694     if (i >= n_bytes) {
     695        buf[buf_pos++] = 0; // sck down
     696     }
     697     n = j;
     698     ft245r_send(pgm, buf, buf_pos);
     699     put_request(addr_save, buf_pos, n);
     700     req_count++;
     701     if (req_count > REQ_OUTSTANDINGS)
     702        do_request(pgm, m);
     703     report_progress(i, n_bytes, NULL);
     704  }
     705  while (do_request(pgm, m))
     706          ;
     707  return 0;
     708}
     709
     710static int ft245r_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
     711                             int page_size, int n_bytes)
     712{
     713  if (strcmp(m->desc, "flash") == 0) {
     714    return ft245r_paged_load_flash(pgm, p, m, page_size, n_bytes);
     715  }
     716  else if (strcmp(m->desc, "eeprom") == 0) {
     717    return ft245r_paged_load_gen(pgm, p, m, page_size, n_bytes);
     718  }
     719  else {
     720    return -2;
     721  }
     722}
     723
     724void ft245r_initpgm(PROGRAMMER * pgm)
     725{
     726  strcpy(pgm->type, "ft245r");
     727
     728  /*
     729   * mandatory functions
     730   */
     731  pgm->initialize     = ft245r_initialize;
     732  pgm->display        = ft245r_display;
     733  pgm->enable         = ft245r_enable;
     734  pgm->disable        = ft245r_disable;
     735  pgm->program_enable = ft245r_program_enable;
     736  pgm->chip_erase     = ft245r_chip_erase;
     737  pgm->cmd            = ft245r_cmd;
     738  pgm->open           = ft245r_open;
     739  pgm->close          = ft245r_close;
     740  pgm->read_byte      = avr_read_byte_default;
     741  pgm->write_byte     = avr_write_byte_default;
     742
     743  /*
     744   * optional functions
     745   */
     746  pgm->paged_write = ft245r_paged_write;
     747  pgm->paged_load = ft245r_paged_load;
     748
     749  pgm->read_sig_bytes = ft245r_read_sig_bytes;
     750}
     751#else
     752static int ft245r_initialize(PROGRAMMER * pgm, AVRPART * p)
     753{
     754        return -1;
     755}
     756
     757void ft245r_initpgm(PROGRAMMER * pgm)
     758{
     759  pgm->initialize     = ft245r_initialize;
     760}
     761
     762#endif