//---------------------------------------------------------------------------
// Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
// Except as contained in this notice, the name of Dallas Semiconductor
// shall not be used except as stated in the Dallas Semiconductor
// Branding Policy.
//--------------------------------------------------------------------------
//
//  owprgm.c - This source file contains the EPROM Program routines.
//  version 1.00
//

// Include Files
#include "ownet.h"
#include "owfile.h"
#include "rawmem.h"
#include "mbeprom.h"
#include <string.h>

// global paramters
SMALLINT   job_started = FALSE;
ProgramJob job;


//--------------------------------------------------------------------------
//  Start an programming job.  This function assumes that the Garbage bag D
//  is at least 11049 bytes long. This function check to see if the
//  current device is of the correct type.  It reads the bitmap of the
//  device for reference during accumulation of Program write jobs.
//
// portnum    the port number of the port being used for the
//            1-Wire Network.
// SNum       the serial number for the job part to be executed on.
//
//  Returns:    TRUE  program job created
//              FALSE error
//
SMALLINT owCreateProgramJob(int portnum, uchar *SNum) 
{
   SMALLINT bank = 1;
   short i,j;
       
   // Make sure there is no current job
   job_started = FALSE;  
   
   // check the device type
   if(!owIsWriteOnce(bank,portnum,SNum))
   {
      OWERROR(OWERROR_WRONG_TYPE);
      return FALSE;
   }
      
   // flush all of the cached pages
   InitDHash();

   // read the bitmap 
   if(!ReadBitMap(portnum,SNum,&job.EBitmap[0]))
      return FALSE;
         
   // keep the original bitmap
   for (i = 0; i < 32; i++)
      job.OrgBitmap[i] = job.EBitmap[i];
   
   // clear all the job pages
   for (i = 0; i < MAX_NUM_PGS; i++)   
   {
      job.Page[i].wr = PJOB_NONE; 
      // clear bits in each page 
      for (j = 0; j < 29; j++)
         job.Page[i].data[j] = 0xFF;
   }      
   // record the current rom
   for (i = 0; i < 8; i++)
      job.ERom[i] = SNum[i];
      
   // Set the job to true
   job_started = TRUE;
   
   return TRUE;
}
         

