From 00791df09d0fdc63fd95167ca682dcd144f1ecb8 Mon Sep 17 00:00:00 2001
From: Joerg Wunsch <j@uriah.heep.sax.de>
Date: Tue, 29 Aug 2006 23:12:15 +0000
Subject: [PATCH] Rework the exit specs so they actually work again.  It should
 be possible to extend them for other programmers than PPI now (serbb,
 stk500*).

* pgm.h: Keep the exit specs in an abstract form inside struct
programmer_t.  (Should be moved out into some programmer-specific
structure.)  Rename the getexitspecs() method into
parseexitspecs().
* main.c: Move the exit specs stuff out to the programmer
implementation.
* par.c: Implement the new exit spec handling.  Everything is now
done using the generic abstraction layer.

Closes bug #16443: No disable Resetsignal at the end of
Programming Session

Obviates need for patch #5057: quick and dirty Hack to unset Reset
after Programming


git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk@629 81a1dc3b-b13d-400b-aceb-764788c761c2
---
 avrdude/ChangeLog | 18 +++++++++++++
 avrdude/main.c    | 16 ++----------
 avrdude/par.c     | 65 +++++++++++++++++++++++++++++++----------------
 avrdude/pgm.h     | 16 +++++++++++-
 4 files changed, 78 insertions(+), 37 deletions(-)

diff --git a/avrdude/ChangeLog b/avrdude/ChangeLog
index bdb1903e..5cd18690 100644
--- a/avrdude/ChangeLog
+++ b/avrdude/ChangeLog
@@ -1,3 +1,21 @@
+2006-08-30 Joerg Wunsch <j@uriah.heep.sax.de>
+
+	Rework the exit specs so they actually work again.  It should be
+	possible to extend them for other programmers than PPI now (serbb,
+	stk500*).
+	* pgm.h: Keep the exit specs in an abstract form inside struct
+	programmer_t.  (Should be moved out into some programmer-specific
+	structure.)  Rename the getexitspecs() method into
+	parseexitspecs().
+	* main.c: Move the exit specs stuff out to the programmer
+	implementation.
+	* par.c: Implement the new exit spec handling.  Everything is now
+	done using the generic abstraction layer.
+	Closes bug #16443: No disable Resetsignal at the end of
+	Programming Session
+	Obviates need for patch #5057: quick and dirty Hack to unset Reset
+	after Programming
+
 2006-08-29 Joerg Wunsch <j@uriah.heep.sax.de>
 
 	This patch has been contributed by an anonymous developer
diff --git a/avrdude/main.c b/avrdude/main.c
index 4de31113..a29a2b6e 100644
--- a/avrdude/main.c
+++ b/avrdude/main.c
@@ -673,8 +673,6 @@ int main(int argc, char * argv [])
   int     terminal;    /* 1=enter terminal mode, 0=don't */
   int     nowrite;     /* don't actually write anything to the chip */
   int     verify;      /* perform a verify operation */
-  int     ppisetbits;  /* bits to set in ppi data register at exit */
-  int     ppiclrbits;  /* bits to clear in ppi data register at exit */
   char  * exitspecs;   /* exit specs string from command line */
   char  * programmer;  /* programmer id */
   char  * partdesc;    /* part id */
@@ -733,8 +731,6 @@ int main(int argc, char * argv [])
   nowrite       = 0;
   verify        = 1;        /* on by default */
   quell_progress = 0;
-  ppisetbits    = 0;
-  ppiclrbits    = 0;
   exitspecs     = NULL;
   pgm           = NULL;
   programmer    = default_programmer;
