/************************************************************************
*                                                                       *
*                             ispCODE.C                                 *
*   Lattice Semiconductor Corp. Copyright 1995.                         *
*                                                                       *
*   3.00  Howard Tang   04/12/95 1st V3.0 Release.                      *
*   3.01  Howard Tang   05/11/95 Add dynamic ues support for operation  *
*                                "PU".                                  *
*                                                                       *
************************************************************************/

#include <stdio.h>
#include <dos.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "lattice.h"

int             inputport,
                outputport,
                port;
/*prototypes*/
void            find_port(void);
int             power_ok(void);
int             port_ok(void);
void            pulse_width(unsigned int milliseconds);
void            execute(void);
void            move_to_id_state(void);
void            program_ues(unsigned char *ues, unsigned char *ues_mask,
                                        unsigned char *buff, int data_length);
int             ispstream_pump(char *filename, int *end);
void            error_handler(int rcode, char *message);


/*************************************************************
*                                                            *
*                         FIND_PORT                          *
*                                                            *
*  This procedure tries to locate the isp cable on parallel  *
*  ports 1,2, or 3, and sets inputport, and outputport       *
*  appropriately.  It returns upon successfully finding the  *
*  first port which has the cable attached, or upon failing  *
*  to find the cable attached to any port.                   *
*                                                            *
*************************************************************/

void            find_port()
{
   port = 0;

   do {                                          /* find cable on port */
      ++port;

      if (port == 1) {
         outputport = outport1;
         inputport = inport1;
      } else if (port == 2) {
         outputport = outport2;
         inputport = inport2;
      } else {
         outputport = outport3;
         inputport = inport3;
      }
   }
   while (!port_ok() && (port < 3));
}


/*************************************************************
*                                                            *
*                          POWER OK                          *
*                                                            *
*  This procedure determines if the parallel port has power. *
*                                                            *
*************************************************************/

int             power_ok()
{
   int             rcode,
                   oldrcode;

   outp(outputport, NUL);
   oldrcode = (in_VCC_OK & inp(inputport));
   pulse_width(5);
   rcode = (in_VCC_OK & inp(inputport));
   if ((oldrcode != rcode) || (rcode == 0) || (oldrcode == 0))
      rcode = POWER_OFF;
   return (rcode);
}


/*************************************************************
*                                                            *
*                          PORT OK                           *
*                                                            *
*  This procedure determines if the cable is connected to    *
*  specified parallel port.                                  *
*                                                            *
*************************************************************/

int             port_ok()
{
   int             d1,
                   d2;
   int             rcode;
   outp(outputport, NUL + out_SENSE_CABLE_OUT);
   d1 = (in_CABLE_SENSE_IN & inp(inputport));
   outp(outputport, NUL);
   d2 = (in_CABLE_SENSE_IN & inp(inputport));


   if ((d2 != d1) || (NUL > 0))
      rcode = 1;
   else
      rcode = CABLE_NOT_FOUND;
   return rcode;
}

/*************************************************************
*                                                            *
*                         PULSE_WIDTH                        *
*                                                            *
*************************************************************/