//--------------------------------------------------------------------------
//  Do an program job.  This function assumes that the Garbage back D
//  is at least 11049 bytes long. This function check to see if the
//  current device is of the correct type.  It reads the bitmap of the
//  device for reference during accumulation of Program write jobs.
//
// portnum    the port number of the port being used for the
//            1-Wire Network.
// SNum       the serial number for the job part to be executed on.
//
//  Returns:    TURE  program job created
//              FALSE error
//
SMALLINT owDoProgramJob(int portnum, uchar *SNum) 
{                       
   uchar BM[32],WPBM[32],RWPBM[32],pgbuf[32],RDB[256],tpg;
   uchar tmpBM[4];
   short i,j,l,Bcnt=0,mBcnt,xtra,pg,inflp=0,redit;
   uchar ROM[8]; 
   SMALLINT  bank = 1;
   PAGE_TYPE page = 0;
   int maxp = 0;
   int flag;
   PAGE_TYPE bmpg,rdpg;
   uchar buff[5];

   memset(tmpBM, 0xFF, 4);
      
   // checks to see if the ROM number has changed
   for(i=0;i<8;i++)
      if(job.ERom[i] != SNum[i])
      {
         OWERROR(OWERROR_NONMATCHING_SNUM);
         return FALSE;
      }
            
   // Make sure there is a job open
   if (job_started != TRUE)
   {
      OWERROR(OWERROR_NO_PROGRAM_JOB);
      return FALSE;
   }

   // Make sure that only eproms are on the line    
   l = TRUE;  // flag to see if operation is ok
   flag = owFirst(portnum,TRUE,FALSE);
   while(flag)
   {
      // check the family code
      owSerialNum(portnum,&ROM[0],TRUE);
      if(!owIsWriteOnce(bank,portnum,&ROM[0]))
      {
         l = FALSE;
         break;
      }
      
      // look for next device
      flag = owNext(portnum,FALSE,FALSE);
   }                          
   
   // restore the rom number 
   for (i = 0; i < 8; i ++)
      ROM[i] = job.ERom[i];
   owSerialNum(portnum,&ROM[0],FALSE);
      
   // check for fail
   if (l == FALSE)  
   {
      OWERROR(OWERROR_NON_PROGRAM_PARTS);
      return FALSE;
   }
   
   // flush all of the cached pages
   InitDHash();
   
   maxp = maxPages(portnum,SNum);

   // read the write protect bits and redirect write protect bits
   // and redirection bytes       
   if(owIsWriteOnce(bank,portnum,&ROM[0]) && ((ROM[0] == 0x0B) ||
                                              (ROM[0] == 0x0F)))
   {  // DS1985,DS1986
      for(i=0;i<32;i++)
         BM[i] = job.OrgBitmap[i];

      // get number of status bytes needed
      mBcnt = ((maxp+1) / 8) +
         ((((maxp+1) % 8) > 0) ? 1 : 0);

      // get number of pages to get that many bytes
      l = (mBcnt / 8) + ((mBcnt % 8) > 0 ? 1 : 0);

      // loop through the number of write protect bitmap pages
      for(i=0;i<l;i++)
      {
         // read stat mem page
         tpg = (uchar) i+8;

         if(!Read_Page(portnum,&ROM[0],&pgbuf[0],STATUSMEM,&tpg,&flag))
            return FALSE;

         if(flag == 8)
         {
            // copy bitmap read 
            for(j=0;j<8;j++)
               if(Bcnt <= mBcnt)
                  WPBM[Bcnt++] = ~pgbuf[j];
               else
                  break;
         }
         else
            return TRUE;
      }

      // loop through the number of redirection write protect bitmap pages
      Bcnt = 0;
      for(i=0;i<l;i++)
      {
         // read stat mem page
         tpg = i+4;
         if(!Read_Page(portnum,&ROM[0],&pgbuf[0],STATUSMEM,&tpg,&flag))
            return FALSE;
         
         // check results
         if(flag == 8)
         {
            // copy bitmap read buffer
            for(j=0;j<8;j++)
               if(Bcnt <= mBcnt)
                  RWPBM[Bcnt++] = ~pgbuf[j];
               else
                  break;
         }
         else
            return TRUE;
      }

      // read the redirection bytes  (mBcnt number of pages in redirection)
      Bcnt = 0;
      for(i=0;i<mBcnt;i++)
      {
         // read stat mem page
         tpg = i+32;
         if(!Read_Page(portnum,&ROM[0],&pgbuf[0],STATUSMEM,&tpg,&flag))
            return FALSE;
                                  
         // check results                             
         if (flag == 8)
         {              
            // copy bitmap read shorto buffer               
            for (j=0;j<8;j++)
               if (Bcnt <= maxp)
                  RDB[Bcnt++] = ~pgbuf[j];  
               else
                  break;   // quit the loop because done
         }                                 
         else 
            return TRUE;
      }
   }
   else if(owIsWriteOnce(bank,portnum,&ROM[0]))
   {
      // read status memory page 0
      tpg = 0;
      if(!Read_Page(portnum,&ROM[0],&pgbuf[0],STATUSMEM,&tpg,&flag))
         return FALSE;
      
      // check result of status read
      if (flag == 8)           
      {                 
         // extract the bitmap
         BM[0] = ~(pgbuf[0] >> 4) & 0x0F;  
         // extract the write protect bitmap 
         WPBM[0] = (~pgbuf[0]) & 0x0F;
         // extract the redirection write protect   
         RWPBM[0] = 0;  // there are non in the DS1982
         // extract the redirection bytes
         for (i = 0; i < 4; i++)
            RDB[i] = ~(pgbuf[i+1]);
      }
      else
         return TRUE;   
   }   
   else
   {
      OWERROR(OWERROR_NON_PROGRAM_PARTS);
      return FALSE;
   }

   
   // flush all of the cached pages
   InitDHash();

   // loop through all of the pages and check too see how many pages need to 
   // be re-directed.  From that see if there is enough room on the device
   // to do all of the desired operations  
   // Count the extra-pages for later    
   xtra = maxp+1;     
   for(i=0;i<=maxp;i++)
   {                                                            
      // if the page is aleady taken then subtract 2 pages 
      if ((job.Page[i].wr & PJOB_MASK) == PJOB_WRITE)  // (2.01)
         xtra -= (((BM[i / 8] >> (i % 8)) & 0x01) ? 2 : 1);    
      else if ((BM[i / 8] >> (i % 8)) & 0x01)
         xtra--;  
   }                       
   // check to see if the changes will really fit on the devices
   if (xtra < 0)
   {
      OWERROR(OWERROR_OUT_OF_SPACE);
      return FALSE;
   }
   
   // loop to write each page that has an eprom job
   for(i=0;i<=maxp;i++)
   {   
      // check for an infinite loop (if redirection point to each other)
      if (inflp++ > 20480)
      {
         OWERROR(OWERROR_PROGRAM_WRITE_PROTECT);
         return FALSE;
      }
      
      // check the type of operation (1 = page write, 2 redirection)
      // page write
      if ((job.Page[i].wr & PJOB_MASK) == PJOB_WRITE || 
          (job.Page[i].wr & PJOB_MASK) == PJOB_TERM)  
      {     
         // flag the says we are going to re-direct to this page                                   
         redit = FALSE;                                              
         pg = -1;
         
         // check to see if this page is already re-directed
         if (RDB[i] != 0x00)
         {
            // get the page and redirect
            pg = RDB[i];
            redit = TRUE;
            
            // check to see if this could be real
            if ((job.Page[pg].wr & PJOB_MASK) != PJOB_NONE)  
            {
               OWERROR(OWERROR_PROGRAM_WRITE_PROTECT);
               return FALSE;
            }
         }
         // not re-directed
         else
         {         
            // if write protected set or bitmap says already used then write 
            // redirection byte and change the Program job to an empty page  
            // only redirect this is a JOB_WRITE job
            if (((WPBM[i / 8] >> (i % 8)) & 0x01) || 
                (((BM[i / 8] >> (i % 8)) & 0x01) && 
                ((job.Page[i].wr & PJOB_MASK) == PJOB_WRITE)))
            {
               // check if the write-protect redirection byte is set
               if ((RWPBM[i / 8] >> (i % 8)) & 0x01)   
               {
                  OWERROR(OWERROR_PROGRAM_WRITE_PROTECT);
                  return FALSE;
               }
               // able to be re-directed so do it
               else  
                  redit = TRUE;
            }   
            // ok so write the page
            else                   
            {          
               
               // construct the page to write
               for(j=0;j<=job.Page[i].len;j++) 
                  pgbuf[j] = job.Page[i].data[j];
                  
               // set this page as having an attempt made to programming
               job.Page[getLastPage(portnum,SNum)].wr |= PJOB_START;
               
               bank = getBank(portnum,SNum,(PAGE_TYPE)i,REGMEM);
               page = (uchar)getPage(portnum,SNum,(PAGE_TYPE)i,REGMEM);

               if(!owWritePagePacket(bank,portnum,SNum,page,&pgbuf[0],job.Page[i].len))
                  return FALSE;
                          
               // check to see if the bitmap is not set 
               if (!(BM[i / 8] & (0x01 << (i % 8))))   
               {
                  // set the bitmap bit for this page
                  // EPROM1/EPROM3 exception
                  if((ROM[0] == 0x0B) || (ROM[0] == 0x0F))
                  {
                     // set to 8 for status memory pages and reserved pages
                     bmpg  = 8;

                     if(!owRead(getBank(portnum,SNum,bmpg,STATUSMEM),portnum,SNum,
                                    (i/8),FALSE,buff,1))
                        return FALSE;

                     tmpBM[i/8] = buff[0];
                     tmpBM[i/8] &= ~(0x01 << i%8);

                     if(!owWrite(getBank(portnum,SNum,bmpg,STATUSMEM),portnum,
                                         SNum,(i/8),&tmpBM[i/8],1))
                        return FALSE;
//                     if(owProgramByte(portnum,(~(0x01 << (i%8))),(0x40+(i/8)),0x55,1,TRUE) == -1)
//                        return FALSE;
                  }
                  else
                  {
                     // set to 0 for status memory pages
                     bmpg  = 0;

                     if(!owRead(getBank(portnum,SNum,bmpg,STATUSMEM),portnum,
                                        SNum,0,FALSE,buff,1))
                        return FALSE;

                     tmpBM[i/8] = buff[0];
                     tmpBM[i/8] &= ~(0x01 << (i+4));

                     if(!owWrite(getBank(portnum,SNum,bmpg,STATUSMEM),portnum,
                                         SNum,0,&tmpBM[i/8],1))
                        return FALSE;

//                     if(owProgramByte(portnum,(~(0x01 << (i+4))),0,0x55,0,TRUE) == -1)
//                        return FALSE;
                  }
                     
                  // update the bitmap
                  if(!BitMapChange(portnum,SNum,(uchar)i,1,&BM[0]))
                     return FALSE;
                     
                  // clear this Program job                   
                  job.Page[i].wr = PJOB_NONE;   
               }
            }
         }
         
         // check to see if need to re-direct the page        
         if (redit == TRUE)
         {               
            // find an empty page in the Program job and bitmap
            if (pg == -1)
            {
               for(j=1;j<=maxp;j++)   
               {
                  // loop for a spot that is free in the bitmap, has not
                  // Program job on it, can be redirected, and is not write
                  // protected.
                  if (!((BM[j / 8] >> (j % 8)) & 0x01) && 
                       ((job.Page[j].wr & PJOB_MASK) == PJOB_NONE) && 
                      (RDB[j] == 0x00) && !((WPBM[j / 8] >> (j % 8)) & 0x01) &&
                      !((RWPBM[j / 8] >> (j % 8)) & 0x01))
                  {
                     pg = j;  
                     break;
                  }
               }
   
               // check to see if one was found, if not then we are out of space
               if (pg == -1)
               {
                  OWERROR(OWERROR_OUT_OF_SPACE);
                  return FALSE;
               }
            }
                                         
            // change the Program job to reflect the change
            job.Page[pg].wr = PJOB_WRITE;                       
            job.Page[pg].len = job.Page[i].len;
            // copy the data to the new job location
            for(j=0;j<job.Page[i].len;j++)
               job.Page[pg].data[j] = job.Page[i].data[j];   
                  
            // change the old job page to a redirect job
            job.Page[i].data[0] = (uchar)pg; // redirection page
            job.Page[i].wr = PJOB_REDIR;      // write redireciton job

            // optionally set back the loop if the new page is before
            // the current page
            i--;
            if (pg < i)
               i = pg - 1;           
               
            // loop back
            continue;
         
         }
               
      }            
      // redirection write
      else if ((job.Page[i].wr & PJOB_MASK) == PJOB_REDIR)  
      {
         // get the re-direction byte from the page data
         pg = job.Page[i].data[0];
         
         // check for redirection write protect with incorrect rdb   
         // or not possible write
         if ((((RWPBM[i / 8] >> (i % 8)) & 0x01) && (RDB[i] != pg)) ||
              ((RDB[i] | pg) ^ pg))
         {
            OWERROR(OWERROR_PROGRAM_WRITE_PROTECT);
            return FALSE;
         }
   
         // write the redirection byte and set the bitmap
         // EPROM1/EPROM3 exception
         if((ROM[0] == 0x0B) || (ROM[0] == 0x0F))
         {
            // set to 8 for status memory pages and reserved pages for bitmap
            bmpg  = 8;
            // set to   for redirection pages
            rdpg  = 32;

            if(!owRead(getBank(portnum,SNum,bmpg,STATUSMEM),portnum,SNum,
                               (i/8),FALSE,buff,1))
               return FALSE;

            tmpBM[i/8] = buff[0];
            tmpBM[i/8] &= ~(0x01 << i%8);

            if((!redirectPage(getBank(portnum,SNum,rdpg,STATUSMEM),portnum,
                              SNum,i,pg)) || (!owWrite(getBank(portnum,SNum,
                              bmpg,STATUSMEM),portnum,SNum,(i/8),&tmpBM[i/8],1)))
               return FALSE;

//            if((owProgramByte(portnum,(~pg),(0x100+i),0x55,1,TRUE) == -1)
//               ||(owProgramByte(portnum,(~(0x01 << (i%8))),(0x40+(i/8)),0x55,1,TRUE) == -1))
//               return FALSE;
         }
         else  
         {
            // set to 0 for status memory pages
            bmpg  = 0;

            if(!owRead(getBank(portnum,SNum,bmpg,STATUSMEM),portnum,SNum,0,
                               FALSE,buff,1))
               return FALSE;

            tmpBM[i/8] = buff[0];
            tmpBM[i/8] &= ~(0x01 << (i+4));
            tmpBM[i/8] &= (~pg);

            if((!redirectPage(getBank(portnum,SNum,bmpg,STATUSMEM),portnum,SNum,i,pg)) ||
               (!owWrite(getBank(portnum,SNum,bmpg,STATUSMEM),portnum,SNum,0,&tmpBM[i/8],1)))
               return FALSE;
//            if((owProgramByte(portnum,(~pg),(1+i),0x55,0,TRUE) == -1) 
//               ||(owProgramByte(portnum,(~(0x01 << (i+4))),0,0x55,0,TRUE) == -1))
//               return FALSE;
         }  
            
         if(!BitMapChange(portnum,SNum,(uchar)i,1,&BM[0]))
            return FALSE;
            
         // clear this Program job                   
         job.Page[i].wr = PJOB_NONE; 
      }                            
      // overwrite add file page                                       
      else if((job.Page[i].wr & PJOB_MASK) == PJOB_ADD) 
      {    
         for(j=1;j<=29;j++)    
         {                 
            // check to see if this byte needs to be programmed
            if(job.Page[i].bm[j / 8] & (0x01 << (j % 8)))
            {
               // write the byte
               if((ROM[0] == 0x0B) || (ROM[0] == 0x0F))
               {
                  if(owProgramByte(portnum,job.Page[i].data[j-1],((i<<5)+j),0x0F,1,TRUE) == -1)
                     return FALSE;
               }
               else
               {
                  if(owProgramByte(portnum,job.Page[i].data[j-1],((i<<5)+j),0x0F,0,TRUE) == -1)
                     return FALSE;
               }
            }
         }
         
         // check to see if the bitmap is not set
         if (!(BM[i / 8] & (0x01 << (i % 8))))   
         {         
            // set the bitmap bit for this page
            // EPROM1/EPROM3 exception
            if ((ROM[0] == 0x0B) || (ROM[0] == 0x0F))
            {
               // set to 8 for status memory pages and reserved pages
               bmpg  = 8;

               if(!owRead(getBank(portnum,SNum,bmpg,STATUSMEM),portnum,SNum,
                                  (i/8),FALSE,buff,1))
                  return FALSE;

               tmpBM[i/8] = buff[0];
               tmpBM[i/8] &= ~(0x01 << i%8);

               if(!owWrite(getBank(portnum,SNum,bmpg,STATUSMEM),portnum,
                                   SNum,(i/8),&tmpBM[i/8],1))
                  return FALSE;

//               if(owProgramByte(portnum,(~(0x01 << (i%8))),(0x40+(i/8)),0x55,1,TRUE) == -1)
//                  return FALSE;
            }
            else   
            {
               // set to 0 for status memory pages
               bmpg  = 0;

               if(!owRead(getBank(portnum,SNum,bmpg,STATUSMEM),portnum,SNum,0,
                                  FALSE,buff,1))
                  return FALSE;

               tmpBM[i/8] = buff[0];
               tmpBM[i/8] &= ~(0x01 << (i+4));

               if(!owWrite(getBank(portnum,SNum,bmpg,STATUSMEM),portnum,
                                   SNum,0,&tmpBM[i/8],1))
                  return FALSE;

//               if(owProgramByte(portnum,(~(0x01 << (i+4))),0,0x55,0,TRUE) == -1)
//                  return FALSE;
            }
                              
            if(!BitMapChange(portnum,SNum,(uchar)i,1,&BM[0]))
               return FALSE;
         }
                                     
         // clear this Program job                   
         job.Page[i].wr = PJOB_NONE; 
      }

   }
                      
   // turn off the Program job
   job_started = FALSE;
                      
   // finished
   return TRUE;                   
}                   