@@ -1074,13 +1070,13 @@ int main(int argc, char * argv [])
 
 
   if (exitspecs != NULL) {
-    if (pgm->getexitspecs == NULL) {
+    if (pgm->parseexitspecs == NULL) {
       fprintf(stderr,
               "%s: WARNING: -E option not supported by this programmer type\n",
               progname);
       exitspecs = NULL;
     }
-    else if (pgm->getexitspecs(pgm, exitspecs, &ppisetbits, &ppiclrbits) < 0) {
+    else if (pgm->parseexitspecs(pgm, exitspecs) < 0) {
       usage();
       exit(1);
     }
@@ -1152,14 +1148,6 @@ int main(int argc, char * argv [])
 
   exitrc = 0;
 
-  /*
-   * handle exit specs. FIXME: this should be moved to "par.c"
-   */
-  if (strcmp(pgm->type, "PPI") == 0) {
-    pgm->ppidata &= ~ppiclrbits;
-    pgm->ppidata |= ppisetbits;
-  }
-
   /*
    * enable the programmer
    */
diff --git a/avrdude/par.c b/avrdude/par.c
index ba9adfc7..9b36c831 100644
--- a/avrdude/par.c
+++ b/avrdude/par.c
@@ -180,17 +180,6 @@ static int par_highpulsepin(PROGRAMMER * pgm, int pin)
   return 0;
 }
 
-static int par_getpinmask(int pin)
-{
-  pin &= PIN_MASK;
-
-  if (pin < 1 || pin > 17)
-    return -1;
-
-  return ppipins[pin-1].bit;
-}
-
-
 static char * pins_to_str(unsigned int pmask)
 {
   static char buf[64];
@@ -291,14 +280,46 @@ static int par_open(PROGRAMMER * pgm, char * port)
 
 static void par_close(PROGRAMMER * pgm)
 {
+
   /*
    * Restore pin values before closing,
    * but ensure that buffers are turned off.
    */
-  pgm->ppidata |= pgm->pinno[PPI_AVR_BUFF];
   ppi_setall(pgm->fd, PPIDATA, pgm->ppidata);
   ppi_setall(pgm->fd, PPICTRL, pgm->ppictrl);
 
+  par_setpin(pgm, pgm->pinno[PPI_AVR_BUFF], 1);
+
+  /*
+   * Handle exit specs.
+   */
+  switch (pgm->exit_reset) {
+  case EXIT_RESET_ENABLED:
+    par_setpin(pgm, pgm->pinno[PIN_AVR_RESET], 0);
+    break;
+
+  case EXIT_RESET_DISABLED:
+    par_setpin(pgm, pgm->pinno[PIN_AVR_RESET], 1);
+    break;
+
+  case EXIT_RESET_UNSPEC:
+    /* Leave it alone. */
+    break;
+  }
+  switch (pgm->exit_vcc) {
+  case EXIT_VCC_ENABLED:
+    par_setmany(pgm, pgm->pinno[PPI_AVR_VCC], 1);
+    break;
+
+  case EXIT_VCC_DISABLED:
+    par_setmany(pgm, pgm->pinno[PPI_AVR_VCC], 0);
+    break;
+
+  case EXIT_VCC_UNSPEC:
+    /* Leave it alone. */
+    break;
+  }
+
   ppi_close(pgm->fd);
   pgm->fd = -1;
 }
@@ -348,27 +369,26 @@ static void par_display(PROGRAMMER * pgm, char * p)
           p, pgm->pinno[PIN_LED_VFY]);
 }
 
+
 /*
  * parse the -E string
  */
-static int par_getexitspecs(PROGRAMMER * pgm, char *s, int *set, int *clr)
+static int par_parseexitspecs(PROGRAMMER * pgm, char *s)
 {
   char *cp;
 
   while ((cp = strtok(s, ","))) {
     if (strcmp(cp, "reset") == 0) {
-      *clr |= par_getpinmask(pgm->pinno[PIN_AVR_RESET]);
+      pgm->exit_reset = EXIT_RESET_ENABLED;
     }
     else if (strcmp(cp, "noreset") == 0) {
-      *set |= par_getpinmask(pgm->pinno[PIN_AVR_RESET]);
+      pgm->exit_reset = EXIT_RESET_DISABLED;
     }
     else if (strcmp(cp, "vcc") == 0) {
-      if (pgm->pinno[PPI_AVR_VCC])
-        *set |= pgm->pinno[PPI_AVR_VCC];
+      pgm->exit_vcc = EXIT_VCC_ENABLED;
     }
     else if (strcmp(cp, "novcc") == 0) {
-      if (pgm->pinno[PPI_AVR_VCC])
-        *clr |= pgm->pinno[PPI_AVR_VCC];
+      pgm->exit_vcc = EXIT_VCC_DISABLED;
     }
     else {
       return -1;
@@ -379,12 +399,13 @@ static int par_getexitspecs(PROGRAMMER * pgm, char *s, int *set, int *clr)
   return 0;
 }
 
-
-
 void par_initpgm(PROGRAMMER * pgm)
 {
   strcpy(pgm->type, "PPI");
 
+  pgm->exit_vcc = EXIT_VCC_UNSPEC;
+  pgm->exit_reset = EXIT_RESET_UNSPEC;
+
   pgm->rdy_led        = bitbang_rdy_led;
   pgm->err_led        = bitbang_err_led;
   pgm->pgm_led        = bitbang_pgm_led;
@@ -403,7 +424,7 @@ void par_initpgm(PROGRAMMER * pgm)
   pgm->setpin         = par_setpin;
   pgm->getpin         = par_getpin;
   pgm->highpulsepin   = par_highpulsepin;
-  pgm->getexitspecs   = par_getexitspecs;
+  pgm->parseexitspecs = par_parseexitspecs;
 }
 
 #else  /* !HAVE_PARPORT */
diff --git a/avrdude/pgm.h b/avrdude/pgm.h
index be4bd105..cb644f89 100644
--- a/avrdude/pgm.h
+++ b/avrdude/pgm.h
@@ -38,12 +38,26 @@
 
 extern LISTID       programmers;
 
+typedef enum {
+  EXIT_VCC_UNSPEC,
+  EXIT_VCC_ENABLED,
+  EXIT_VCC_DISABLED
+} exit_vcc_t;
+
+typedef enum {
+  EXIT_RESET_UNSPEC,
+  EXIT_RESET_ENABLED,
+  EXIT_RESET_DISABLED
+} exit_reset_t;
+
 typedef struct programmer_t {
   LISTID id;
   char desc[PGM_DESCLEN];
   char type[PGM_TYPELEN];
   char port[PGM_PORTLEN];
   unsigned int pinno[N_PINS];
+  exit_vcc_t exit_vcc;
+  exit_reset_t exit_reset;
   int ppidata;
   int ppictrl;
   int baudrate;
@@ -85,7 +99,7 @@ typedef struct programmer_t {
   int  (*setpin)         (struct programmer_t * pgm, int pin, int value);
   int  (*getpin)         (struct programmer_t * pgm, int pin);
   int  (*highpulsepin)   (struct programmer_t * pgm, int pin);
-  int  (*getexitspecs)   (struct programmer_t * pgm, char *s, int *set, int *clr);
+  int  (*parseexitspecs) (struct programmer_t * pgm, char *s);
   char config_file[PATH_MAX]; /* config file where defined */
   int  lineno;                /* config file line number */
   char flag;		      /* for private use of the programmer */