void            pulse_width(unsigned int milliseconds)
{
   static unsigned int ticks_per_ms = 0;
   static int      mode2 = false;
   static long     pre_ticks = 0L;
   unsigned int    start,
                   end;
   long            ticks,
                   cur_ticks;
   static int      count = 0;


   cur_ticks = 0L;
   outp(0x43, 0x00);
   start = inp(0x40);
   start += inp(0x40) << 8;
   if (ticks_per_ms == 0) {
      ticks_per_ms = (0xFFFF / 55) * 2;
      if (start & 0x0001) {
         ticks_per_ms = 0xFFFF / 55;
         mode2 = true;
      }
   }
   ticks = (long) ticks_per_ms *milliseconds;
   while (ticks > 0L) {
      if (pre_ticks == 0L)
         pre_ticks = cur_ticks;
      else if (count < 5) {                      /* calibration count *//* keep
                                                  * the most conservative ticks
                                                  * per loop as calibrated
                                                  * value */
         if (pre_ticks > cur_ticks)
            pre_ticks = cur_ticks;
         count++;
      }
      outp(0x43, 0x00);
      end = inp(0x40);
      end += inp(0x40) << 8;
      if ((!mode2) && (end & 0x0001)) {
         ticks_per_ms = 0xFFFF / 55;
         ticks -= (long) ticks_per_ms *milliseconds;
         mode2 = true;
         if (ticks <= 0L)
            break;                               /* done already */
      }
      cur_ticks = (long) (start - end);          /* number of ticks elapsed */
      if (cur_ticks == 0L) {                     /* this can happen only when
                                                  * in Window DOS */
         cur_ticks = pre_ticks;
         ticks -= cur_ticks;
      } else if (cur_ticks > 0L)
         ticks -= cur_ticks;
      else {
         cur_ticks = (long) (0xFFFF - end + start);
         ticks -= cur_ticks;
      }
      /* safe guard against stolen ticks in Window DOS */
      if ((pre_ticks > 0L) && ((cur_ticks - pre_ticks) > (ticks_per_ms / 4))) {
         ticks += (cur_ticks - pre_ticks);
         cur_ticks = pre_ticks;
      }
      start = end;
   }
}



/*************************************************************
*                                                            *
*                       SHIFT/EXECUTE                        *
*                                                            *
*************************************************************/
void            execute()
{

   outp(outputport, out_MODE);
   outp(outputport, out_MODE + out_SDI);
   outp(outputport, out_MODE + out_SDI + out_SCLK);
   outp(outputport, out_MODE + out_SDI);
   outp(outputport, out_MODE);
   outp(outputport, NUL);

}


/*************************************************************
*                                                            *
*                      MOVE TO ID STATE                      *
*                                                            *
*************************************************************/

void            move_to_id_state()
{
   outp(outputport, out_MODE);                   /* MOVE DEVICE TO ID STATE */
   pulse_width(10);                              /* allow 10 mS delay for 1st
                                                  * clock */
   outp(outputport, out_MODE + out_SCLK);
   outp(outputport, out_MODE);
   outp(outputport, NUL);
}



/*************************************************************
*                                                            *
*                     PROGRAM_UES                            *
*                                                            *
*  ues-      contain the ues string read from ispLSI devices *
*            under operation "PU" in the .dld file with fill *
*            bits if any removed.                            *
*            user can modify the content of ues.             *
*  ues_mask- bit 1 represent a valid ues bit. user shall not *
*            alter its content.                              *
*  buff-     contain the ues string with fill bits if needed.*
*            user shall not alter its content                *
*  This function is to program the UES at *ues in place of   *
*  the UES embedded in the ispSTREAM file or JEDEC file.     *
*  Example: The .dld file is as follows:                     *
*           1032  PU 1032.jed                                *
*           3256  PV 3256.jed                                *
*           1032  PU 1032_1.jed
*                                                            *
*           The exisiting UES in the ispLSI 1032 devices are *
*           read and store in *ues. The 1032.jed files may or*
*           may not have UES, however it will be ignored.    *
*           Users may alter the content in *ues prior to     *
*           re-program the UES into the ispLSI 1032 devices. *
*           Please note that the string length of *ues is the*
*           maximum length of the UES. Excess UES will be    *
*           truncated. The ues string length is the sum of   *
*           the UES length of devices with operation "PU".   *
*           So the example above has ues string length of    *
*           160+160=320 bits or 40 ASCII characters long.    *
*************************************************************/
void            program_ues(unsigned char *ues, unsigned char *ues_mask,
                                         unsigned char *buff, int data_length)
{
   int             i,
                   pos,
                   col,
                   in_pos,
                   in_col;
   unsigned char   curch,
                   xch;

   pos = in_pos = 0;
   col = in_col = 8;

   curch = xch = NUL;
   /*This is the location to insert your own UES operation codes*/
   /*example:
   printf("\nThe UES string to be program in:\n");
   printf("(%s)\n", ues);  */
   for (i = 0; i < data_length; i++) {
      --col;
      if (col < 0) {
         col = 7;
         pos++;
      }
      if ((ues_mask[pos] >> col) & 0x01) {
         --in_col;
         if (in_col < 0) {
            in_col = 7;
            in_pos++;
         }
         if ((ues[in_pos] >> in_col) & 0x01) {
            curch = out_SDI;
            buff[pos] |= 0x01 << col;
         } else {
            curch = NUL;
            buff[pos] &= ~(0x01 << col);
         }
      } else {
         buff[pos] |= 0x01 << col;
         curch = out_SDI;
      }
      if (xch != curch) {
         outp(outputport, curch);
         xch = curch;
      }
      outp(outputport, xch + out_SCLK);          /* shift the ues bits in */
      outp(outputport, xch);
   }
   execute();
}


