Ticket #20526: patch-serjtag.c.diff

File patch-serjtag.c.diff, 17.9 KB (added by ranauei@…, 15 years ago)
  • new file serjtag.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/* serjtag -- Serial Jtag Cable (using AVR) */
     23
     24#include "ac_cfg.h"
     25
     26#include <stdio.h>
     27#include <stdlib.h>
     28#include <string.h>
     29#include <errno.h>
     30#include <sys/time.h>
     31#include <unistd.h>
     32
     33#include "avr.h"
     34#include "pgm.h"
     35#include "serjtag.h"
     36#include "serial.h"
     37
     38#define SERJTAG_DEBUG   0
     39
     40extern char * progname;
     41extern int do_cycles;
     42extern int ovsigck;
     43extern int verbose;
     44
     45static int serjtag_send(PROGRAMMER * pgm, char * buf, size_t len)
     46{
     47  return serial_send(&pgm->fd, (unsigned char *)buf, len);
     48}
     49
     50
     51static int serjtag_recv(PROGRAMMER * pgm, char * buf, size_t len)
     52{
     53  int rv;
     54
     55  rv = serial_recv(&pgm->fd, (unsigned char *)buf, len);
     56  if (rv < 0) {
     57    fprintf(stderr,
     58            "%s: serjtag_recv(): programmer is not responding\n",
     59            progname);
     60    exit(1);
     61  }
     62  return 0;
     63}
     64
     65
     66static int serjtag_drain(PROGRAMMER * pgm, int display)
     67{
     68  return serial_drain(&pgm->fd, display);
     69}
     70
     71static int serjtag_chip_erase(PROGRAMMER * pgm, AVRPART * p)
     72{
     73  unsigned char cmd[4];
     74  unsigned char res[4];
     75
     76  if (p->op[AVR_OP_CHIP_ERASE] == NULL) {
     77    fprintf(stderr, "chip erase instruction not defined for part \"%s\"\n",
     78            p->desc);
     79    return -1;
     80  }
     81
     82  memset(cmd, 0, sizeof(cmd));
     83
     84  avr_set_bits(p->op[AVR_OP_CHIP_ERASE], cmd);
     85  pgm->cmd(pgm, cmd, res);
     86  usleep(p->chip_erase_delay);
     87  pgm->initialize(pgm, p);
     88
     89  return 0;
     90}
     91
     92#if SERJTAG_DEBUG == 1
     93static void  serjtag_check(PROGRAMMER * pgm) {
     94  int i,bytes;
     95  char buf[128];
     96
     97fprintf(stderr,"check response\n");
     98fflush(stderr);
     99  i=0;
     100  buf[i++] = 'r';
     101  buf[i++] = 0;
     102  buf[i++] = 0;
     103  serjtag_send(pgm, buf, i);
     104  serjtag_recv(pgm, buf, 1);
     105fprintf(stderr,"\tCommonad = 0x%02x %c\n",buf[0],buf[0]);
     106  serjtag_recv(pgm, buf+1, 1);
     107fprintf(stderr,"\tFlags = 0x%02x\n",buf[1]);
     108  serjtag_recv(pgm, buf+2, 1);
     109fprintf(stderr,"\tBytes = 0x%02x\n",buf[2]);
     110  bytes = buf[2];
     111  if (buf[1] & JTAG_BITS) bytes++;
     112  if (bytes) {
     113        fprintf(stderr,"\t");
     114        for (i=0; i<bytes; i++) {
     115                serjtag_recv(pgm, buf+2+i, 1);
     116                fprintf(stderr,"%02x ",buf[2+i]);
     117        }
     118        fprintf(stderr,"\n");
     119  }
     120}
     121#endif
     122
     123static int serjtag_recv_j(PROGRAMMER * pgm, char * buf, size_t len, int verbose)
     124{
     125  int bytes;
     126  serjtag_recv(pgm, buf, 3);    /* header */
     127#if 0
     128  if (verbose) {
     129        fprintf(stderr,"recv_j(0) %c 0x%02x %d :",buf[0],buf[1],buf[2]);
     130  }
     131#endif
     132  bytes = buf[2];
     133  if (buf[1] & JTAG_BITS) {
     134          bytes++;
     135  }
     136  len -= 3;
     137  if (len >= bytes) {
     138    serjtag_recv(pgm, buf+3, bytes);
     139  } else {
     140        char tmp[1];
     141        int i;
     142        serjtag_recv(pgm, buf+3, len);
     143        for (i=0; i< bytes - len; i++) {
     144                serjtag_recv(pgm, tmp, 1);
     145        }
     146  }
     147  if (verbose) {
     148        int i;
     149        fprintf(stderr,"recv_j %c 0x%02x %d :",buf[0],buf[1],buf[2]);
     150        for (i=0; i<bytes; i++) {
     151                fprintf(stderr,"%02x ",buf[3+i]&0xff);
     152        }
     153        fprintf(stderr,"\n");
     154  }
     155  return 0;
     156}
     157
     158static int delay_param = 3;
     159static int use_delay = JTAG_USE_DELAY;
     160static unsigned char saved_signature[3];
     161
     162static void serjtag_set_delay(PROGRAMMER * pgm) {
     163   use_delay = JTAG_USE_DELAY;
     164  if (pgm->bitclock == 0.0) { // using default
     165        delay_param = 3;
     166  } else if (pgm->bitclock >= 4.0) {
     167        delay_param = 0;
     168        use_delay = 0;
     169  } else {
     170        delay_param =  (int)((2.26/3.0) / pgm->bitclock);
     171        if (delay_param > 15) delay_param = 15;
     172  }
     173  if ((verbose>=1) || SERJTAG_DEBUG) {
     174        fprintf(stderr," serjtag:delay %d (%s) ( bitclk %.3f )\n"
     175                ,delay_param, use_delay? "enabled":"disabled", pgm->bitclock);
     176  }
     177}
     178
     179/*
     180 * issue the 'program enable' command to the AVR device
     181 */
     182static int serjtag_program_enable(PROGRAMMER * pgm, AVRPART * p)
     183{
     184  char buf[128];
     185  int i;
     186  int retry_count = 0;
     187
     188   serjtag_set_delay(pgm);
     189
     190  serjtag_send(pgm, "j", 1); // enter jtag mode
     191  serjtag_recv(pgm, buf, 1);
     192  if (buf[0] != 'Y') {
     193          return -1;
     194  }
     195#if SERJTAG_DEBUG == 1
     196fprintf(stderr," Enter jtag mode .. success \n");
     197#endif
     198
     199retry:
     200  i=0;
     201  buf[i++] = 's';               /* Set Port */
     202  buf[i++] = 0;                 /* flags */
     203  buf[i++] = 1;                 /* bytes */
     204  buf[i++] = 0;  /* TDI(MOSI) = 0, TMS(RESET) = 0, TCK(SCK) = 0 */
     205  serjtag_send(pgm, buf, i);
     206  usleep(5000); // 5ms
     207  i=0;
     208  buf[i++] = 's'; /* Set Port */
     209  buf[i++] = 0;  /* flags */
     210  buf[i++] = 1;   /* bytes */
     211  buf[i++] = JTAG_SET_TMS;  /* TDI(MOSI) = 0, TMS(RESET) = 1, TCK(SCK) = 0 */
     212  serjtag_send(pgm, buf, i);
     213  usleep(5000); // 5ms
     214  i=0;
     215  buf[i++] = 's';               /* Set Port */
     216  buf[i++] = 0;                 /* flags */
     217  buf[i++] = 1;                 /* bytes */
     218  buf[i++] = delay_param & JTAG_SET_DELAY;  /* TMS(RESET) = 0, set delay */
     219  serjtag_send(pgm, buf, i);
     220  usleep(5000); // 5ms
     221
     222  i = 0;
     223  buf[i++] = 'd';               /* PUT TDI Stream */
     224  buf[i++] = JTAG_RECIEVE | JTAG_USE_DELAY;
     225  buf[i++] = 0;                 /* bytes : set after*/
     226  /* check */
     227  buf[i++] = 0xAC;
     228  buf[i++] = 0x53;
     229  buf[i++] = 0;
     230  buf[i++] = 0;
     231  /* signature[0] */
     232  buf[i++] = 0x30;
     233  buf[i++] = 0;
     234  buf[i++] = 0;
     235  buf[i++] = 0;
     236  /* signature[1] */
     237  buf[i++] = 0x30;
     238  buf[i++] = 0;
     239  buf[i++] = 1;
     240  buf[i++] = 0;
     241  /* signature[2] */
     242  buf[i++] = 0x30;
     243  buf[i++] = 0;
     244  buf[i++] = 2;
     245  buf[i++] = 0;
     246  buf[2] = i - 3; /* set bytes */
     247  buf[i++] = 'r';                /* Request Recieved Data */
     248  buf[i++] = 0;                  /* flags */
     249  buf[i++] = 0;                  /* bytes */
     250  serjtag_send(pgm, buf, i);
     251#if SERJTAG_DEBUG == 1
     252  fprintf(stderr,"enabling program delay %d retry %d\n",delay_param,retry_count);
     253#endif
     254  serjtag_recv_j(pgm, buf, 3+4*4, SERJTAG_DEBUG?1:0);
     255
     256  saved_signature[0] = buf[3+4*1 +3];
     257  saved_signature[1] = buf[3+4*2 +3];
     258  saved_signature[2] = buf[3+4*3 +3];
     259#if SERJTAG_DEBUG == 1
     260  fprintf(stderr,"saved_signature %02x %02x %02x\n"
     261                  , saved_signature[0]
     262                  , saved_signature[1]
     263                  , saved_signature[2]);
     264#endif
     265  if ((buf[3+2] == 0x53) && (saved_signature[0] == 0x1e)) // success
     266  {
     267          return 0;
     268  }
     269  if (retry_count < 5) {
     270          retry_count++;
     271          goto retry;
     272  }
     273  return -1;
     274}
     275
     276static int serjtag_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m)
     277{
     278   m->buf[0] = saved_signature[0];
     279   m->buf[1] = saved_signature[1];
     280   m->buf[2] = saved_signature[2];
     281   return 3;
     282}
     283
     284/*
     285 * initialize the AVR device and prepare it to accept commands
     286 */
     287static int serjtag_initialize(PROGRAMMER * pgm, AVRPART * p)
     288{
     289  char id[8];
     290  char sw[3];
     291
     292  /* Get the programmer identifier. Programmer returns exactly 7 chars
     293     _without_ the null.*/
     294
     295  serjtag_send(pgm, "S", 1);
     296  serjtag_recv(pgm, id, 7);
     297  id[7] = 0;
     298
     299  /* Get the HW and SW versions to see if the programmer is present. */
     300
     301  serjtag_send(pgm, "V", 1);
     302  serjtag_recv(pgm, sw, 2);
     303  sw[2] = 0;
     304
     305  fprintf(stderr, "Found programmer: Id = \"%s\"; Revison = %s\n", id, sw);
     306
     307  if (strncmp(id, "SERJTAG", 7) && strncmp(id, "USB910A", 7)
     308       && strncmp(id, "USB910A", 7) )
     309  {
     310     fprintf(stderr, "\tserjtag protocol not supported.\n");
     311     exit(1);
     312  }
     313  return serjtag_program_enable(pgm, p);
     314}
     315
     316static void serjtag_disable(PROGRAMMER * pgm)
     317{
     318  char buf[2];
     319  serjtag_send(pgm, "V", 1);
     320  serjtag_recv(pgm, buf, 2);
     321
     322  return;
     323}
     324
     325
     326static void serjtag_enable(PROGRAMMER * pgm)
     327{
     328  /* Do nothing. */
     329
     330  return;
     331}
     332
     333
     334/*
     335 * transmit an AVR device command and return the results; 'cmd' and
     336 * 'res' must point to at least a 4 byte data buffer
     337 */
     338static int serjtag_cmd(PROGRAMMER * pgm, unsigned char cmd[4],
     339                      unsigned char res[4])
     340{
     341  char buf[10];
     342
     343  /* FIXME: Insert version check here */
     344
     345  buf[0] = 'd';                 /* PUT TDI Stream */
     346  buf[1] = JTAG_RECIEVE | use_delay;
     347  buf[2] = 4;                   /* bytes */
     348  buf[3] = cmd[0];
     349  buf[4] = cmd[1];
     350  buf[5] = cmd[2];
     351  buf[6] = cmd[3];
     352  buf[7] = 'r';                 /* Request Recieved Data */
     353  buf[8] = 0;
     354  buf[9] = 0;
     355
     356  serjtag_send (pgm, buf, 10);
     357  serjtag_recv (pgm, buf, 7);
     358
     359  res[0] = 0x00;                /* Dummy value */
     360  res[1] = cmd[0];
     361  res[2] = cmd[1];
     362  res[3] = buf[6];
     363
     364  return 0;
     365}
     366
     367
     368static int serjtag_open(PROGRAMMER * pgm, char * port)
     369{
     370  /*
     371   *  If baudrate was not specified use 19.200 Baud
     372   */
     373  if(pgm->baudrate == 0) {
     374    pgm->baudrate = 19200;
     375  }
     376
     377  strcpy(pgm->port, port);
     378  serial_open(port, pgm->baudrate, &pgm->fd);
     379
     380  /*
     381   * drain any extraneous input
     382   */
     383  serjtag_drain (pgm, 0);
     384       
     385  return 0;
     386}
     387
     388static void serjtag_close(PROGRAMMER * pgm)
     389{
     390  serial_close(&pgm->fd);
     391  pgm->fd.ifd = -1;
     392}
     393
     394
     395static void serjtag_display(PROGRAMMER * pgm, char * p)
     396{
     397  return;
     398}
     399
     400static int serjtag_paged_write_gen(PROGRAMMER * pgm, AVRPART * p,
     401                                     AVRMEM * m, int page_size, int n_bytes)
     402{
     403  unsigned long    i;
     404  int rc;
     405  for (i=0; i<n_bytes; i++) {
     406    report_progress(i, n_bytes, NULL);
     407
     408    rc = avr_write_byte_default(pgm, p, m, i, m->buf[i]);
     409    if (rc != 0) {
     410      return -2;
     411    }
     412
     413    if (m->paged) {
     414      /*
     415       * check to see if it is time to flush the page with a page
     416       * write
     417       */
     418      if (((i % m->page_size) == m->page_size-1) || (i == n_bytes-1)) {
     419        rc = avr_write_page(pgm, p, m, i);
     420        if (rc != 0) {
     421          return -2;
     422        }
     423      }
     424    }
     425  }
     426  return i;
     427}
     428
     429#define SERJTAG_BUFFERD_WRITE
     430
     431#ifdef SERJTAG_BUFFERD_WRITE
     432#define SERJTAG_BUF_SIZE        1024
     433unsigned char *serjtag_buf;
     434int serjtag_buf_len;
     435
     436static void serjtag_flush(PROGRAMMER * pgm) {
     437   if (!serjtag_buf || (serjtag_buf_len == 0)) return;
     438   serjtag_send(pgm, serjtag_buf, serjtag_buf_len);
     439   serjtag_buf_len = 0;
     440}
     441
     442static void serjtag_write(PROGRAMMER * pgm, unsigned char *buf, int size) {
     443  if (!serjtag_buf) {
     444     serjtag_buf = malloc(SERJTAG_BUF_SIZE);
     445     if (!serjtag_buf) {
     446       fprintf(stderr, "can't alloc memory\n");
     447       exit(1);
     448     }
     449  }
     450  if (SERJTAG_BUF_SIZE < serjtag_buf_len + size) {
     451      serjtag_flush(pgm);
     452  }
     453  memcpy(serjtag_buf + serjtag_buf_len, buf, size);
     454  serjtag_buf_len += size;
     455}
     456#else
     457static void serjtag_flush(PROGRAMMER * pgm) {
     458}
     459static void serjtag_write(PROGRAMMER * pgm, unsigned char *buf, int size) {
     460   serjtag_send(pgm, buf, size);
     461}
     462#endif
     463
     464#define USE_INLINE_WRITE_PAGE
     465
     466static int serjtag_paged_write_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
     467                                    int page_size, int n_bytes)
     468{
     469  unsigned int    i,j;
     470  int addr,addr_save,buf_pos,do_page_write;
     471  char buf[128];
     472
     473  addr = 0;
     474  for (i=0; i<n_bytes; ) {
     475     addr_save = addr;
     476     buf_pos = 0;
     477     buf[buf_pos++] = 'd';               /* PUT TDI Stream */
     478     buf[buf_pos++] = use_delay;
     479     buf[buf_pos++] = 0; /* bytes : set after */
     480     do_page_write = 0;
     481     for (j=0; j<(JTAG_BUFSIZE-3)/4; j++) { // 15 bytes
     482        buf[buf_pos++] = (addr & 1)?0x48:0x40;
     483        buf[buf_pos++] = (addr >> 9) & 0xff;
     484        buf[buf_pos++] = (addr >> 1) & 0xff;
     485        buf[buf_pos++] = m->buf[i];
     486        addr ++;
     487        i++;
     488        if ( (m->paged) &&
     489             (((i % m->page_size) == 0) || (i == n_bytes))) {
     490                do_page_write = 1;
     491                break;
     492        }
     493     }
     494     buf[2] = buf_pos - 3;
     495#ifdef USE_INLINE_WRITE_PAGE
     496     if (do_page_write) {
     497        int addr_wk = addr_save - (addr_save % m->page_size);
     498        /* If this device has a "load extended address" command, issue it. */
     499        if (m->op[AVR_OP_LOAD_EXT_ADDR]) {
     500            OPCODE *lext = m->op[AVR_OP_LOAD_EXT_ADDR];
     501
     502            buf[buf_pos++] = 'd';               /* PUT TDI Stream */
     503            buf[buf_pos++] = JTAG_RECIEVE | use_delay;
     504            buf[buf_pos++] = 4; /* bytes */
     505
     506            memset(buf+buf_pos, 0, 4);
     507            avr_set_bits(lext, buf+buf_pos);
     508            avr_set_addr(lext, buf+buf_pos, addr/2);
     509            buf_pos += 4;
     510        }
     511        buf[buf_pos++] = 'd';               /* PUT TDI Stream */
     512        buf[buf_pos++] = JTAG_RECIEVE | use_delay;
     513        buf[buf_pos++] = 4; /* bytes */
     514        buf[buf_pos++] = 0x4C; /* Issue Page Write */
     515        buf[buf_pos++] = (addr_wk >> 9) & 0xff;
     516        buf[buf_pos++] = (addr_wk >> 1) & 0xff;
     517        buf[buf_pos++] = 0;
     518        buf[buf_pos++] = 'r';                /* Request Recieved Data */
     519        buf[buf_pos++] = 0;
     520        buf[buf_pos++] = 0;
     521     }
     522#endif
     523     serjtag_write(pgm, buf, buf_pos);
     524#if 0
     525fprintf(stderr, "send addr 0x%04x size %d bufsize %d i %d page_write %d\n",
     526                addr_wk,buf[2],buf_pos,i,do_page_write);
     527#endif
     528     if (do_page_write) {
     529#ifdef USE_INLINE_WRITE_PAGE
     530        serjtag_flush(pgm);
     531        usleep(m->max_write_delay);
     532        serjtag_recv_j(pgm, buf, 4 + 3, 0);
     533#else
     534        int rc;
     535        serjtag_flush(pgm);
     536        addr_wk = (i-1) / m->page_size * m->page_size;
     537        rc = avr_write_page(pgm, p, m, addr_wk);
     538        if (rc != 0) {
     539          return -2;
     540        }
     541#endif
     542     }
     543     report_progress(i, n_bytes, NULL);
     544  }
     545  serjtag_flush(pgm);
     546  return i;
     547}
     548
     549
     550static int serjtag_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
     551                              int page_size, int n_bytes)
     552{
     553  if (strcmp(m->desc, "flash") == 0) {
     554    return serjtag_paged_write_flash(pgm, p, m, page_size, n_bytes);
     555  }
     556  else if (strcmp(m->desc, "eeprom") == 0) {
     557    return serjtag_paged_write_gen(pgm, p, m, page_size, n_bytes);
     558  }
     559  else {
     560    return -2;
     561  }
     562}
     563
     564
     565static int serjtag_paged_load_gen(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
     566                             int page_size, int n_bytes)
     567{
     568  unsigned char    rbyte;
     569  unsigned long    i;
     570  int rc;
     571
     572  for (i=0; i<n_bytes; i++) {
     573     rc = avr_read_byte_default(pgm, p, m, i, &rbyte);
     574     if (rc != 0) {
     575       return -2;
     576     }
     577     m->buf[i] = rbyte;
     578     report_progress(i, n_bytes, NULL);
     579  }
     580  return 0;
     581}
     582
     583
     584static struct serjtag_request {
     585        int addr;
     586        int bytes;
     587        int n;
     588        struct serjtag_request *next;
     589} *req_head,*req_tail,*req_pool;
     590
     591static void put_request(int addr, int bytes, int n)
     592{
     593  struct serjtag_request *p;
     594  if (req_pool) {
     595     p = req_pool;
     596     req_pool = p->next;
     597  } else {
     598     p = malloc(sizeof(struct serjtag_request));
     599     if (!p) {
     600       fprintf(stderr, "can't alloc memory\n");
     601       exit(1);
     602     }
     603  }
     604  memset(p, 0, sizeof(struct serjtag_request));
     605  p->addr = addr;
     606  p->bytes = bytes;
     607  p->n = n;
     608  if (req_tail) {
     609     req_tail->next = p;
     610     req_tail = p;
     611  } else {
     612     req_head = req_tail = p;
     613  }
     614}
     615
     616static int do_request(PROGRAMMER * pgm, AVRMEM *m)
     617{
     618  struct serjtag_request *p;
     619  int addr, bytes, j, n;
     620  char buf[128];
     621
     622  if (!req_head) return 0;
     623  p = req_head;
     624  req_head = p->next;
     625  if (!req_head) req_tail = req_head;
     626
     627  addr = p->addr;
     628  bytes = p->bytes;
     629  n = p->n;
     630  memset(p, 0, sizeof(struct serjtag_request));
     631  p->next = req_pool;
     632  req_pool = p;
     633
     634  serjtag_recv_j(pgm, buf, bytes + 3, 0);
     635  for (j=0; j<n; j++) {
     636     m->buf[addr++] = buf[3 + 4*j + 3];
     637  }
     638  return 1;
     639}
     640
     641#define REQ_OUTSTANDINGS        10
     642static int serjtag_paged_load_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
     643                             int page_size, int n_bytes)
     644{
     645  unsigned long    i,j,n;
     646  //int rc;
     647  int addr,addr_save,bytes,buf_pos;
     648  int req_count = 0;
     649  char buf[128];
     650
     651  addr = 0;
     652  for (i=0; i<n_bytes; ) {
     653     buf_pos = 0;
     654     buf[buf_pos++] = 'd';               /* PUT TDI Stream */
     655     buf[buf_pos++] = JTAG_RECIEVE | use_delay;
     656     buf[buf_pos++] = 0; /* bytes : set after */
     657     addr_save = addr;
     658     for (j=0; j<(JTAG_BUFSIZE-3*2)/4; j++) { // 14 bytes
     659        if (i >= n_bytes) break;
     660        buf[buf_pos++] = (addr & 1)?0x28:0x20;
     661        buf[buf_pos++] = (addr >> 9) & 0xff;
     662        buf[buf_pos++] = (addr >> 1) & 0xff;
     663        buf[buf_pos++] = 0;
     664        addr ++;
     665        i++;
     666     }
     667     n = j;
     668     buf[2] = bytes =  buf_pos - 3;
     669     buf[buf_pos++] = 'r';                /* Request Recieved Data */
     670     buf[buf_pos++] = 0;
     671     buf[buf_pos++] = 0;
     672     serjtag_send(pgm, buf, buf_pos);
     673     put_request(addr_save, bytes, n);
     674     req_count++;
     675     if (req_count > REQ_OUTSTANDINGS)
     676        do_request(pgm, m);
     677     report_progress(i, n_bytes, NULL);
     678  }
     679  while (do_request(pgm, m))
     680          ;
     681  return 0;
     682}
     683
     684static int serjtag_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
     685                             int page_size, int n_bytes)
     686{
     687  if (strcmp(m->desc, "flash") == 0) {
     688    return serjtag_paged_load_flash(pgm, p, m, page_size, n_bytes);
     689  }
     690  else if (strcmp(m->desc, "eeprom") == 0) {
     691    return serjtag_paged_load_gen(pgm, p, m, page_size, n_bytes);
     692  }
     693  else {
     694    return -2;
     695  }
     696}
     697
     698void serjtag_initpgm(PROGRAMMER * pgm)
     699{
     700  strcpy(pgm->type, "serjtag");
     701
     702  /*
     703   * mandatory functions
     704   */
     705  pgm->initialize     = serjtag_initialize;
     706  pgm->display        = serjtag_display;
     707  pgm->enable         = serjtag_enable;
     708  pgm->disable        = serjtag_disable;
     709  pgm->program_enable = serjtag_program_enable;
     710  pgm->chip_erase     = serjtag_chip_erase;
     711  pgm->cmd            = serjtag_cmd;
     712  pgm->open           = serjtag_open;
     713  pgm->close          = serjtag_close;
     714  pgm->read_byte      = avr_read_byte_default;
     715  pgm->write_byte     = avr_write_byte_default;
     716
     717  /*
     718   * optional functions
     719   */
     720
     721  pgm->paged_write = serjtag_paged_write;
     722  pgm->paged_load = serjtag_paged_load;
     723  pgm->read_sig_bytes = serjtag_read_sig_bytes;
     724}