//--------------------------------------------------------------------------
// Indicates if a job has already been initialized and waiting to be 
// written.
//
// portnum    the port number of the port being used for the 
//            1-Wire Network
// SNum       the serial number for the part that the read is
//            to be done on.
//
// return:  TRUE  : job started
//          FALSE : no jobs 
//                                    
SMALLINT isJob(int portnum, uchar *SNum)
{
   int i;

   for(i=0;i<8;i++)
      if(SNum[i] != job.ERom[i])
      {
         return FALSE;
      }

   return job_started;
}

//-------------------------------------------------------------------------
// Indicates weather a page needs to be written
//
// portnum    the port number of the port being used for the 
//            1-Wire Network
// SNum       the serial number for the part that the read is
//            to be done on.
// pg         the page that is checked to see if it needs to
//            be written.
//
// return:  TRUE:   page needs to be written
//          FALSE:  doesn't need to be written
//
SMALLINT isJobWritten(int portnum,uchar *SNum,PAGE_TYPE pg)
{
   int i;

   for(i=0;i<8;i++)
      if(SNum[i] != job.ERom[i])
      {
         OWERROR(OWERROR_NONMATCHING_SNUM);
         return FALSE;
      }

   return job.Page[pg].wr;
}

//-------------------------------------------------------------------------
// Sets the status for the job on that page
//
// portnum    the port number of the port being used for the 
//            1-Wire Network
// SNum       the serial number for the part that the read is
//            to be done on.
// pg         the page that is checked to see if it needs to
//            be written.
// status     the status that the page is being set to.
//
// return:  TRUE:   page needs to be written
//          FALSE:  doesn't need to be written
//
SMALLINT setJobWritten(int portnum,uchar *SNum,PAGE_TYPE pg,SMALLINT status)
{
   int i;

   for(i=0;i<8;i++)
      if(SNum[i] != job.ERom[i])
      {
         OWERROR(OWERROR_NONMATCHING_SNUM);
         return FALSE;
      }

   job.Page[pg].wr = (uchar)status;

   return TRUE;
}