/*************************************************************
*                                                            *
*                     ISPSTREAM_PUMP                         *
*                                                            *
*************************************************************/

int             ispstream_pump(char *filename, int *end)
{
   unsigned int    n,
                   error,
                   length,
                   index,
                   width;
   int             rcode,
                   i,
                   j,
                   out_pos,
                   out_col,
                   in_col;
   unsigned char  *data,
                  *buf,
                  *buff,
                   curch,
                   sdo,
                   cur_bit,
                   uch;
   char            do_shift_instruction,
                   condition,
                   shiftstate;
   char            do_program,
                   do_erase,
                   do_shift_in_data,
                   do_shift_out_data,
                   do_store_data;
   char            do_verify_delay,
                   do_ues,
                   done_shift_in_data,
                   xch,
                   ych;
   unsigned int    bit_1_count;
   register int    row;
   register unsigned char port_bit;
   int             last_row,
                   erase_pulse,
                   program_pulse,
                   devices_in_chain;
   unsigned int    maxi_data,
                   data_length;
   int             last_be_row;
   FILE           *fp;
   unsigned long   checksum;
   unsigned char   var[2];
   unsigned char  *ues = NULL,
                  *ues_mask = NULL;

   do_ues = false;
   checksum = 0;
   if ((fp = fopen(filename, "rb")) == NULL)
      return FILE_NOT_FOUND;
   if ((xch = fgetc(fp)) == 0x0F) {
   }
    /* look for ispSTREAM file */ 
   else
      return FILE_NOT_JEDEC;
   checksum += xch;
   devices_in_chain = fgetc(fp);
   checksum += devices_in_chain;
   var[1] = fgetc(fp);
   var[0] = fgetc(fp);
   checksum += var[1];
   checksum += var[0];
   erase_pulse = var[1];
   erase_pulse = erase_pulse * 0x100 + var[0];
   program_pulse = fgetc(fp);
   checksum += program_pulse;
   var[1] = fgetc(fp);
   var[0] = fgetc(fp);
   checksum += var[1];
   checksum += var[0];
   last_row = var[1];
   last_row = last_row * 0x100 + var[0];;
   var[1] = fgetc(fp);
   var[0] = fgetc(fp);
   checksum += var[1];
   checksum += var[0];
   maxi_data = var[1];
   maxi_data = maxi_data * 0x100 + var[0];;
   var[1] = fgetc(fp);
   var[0] = fgetc(fp);
   checksum += var[1];
   checksum += var[0];
   last_be_row = var[1];
   last_be_row = last_be_row * 0x100 + var[0];;
   port_bit = xch = NUL;
   rcode = OK;
   shiftstate = true;
   if ((buf = (unsigned char *) (malloc(maxi_data / 8 + 1))) == NULL) {
      free(buf);
      return ABORT;
   }
   if ((buff = (unsigned char *) (malloc(maxi_data / 8 + 1))) == NULL) {
      free(buf);
      free(buff);
      return ABORT;
   }
   if ((ues_mask = (unsigned char *) (malloc(maxi_data / 8 + 1))) == NULL) {
      free(buf);
      free(buff);
      return ABORT;
   }
   if ((ues = (unsigned char *) (malloc(maxi_data / 8 + 2))) == NULL) {
      free(buf);
      free(buff);
      free(ues_mask);
      return ABORT;
   }
   move_to_id_state();                           /* move to idle state */
   done_shift_in_data = false;
   error = 0;
   length = 0;
   curch = fgetc(fp);
   checksum += curch;
   in_col = 8;
   for (row = 0; row <= last_row; row++) {
      *end = row;
      condition = 0;
      do_program = false;
      do_erase = false;
      do_shift_instruction = false;
      do_shift_in_data = false;
      do_shift_out_data = false;
      do_store_data = false;
      do_verify_delay = false;
      for (i = 1; i >= 0; i--) {
         for (j = 7; j >= 0; j--) {
            --in_col;
            if (in_col < 0) {
               in_col = 7;
               curch = fgetc(fp);
               checksum += curch;
            }
            if ((curch >> in_col) & 0x01)
               var[i] |= 0x01 << j;
            else
               var[i] &= ~(0x01 << j);
         }
      }
      data_length = var[1];
      data_length = data_length * 0x100 + var[0];
      width = data_length;
      printf("Operating On Row %04d", row);
      uch = 13;
      printf("%c", uch);
      data = buf;                                /* default storage space */
      if (row < 9) {                             /* id chains */
         if (data_length == 0)
            condition = 9;
         else
            condition = row;
         switch (condition) {
            case 0:
               data = buff;
               do_store_data = true;
               do_shift_out_data = true;
               shiftstate = false;
               break;
            case 1:
            case 5:
               do_verify_delay = true;
            case 2:
            case 6:
               do_shift_instruction = true;
               break;
            case 3:
               data = buff;                      /* switch to alternative
                                                  * storage */
               do_store_data = true;
               break;
            case 4:
               do_store_data = true;
               do_shift_out_data = true;
               break;
            case 7:
               do_ues = true;                    /* operation PU detected */
               data = ues_mask;                  /* switch to ues mask storage */
               for (i = 0; i < (int) (maxi_data / 8 + 1); i++)
                  ues_mask[i] = ues[i] = 0x00;   /* clear ues string and mask */
               do_store_data = true;
               do_shift_out_data = true;
               i = 0;                            /* byte of ues string */
               j = 8;                            /* bit of ues string */
               break;
            case 8:
               move_to_id_state();
               execute();
               shiftstate = true;
               if (erase_pulse > 0) {
                  do_erase = true;
                  do_shift_instruction = true;
               } else
                  do_store_data = true;
               break;
            case 9:
            default:
               break;
         }
      } else {
         if (data_length == 0)
            condition = 13;                      /* encounter do nothing row */
         else if (row == last_row)
            condition = 12;                      /* security fuse row */
         else if ((erase_pulse == 0) && (row >= 9) && (row < last_be_row)) {
            condition = (row - 9) % 12;
            if ((condition == 3) || (condition == 8)) {
            } else
               do_store_data = true;
            condition = 13;
         } else
            condition = (row - 9) % 12;
         switch (condition) {
            case 0:                              /* shift in address
                                                  * instruction */
            case 2:                              /* shift in/out data for
                                                  * programming */
            case 7:                              /* shift in/out for
                                                  * programming */
               do_shift_instruction = true;
               break;
            case 1:                              /* address bits */
               do_shift_in_data = true;
               break;
            case 3:                              /* pack data for even row of
                                                  * HD devices */
            case 8:                              /* data for odd row of HD
                                                  * devices */
               if (row > last_be_row)
                  do_shift_in_data = true;
               else
                  for (i = 0; i < (int) (maxi_data / 8 + 1); i++)
                     buff[i] = 0xFF;             /* for Bulk Erase verify */
               if (done_shift_in_data)
                  do_shift_out_data = true;
               done_shift_in_data = true;
               bit_1_count = 0;                  /* clear the counter for fuse
                                                  * bit 1s */
               length = width;                   /* number of bits for
                                                  * verification */
               data = buff;
               if ((do_ues) && (row == last_row - 4)) {
                  program_ues(ues, ues_mask, buff, data_length);
                  shiftstate = true;
                  do_shift_in_data = false;
                  do_store_data = true;
                  data = buf;
               }                                 /* go program in the ues */
               break;
            case 4:                              /* program command */
            case 9:
               do_shift_instruction = true;
               if (((program_pulse == 0) || ((bit_1_count == length)
                                    && (bit_1_count > 0))) || (length == 0)) {
                  do_store_data = true;
                  do_shift_instruction = false;
                  break;
               } else if (program_pulse > 0)
                  do_program = true;
               break;
            case 5:                              /* verify command for all
                                                  * devices in the chain */
            case 10:
               do_shift_instruction = true;
               do_verify_delay = true;
               break;
            case 6:                              /* shift out the bits of even
                                                  * rows */
            case 11:                             /* shift out the bits of odd
                                                  * rows */
               done_shift_in_data = false;
               width = length;
               do_shift_out_data = true;
               do_shift_instruction = true;
               break;
            case 12:                             /* take care of programming
                                                  * security fuses */
               do_shift_instruction = true;
               if (program_pulse > 0)
                  do_program = true;
               break;
            case 13:                             /* do nothing row */
               break;
            default:                             /* take care of do nothing row */
               break;
         }
      }

      if ((do_shift_instruction) || (do_store_data)) {
         /* check the purpose of the instruction */
         out_pos = 0;
         out_col = 8;
         for (index = 0; index < data_length; index++) {
            --in_col;
            --out_col;
            if (out_col < 0) {
               out_col = 7;
               out_pos++;
            }
            if (in_col < 0) {
               in_col = 7;
               curch = fgetc(fp);
               checksum += curch;
            }
            if ((curch >> in_col) & 0x01) {
               if (do_store_data) {
                  data[out_pos] |= 0x01 << out_col;
               }
                /* don't pump data to device */ 
               else {
                  if (port_bit & out_SDI) {
                  }
                   /* SDI is already a 1 */ 
                  else
                     outp(outputport, out_SDI);
                  outp(outputport, out_SDI + out_SCLK);
                  outp(outputport, out_SDI);
                  port_bit = out_SDI;            /* clock a 1 into sdi */
               }
            } else {
               if (do_store_data) {
                  data[out_pos] &= ~(0x01 << out_col);
               } else {
                  if (port_bit & out_SDI)        /* bring SDI to 0? */
                     outp(outputport, NUL);
                  outp(outputport, NUL + out_SCLK);
                  outp(outputport, NUL);
                  port_bit = NUL;                /* clock a zero into sdi */
               }
            }
         }
      }
      /* execute the instruction shifted in */
      if ((do_shift_instruction) && (shiftstate)) {
         shiftstate = false;
         port_bit = NUL;
         execute();
      }
      /* perform simultaneous shift in and out */
      if ((do_shift_in_data) || (do_shift_out_data)) {
         ych = 0;
         out_pos = 0;
         out_col = 8;
         uch = buff[out_pos];
         for (index = 0; index < width; index++) {
            --out_col;
            if (out_col < 0) {
               out_col = 7;
               out_pos++;
               uch = buff[out_pos];
            }
            if (do_shift_in_data) {
               --in_col;
               if (in_col < 0) {
                  in_col = 7;
                  curch = fgetc(fp);
                  checksum += curch;
               }
               if ((curch >> in_col) & 0x01) {
                  data[out_pos] |= 0x01 << out_col;
                  if (port_bit & out_SDI) {
                  }
                   /* SDI is already a 1 */ 
                  else
                     outp(outputport, out_SDI);
                  xch = out_SDI;
                  port_bit = out_SDI;            /* drive a 1 into sdi */
                  bit_1_count++;                 /* count the bits of 1s
                                                  * shifted in */
               } else {
                  data[out_pos] &= ~(0x01 << out_col);
                  if (port_bit & out_SDI)        /* bring SDI to 0? */
                     outp(outputport, NUL);
                  xch = NUL;
                  port_bit = NUL;                /* drive a zero into sdi */
               }
            }
            if (do_shift_out_data) {             /* read sdo */
               if (cur_bit = ((uch >> out_col) & 0x01))
                  cur_bit = in_SDO;              /* map to the SDO bit */
               else
                  cur_bit = NUL;
               sdo = (in_SDO & inp(inputport));  /* read the first bit */
               if ((row == 4) && ((buf[out_pos] >> out_col) & 0x01)) {
                  if (error == 0)
                     ych = 1;
               }
               if ((do_ues) && (row == 7)) {     /* read and save the ues
                                                  * string */
                  if ((ues_mask[out_pos] >> out_col) & 0x01) {
                     --j;
                     if (j < 0) {
                        j = 7;
                        i++;
                     }                           /* fill next byte */
                     if (sdo & in_SDO)
                        ues[i] |= 0x01 << j;
                  }
                  cur_bit = sdo;                 /* no comparsion required */
               }
               if ((row == 4) && (!((buf[out_pos] >> out_col) & 0x01))) {
                  if (ych) {
                     error++;
                     rcode = NON_ISP_PART;
                     break;
                  } else
                     error = 0;                  /* reset error for next part */
               } else if (sdo != cur_bit) {
                  ych = 0;
                  if (row == 0)
                     rcode = UNKNOWN_CHIP;
                  else
                     rcode = VALIDATION_ERROR;
                  error++;
               }
            }                                    /* shift the 1st bit in */
            outp(outputport, xch + out_SCLK);    /* and shift the 2nd bit out */
            outp(outputport, xch);
         }
      }                                          /* complete instruction or
                                                  * command shifting for loop */
      if ((do_erase) || (do_program)) {          /* program devices */
         port_bit = NUL;
         if (do_erase) {
            outp(outputport, NUL);
            outp(outputport, NUL + out_SCLK);
            outp(outputport, NUL);
            pulse_width(erase_pulse);
            outp(outputport, NUL + out_MODE);
            outp(outputport, NUL + out_MODE + out_SDI);
            pulse_width(1);                      /* 1ms delay from mode to
                                                  * clock */
            outp(outputport, NUL + out_MODE + out_SDI + out_SCLK);
            outp(outputport, NUL + out_MODE + out_SDI);
            outp(outputport, NUL + out_MODE);
            outp(outputport, NUL);

            /* to reset the security cell of 22v10 */
            outp(outputport, NUL + out_MODE);    /* MOVE DEVICE TO ID STATE */
            outp(outputport, NUL + out_MODE + out_SCLK);
            outp(outputport, NUL + out_MODE);
            outp(outputport, NUL);
            port_bit = NUL;
            execute();                           /* back into isp mode */
            shiftstate = true;                   /* chain back in shift state */
         } else if (do_program) {
            outp(outputport, NUL);
            outp(outputport, NUL + out_SCLK);
            outp(outputport, NUL);
            pulse_width(program_pulse);
            execute();
            port_bit = NUL;
            shiftstate = true;                   /* chain back in shift state */
         }
      } else if ((!shiftstate) && ((do_shift_in_data) || (do_shift_out_data)
                                   || (do_verify_delay))) {
         if (do_verify_delay) {
            outp(outputport, NUL + out_SCLK);
            for (i = 0; i < 30; i++)             /* simulate a 30uS min delay */
               outp(outputport, NUL);
         }
         port_bit = NUL;
         execute();
         shiftstate = true;
      }                                          /* chain in shift state */
      if (error > 0) {
         break;
      }
   }                                             /* end of for */

   move_to_id_state();
   if (buf != NULL)
      free(buf);
   if (buff != NULL)
      free(buff);
   if (ues != NULL)
      free(ues);
   if (ues_mask != NULL)
      free(ues_mask);
   in_col = 0;
   for (i = 1; i >= 0; i--) {
      for (j = 7; j >= 0; j--) {
         --in_col;
         if (in_col < 0) {
            in_col = 7;
            curch = fgetc(fp);
         }
         if ((curch >> in_col) & 0x01)
            var[i] |= 0x01 << j;
         else
            var[i] &= ~(0x01 << j);
      }
   }
   n = (unsigned int) checksum;
   data_length = var[1];
   data_length = data_length * 0x100 + var[0];
   if ((error == 0) && (n != data_length)) {
      error++;
      rcode = FILE_ERROR;
   }
   if (error > 0) {
      return (rcode);
   } else {
      /* set ISP and RESET high, so customer can see device working */
      /* activate  the chain only if no port precondition */
      if (NUL == 0)
         outp(outputport, NUL + out_ISP + out_RESET);
   }
   return (OK);

}



