Merge branch 'master' of /home/stefan/git/u-boot/u-boot into for-1.3.2-ver2
[platform/kernel/u-boot.git] / board / hymod / eeprom.c
1 /*
2  * (C) Copyright 2001
3  * Murray Jensen, CSIRO-MIT, <Murray.Jensen@csiro.au>
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 #include <common.h>
25 #include <mpc8260.h>
26
27 /* imports from fetch.c */
28 extern int fetch_and_parse (char *, ulong, int (*)(uchar *, uchar *));
29
30 /* imports from input.c */
31 extern int hymod_get_serno (const char *);
32
33 /* this is relative to the root of the server's tftp directory */
34 static char *def_bddb_cfgdir = "/hymod/bddb";
35
36 static int
37 hymod_eeprom_load (int which, hymod_eeprom_t *ep)
38 {
39         unsigned dev_addr = CFG_I2C_EEPROM_ADDR | \
40                 (which ? HYMOD_EEOFF_MEZZ : HYMOD_EEOFF_MAIN);
41         unsigned offset = 0;
42         uchar data[HYMOD_EEPROM_MAXLEN], *dp, *edp;
43         hymod_eehdr_t hdr;
44         ulong len, crc;
45
46         memset (ep, 0, sizeof *ep);
47
48         eeprom_read (dev_addr, offset, (uchar *)&hdr, sizeof (hdr));
49         offset += sizeof (hdr);
50
51         if (hdr.id != HYMOD_EEPROM_ID || hdr.ver > HYMOD_EEPROM_VER ||
52           (len = hdr.len) > HYMOD_EEPROM_MAXLEN)
53             return (0);
54
55         eeprom_read (dev_addr, offset, data, len);
56         offset += len;
57
58         eeprom_read (dev_addr, offset, (uchar *)&crc, sizeof (ulong));
59         offset += sizeof (ulong);
60
61         if (crc32 (crc32 (0, (uchar *)&hdr, sizeof hdr), data, len) != crc)
62                 return (0);
63
64         ep->ver = hdr.ver;
65         dp = data; edp = dp + len;
66
67         for (;;) {
68                 ulong rtyp;
69                 uchar rlen, *rdat;
70
71                 rtyp = *dp++;
72                 if ((rtyp & 0x80) == 0)
73                         rlen = *dp++;
74                 else {
75                         uchar islarge = rtyp & 0x40;
76
77                         rtyp = ((rtyp & 0x3f) << 8) | *dp++;
78                         if (islarge) {
79                                 rtyp = (rtyp << 8) | *dp++;
80                                 rtyp = (rtyp << 8) | *dp++;
81                         }
82
83                         rlen = *dp++;
84                         rlen = (rlen << 8) | *dp++;
85                         if (islarge) {
86                                 rlen = (rlen << 8) | *dp++;
87                                 rlen = (rlen << 8) | *dp++;
88                         }
89                 }
90
91                 if (rtyp == 0)
92                         break;
93
94                 rdat = dp;
95                 dp += rlen;
96
97                 if (dp > edp)   /* error? */
98                         break;
99
100                 switch (rtyp) {
101
102                 case HYMOD_EEREC_SERNO:         /* serial number */
103                         if (rlen == sizeof (ulong))
104                                 ep->serno = \
105                                         ((ulong)rdat[0] << 24) | \
106                                         ((ulong)rdat[1] << 16) | \
107                                         ((ulong)rdat[2] << 8) | \
108                                         (ulong)rdat[3];
109                         break;
110
111                 case HYMOD_EEREC_DATE:          /* date */
112                         if (rlen == sizeof (hymod_date_t)) {
113                                 ep->date.year = ((ushort)rdat[0] << 8) | \
114                                         (ushort)rdat[1];
115                                 ep->date.month = rdat[2];
116                                 ep->date.day = rdat[3];
117                         }
118                         break;
119
120                 case HYMOD_EEREC_BATCH:         /* batch */
121                         if (rlen <= HYMOD_MAX_BATCH)
122                                 memcpy (ep->batch, rdat, ep->batchlen = rlen);
123                         break;
124
125                 case HYMOD_EEREC_TYPE:          /* board type */
126                         if (rlen == 1)
127                                 ep->bdtype = *rdat;
128                         break;
129
130                 case HYMOD_EEREC_REV:           /* board revision */
131                         if (rlen == 1)
132                                 ep->bdrev = *rdat;
133                         break;
134
135                 case HYMOD_EEREC_SDRAM:         /* sdram size(s) */
136                         if (rlen > 0 && rlen <= HYMOD_MAX_SDRAM) {
137                                 int i;
138
139                                 for (i = 0; i < rlen; i++)
140                                         ep->sdramsz[i] = rdat[i];
141                                 ep->nsdram = rlen;
142                         }
143                         break;
144
145                 case HYMOD_EEREC_FLASH:         /* flash size(s) */
146                         if (rlen > 0 && rlen <= HYMOD_MAX_FLASH) {
147                                 int i;
148
149                                 for (i = 0; i < rlen; i++)
150                                         ep->flashsz[i] = rdat[i];
151                                 ep->nflash = rlen;
152                         }
153                         break;
154
155                 case HYMOD_EEREC_ZBT:           /* zbt ram size(s) */
156                         if (rlen > 0 && rlen <= HYMOD_MAX_ZBT) {
157                                 int i;
158
159                                 for (i = 0; i < rlen; i++)
160                                         ep->zbtsz[i] = rdat[i];
161                                 ep->nzbt = rlen;
162                         }
163                         break;
164
165                 case HYMOD_EEREC_XLXTYP:        /* xilinx fpga type(s) */
166                         if (rlen > 0 && rlen <= HYMOD_MAX_XLX) {
167                                 int i;
168
169                                 for (i = 0; i < rlen; i++)
170                                         ep->xlx[i].type = rdat[i];
171                                 ep->nxlx = rlen;
172                         }
173                         break;
174
175                 case HYMOD_EEREC_XLXSPD:        /* xilinx fpga speed(s) */
176                         if (rlen > 0 && rlen <= HYMOD_MAX_XLX) {
177                                 int i;
178
179                                 for (i = 0; i < rlen; i++)
180                                         ep->xlx[i].speed = rdat[i];
181                         }
182                         break;
183
184                 case HYMOD_EEREC_XLXTMP:        /* xilinx fpga temperature(s) */
185                         if (rlen > 0 && rlen <= HYMOD_MAX_XLX) {
186                                 int i;
187
188                                 for (i = 0; i < rlen; i++)
189                                         ep->xlx[i].temp = rdat[i];
190                         }
191                         break;
192
193                 case HYMOD_EEREC_XLXGRD:        /* xilinx fpga grade(s) */
194                         if (rlen > 0 && rlen <= HYMOD_MAX_XLX) {
195                                 int i;
196
197                                 for (i = 0; i < rlen; i++)
198                                         ep->xlx[i].grade = rdat[i];
199                         }
200                         break;
201
202                 case HYMOD_EEREC_CPUTYP:        /* CPU type */
203                         if (rlen == 1)
204                                 ep->mpc.type = *rdat;
205                         break;
206
207                 case HYMOD_EEREC_CPUSPD:        /* CPU speed */
208                         if (rlen == 1)
209                                 ep->mpc.cpuspd = *rdat;
210                         break;
211
212                 case HYMOD_EEREC_CPMSPD:        /* CPM speed */
213                         if (rlen == 1)
214                                 ep->mpc.cpmspd = *rdat;
215                         break;
216
217                 case HYMOD_EEREC_BUSSPD:        /* bus speed */
218                         if (rlen == 1)
219                                 ep->mpc.busspd = *rdat;
220                         break;
221
222                 case HYMOD_EEREC_HSTYPE:        /* hs-serial chip type */
223                         if (rlen == 1)
224                                 ep->hss.type = *rdat;
225                         break;
226
227                 case HYMOD_EEREC_HSCHIN:        /* num hs-serial input chans */
228                         if (rlen == 1)
229                                 ep->hss.nchin = *rdat;
230                         break;
231
232                 case HYMOD_EEREC_HSCHOUT:       /* num hs-serial output chans */
233                         if (rlen == 1)
234                                 ep->hss.nchout = *rdat;
235                         break;
236
237                 default:        /* ignore */
238                         break;
239                 }
240         }
241
242         return (1);
243 }
244
245 /* maps an ascii "name=value" into a binary eeprom data record */
246 typedef
247         struct _eerec_map {
248                 char *name;
249                 uint type;
250                 uchar *(*handler) \
251                         (struct _eerec_map *, uchar *, uchar *, uchar *);
252                 uint length;
253                 uint maxlen;
254         }
255 eerec_map_t;
256
257 static uchar *
258 uint_handler (eerec_map_t *rp, uchar *val, uchar *dp, uchar *edp)
259 {
260         char *eval;
261         ulong lval;
262
263         lval = simple_strtol ((char *)val, &eval, 10);
264
265         if ((uchar *)eval == val || *eval != '\0') {
266                 printf ("%s rec (%s) is not a valid uint\n", rp->name, val);
267                 return (NULL);
268         }
269
270         if (dp + 2 + rp->length > edp) {
271                 printf ("can't fit %s rec into eeprom\n", rp->name);
272                 return (NULL);
273         }
274
275         *dp++ = rp->type;
276         *dp++ = rp->length;
277
278         switch (rp->length) {
279
280         case 1:
281                 if (lval >= 256) {
282                         printf ("%s rec value (%lu) out of range (0-255)\n",
283                                 rp->name, lval);
284                         return (NULL);
285                 }
286                 *dp++ = lval;
287                 break;
288
289         case 2:
290                 if (lval >= 65536) {
291                         printf ("%s rec value (%lu) out of range (0-65535)\n",
292                                 rp->name, lval);
293                         return (NULL);
294                 }
295                 *dp++ = lval >> 8;
296                 *dp++ = lval;
297                 break;
298
299         case 4:
300                 *dp++ = lval >> 24;
301                 *dp++ = lval >> 16;
302                 *dp++ = lval >> 8;
303                 *dp++ = lval;
304                 break;
305
306         default:
307                 printf ("huh? rp->length not 1, 2 or 4! (%d)\n", rp->length);
308                 return (NULL);
309         }
310
311         return (dp);
312 }
313
314 static uchar *
315 date_handler (eerec_map_t *rp, uchar *val, uchar *dp, uchar *edp)
316 {
317         hymod_date_t date;
318         char *p = (char *)val;
319         char *ep;
320         ulong lval;
321
322         lval = simple_strtol (p, &ep, 10);
323         if (ep == p || *ep++ != '-') {
324 bad_date:
325                 printf ("%s rec (%s) is not a valid date\n", rp->name, val);
326                 return (NULL);
327         }
328         if (lval >= 65536)
329                 goto bad_date;
330         date.year = lval;
331
332         lval = simple_strtol (p = ep, &ep, 10);
333         if (ep == p || *ep++ != '-' || lval == 0 || lval > 12)
334                 goto bad_date;
335         date.month = lval;
336
337         lval = simple_strtol (p = ep, &ep, 10);
338         if (ep == p || *ep != '\0' || lval == 0 || lval > 31)
339                 goto bad_date;
340         date.day = lval;
341
342         if (dp + 2 + rp->length > edp) {
343                 printf ("can't fit %s rec into eeprom\n", rp->name);
344                 return (NULL);
345         }
346
347         *dp++ = rp->type;
348         *dp++ = rp->length;
349         *dp++ = date.year >> 8;
350         *dp++ = date.year;
351         *dp++ = date.month;
352         *dp++ = date.day;
353
354         return (dp);
355 }
356
357 static uchar *
358 string_handler (eerec_map_t *rp, uchar *val, uchar *dp, uchar *edp)
359 {
360         uint len;
361
362         if ((len = strlen ((char *)val)) > rp->maxlen) {
363                 printf ("%s rec (%s) string is too long (%d>%d)\n",
364                         rp->name, val, len, rp->maxlen);
365                 return (NULL);
366         }
367
368         if (dp + 2 + len > edp) {
369                 printf ("can't fit %s rec into eeprom\n", rp->name);
370                 return (NULL);
371         }
372
373         *dp++ = rp->type;
374         *dp++ = len;
375         memcpy (dp, val, len);
376         dp += len;
377
378         return (dp);
379 }
380
381 static uchar *
382 bytes_handler (eerec_map_t *rp, uchar *val, uchar *dp, uchar *edp)
383 {
384         uchar bytes[HYMOD_MAX_BYTES], nbytes, *p;
385         char *ep;
386
387         for (nbytes = 0, p = val; *p != '\0'; p = (uchar *)ep) {
388                 ulong lval;
389
390                 lval = simple_strtol ((char *)p, &ep, 10);
391                 if ((uchar *)ep == p || (*ep != '\0' && *ep != ',') || \
392                     lval >= 256) {
393                         printf ("%s rec (%s) byte array has invalid uint\n",
394                                 rp->name, val);
395                         return (NULL);
396                 }
397                 if (nbytes >= HYMOD_MAX_BYTES) {
398                         printf ("%s rec (%s) byte array too long\n",
399                                 rp->name, val);
400                         return (NULL);
401                 }
402                 bytes[nbytes++] = lval;
403
404                 if (*ep != '\0')
405                         ep++;
406         }
407
408         if (dp + 2 + nbytes > edp) {
409                 printf ("can't fit %s rec into eeprom\n", rp->name);
410                 return (NULL);
411         }
412
413         *dp++ = rp->type;
414         *dp++ = nbytes;
415         memcpy (dp, bytes, nbytes);
416         dp += nbytes;
417
418         return (dp);
419 }
420
421 static eerec_map_t eerec_map[] = {
422         /* name      type                 handler         len max             */
423         { "serno",   HYMOD_EEREC_SERNO,   uint_handler,   4,  0               },
424         { "date",    HYMOD_EEREC_DATE,    date_handler,   4,  0               },
425         { "batch",   HYMOD_EEREC_BATCH,   string_handler, 0,  HYMOD_MAX_BATCH },
426         { "type",    HYMOD_EEREC_TYPE,    uint_handler,   1,  0               },
427         { "rev",     HYMOD_EEREC_REV,     uint_handler,   1,  0               },
428         { "sdram",   HYMOD_EEREC_SDRAM,   bytes_handler,  0,  HYMOD_MAX_SDRAM },
429         { "flash",   HYMOD_EEREC_FLASH,   bytes_handler,  0,  HYMOD_MAX_FLASH },
430         { "zbt",     HYMOD_EEREC_ZBT,     bytes_handler,  0,  HYMOD_MAX_ZBT   },
431         { "xlxtyp",  HYMOD_EEREC_XLXTYP,  bytes_handler,  0,  HYMOD_MAX_XLX   },
432         { "xlxspd",  HYMOD_EEREC_XLXSPD,  bytes_handler,  0,  HYMOD_MAX_XLX   },
433         { "xlxtmp",  HYMOD_EEREC_XLXTMP,  bytes_handler,  0,  HYMOD_MAX_XLX   },
434         { "xlxgrd",  HYMOD_EEREC_XLXGRD,  bytes_handler,  0,  HYMOD_MAX_XLX   },
435         { "cputyp",  HYMOD_EEREC_CPUTYP,  uint_handler,   1,  0               },
436         { "cpuspd",  HYMOD_EEREC_CPUSPD,  uint_handler,   1,  0               },
437         { "cpmspd",  HYMOD_EEREC_CPMSPD,  uint_handler,   1,  0               },
438         { "busspd",  HYMOD_EEREC_BUSSPD,  uint_handler,   1,  0               },
439         { "hstype",  HYMOD_EEREC_HSTYPE,  uint_handler,   1,  0               },
440         { "hschin",  HYMOD_EEREC_HSCHIN,  uint_handler,   1,  0               },
441         { "hschout", HYMOD_EEREC_HSCHOUT, uint_handler,   1,  0               },
442 };
443
444 static int neerecs = sizeof eerec_map / sizeof eerec_map[0];
445
446 static uchar data[HYMOD_EEPROM_SIZE], *sdp, *dp, *edp;
447
448 static int
449 eerec_callback (uchar *name, uchar *val)
450 {
451         eerec_map_t *rp;
452
453         for (rp = eerec_map; rp < &eerec_map[neerecs]; rp++)
454                 if (strcmp ((char *)name, rp->name) == 0)
455                         break;
456
457         if (rp >= &eerec_map[neerecs])
458                 return (0);
459
460         if ((dp = (*rp->handler) (rp, val, dp, edp)) == NULL)
461                 return (0);
462
463         return (1);
464 }
465
466 static int
467 hymod_eeprom_fetch(int which, char *filename, ulong addr)
468 {
469         unsigned dev_addr = CFG_I2C_EEPROM_ADDR | \
470                 (which ? HYMOD_EEOFF_MEZZ : HYMOD_EEOFF_MAIN);
471         hymod_eehdr_t *hp = (hymod_eehdr_t *)&data[0];
472         ulong crc;
473
474         memset (hp, 0, sizeof *hp);
475         hp->id = HYMOD_EEPROM_ID;
476         hp->ver = HYMOD_EEPROM_VER;
477
478         dp = sdp = (uchar *)(hp + 1);
479         edp = dp + HYMOD_EEPROM_MAXLEN;
480
481         if (fetch_and_parse (filename, addr, eerec_callback) == 0)
482                 return (0);
483
484         hp->len = dp - sdp;
485
486         crc = crc32 (0, data, dp - data);
487         memcpy (dp, &crc, sizeof (ulong));
488         dp += sizeof (ulong);
489
490         eeprom_write (dev_addr, 0, data, dp - data);
491
492         return (1);
493 }
494
495 static char *type_vals[] = {
496         "NONE", "IO", "CLP", "DSP", "INPUT", "ALT-INPUT", "DISPLAY"
497 };
498
499 static char *xlxtyp_vals[] = {
500         "NONE", "XCV300E", "XCV400E", "XCV600E"
501 };
502
503 static char *xlxspd_vals[] = {
504         "NONE", "6", "7", "8"
505 };
506
507 static char *xlxtmp_vals[] = {
508         "NONE", "COM", "IND"
509 };
510
511 static char *xlxgrd_vals[] = {
512         "NONE", "NORMAL", "ENGSAMP"
513 };
514
515 static char *cputyp_vals[] = {
516         "NONE", "MPC8260"
517 };
518
519 static char *clk_vals[] = {
520         "NONE", "33", "66", "100", "133", "166", "200"
521 };
522
523 static char *hstype_vals[] = {
524         "NONE", "AMCC-S2064A"
525 };
526
527 static void
528 print_mem (char *l, char *s, uchar n, uchar a[])
529 {
530         if (n > 0) {
531                 if (n == 1)
532                         printf ("%s%dMB %s", s, 1 << (a[0] - 20), l);
533                 else {
534                         ulong t = 0;
535                         int i;
536
537                         for (i = 0; i < n; i++)
538                                 t += 1 << (a[i] - 20);
539
540                         printf ("%s%luMB %s (%d banks:", s, t, l, n);
541
542                         for (i = 0; i < n; i++)
543                                 printf ("%dMB%s",
544                                         1 << (a[i] - 20),
545                                         (i == n - 1) ? ")" : ",");
546                 }
547         }
548         else
549                 printf ("%sNO %s", s, l);
550 }
551
552 void
553 hymod_eeprom_print (hymod_eeprom_t *ep)
554 {
555         int i;
556
557         printf ("         Hymod %s board, rev %03d\n",
558                 type_vals[ep->bdtype], ep->bdrev);
559
560         printf ("         serial #: %010lu, date %04d-%02d-%02d",
561                 ep->serno, ep->date.year, ep->date.month, ep->date.day);
562         if (ep->batchlen > 0)
563                 printf (", batch \"%.*s\"", ep->batchlen, ep->batch);
564         puts ("\n");
565
566         switch (ep->bdtype) {
567
568         case HYMOD_BDTYPE_IO:
569         case HYMOD_BDTYPE_CLP:
570         case HYMOD_BDTYPE_DSP:
571                 printf ("         Motorola %s CPU, speeds: %s/%s/%s",
572                     cputyp_vals[ep->mpc.type], clk_vals[ep->mpc.cpuspd],
573                     clk_vals[ep->mpc.cpmspd], clk_vals[ep->mpc.busspd]);
574
575                 print_mem ("SDRAM", ", ", ep->nsdram, ep->sdramsz);
576
577                 print_mem ("FLASH", ", ", ep->nflash, ep->flashsz);
578
579                 puts ("\n");
580
581                 print_mem ("ZBT", "         ", ep->nzbt, ep->zbtsz);
582
583                 if (ep->nxlx > 0) {
584                         hymod_xlx_t *xp;
585
586                         if (ep->nxlx == 1) {
587                                 xp = &ep->xlx[0];
588                                 printf (", Xilinx %s FPGA (%s/%s/%s)",
589                                         xlxtyp_vals[xp->type],
590                                         xlxspd_vals[xp->speed],
591                                         xlxtmp_vals[xp->temp],
592                                         xlxgrd_vals[xp->grade]);
593                         }
594                         else {
595                                 printf (", %d Xilinx FPGAs (", ep->nxlx);
596                                 for (i = 0; i < ep->nxlx; i++) {
597                                         xp = &ep->xlx[i];
598                                         printf ("%s[%s/%s/%s]%s",
599                                             xlxtyp_vals[xp->type],
600                                             xlxspd_vals[xp->speed],
601                                             xlxtmp_vals[xp->temp],
602                                             xlxgrd_vals[xp->grade],
603                                             (i == ep->nxlx - 1) ? ")" : ", ");
604                                 }
605                         }
606                 }
607                 else
608                         puts(", NO FPGAs");
609
610                 puts ("\n");
611
612                 if (ep->hss.type > 0)
613                         printf ("         High Speed Serial: "
614                                 "%s, %d input%s, %d output%s\n",
615                                 hstype_vals[ep->hss.type],
616                                 ep->hss.nchin,
617                                 (ep->hss.nchin == 1 ? "" : "s"),
618                                 ep->hss.nchout,
619                                 (ep->hss.nchout == 1 ? "" : "s"));
620                 break;
621
622         case HYMOD_BDTYPE_INPUT:
623         case HYMOD_BDTYPE_ALTINPUT:
624         case HYMOD_BDTYPE_DISPLAY:
625                 break;
626
627         default:
628                 /* crap! */
629                 printf ("         UNKNOWN BOARD TYPE: %d\n", ep->bdtype);
630                 break;
631         }
632 }
633
634 int
635 hymod_eeprom_read (int which, hymod_eeprom_t *ep)
636 {
637         char *label = which ? "mezzanine" : "main";
638         unsigned dev_addr = CFG_I2C_EEPROM_ADDR | \
639                 (which ? HYMOD_EEOFF_MEZZ : HYMOD_EEOFF_MAIN);
640         char filename[50], prompt[50], *dir;
641         int serno, count = 0, rc;
642
643         rc = eeprom_probe (dev_addr, 0);
644
645         if (rc > 0) {
646                 printf ("*** probe for eeprom failed with code %d\n", rc);
647                 return (0);
648         }
649
650         if (rc < 0)
651                 return (rc);
652
653         sprintf (prompt, "Enter %s board serial number: ", label);
654
655         if ((dir = getenv ("bddb_cfgdir")) == NULL)
656                 dir = def_bddb_cfgdir;
657
658         for (;;) {
659                 int rc;
660
661                 if (hymod_eeprom_load (which, ep))
662                         return (1);
663
664                 printf ("*** %s board EEPROM contents are %sinvalid\n",
665                         label, count == 0 ? "" : "STILL ");
666
667                 puts ("*** will fetch from server (Ctrl-C to abort)\n");
668
669                 serno = hymod_get_serno (prompt);
670
671                 if (serno < 0) {
672                         if (serno == -1)
673                                 puts ("\n*** interrupted!");
674                         else
675                                 puts ("\n*** timeout!");
676                         puts (" - ignoring eeprom contents\n");
677                         return (0);
678                 }
679
680                 sprintf (filename, "%s/%010d.cfg", dir, serno);
681
682                 printf ("*** fetching %s board EEPROM contents from server\n",
683                         label);
684
685                 rc = hymod_eeprom_fetch (which, filename, CFG_LOAD_ADDR);
686
687                 if (rc == 0) {
688                         puts ("*** fetch failed - ignoring eeprom contents\n");
689                         return (0);
690                 }
691
692                 count++;
693         }
694 }