//-------------------------------------------------------------------------
// The purpose is to get the original bitmap.
//
// portnum    the port number of the port being used for the 
//            1-Wire Network
// SNum       the serial number for the part that the read is
//            to be done on.
// BM         the bitmap to set to the original bitmap.
//
// return:  TRUE:   page needs to be written
//          FALSE:  doesn't need to be written
//
SMALLINT getOrigBM(int portnum, uchar *SNum, uchar *BM)
{
   int i;

   for(i=0;i<8;i++)
      if(SNum[i] != job.ERom[i])
      {
         OWERROR(OWERROR_NONMATCHING_SNUM);
         return FALSE;
      }

   for(i=0;i<32;i++)
      BM[i] = job.OrgBitmap[i];

   return TRUE;
}

//-------------------------------------------------------------------------
// Gets the page data of the job
//
// portnum    the port number of the port being used for the 
//            1-Wire Network
// SNum       the serial number for the part that the read is
//            to be done on.
// page       the page that the data is gotten from.
// buff       the buffer to store the data on that page
// len        the len of the data for that page
//
// return:  TRUE:   page needs to be written
//          FALSE:  doesn't need to be written
//
SMALLINT getJobData(int portnum,uchar *SNum,PAGE_TYPE page,uchar *buff,int *len)
{
   int i;

   for(i=0;i<8;i++)
      if(SNum[i] != job.ERom[i])
      {
         OWERROR(OWERROR_NONMATCHING_SNUM);
         return FALSE;
      }

   if(job.Page[page].wr != PJOB_NONE)
   {
      for(i=0;i<job.Page[page].len;i++)
         buff[i] = job.Page[page].data[i];

      *len = job.Page[page].len;
   }
   else
   {
      return FALSE;
   }

   return TRUE;
}