/*************************************************************
*                                                            *
*                         error_handler                      *
*                                                            *
*  rcode                  - error code                       *
*                                                            *
*                                                            *
*  This procedure return the address of the message string   *
*  for the corresponding error code.                         *
*                                                            *
*************************************************************/

void            error_handler(int rcode, char *message)
{
   char           *error_message[] = {{"PASS"}, {""}, {""}, {"PC Hardware Problem"}, {"Chip and JEDEC File Doesn't Match"},
   {"Can't Find the Download Cable"}, {"The VCC on Board Is Not On"},
   {"No Device Found/Open Download Cable/Open Daisychain"},
   {"Can't Find the File"}, {"The File Is Not Complete"}, {"Not Enough PC Memory"},
   {"Verification Fail"}, {"The Device is Secured"}, {"Non isp Part Found"},
   {"The File Contain Operation Not Supported in This Mode"},
   {"The Chip Count In the Chain and The File Do not Match"},
   {"Unknown Device Found"}, {"Wrong File Type"}, {"The File Has Error"},
   {"The File Has Invalid UES Character"}};

   strcpy(message, error_message[-rcode]);
}



/*************************************************************
*                                                            *
*                            MAIN                            *
*                                                            *
*************************************************************/

int             main(int argc, char *argv[])
{
   int             rcode = OK,
                   end = 0;
   FILE           *fpr;
   char           *ptr,
                   filename[300],
                   str[300];


   printf("\n           Lattice Semiconductor Corp.\n");
   printf("\n          ispCODE V3.01 Copyright 1995.\n");
   printf("\n              ispSTREAM Driver\n\n");

   if ((argc < 2) || (argc > 2)) {
      printf("\nUsage: isppump [drive:][path]isp_filename\n");
      printf("Example: isppump my_file.isp\n");
      printf("\n");
      printf("isp_filename         The ispSTREAM File Created From A Valid \n");
      printf("                     Daisy Chain Configuration File\n");
      exit(1);
   }
   if ((fpr = fopen(argv[1], "r")) == NULL) {
      printf("\n%s File not found!\n", argv[1]);
      exit(1);
   }
   fclose(fpr);
   strcpy(str, argv[1]);
   ptr = strchr(str, '.');
   if (ptr)
      *ptr = '\0';
   sprintf(filename, "%s.isp", str);
   strcpy(str, argv[1]);
   if (stricmp(str, filename)) {
      printf("\nFile %s Is Not An ispSTREAM File\n", str);
      exit(1);
   }
   printf("\nStart Program and Verify.......\n");

   find_port();
   rcode = port_ok();
   if (rcode > 0) {
      rcode = power_ok();
      if (rcode > 0)
         rcode = ispstream_pump(filename, &end);
   }
   if (rcode != OK) {
      error_handler(rcode, str);
      printf("\nFailed At Row %d in Program and Verify Due To %s\n", end, str);
      printf("\n");
      printf("+-------+\n");
      printf("| FAIL! |\n");
      printf("+-------+\n");
      exit(rcode);
   } else {
      printf("\n");
      printf("+=======+\n");
      printf("| PASS! |\n");
      printf("+=======+\n");
      exit(0);
   }

   exit(0);
}
