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