//-------------------------------------------------------------------------
// Sets the page data for that page in the job
//
// portnum    the port number of the port being used for the 
//            1-Wire Network
// SNum       the serial number for the part that the read is
//            to be done on.
// pg         the page that the data is set on.
// buff       the buffer of the data to be programmed
// len        the len of the data for that page
//
// return:  TRUE:   page needs to be written
//          FALSE:  doesn't need to be written
//
SMALLINT setJobData(int portnum,uchar *SNum,PAGE_TYPE pg,uchar *buff,int len)
{
   int i;

   for(i=0;i<8;i++)
      if(SNum[i] != job.ERom[i])
      {
         OWERROR(OWERROR_NONMATCHING_SNUM);
         return FALSE;
      }

   for(i=0;i<len;i++)
      job.Page[pg].data[i] = buff[i];

   job.Page[pg].len = (uchar)len;

   if(len > 0)
   {
      job.Page[pg].wr = PJOB_WRITE;
   }

   return TRUE;
}

//-------------------------------------------------------------------------
// Sets a certain job for programming.
//
// portnum    the port number of the port being used for the 
//            1-Wire Network
// SNum       the serial number for the part that the read is
//            to be done on.
// value      the value to set in the bitmap.
// spot       the spot to set the bitmap.
//
// return:  TRUE:   page needs to be written
//          FALSE:  doesn't need to be written
//
SMALLINT setProgramJob(int portnum,uchar *SNum,uchar value,int spot)
{
   int i;

   for(i=0;i<8;i++)
      if(SNum[i] != job.ERom[i])
      {
         OWERROR(OWERROR_NONMATCHING_SNUM);
         return FALSE;
      }

   job.EBitmap[spot] = value;

   return TRUE;
}

