1 //---------------------------------------------------------------------------
2 // Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved.
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a
5 // copy of this software and associated documentation files (the "Software"),
6 // to deal in the Software without restriction, including without limitation
7 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 // and/or sell copies of the Software, and to permit persons to whom the
9 // Software is furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included
12 // in all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
18 // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 // OTHER DEALINGS IN THE SOFTWARE.
21 //
22 // Except as contained in this notice, the name of Dallas Semiconductor
23 // shall not be used except as stated in the Dallas Semiconductor
24 // Branding Policy.
25 //--------------------------------------------------------------------------
26 //
27 //  mbNV.c - Reads and writes to memory locations for the NV memory bank.
28 //  version 1.00
29 //
30 
31 // Include Files
32 #include "ownet.h"
33 #include "mbnv.h"
34 #include "mbscr.h"
35 #include "mbscree.h"
36 #include "mbscrex.h"
37 #include "mbscrcrc.h"
38 #include "mbsha.h"
39 #include "mbnvcrc.h"
40 
41 // External functions
42 extern SMALLINT owBlock(int,int,uchar *,int);
43 extern SMALLINT owReadByte(int);
44 extern SMALLINT owWriteByte(int,int);
45 extern void     output_status(int, char *);
46 extern void     msDelay(int);
47 extern void     owSerialNum(int,uchar *,int);
48 extern SMALLINT owAccess(int);
49 extern SMALLINT owWriteByte(int,int);
50 extern void     setcrc16(int,ushort);
51 extern ushort   docrc16(int,ushort);
52 extern SMALLINT owWriteBytePower(int,int);
53 extern SMALLINT owLevel(int,int);
54 
55 // General command defines
56 #define READ_MEMORY_COMMAND_NV      0xF0
57 
58 // Local defines
59 #define PAGE_LENGTH_NV 32
60 #define SIZE_NV        512
61 
62 // Global variables
63 char    *bankDescriptionNV     = "Main Memory";
64 SMALLINT writeVerificationNV    = TRUE;
65 SMALLINT generalPurposeMemoryNV = TRUE;
66 SMALLINT readWriteNV            = TRUE;
67 SMALLINT writeOnceNV            = FALSE;
68 SMALLINT readOnlyNV             = FALSE;
69 SMALLINT nonVolatileNV          = TRUE;
70 SMALLINT needProgramPulseNV     = FALSE;
71 SMALLINT needPowerDeliveryNV    = FALSE;
72 SMALLINT ExtraInfoNV            = FALSE;
73 SMALLINT extraInfoLengthNV      = 0;
74 char    *extraInfoDescNV       = "";
75 SMALLINT pageAutoCRCNV          = FALSE;
76 
77 
78 /**
79  * Read  memory in the current bank with no CRC checking (device or
80  * data). The resulting data from this API may or may not be what is on
81  * the 1-Wire device.  It is recommends that the data contain some kind
82  * of checking (CRC) like in the readPagePacketNV() method or have
83  * the 1-Wire device provide the CRC as in readPageCRCNV().  readPageCRCNV()
84  * however is not supported on all memory types, see 'hasPageAutoCRCNV()'.
85  * If neither is an option then this method could be called more
86  * then once to at least verify that the same thing is read consistantly.
87  *
88  * bank     to tell what memory bank of the ibutton to use.
89  * portnum  the port number of the port being used for the
90  *          1-Wire Network.
91  * SNum     the serial number for the part that the read is
92  *          to be done on.
93  * str_add  starting physical address
94  * rd_cont  if 'true' then device read is continued without
95  *          re-selecting.  This can only be used if the new
96  *          read() continious where the last one led off
97  *          and it is inside a 'beginExclusive/endExclusive'
98  *          block.
99  * buff     byte array to place read data into
100  * len      length in bytes to read
101  *
102  * @return 'true' if the read was complete
103  */
readNV(SMALLINT bank,int portnum,uchar * SNum,int str_add,SMALLINT rd_cont,uchar * buff,int len)104 SMALLINT readNV(SMALLINT bank, int portnum, uchar *SNum, int str_add,
105                 SMALLINT rd_cont, uchar *buff, int len)
106 {
107 
108    int i,addr,pgs,extra;
109    uchar raw_buf[PAGE_LENGTH_NV];
110 
111    // check if read exceeds memory
112    if ((str_add + len) > getSizeNV(bank,SNum))
113    {
114       OWERROR(OWERROR_READ_OUT_OF_RANGE);
115       return FALSE;
116    }
117 
118    // see if need to access the device
119    if (!rd_cont)
120    {
121 
122       owSerialNum(portnum,SNum,FALSE);
123 
124       // select the device
125       if (!owAccess(portnum))
126       {
127          OWERROR(OWERROR_DEVICE_SELECT_FAIL);
128          return FALSE;
129       }
130 
131       // build start reading memory block
132       addr    = str_add + getStartingAddressNV(bank,SNum);
133 
134       raw_buf[0] = READ_MEMORY_COMMAND_NV;
135       raw_buf[1] = addr & 0xFF;
136       raw_buf[2] = ((addr & 0xFFFF) >> 8) & 0xFF;
137 
138       // do the first block for command, address
139       if(!owBlock(portnum,FALSE,raw_buf,3))
140       {
141          OWERROR(OWERROR_BLOCK_FAILED);
142          return FALSE;
143       }
144 
145    }
146 
147    // pre-fill readBuf with 0xFF
148    pgs   = len / PAGE_LENGTH_NV;
149    extra = len % PAGE_LENGTH_NV;
150 
151    for(i=0;i<(pgs*PAGE_LENGTH_NV)+extra;i++)
152       buff[i] = 0xFF;
153 
154    // send second block to read data, return result
155    if(!owBlock(portnum,FALSE,buff,len))
156    {
157       OWERROR(OWERROR_BLOCK_FAILED);
158       return FALSE;
159    }
160 
161    return TRUE;
162 }
163 
164 /**
165  * Write  memory in the current bank.  It is recommended that
166  * when writing  data that some structure in the data is created
167  * to provide error free reading back with readNV().  Or the
168  * method 'writePagePacketNV()' could be used which automatically
169  * wraps the data in a length and CRC.
170  *
171  * When using on Write-Once devices care must be taken to write into
172  * into empty space.  If write() is used to write over an unlocked
173  * page on a Write-Once device it will fail.
174  *
175  * bank     to tell what memory bank of the ibutton to use.
176  * portnum  the port number of the port being used for the
177  *          1-Wire Network.
178  * SNum     the serial number for the part that the write is
179  *          to be done on.
180  * str_add  starting address
181  * buff     byte array containing data to write
182  * len      length in bytes to write
183  *
184  * @return 'true' if the write was complete.
185  */
writeNV(SMALLINT bank,int portnum,uchar * SNum,int str_add,uchar * buff,int len)186 SMALLINT writeNV(SMALLINT bank, int portnum, uchar *SNum, int str_add,
187                  uchar *buff, int len)
188 {
189    int i, room_left, startx, nextx, addr, pl;
190    uchar raw_buf[PAGE_LENGTH_NV];
191    uchar extra[PAGE_LENGTH_NV];
192 
193    // return if nothing to do
194    if (len == 0)
195       return TRUE;
196 
197    owSerialNum(portnum,SNum,FALSE);
198 
199    // check if write exceeds memory
200    if ((str_add + len) > getSizeNV(bank,SNum))
201    {
202       OWERROR(OWERROR_WRITE_OUT_OF_RANGE);
203       return FALSE;
204    }
205 
206    // check if trying to write read only bank
207    if(isReadOnlyNV(bank,portnum,SNum))
208    {
209       OWERROR(OWERROR_READ_ONLY);
210       return FALSE;
211    }
212 
213    // loop while still have pages to write
214    startx = 0;
215    nextx  = 0;
216    addr   = getStartingAddressNV(bank,SNum) + str_add;
217    pl     = PAGE_LENGTH_NV;
218 
219    do
220    {
221       // calculate room left in current page
222       room_left = pl - ((addr + startx) % pl);
223 
224       // check if block left will cross end of page
225       if ((len - startx) > room_left)
226          nextx = startx + room_left;
227       else
228          nextx = len;
229 
230       // write the page of data to scratchpad
231       switch(SNum[0])
232       {
233          case 0x18:
234             if(bank == 3)
235             {
236                if(!writeScratchpd(portnum,addr+startx,&buff[startx],nextx-startx))
237                   return FALSE;
238             }
239             else if(!writeScratchPadSHA(portnum,addr+startx,&buff[startx],nextx-startx))
240                return FALSE;
241             break;
242 
243          case 0x21:
244             if(!writeScratchPadEx(portnum,addr+startx,&buff[startx],nextx-startx))
245                return FALSE;
246             break;
247 
248          case 0x23:
249             if(!writeScratchPadEE(portnum,addr+startx,&buff[startx],nextx-startx))
250                return FALSE;
251             break;
252 
253          default:
254             if(!writeScratchpd(portnum,addr+startx,&buff[startx],nextx-startx))
255                return FALSE;
256             break;
257       }
258 
259       // read to verify ok
260       switch(SNum[0])
261       {
262          case 0x18:
263             if(bank == 3)
264             {
265                if(!readScratchpdExtra(portnum,raw_buf,pl,extra))
266                   return FALSE;
267             }
268             else if(!readScratchPadCRC(portnum,raw_buf,pl,extra))
269                return FALSE;
270             break;
271 
272          case 0x21:
273             if(!readScratchPadCRC(portnum,raw_buf,pl,extra))
274                return FALSE;
275             break;
276 
277          default:
278             if(!readScratchpdExtra(portnum,raw_buf,pl,extra))
279                return FALSE;
280             break;
281       }
282 
283       // check to see if the same
284       for (i = 0; i < (nextx - startx); i++)
285          if (raw_buf[i] != buff[i + startx])
286          {
287             OWERROR(OWERROR_READ_SCRATCHPAD_VERIFY);
288             return FALSE;
289          }
290 
291       // check to make sure that the address is correct
292       if ((((extra[0] & 0x00FF) | ((extra[1] << 8) & 0x00FF00))
293               & 0x00FFFF) != (addr + startx))
294       {
295          OWERROR(OWERROR_ADDRESS_READ_BACK_FAILED);
296          return FALSE;
297       }
298 
299       // do the copy
300       switch(SNum[0])
301       {
302          case 0x18:
303             if(bank == 3)
304             {
305                if(!copyScratchpd(portnum,addr+startx,nextx-startx))
306                   return FALSE;
307             }
308             else if(!copyScratchPadSHA(portnum,addr+startx,nextx-startx))
309                return FALSE;
310             break;
311 
312          case 0x1A:
313             if(!copyScratchPadEx(portnum,addr+startx,nextx-startx))
314                return FALSE;
315             break;
316 
317          case 0x21:
318             if(!copyScratchPadCRC(portnum,addr+startx,nextx-startx))
319                return FALSE;
320             break;
321 
322          case 0x23:
323             if(!copyScratchPadEE(portnum,addr+startx,nextx-startx))
324                return FALSE;
325             break;
326 
327          default:
328             if(!copyScratchpd(portnum,addr+startx,nextx-startx))
329                return FALSE;
330             break;
331       }
332 
333       // point to next index
334       startx = nextx;
335    } while (nextx < len);
336 
337    return TRUE;
338 }
339 
340 /**
341  * Read  page in the current bank with no
342  * CRC checking (device or data). The resulting data from this API
343  * may or may not be what is on the 1-Wire device.  It is recommends
344  * that the data contain some kind of checking (CRC) like in the
345  * readPagePacketNV() method or have the 1-Wire device provide the
346  * CRC as in readPageCRCNV().  readPageCRCNV() however is not
347  * supported on all memory types, see 'hasPageAutoCRCNV()'.
348  * If neither is an option then this method could be called more
349  * then once to at least verify that the same thing is read consistantly.
350  *
351  * bank     to tell what memory bank of the ibutton to use.
352  * portnum  the port number of the port being used for the
353  *          1-Wire Network.
354  * SNum     the serial number for the part.
355  * page     the page to read
356  * rd_cont  if 'true' then device read is continued without
357  *          re-selecting.  This can only be used if the new
358  *          read() continious where the last one led off
359  *          and it is inside a 'beginExclusive/endExclusive'
360  *          block.
361  * buff     byte array containing data that was read.
362  * len      length in bytes to write
363  *
364  * @return - returns '0' if the read page wasn't completed.
365  *                   '1' if the operation is complete.
366  */
readPageNV(SMALLINT bank,int portnum,uchar * SNum,int page,SMALLINT rd_cont,uchar * buff)367 SMALLINT readPageNV(SMALLINT bank, int portnum, uchar *SNum, int page,
368                     SMALLINT rd_cont, uchar *buff)
369 {
370    if(((SNum[0] == 0x18) && (bank != 3))|| (SNum[0] == 0x1A) || (SNum[0] == 0x1D) ||
371       (SNum[0] == 0x21))
372       return readPageNVCRC(bank,portnum,SNum,page,rd_cont,buff);
373 
374    if((page < 0) || (page > getNumberPagesNV(bank,SNum)))
375    {
376       OWERROR(OWERROR_INVALID_PAGE_NUMBER);
377       return FALSE;
378    }
379 
380    return readNV(bank,portnum,SNum,page*PAGE_LENGTH_NV,
381                  rd_cont,buff,PAGE_LENGTH_NV);
382 }
383 
384 /**
385  * Read  page with extra information in the current bank with no
386  * CRC checking (device or data). The resulting data from this API
387  * may or may not be what is on the 1-Wire device.  It is recommends
388  * that the data contain some kind of checking (CRC) like in the
389  * readPagePacketNV() method or have the 1-Wire device provide the
390  * CRC as in readPageCRCNV().  readPageCRCNV() however is not
391  * supported on all memory types, see 'hasPageAutoCRCNV()'.
392  * If neither is an option then this method could be called more
393  * then once to at least verify that the same thing is read consistantly.
394  * See the method 'hasExtraInfoNV()' for a description of the optional
395  * extra information some devices have.
396  *
397  * bank     to tell what memory bank of the ibutton to use.
398  * portnum  the port number of the port being used for the
399  *          1-Wire Network.
400  * SNum     the serial number for the part.
401  * page     the page to read
402  * rd_cont  if 'true' then device read is continued without
403  *          re-selecting.  This can only be used if the new
404  *          read() continious where the last one led off
405  *          and it is inside a 'beginExclusive/endExclusive'
406  *          block.
407  * buff     byte array containing data that was read
408  * len      length in bytes to write
409  * extra    the extra information
410  *
411  * @return - returns '0' if the read page wasn't completed with extra info.
412  *                   '1' if the operation is complete.
413  */
readPageExtraNV(SMALLINT bank,int portnum,uchar * SNum,int page,SMALLINT rd_cont,uchar * buff,uchar * extra)414 SMALLINT readPageExtraNV(SMALLINT bank, int portnum, uchar *SNum, int page,
415                     SMALLINT rd_cont, uchar *buff, uchar *extra)
416 {
417    if(((SNum[0] == 0x18) && (bank != 3)) || (SNum[0] == 0x1A) || (SNum[0] == 0x1D) ||
418       (SNum[0] == 0x21))
419       return readPageExtraNVCRC(bank,portnum,SNum,page,rd_cont,buff,extra);
420 
421    OWERROR(OWERROR_EXTRA_INFO_NOT_SUPPORTED);
422    return FALSE;
423 }
424 
425 /**
426  * Read a complete memory page with CRC verification provided by the
427  * device with extra information.  Not supported by all devices.
428  * See the method 'hasPageAutoCRC()'.
429  * See the method 'haveExtraInfo()' for a description of the optional
430  * extra information.
431  *
432  * bank     to tell what memory bank of the ibutton to use.
433  * portnum  the port number of the port being used for the
434  *          1-Wire Network.
435  * SNum     the serial number for the part.
436  * page     the page to read
437  * buff     byte array containing data that was read.
438  * extra    the extra information
439  *
440  * @return - returns '0' if the read page wasn't completed with extra info.
441  *                   '1' if the operation is complete.
442  */
readPageExtraCRCNV(SMALLINT bank,int portnum,uchar * SNum,int page,uchar * read_buff,uchar * extra)443 SMALLINT readPageExtraCRCNV(SMALLINT bank, int portnum, uchar *SNum, int page,
444                             uchar *read_buff, uchar *extra)
445 {
446    if(((SNum[0] == 0x18) && (bank != 3))|| (SNum[0] == 0x1A) || (SNum[0] == 0x1D) ||
447       (SNum[0] == 0x21))
448       return readPageExtraCRCNVCRC(bank,portnum,SNum,page,read_buff,extra);
449 
450    OWERROR(OWERROR_CRC_EXTRA_INFO_NOT_SUPPORTED);
451    return FALSE;
452 }
453 
454 /**
455  * Read a complete memory page with CRC verification provided by the
456  * device.  Not supported by all devices.  See the method
457  * 'hasPageAutoCRCNV()'.
458  *
459  * bank     to tell what memory bank of the ibutton to use.
460  * portnum  the port number of the port being used for the
461  *          1-Wire Network.
462  * SNum     the serial number for the part.
463  * page     the page to read
464  * buff     byte array containing data that was read
465  *
466  * @return - returns '0' if the read page wasn't completed.
467  *                   '1' if the operation is complete.
468  */
readPageCRCNV(SMALLINT bank,int portnum,uchar * SNum,int page,uchar * buff)469 SMALLINT readPageCRCNV(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *buff)
470 {
471    if(((SNum[0] == 0x18) && (bank != 3)) || (SNum[0] == 0x1A) || (SNum[0] == 0x1D) ||
472       (SNum[0] == 0x21))
473       return readPageCRCNVCRC(bank,portnum,SNum,page,buff);
474 
475    OWERROR(OWERROR_CRC_NOT_SUPPORTED);
476    return FALSE;
477 }
478 
479 /**
480  * Read a Universal Data Packet.
481  *
482  * The Universal Data Packet always starts on page boundaries but
483  * can end anywhere in the page.  The structure specifies the length of
484  * data bytes not including the length byte and the CRC16 bytes.
485  * There is one length byte. The CRC16 is first initialized to
486  * the page number.  This provides a check to verify the page that
487  * was intended is being read.  The CRC16 is then calculated over
488  * the length and data bytes.  The CRC16 is then inverted and stored
489  * low byte first followed by the high byte.  This is structure is
490  * used by this method to verify the data but is not returned, only
491  * the data payload is returned.
492  *
493  * bank     to tell what memory bank of the ibutton to use.
494  * portnum  the port number of the port being used for the
495  *          1-Wire Network.
496  * SNum     the serial number for the part.
497  * page     the page to read
498  * rd_cont  if 'true' then device read is continued without
499  *          re-selecting.  This can only be used if the new
500  *          read() continious where the last one led off
501  *          and it is inside a 'beginExclusive/endExclusive'
502  *          block.
503  * buff     byte array containing data that was read.
504  * len      length of the packet
505  *
506  * @return - returns '0' if the read page packet wasn't completed
507  *                   '1' if the operation is complete.
508  */
readPagePacketNV(SMALLINT bank,int portnum,uchar * SNum,int page,SMALLINT rd_cont,uchar * buff,int * len)509 SMALLINT readPagePacketNV(SMALLINT bank, int portnum, uchar *SNum, int page,
510                           SMALLINT rd_cont, uchar *buff, int *len)
511 {
512 
513    uchar raw_buf[PAGE_LENGTH_NV];
514    ushort lastcrc16;
515    int i;
516 
517    // read the  page
518    readPageNV(bank,portnum,SNum,page,rd_cont,&raw_buf[0]);
519 
520    // check if length is realistic
521    if ((raw_buf[0] > getMaxPacketDataLengthNV(bank,SNum)) || (raw_buf[0] <= 0))
522    {
523       OWERROR(OWERROR_INVALID_PACKET_LENGTH);
524       return FALSE;
525    }
526 
527    // verify the CRC is correct
528    setcrc16(portnum,(ushort) ((getStartingAddressNV(bank,SNum)/PAGE_LENGTH_NV) + page));
529    for(i=0;i<(raw_buf[0]+3);i++)
530       lastcrc16 = docrc16(portnum,raw_buf[i]);
531 
532    if(lastcrc16 == 0xB001)
533    {
534       for(i=1;i<raw_buf[0]+1;i++)
535          buff[i-1] = raw_buf[i];
536 
537       // return the length
538       *len = (int) raw_buf [0];
539    }
540    else
541    {
542       OWERROR(OWERROR_CRC_FAILED);
543       return FALSE;
544    }
545 
546    return TRUE;
547 }
548 
549 /**
550  * Read a Universal Data Packet and extra information.  See the
551  * method 'readPagePacketNV()' for a description of the packet structure.
552  * See the method 'hasExtraInfoNV()' for a description of the optional
553  * extra information some devices have.
554  *
555  * bank     to tell what memory bank of the ibutton to use.
556  * portnum  the port number of the port being used for the
557  *          1-Wire Network.
558  * SNum     the serial number for the part.
559  * page     the page to read
560  * rd_cont  if 'true' then device read is continued without
561  *          re-selecting.  This can only be used if the new
562  *          read() continious where the last one led off
563  *          and it is inside a 'beginExclusive/endExclusive'
564  *          block.
565  * buff     byte array containing data that was read.
566  * len      length of the packet
567  * extra    extra information
568  *
569  * @return - returns '0' if the read page packet wasn't completed
570  *                   '1' if the operation is complete.
571  */
readPagePacketExtraNV(SMALLINT bank,int portnum,uchar * SNum,int page,SMALLINT rd_cont,uchar * buff,int * len,uchar * extra)572 SMALLINT readPagePacketExtraNV(SMALLINT bank, int portnum, uchar *SNum,
573                                int page, SMALLINT rd_cont, uchar *buff,
574                                int *len, uchar *extra)
575 {
576    if(((SNum[0] == 0x18) && (bank != 3)) || (SNum[0] == 0x1A) || (SNum[0] == 0x1D) ||
577       (SNum[0] == 0x21))
578       return readPagePacketExtraNVCRC(bank,portnum,SNum,page,rd_cont,buff,
579                                       len,extra);
580 
581    OWERROR(OWERROR_PG_PACKET_WITHOUT_EXTRA);
582    return FALSE;
583 }
584 
585 /**
586  * Write a Universal Data Packet.  See the method 'readPagePacketNV()'
587  * for a description of the packet structure.
588  *
589  * bank     to tell what memory bank of the ibutton to use.
590  * portnum  the port number of the port being used for the
591  *          1-Wire Network.
592  * SNum     the serial number for the part.
593  * page     the page the packet is being written to.
594  * rd_cont  if 'true' then device read is continued without
595  *          re-selecting.  This can only be used if the new
596  *          read() continious where the last one led off
597  *          and it is inside a 'beginExclusive/endExclusive'
598  *          block.
599  * buff     byte array containing data that to write.
600  * len      length of the packet
601  *
602  * @return - returns '0' if the write page packet wasn't completed
603  *                   '1' if the operation is complete.
604  */
writePagePacketNV(SMALLINT bank,int portnum,uchar * SNum,int page,uchar * buff,int len)605 SMALLINT writePagePacketNV(SMALLINT bank, int portnum, uchar *SNum, int page,
606                            uchar *buff, int len)
607 {
608    uchar raw_buf[PAGE_LENGTH_NV];
609    int i;
610    ushort crc;
611 
612    // make sure length does not exceed max
613    if (len > getMaxPacketDataLengthNV(bank,SNum))
614    {
615       OWERROR(OWERROR_PACKET_LENGTH_EXCEEDS_PAGE);
616       return FALSE;
617    }
618 
619    // see if this bank is general read/write
620    if (!isGeneralPurposeMemoryNV(bank,SNum))
621    {
622       OWERROR(OWERROR_NOT_GENERAL_PURPOSE);
623       return FALSE;
624    }
625 
626    // construct the packet to write
627    raw_buf[0] = (uchar) len;
628 
629    for(i=1;i<(len+1);i++)
630       raw_buf[i] = buff[i-1];
631 
632    setcrc16(portnum,(ushort) ((getStartingAddressNV(bank,SNum)/PAGE_LENGTH_NV) + page));
633    for(i=0;i<(len+1);i++)
634       crc = docrc16(portnum,raw_buf[i]);
635 
636    raw_buf[len + 1] = ~crc & 0xFF;
637    raw_buf[len + 2] = ((~crc & 0xFFFF) >> 8) & 0xFF;
638 
639    // write the packet, return result
640    if(!writeNV(bank,portnum,SNum,page*PAGE_LENGTH_NV,&raw_buf[0],len+3))
641       return FALSE;
642 
643    return TRUE;
644 }
645 
646 /**
647  * Query to get the number of pages in current memory bank.
648  *
649  * bank     to tell what memory bank of the ibutton to use.
650  * SNum     the serial number for the part.
651  *
652  * @return  number of pages in current memory bank
653  */
getNumberPagesNV(SMALLINT bank,uchar * SNum)654 SMALLINT getNumberPagesNV(SMALLINT bank, uchar *SNum)
655 {
656    int pages = 16;
657 
658    switch(SNum[0])
659    {
660       case 0x04:
661          if(bank == 1)
662             pages = 16;
663          else if(bank == 2)
664             pages = 1;
665          else if(bank == 3)
666             pages = 3;
667          break;
668 
669       case 0x08:
670          pages = 4;
671          break;
672 
673       case 0x0A:
674          pages = 64;
675          break;
676 
677       case 0x0C:
678          pages = 256;
679          break;
680 
681       case 0x18:
682          if(bank == 3)
683             pages = 3;
684          else if(bank == 2)
685             pages = 8;
686          else if(bank == 1)
687             pages = 8;
688          break;
689 
690       case 0x1A:
691          if(bank == 2)
692             pages = 4;
693          else if(bank == 1)
694             pages = 12;
695          break;
696 
697       case 0x1D:
698          if(bank >= 2)
699             pages = 2;
700          else if(bank == 1)
701             pages = 12;
702          break;
703 
704       case 0x21:
705          if(bank == 5)
706             pages = 64;
707          else if(bank == 4)
708             pages = 4;
709          else if(bank == 3)
710             pages = 3;
711          else if(bank == 2)
712             pages = 1;
713          break;
714 
715       case 0x23:
716          if(bank == 1)
717             pages = 16;
718          break;
719 
720       default:
721          pages = 16;
722          break;
723    }
724 
725    return pages;
726 }
727 
728 /**
729  * Query to get the memory bank size in bytes.
730  *
731  * bank     to tell what memory bank of the ibutton to use.
732  * SNum     the serial number for the part.
733  *
734  * @return  memory bank size in bytes.
735  */
getSizeNV(SMALLINT bank,uchar * SNum)736 int getSizeNV(SMALLINT bank, uchar *SNum)
737 {
738    int size = 512;
739 
740    switch(SNum[0])
741    {
742       case 0x04:
743          if(bank == 1)
744             size = 512;
745          else if(bank == 2)
746             size = 32;
747          else if(bank == 3)
748             size = 96;
749          break;
750 
751       case 0x06:
752          size = 512;
753          break;
754 
755       case 0x08:
756          size = 128;
757          break;
758 
759       case 0x0A:
760          size = 2048;
761          break;
762 
763       case 0x0C:
764          size = 8192;
765          break;
766 
767       case 0x18:
768          if(bank == 3)
769             size = 96;
770          else if(bank == 2)
771             size = 256;
772          else if(bank == 1)
773             size = 256;
774          break;
775 
776       case 0x1A:
777          if(bank == 2)
778             size = 128;
779          else if(bank == 1)
780             size = 384;
781          break;
782 
783       case 0x1D:
784          if(bank <= 3)
785             size = 64;
786          else if(bank == 1)
787             size = 384;
788          break;
789 
790       case 0x21:
791          if(bank == 5)
792             size = 2048;
793          else if(bank == 4)
794             size = 128;
795          else if(bank == 3)
796             size = 96;
797          else if(bank == 2)
798             size = 32;
799          break;
800 
801       case 0x23:
802          if(bank == 1)
803             size = 512;
804          else if(bank == 2)
805             size = 32;
806          break;
807 
808       default:
809          size = 512;
810          break;
811    }
812 
813    return size;
814 }
815 
816 /**
817  * Query to get the starting physical address of this bank.  Physical
818  * banks are sometimes sub-divided into logical banks due to changes
819  * in attributes.
820  *
821  * bank     to tell what memory bank of the ibutton to use.
822  * SNum     the serial number for the part.
823  *
824  * @return  physical starting address of this logical bank.
825  */
getStartingAddressNV(SMALLINT bank,uchar * SNum)826 int getStartingAddressNV(SMALLINT bank, uchar *SNum)
827 {
828    int start = 0;
829 
830    switch(SNum[0])
831    {
832       case 0x04:
833          if(bank == 2)
834             start = 512;
835          break;
836 
837       case 0x18:
838          if(bank == 3)
839             start = 608;
840          else if(bank == 2)
841             start = 256;
842          break;
843 
844       case 0x1A:
845          if(bank == 2)
846             start = 384;
847          break;
848 
849       case 0x1D:
850          if(bank == 3)
851             start = 448;
852          else if(bank == 2)
853             start = 384;
854          break;
855 
856       case 0x21:
857          if(bank == 5)
858             start = 4096;
859          else if(bank == 4)
860             start = 2048;
861          else if(bank == 3)
862             start = 544;
863          else if(bank == 2)
864             start = 512;
865          break;
866 
867       default:
868          start = 0;
869          break;
870    }
871 
872    return start;
873 }
874 
875 /**
876  * Query to get page length in bytes in current memory bank.
877  *
878  * bank     to tell what memory bank of the ibutton to use.
879  * SNum     the serial number for the part.
880  *
881  * @return   page length in bytes in current memory bank
882  */
getPageLengthNV(SMALLINT bank,uchar * SNum)883 SMALLINT getPageLengthNV(SMALLINT bank, uchar *SNum)
884 {
885    return PAGE_LENGTH_NV;
886 }
887 
888 /**
889  * Query to see get a string description of the current memory bank.
890  *
891  * bank     to tell what memory bank of the ibutton to use.
892  * SNum     the serial number for the part.
893  *
894  * @return  String containing the memory bank description
895  */
getBankDescriptionNV(SMALLINT bank,uchar * SNum)896 char *getBankDescriptionNV(SMALLINT bank, uchar *SNum)
897 {
898    switch(SNum[0])
899    {
900       case 0x04:
901          if(bank == 2)
902             return "Clock/Alarm registers.";
903          break;
904 
905       case 0x18:
906          if(bank == 3)
907             return "Write cycle counters and PRNG counter.";
908          else if(bank == 2)
909             return "Memory with write cycle counter.";
910          break;
911 
912       case 0x1A:
913          if(bank == 2)
914             return "Memory with write cycle counter.";
915          break;
916 
917       case 0x1D:
918          if(bank == 3)
919             return "Memory with externally triggered counter.";
920          else if(bank == 2)
921             return "Memory with write cycle counter.";
922          break;
923 
924       case 0x21:
925          if(bank == 5)
926             return "Temperature log.";
927          else if(bank == 4)
928             return "Temperature Histogram.";
929          else if(bank == 3)
930             return "Alarm time stamps.";
931          else if(bank == 2)
932             return "Register control.";
933          break;
934 
935       default:
936          return bankDescriptionNV;
937          break;
938    }
939 
940    return bankDescriptionNV;
941 }
942 
943 /**
944  * Query to see if the current memory bank is general purpose
945  * user memory.  If it is NOT then it is Memory-Mapped and writing
946  * values to this memory will affect the behavior of the 1-Wire
947  * device.
948  *
949  * bank     to tell what memory bank of the ibutton to use.
950  * SNum     the serial number for the part.
951  *
952  * @return  'true' if current memory bank is general purpose
953  */
isGeneralPurposeMemoryNV(SMALLINT bank,uchar * SNum)954 SMALLINT isGeneralPurposeMemoryNV(SMALLINT bank, uchar *SNum)
955 {
956    SMALLINT gp = generalPurposeMemoryNV;
957 
958    switch(SNum[0])
959    {
960       case 0x04:
961          if(bank == 2)
962             gp = FALSE;
963          break;
964 
965       case 0x18:
966          if(bank == 3)
967             return FALSE;
968          break;
969 
970       case 0x21:
971          if(bank == 5)
972             gp = FALSE;
973          else if(bank == 4)
974             gp = FALSE;
975          else if(bank == 3)
976             gp = FALSE;
977          else if(bank == 2)
978             gp = FALSE;
979          break;
980 
981       default:
982          gp = generalPurposeMemoryNV;
983          break;
984    }
985 
986    return gp;
987 }
988 
989 /**
990  * Query to see if current memory bank is read/write.
991  *
992  * bank     to tell what memory bank of the ibutton to use.
993  * SNum     the serial number for the part.
994  *
995  * @return  'true' if current memory bank is read/write
996  */
isReadWriteNV(SMALLINT bank,int portnum,uchar * SNum)997 SMALLINT isReadWriteNV(SMALLINT bank, int portnum, uchar *SNum)
998 {
999    SMALLINT rw = readWriteNV;
1000 
1001    switch(SNum[0])
1002    {
1003       case 0x18:
1004          if(bank == 3)
1005             rw = FALSE;
1006          break;
1007 
1008       case 0x21:
1009          if(bank == 5)
1010             rw = FALSE;
1011          else if(bank == 4)
1012             rw = FALSE;
1013          else if(bank == 3)
1014             rw = FALSE;
1015          break;
1016 
1017       default:
1018          rw = readWriteNV;
1019    }
1020 
1021    return rw;
1022 }
1023 
1024 /**
1025  * Query to see if current memory bank is write write once such
1026  * as with EPROM technology.
1027  *
1028  * bank     to tell what memory bank of the ibutton to use.
1029  * SNum     the serial number for the part.
1030  *
1031  * @return  'true' if current memory bank can only be written once
1032  */
isWriteOnceNV(SMALLINT bank,int portnum,uchar * SNum)1033 SMALLINT isWriteOnceNV(SMALLINT bank, int portnum, uchar *SNum)
1034 {
1035    return writeOnceNV;
1036 }
1037 
1038 /**
1039  * Query to see if current memory bank is read only.
1040  *
1041  * @return  'true' if current memory bank can only be read
1042  */
isReadOnlyNV(SMALLINT bank,int portnum,uchar * SNum)1043 SMALLINT isReadOnlyNV(SMALLINT bank, int portnum, uchar *SNum)
1044 {
1045    SMALLINT ro = readOnlyNV;
1046 
1047    switch(SNum[0])
1048    {
1049       case 0x18:
1050          if(bank == 3)
1051             ro = TRUE;
1052          break;
1053 
1054       case 0x21:
1055          if(bank == 5)
1056             ro = TRUE;
1057          else if(bank == 4)
1058             ro = TRUE;
1059          else if(bank == 3)
1060             ro = TRUE;
1061          break;
1062 
1063       default:
1064          ro = readOnlyNV;
1065          break;
1066    }
1067 
1068    return ro;
1069 }
1070 
1071 /**
1072  * Query to see if current memory bank non-volatile.  Memory is
1073  * non-volatile if it retains its contents even when removed from
1074  * the 1-Wire network.
1075  *
1076  * bank     to tell what memory bank of the ibutton to use.
1077  * SNum     the serial number for the part.
1078  *
1079  * @return  'true' if current memory bank non volatile.
1080  */
isNonVolatileNV(SMALLINT bank,uchar * SNum)1081 SMALLINT isNonVolatileNV(SMALLINT bank, uchar *SNum)
1082 {
1083    return nonVolatileNV;
1084 }
1085 
1086 /**
1087  * Query to see if current memory bank pages need the adapter to
1088  * have a 'ProgramPulse' in order to write to the memory.
1089  *
1090  * bank     to tell what memory bank of the ibutton to use.
1091  * SNum     the serial number for the part.
1092  *
1093  * @return  'true' if writing to the current memory bank pages
1094  *                 requires a 'ProgramPulse'.
1095  */
needsProgramPulseNV(SMALLINT bank,uchar * SNum)1096 SMALLINT needsProgramPulseNV(SMALLINT bank, uchar *SNum)
1097 {
1098    return needProgramPulseNV;
1099 }
1100 
1101 /**
1102  * Query to see if current memory bank pages need the adapter to
1103  * have a 'PowerDelivery' feature in order to write to the memory.
1104  *
1105  * bank     to tell what memory bank of the ibutton to use.
1106  * SNum     the serial number for the part.
1107  *
1108  * @return  'true' if writing to the current memory bank pages
1109  *                 requires 'PowerDelivery'.
1110  */
needsPowerDeliveryNV(SMALLINT bank,uchar * SNum)1111 SMALLINT needsPowerDeliveryNV(SMALLINT bank, uchar *SNum)
1112 {
1113    return needPowerDeliveryNV;
1114 }
1115 
1116 /**
1117  * Checks to see if this memory bank's pages deliver extra
1118  * information outside of the normal data space,  when read.  Examples
1119  * of this may be a redirection byte, counter, tamper protection
1120  * bytes, or SHA-1 result.  If this method returns true then the
1121  * methods with an 'extraInfo' parameter can be used.
1122  *
1123  * bank     to tell what memory bank of the ibutton to use.
1124  * SNum     the serial number for the part.
1125  *
1126  * @return  true if reading the this memory bank's
1127  *               pages provides extra information
1128  */
hasExtraInfoNV(SMALLINT bank,uchar * SNum)1129 SMALLINT hasExtraInfoNV(SMALLINT bank, uchar *SNum)
1130 {
1131    SMALLINT extra = ExtraInfoNV;
1132 
1133    switch(SNum[0])
1134    {
1135       case 0x18:
1136          if((bank == 2) || (bank == 1))
1137             extra = TRUE;
1138          break;
1139 
1140       case 0x1A:
1141          if((bank == 2) || (bank == 1))
1142             extra = TRUE;
1143          break;
1144 
1145       case 0x1D:
1146          if((bank == 3) || (bank == 2))
1147             extra = TRUE;
1148          break;
1149 
1150       default:
1151          extra = ExtraInfoNV;
1152          break;
1153    }
1154 
1155    return extra;
1156 }
1157 
1158 /**
1159  * Query to get the length in bytes of extra information that
1160  * is read when read a page in the current memory bank.  See
1161  * 'hasExtraInfoNV()'.
1162  *
1163  * bank     to tell what memory bank of the ibutton to use.
1164  * SNum     the serial number for the part.
1165  *
1166  * @return  number of bytes in Extra Information read when reading
1167  *          pages in the current memory bank.
1168  */
getExtraInfoLengthNV(SMALLINT bank,uchar * SNum)1169 SMALLINT getExtraInfoLengthNV(SMALLINT bank, uchar *SNum)
1170 {
1171    SMALLINT len = 0;
1172 
1173    switch(SNum[0])
1174    {
1175       case 0x18:
1176          if(bank == 2)
1177             len = 8;
1178          else if(bank == 1)
1179             len = 8;
1180          break;
1181 
1182       case 0x1A:
1183          if(bank == 2)
1184             len = 8;
1185          else if(bank == 1)
1186             len = 8;
1187          break;
1188 
1189       case 0x1D:
1190          if(bank == 3)
1191             len = 8;
1192          else if(bank == 2)
1193             len = 8;
1194          break;
1195 
1196       default:
1197          len = extraInfoLengthNV;
1198          break;
1199    }
1200 
1201    return len;
1202 }
1203 
1204 /**
1205  * Query to get a string description of what is contained in
1206  * the Extra Informationed return when reading pages in the current
1207  * memory bank.  See 'hasExtraInfoNV()'.
1208  *
1209  * bank     to tell what memory bank of the ibutton to use.
1210  * SNum     the serial number for the part.
1211  *
1212  * @return string describing extra information.
1213  */
getExtraInfoDescNV(SMALLINT bank,uchar * SNum)1214 char *getExtraInfoDescNV(SMALLINT bank, uchar *SNum)
1215 {
1216    switch(SNum[0])
1217    {
1218       case 0x18:
1219          if(bank == 2)
1220             return "Write cycle counter.";
1221          break;
1222 
1223       case 0x1A:
1224          if(bank == 2)
1225             return "Write cycle counter.";
1226          break;
1227 
1228       case 0x1D:
1229          if(bank == 2)
1230             return "Write cycle counter.";
1231          else if(bank == 3)
1232             return "Externally triggered counter.";
1233          break;
1234 
1235       default:
1236          return extraInfoDescNV;
1237          break;
1238    }
1239 
1240    return extraInfoDescNV;
1241 }
1242 
1243 /**
1244  * Query to see if current memory bank pages can be read with
1245  * the contents being verified by a device generated CRC.
1246  * This is used to see if the 'ReadPageCRCNV()' can be used.
1247  *
1248  * bank     to tell what memory bank of the ibutton to use.
1249  * SNum     the serial number for the part.
1250  *
1251  * @return  'true' if current memory bank can be read with self
1252  *          generated CRC.
1253  */
hasPageAutoCRCNV(SMALLINT bank,uchar * SNum)1254 SMALLINT hasPageAutoCRCNV(SMALLINT bank, uchar *SNum)
1255 {
1256    SMALLINT autoCRC = pageAutoCRCNV;
1257 
1258    switch(SNum[0])
1259    {
1260       case 0x18:
1261          if((bank == 1) || (bank == 2))
1262             autoCRC = TRUE;
1263          break;
1264 
1265       case 0x1A:
1266          if((bank == 1) || (bank == 2))
1267             autoCRC = TRUE;
1268          break;
1269 
1270       case 0x1D:
1271          if((bank > 0) && (bank < 4))
1272             autoCRC = TRUE;
1273          break;
1274 
1275       case 0x21:
1276          if((bank > 0) && (bank < 6))
1277             autoCRC = TRUE;
1278          break;
1279 
1280       default:
1281          autoCRC = pageAutoCRCNV;
1282          break;
1283    }
1284 
1285    return autoCRC;
1286 }
1287 
1288 /**
1289  * Query to get Maximum data page length in bytes for a packet
1290  * read or written in the current memory bank.  See the 'ReadPagePacket()'
1291  * and 'WritePagePacket()' methods.  This method is only usefull
1292  * if the current memory bank is general purpose memory.
1293  *
1294  * @return  max packet page length in bytes in current memory bank
1295  */
getMaxPacketDataLengthNV(SMALLINT bank,uchar * SNum)1296 SMALLINT getMaxPacketDataLengthNV(SMALLINT bank, uchar *SNum)
1297 {
1298    return PAGE_LENGTH_NV - 3;
1299 }
1300 
1301 /**
1302  * Query to see if current memory bank pages can be redirected
1303  * to another pages.  This is mostly used in Write-Once memory
1304  * to provide a means to update.
1305  *
1306  * bank     to tell what memory bank of the ibutton to use.
1307  * SNum     the serial number for the part.
1308  *
1309  * @return  'true' if current memory bank pages can be redirected
1310  *          to a new page.
1311  */
canRedirectPageNV(SMALLINT bank,uchar * SNum)1312 SMALLINT canRedirectPageNV(SMALLINT bank, uchar *SNum)
1313 {
1314    return FALSE;
1315 }
1316 
1317 /**
1318  * Query to see if current memory bank pages can be locked.  A
1319  * locked page would prevent any changes to the memory.
1320  *
1321  * bank     to tell what memory bank of the ibutton to use.
1322  * SNum     the serial number for the part.
1323  *
1324  * @return  'true' if current memory bank pages can be redirected
1325  *          to a new page.
1326  */
canLockPageNV(SMALLINT bank,uchar * SNum)1327 SMALLINT canLockPageNV(SMALLINT bank, uchar *SNum)
1328 {
1329    return FALSE;
1330 }
1331 
1332 /**
1333  * Query to see if current memory bank pages can be locked from
1334  * being redirected.  This would prevent a Write-Once memory from
1335  * being updated.
1336  *
1337  * bank     to tell what memory bank of the ibutton to use.
1338  * SNum     the serial number for the part.
1339  *
1340  * @return  'true' if current memory bank pages can be locked from
1341  *          being redirected to a new page.
1342  */
canLockRedirectPageNV(SMALLINT bank,uchar * SNum)1343 SMALLINT canLockRedirectPageNV(SMALLINT bank, uchar *SNum)
1344 {
1345    return FALSE;
1346 }
1347 
1348