//-------------------------------------------------------------------------
// Gets a certain number of bitmap job programming starting from the first
// value in the array.
//
// portnum    the port number of the port being used for the 
//            1-Wire Network
// SNum       the serial number for the part that the read is
//            to be done on.
// BM         the array of values for the bitmap.
// spots      the number of spots copied.
//
// return:  TRUE:   page needs to be written
//          FALSE:  doesn't need to be written
//
SMALLINT getProgramJob(int portnum,uchar *SNum,uchar *BM,int spots)
{
   int i;

   for(i=0;i<8;i++)
      if(SNum[i] != job.ERom[i])
      {
         OWERROR(OWERROR_NONMATCHING_SNUM);
         return FALSE;
      }

   for(i=0;i<spots;i++)
      BM[i] = job.EBitmap[i];

   return TRUE;
}

//--------------------------------------------------------------------------
// Write a byte into the Job space directly
//        
// portnum    the port number of the port being used for the 
//            1-Wire Network
// SNum       the serial number for the part that the read is
//            to be done on.
// pg         the page to write the byte
// spot       the spot on the page to write the byte
// wbyte      the byte that is to be written
//
// return TRUE if the write was successful.
//
SMALLINT WriteJobByte(int portnum, uchar *SNum, PAGE_TYPE pg, short spot,
                      uchar wbyte, short zeros)
{    
   uchar pgbuf[34];   
   short i;
                     
   if(!isJob(portnum,SNum))
      if(!owCreateProgramJob(portnum,SNum))
         return FALSE;

   // check to see if this page is not in the job yet
   if ((job.Page[pg].wr & PJOB_MASK) == PJOB_NONE) 
   {
      for(i=0;i<32;i++)
         pgbuf[i] = 0xFF;

      // read the page first
      if(!ExtendedRead_Page(portnum,SNum,&pgbuf[0],pg))
         return FALSE;

      // copy the page contents into the job file
      for (i = 0; i < 29; i++)
         job.Page[pg].data[i] = pgbuf[i+1];
      
      // zero the bitmap for the page
      for (i = 0; i < 4; i++)
         job.Page[pg].bm[i] = 0;
   } 
   
   // set the program job type (overwrite)
   if (((job.Page[pg].wr & PJOB_MASK) != PJOB_ADD) && 
       ((job.Page[pg].wr & PJOB_MASK) != PJOB_TERM)) 
      job.Page[pg].wr = PJOB_ADD;                      
                                    
   // set the bitmap to mark this byte as one to program
   job.Page[pg].bm[spot / 8] |=  (0x01 << (spot % 8));                                 
                                    
   // depending on 'zeros' set the byte to write
   if (zeros)
      job.Page[pg].data[spot-1] = (uchar)~(~job.Page[pg].data[spot-1] | ~wbyte);       
   else
      job.Page[pg].data[spot-1] = (uchar)wbyte;

   return TRUE;
}                                       


//--------------------------------------------------------------------------
// Set the program job to terminate that page provided in the buffer.  The
// page data is provided to prevent it from being read twice since the calling
// function will read the page to see if it is already terminated.
//
// portnum    the port number of the port being used for the 
//            1-Wire Network
// SNum       the serial number for the part that the read is
//            to be done on.
// pg         the page to terminate
// pgbuf      the data to write to the terminated page
//        
// return TRUE if the page was terminated
//
SMALLINT TerminatePage(int portnum, uchar *SNum, short pg, uchar *pgbuf)
{                                
   short i;

   // page is not in job
   if ((job.Page[pg].wr & PJOB_MASK) == PJOB_NONE)
   {                       
      // copy the page contents into the job file
      for (i = 0; i < 29; i++)
         job.Page[pg].data[i] = pgbuf[i+1];
            
      // zero the bitmap for the page
      for (i = 0; i < 4; i++)
         job.Page[pg].bm[i] = 0;
   }
   // error file is already being written to 
   else if (((job.Page[pg].wr & PJOB_MASK) != PJOB_ADD) && 
           ((job.Page[pg].wr & PJOB_MASK) != PJOB_TERM))                                    
      return FALSE;
   
   // set the length to max since we do not know where the end really is in an add file
   job.Page[pg].len = 29;
                                                                                       
   // set the job to a terminate job                                                                                    
   job.Page[pg].wr = PJOB_TERM; 
   
   return TRUE; 
}    
    
    
