]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/sk98lin/skvpd.c
* Patches by Xianghua Xiao, 15 Oct 2003:
[karo-tx-uboot.git] / drivers / sk98lin / skvpd.c
1 /******************************************************************************
2  *
3  * Name:        skvpd.c
4  * Project:     GEnesis, PCI Gigabit Ethernet Adapter
5  * Version:     $Revision: 1.37 $
6  * Date:        $Date: 2003/01/13 10:42:45 $
7  * Purpose:     Shared software to read and write VPD data
8  *
9  ******************************************************************************/
10
11 /******************************************************************************
12  *
13  *      (C)Copyright 1998-2003 SysKonnect GmbH.
14  *
15  *      This program is free software; you can redistribute it and/or modify
16  *      it under the terms of the GNU General Public License as published by
17  *      the Free Software Foundation; either version 2 of the License, or
18  *      (at your option) any later version.
19  *
20  *      The information in this file is provided "AS IS" without warranty.
21  *
22  ******************************************************************************/
23
24 /******************************************************************************
25  *
26  * History:
27  *
28  *      $Log: skvpd.c,v $
29  *      Revision 1.37  2003/01/13 10:42:45  rschmidt
30  *      Replaced check for PCI device Id from YUKON with GENESIS
31  *      to set the VPD size in VpdInit()
32  *      Editorial changes
33  *
34  *      Revision 1.36  2002/11/14 15:16:56  gheinig
35  *      Added const specifier to key and buf parameters for VpdPara, VpdRead
36  *      and VpdWrite for Diag 7 GUI
37  *
38  *      Revision 1.35  2002/10/21 14:31:59  gheinig
39  *      Took out CVS web garbage at head of file
40  *
41  *      Revision 1.34  2002/10/21 11:47:24  gheinig
42  *      Reverted to version 1.32 due to unwanted commit
43  *
44  *      Revision 1.32  2002/10/14 16:04:29  rschmidt
45  *      Added saving of VPD ROM Size from PCI_OUR_REG_2
46  *      Avoid reading of PCI_OUR_REG_2 in VpdTransferBlock()
47  *      Editorial changes
48  *
49  *      Revision 1.31  2002/09/10 09:21:32  mkarl
50  *      Replaced all if(GIChipId == CHIP_ID_GENESIS) with new entry GIGenesis
51  *
52  *      Revision 1.30  2002/09/09 14:43:03  mkarl
53  *      changes for diagnostics in order to read VPD data before the adapter
54  *      has been initialized
55  *      editorial changes
56  *
57  *      Revision 1.29  2002/07/26 13:20:43  mkarl
58  *      added Yukon support
59  *      save size of VPD in pAC->vpd.vpd_size
60  *
61  *      Revision 1.28  2002/04/02 15:31:47  afischer
62  *      Bug fix in VpdWait()
63  *
64  *      Revision 1.27  2000/08/10 11:29:06  rassmann
65  *      Editorial changes.
66  *      Preserving 32-bit alignment in structs for the adapter context.
67  *      Removed unused function VpdWriteDword() (#if 0).
68  *      Made VpdReadKeyword() available for SKDIAG only.
69  *
70  *      Revision 1.26  2000/06/13 08:00:01  mkarl
71  *      additional cast to avoid compile problems in 64 bit environment
72  *
73  *      Revision 1.25  1999/11/22 13:39:32  cgoos
74  *      Changed license header to GPL.
75  *
76  *      Revision 1.24  1999/03/11 14:25:49  malthoff
77  *      Replace __STDC__ with SK_KR_PROTO.
78  *
79  *      Revision 1.23  1999/01/11 15:13:11  gklug
80  *      fix: syntax error
81  *
82  *      Revision 1.22  1998/10/30 06:41:15  gklug
83  *      rmv: WARNING
84  *
85  *      Revision 1.21  1998/10/29 07:15:14  gklug
86  *      fix: Write Stream function needs verify.
87  *
88  *      Revision 1.20  1998/10/28 18:05:08  gklug
89  *      chg: no DEBUG in VpdMayWrite
90  *
91  *      Revision 1.19  1998/10/28 15:56:11  gklug
92  *      fix: Return len at end of ReadStream
93  *      fix: Write even less than 4 bytes correctly
94  *
95  *      Revision 1.18  1998/10/28 09:00:47  gklug
96  *      fix: unreferenced local vars
97  *
98  *      Revision 1.17  1998/10/28 08:25:45  gklug
99  *      fix: WARNING
100  *
101  *      Revision 1.16  1998/10/28 08:17:30  gklug
102  *      fix: typo
103  *
104  *      Revision 1.15  1998/10/28 07:50:32  gklug
105  *      fix: typo
106  *
107  *      Revision 1.14  1998/10/28 07:20:38  gklug
108  *      chg: Interface functions to use IoC as parameter as well
109  *      fix: VpdRead/WriteDWord now returns SK_U32
110  *      chg: VPD_IN/OUT names conform to SK_IN/OUT
111  *      add: usage of VPD_IN/OUT8 macros
112  *      add: VpdRead/Write Stream functions to r/w a stream of data
113  *      fix: VpdTransferBlock swapped illegal
114  *      add: VpdMayWrite
115  *
116  *      Revision 1.13  1998/10/22 10:02:37  gklug
117  *      fix: SysKonnectFileId typo
118  *
119  *      Revision 1.12  1998/10/20 10:01:01  gklug
120  *      fix: parameter to SkOsGetTime
121  *
122  *      Revision 1.11  1998/10/15 12:51:48  malthoff
123  *      Remove unrequired parameter p in vpd_setup_para().
124  *
125  *      Revision 1.10  1998/10/08 14:52:43  malthoff
126  *      Remove CvsId by SysKonnectFileId.
127  *
128  *      Revision 1.9  1998/09/16 07:33:52  malthoff
129  *      replace memcmp() by SK_MEMCMP and
130  *      memcpy() by SK_MEMCPY() to be
131  *      independent from the 'C' Standard Library.
132  *
133  *      Revision 1.8  1998/08/19 12:52:35  malthoff
134  *      compiler fix: use SK_VPD_KEY instead of S_VPD.
135  *
136  *      Revision 1.7  1998/08/19 08:14:01  gklug
137  *      fix: remove struct keyword as much as possible from the C-code (see CCC)
138  *
139  *      Revision 1.6  1998/08/18 13:03:58  gklug
140  *      SkOsGetTime now returns SK_U64
141  *
142  *      Revision 1.5  1998/08/18 08:17:29  malthoff
143  *      Ensure we issue a VPD read in vpd_read_dword().
144  *      Discard all VPD keywords other than Vx or Yx, where
145  *      x is '0..9' or 'A..Z'.
146  *
147  *      Revision 1.4  1998/07/03 14:52:19  malthoff
148  *      Add category SK_DBGCAT_FATAL to some debug macros.
149  *      bug fix: correct the keyword name check in vpd_write().
150  *
151  *      Revision 1.3  1998/06/26 11:16:53  malthoff
152  *      Correct the modified File Identifier.
153  *
154  *      Revision 1.2  1998/06/26 11:13:43  malthoff
155  *      Modify the File Identifier.
156  *
157  *      Revision 1.1  1998/06/19 14:11:08  malthoff
158  *      Created, Tests with AIX were performed successfully
159  *
160  *
161  ******************************************************************************/
162
163 #include <config.h>
164
165 #ifdef CONFIG_SK98
166
167 /*
168         Please refer skvpd.txt for infomation how to include this module
169  */
170 static const char SysKonnectFileId[] =
171         "@(#)$Id: skvpd.c,v 1.37 2003/01/13 10:42:45 rschmidt Exp $ (C) SK";
172
173 #include "h/skdrv1st.h"
174 #include "h/sktypes.h"
175 #include "h/skdebug.h"
176 #include "h/skdrv2nd.h"
177
178 /*
179  * Static functions
180  */
181 #ifndef SK_KR_PROTO
182 static SK_VPD_PARA      *vpd_find_para(
183         SK_AC   *pAC,
184         const char      *key,
185         SK_VPD_PARA *p);
186 #else   /* SK_KR_PROTO */
187 static SK_VPD_PARA      *vpd_find_para();
188 #endif  /* SK_KR_PROTO */
189
190 /*
191  * waits for a completion of a VPD transfer
192  * The VPD transfer must complete within SK_TICKS_PER_SEC/16
193  *
194  * returns      0:      success, transfer completes
195  *              error   exit(9) with a error message
196  */
197 static int VpdWait(
198 SK_AC   *pAC,   /* Adapters context */
199 SK_IOC  IoC,    /* IO Context */
200 int             event)  /* event to wait for (VPD_READ / VPD_write) completion*/
201 {
202         SK_U64  start_time;
203         SK_U16  state;
204
205         SK_DBG_MSG(pAC,SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
206                 ("VPD wait for %s\n", event?"Write":"Read"));
207         start_time = SkOsGetTime(pAC);
208         do {
209                 if (SkOsGetTime(pAC) - start_time > SK_TICKS_PER_SEC) {
210
211                         /* Bug fix AF: Thu Mar 28 2002
212                          * Do not call: VPD_STOP(pAC, IoC);
213                          * A pending VPD read cycle can not be aborted by writing
214                          * VPD_WRITE to the PCI_VPD_ADR_REG (VPD address register).
215                          * Although the write threshold in the OUR-register protects
216                          * VPD read only space from being overwritten this does not
217                          * protect a VPD read from being `converted` into a VPD write
218                          * operation (on the fly). As a consequence the VPD_STOP would
219                          * delete VPD read only data. In case of any problems with the
220                          * I2C bus we exit the loop here. The I2C read operation can
221                          * not be aborted except by a reset (->LR).
222                          */
223                         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_FATAL | SK_DBGCAT_ERR,
224                                 ("ERROR:VPD wait timeout\n"));
225                         return(1);
226                 }
227
228                 VPD_IN16(pAC, IoC, PCI_VPD_ADR_REG, &state);
229
230                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
231                         ("state = %x, event %x\n",state,event));
232         } while((int)(state & PCI_VPD_FLAG) == event);
233
234         return(0);
235 }
236
237 #ifdef SKDIAG
238
239 /*
240  * Read the dword at address 'addr' from the VPD EEPROM.
241  *
242  * Needed Time: MIN 1,3 ms      MAX 2,6 ms
243  *
244  * Note: The DWord is returned in the endianess of the machine the routine
245  *       is running on.
246  *
247  * Returns the data read.
248  */
249 SK_U32 VpdReadDWord(
250 SK_AC   *pAC,   /* Adapters context */
251 SK_IOC  IoC,    /* IO Context */
252 int             addr)   /* VPD address */
253 {
254         SK_U32  Rtv;
255
256         /* start VPD read */
257         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
258                 ("VPD read dword at 0x%x\n",addr));
259         addr &= ~VPD_WRITE;             /* ensure the R/W bit is set to read */
260
261         VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, (SK_U16)addr);
262
263         /* ignore return code here */
264         (void)VpdWait(pAC, IoC, VPD_READ);
265
266         /* Don't swap here, it's a data stream of bytes */
267         Rtv = 0;
268
269         VPD_IN32(pAC, IoC, PCI_VPD_DAT_REG, &Rtv);
270
271         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
272                 ("VPD read dword data = 0x%x\n",Rtv));
273         return(Rtv);
274 }
275
276 #endif  /* SKDIAG */
277
278 #if 0
279
280 /*
281         Write the dword 'data' at address 'addr' into the VPD EEPROM, and
282         verify that the data is written.
283
284  Needed Time:
285
286 .                               MIN             MAX
287 . -------------------------------------------------------------------
288 . write                         1.8 ms          3.6 ms
289 . internal write cyles          0.7 ms          7.0 ms
290 . -------------------------------------------------------------------
291 . over all program time         2.5 ms          10.6 ms
292 . read                          1.3 ms          2.6 ms
293 . -------------------------------------------------------------------
294 . over all                      3.8 ms          13.2 ms
295 .
296
297
298  Returns        0:      success
299                         1:      error,  I2C transfer does not terminate
300                         2:      error,  data verify error
301
302  */
303 static int VpdWriteDWord(
304 SK_AC   *pAC,   /* pAC pointer */
305 SK_IOC  IoC,    /* IO Context */
306 int             addr,   /* VPD address */
307 SK_U32  data)   /* VPD data to write */
308 {
309         /* start VPD write */
310         /* Don't swap here, it's a data stream of bytes */
311         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
312                 ("VPD write dword at addr 0x%x, data = 0x%x\n",addr,data));
313         VPD_OUT32(pAC, IoC, PCI_VPD_DAT_REG, (SK_U32)data);
314         /* But do it here */
315         addr |= VPD_WRITE;
316
317         VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, (SK_U16)(addr | VPD_WRITE));
318
319         /* this may take up to 10,6 ms */
320         if (VpdWait(pAC, IoC, VPD_WRITE)) {
321                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
322                         ("Write Timed Out\n"));
323                 return(1);
324         };
325
326         /* verify data */
327         if (VpdReadDWord(pAC, IoC, addr) != data) {
328                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
329                         ("Data Verify Error\n"));
330                 return(2);
331         }
332         return(0);
333 }       /* VpdWriteDWord */
334
335 #endif  /* 0 */
336
337 /*
338  *      Read one Stream of 'len' bytes of VPD data, starting at 'addr' from
339  *      or to the I2C EEPROM.
340  *
341  * Returns number of bytes read / written.
342  */
343 static int VpdWriteStream(
344 SK_AC   *pAC,   /* Adapters context */
345 SK_IOC  IoC,    /* IO Context */
346 char    *buf,   /* data buffer */
347 int             Addr,   /* VPD start address */
348 int             Len)    /* number of bytes to read / to write */
349 {
350         int             i;
351         int             j;
352         SK_U16  AdrReg;
353         int             Rtv;
354         SK_U8   * pComp;        /* Compare pointer */
355         SK_U8   Data;           /* Input Data for Compare */
356
357         /* Init Compare Pointer */
358         pComp = (SK_U8 *) buf;
359
360         for (i = 0; i < Len; i++, buf++) {
361                 if ((i%sizeof(SK_U32)) == 0) {
362                         /*
363                          * At the begin of each cycle read the Data Reg
364                          * So it is initialized even if only a few bytes
365                          * are written.
366                          */
367                         AdrReg = (SK_U16) Addr;
368                         AdrReg &= ~VPD_WRITE;   /* READ operation */
369
370                         VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
371
372                         /* Wait for termination */
373                         Rtv = VpdWait(pAC, IoC, VPD_READ);
374                         if (Rtv != 0) {
375                                 return(i);
376                         }
377                 }
378
379                 /* Write current Byte */
380                 VPD_OUT8(pAC, IoC, PCI_VPD_DAT_REG + (i%sizeof(SK_U32)),
381                                 *(SK_U8*)buf);
382
383                 if (((i%sizeof(SK_U32)) == 3) || (i == (Len - 1))) {
384                         /* New Address needs to be written to VPD_ADDR reg */
385                         AdrReg = (SK_U16) Addr;
386                         Addr += sizeof(SK_U32);
387                         AdrReg |= VPD_WRITE;    /* WRITE operation */
388
389                         VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
390
391                         /* Wait for termination */
392                         Rtv = VpdWait(pAC, IoC, VPD_WRITE);
393                         if (Rtv != 0) {
394                                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
395                                         ("Write Timed Out\n"));
396                                 return(i - (i%sizeof(SK_U32)));
397                         }
398
399                         /*
400                          * Now re-read to verify
401                          */
402                         AdrReg &= ~VPD_WRITE;   /* READ operation */
403
404                         VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
405
406                         /* Wait for termination */
407                         Rtv = VpdWait(pAC, IoC, VPD_READ);
408                         if (Rtv != 0) {
409                                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
410                                         ("Verify Timed Out\n"));
411                                 return(i - (i%sizeof(SK_U32)));
412                         }
413
414                         for (j = 0; j <= (int)(i%sizeof(SK_U32)); j++, pComp++) {
415
416                                 VPD_IN8(pAC, IoC, PCI_VPD_DAT_REG + j, &Data);
417
418                                 if (Data != *pComp) {
419                                         /* Verify Error */
420                                         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
421                                                 ("WriteStream Verify Error\n"));
422                                         return(i - (i%sizeof(SK_U32)) + j);
423                                 }
424                         }
425                 }
426         }
427
428         return(Len);
429 }
430
431
432 /*
433  *      Read one Stream of 'len' bytes of VPD data, starting at 'addr' from
434  *      or to the I2C EEPROM.
435  *
436  * Returns number of bytes read / written.
437  */
438 static int VpdReadStream(
439 SK_AC   *pAC,   /* Adapters context */
440 SK_IOC  IoC,    /* IO Context */
441 char    *buf,   /* data buffer */
442 int             Addr,   /* VPD start address */
443 int             Len)    /* number of bytes to read / to write */
444 {
445         int             i;
446         SK_U16  AdrReg;
447         int             Rtv;
448
449         for (i = 0; i < Len; i++, buf++) {
450                 if ((i%sizeof(SK_U32)) == 0) {
451                         /* New Address needs to be written to VPD_ADDR reg */
452                         AdrReg = (SK_U16) Addr;
453                         Addr += sizeof(SK_U32);
454                         AdrReg &= ~VPD_WRITE;   /* READ operation */
455
456                         VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
457
458                         /* Wait for termination */
459                         Rtv = VpdWait(pAC, IoC, VPD_READ);
460                         if (Rtv != 0) {
461                                 return(i);
462                         }
463                 }
464                 VPD_IN8(pAC, IoC, PCI_VPD_DAT_REG + (i%sizeof(SK_U32)),
465                         (SK_U8 *)buf);
466         }
467
468         return(Len);
469 }
470
471 /*
472  *      Read ore writes 'len' bytes of VPD data, starting at 'addr' from
473  *      or to the I2C EEPROM.
474  *
475  * Returns number of bytes read / written.
476  */
477 static int VpdTransferBlock(
478 SK_AC   *pAC,   /* Adapters context */
479 SK_IOC  IoC,    /* IO Context */
480 char    *buf,   /* data buffer */
481 int             addr,   /* VPD start address */
482 int             len,    /* number of bytes to read / to write */
483 int             dir)    /* transfer direction may be VPD_READ or VPD_WRITE */
484 {
485         int             Rtv;    /* Return value */
486         int             vpd_rom_size;
487
488         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
489                 ("VPD %s block, addr = 0x%x, len = %d\n",
490                 dir ? "write" : "read", addr, len));
491
492         if (len == 0)
493                 return(0);
494
495         vpd_rom_size = pAC->vpd.rom_size;
496
497         if (addr > vpd_rom_size - 4) {
498                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
499                         ("Address error: 0x%x, exp. < 0x%x\n",
500                         addr, vpd_rom_size - 4));
501                 return(0);
502         }
503
504         if (addr + len > vpd_rom_size) {
505                 len = vpd_rom_size - addr;
506                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
507                         ("Warning: len was cut to %d\n", len));
508         }
509
510         if (dir == VPD_READ) {
511                 Rtv = VpdReadStream(pAC, IoC, buf, addr, len);
512         }
513         else {
514                 Rtv = VpdWriteStream(pAC, IoC, buf, addr, len);
515         }
516
517         return(Rtv);
518 }
519
520 #ifdef SKDIAG
521
522 /*
523  *      Read 'len' bytes of VPD data, starting at 'addr'.
524  *
525  * Returns number of bytes read.
526  */
527 int VpdReadBlock(
528 SK_AC   *pAC,   /* pAC pointer */
529 SK_IOC  IoC,    /* IO Context */
530 char    *buf,   /* buffer were the data should be stored */
531 int             addr,   /* start reading at the VPD address */
532 int             len)    /* number of bytes to read */
533 {
534         return(VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_READ));
535 }
536
537 /*
538  *      Write 'len' bytes of *but to the VPD EEPROM, starting at 'addr'.
539  *
540  * Returns number of bytes writes.
541  */
542 int VpdWriteBlock(
543 SK_AC   *pAC,   /* pAC pointer */
544 SK_IOC  IoC,    /* IO Context */
545 char    *buf,   /* buffer, holds the data to write */
546 int             addr,   /* start writing at the VPD address */
547 int             len)    /* number of bytes to write */
548 {
549         return(VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_WRITE));
550 }
551 #endif  /* SKDIAG */
552
553 /*
554  * (re)initialize the VPD buffer
555  *
556  * Reads the VPD data from the EEPROM into the VPD buffer.
557  * Get the remaining read only and read / write space.
558  *
559  * return       0:      success
560  *              1:      fatal VPD error
561  */
562 static int VpdInit(
563 SK_AC   *pAC,   /* Adapters context */
564 SK_IOC  IoC)    /* IO Context */
565 {
566         SK_VPD_PARA *r, rp;     /* RW or RV */
567         int             i;
568         unsigned char   x;
569         int             vpd_size;
570         SK_U16  dev_id;
571         SK_U32  our_reg2;
572
573         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT, ("VpdInit .. "));
574
575         VPD_IN16(pAC, IoC, PCI_DEVICE_ID, &dev_id);
576
577         VPD_IN32(pAC, IoC, PCI_OUR_REG_2, &our_reg2);
578
579         pAC->vpd.rom_size = 256 << ((our_reg2 & PCI_VPD_ROM_SZ) >> 14);
580
581         /*
582          * this function might get used before the hardware is initialized
583          * therefore we cannot always trust in GIChipId
584          */
585         if (((pAC->vpd.v.vpd_status & VPD_VALID) == 0 &&
586                 dev_id != VPD_DEV_ID_GENESIS) ||
587                 ((pAC->vpd.v.vpd_status & VPD_VALID) != 0 &&
588                 !pAC->GIni.GIGenesis)) {
589
590                 /* for Yukon the VPD size is always 256 */
591                 vpd_size = VPD_SIZE_YUKON;
592         }
593         else {
594                 /* Genesis uses the maximum ROM size up to 512 for VPD */
595                 if (pAC->vpd.rom_size > VPD_SIZE_GENESIS) {
596                         vpd_size = VPD_SIZE_GENESIS;
597                 }
598                 else {
599                         vpd_size = pAC->vpd.rom_size;
600                 }
601         }
602
603         /* read the VPD data into the VPD buffer */
604         if (VpdTransferBlock(pAC, IoC, pAC->vpd.vpd_buf, 0, vpd_size, VPD_READ)
605                 != vpd_size) {
606
607                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
608                         ("Block Read Error\n"));
609                 return(1);
610         }
611
612         pAC->vpd.vpd_size = vpd_size;
613
614         /* find the end tag of the RO area */
615         if (!(r = vpd_find_para(pAC, VPD_RV, &rp))) {
616                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
617                         ("Encoding Error: RV Tag not found\n"));
618                 return(1);
619         }
620
621         if (r->p_val + r->p_len > pAC->vpd.vpd_buf + vpd_size/2) {
622                 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
623                         ("Encoding Error: Invalid VPD struct size\n"));
624                 return(1);
625         }
626         pAC->vpd.v.vpd_free_ro = r->p_len - 1;
627
628         /* test the checksum */
629         for (i = 0, x = 0; (unsigned)i <= (unsigned)vpd_size/2 - r->p_len; i++) {
630                 x += pAC->vpd.vpd_buf[i];
631         }
632
633         if (x != 0) {
634                 /* checksum error */
635                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
636                         ("VPD Checksum Error\n"));
637                 return(1);
638         }
639
640         /* find and check the end tag of the RW area */
641         if (!(r = vpd_find_para(pAC, VPD_RW, &rp))) {
642                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
643                         ("Encoding Error: RV Tag not found\n"));
644                 return(1);
645         }
646
647         if (r->p_val < pAC->vpd.vpd_buf + vpd_size/2) {
648                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
649                         ("Encoding Error: Invalid VPD struct size\n"));
650                 return(1);
651         }
652         pAC->vpd.v.vpd_free_rw = r->p_len;
653
654         /* everything seems to be ok */
655         if (pAC->GIni.GIChipId != 0) {
656                 pAC->vpd.v.vpd_status |= VPD_VALID;
657         }
658
659         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT,
660                 ("done. Free RO = %d, Free RW = %d\n",
661                 pAC->vpd.v.vpd_free_ro, pAC->vpd.v.vpd_free_rw));
662
663         return(0);
664 }
665
666 /*
667  *      find the Keyword 'key' in the VPD buffer and fills the
668  *      parameter struct 'p' with it's values
669  *
670  * returns      *p      success
671  *              0:      parameter was not found or VPD encoding error
672  */
673 static SK_VPD_PARA *vpd_find_para(
674 SK_AC           *pAC,   /* common data base */
675 const char      *key,   /* keyword to find (e.g. "MN") */
676 SK_VPD_PARA *p)         /* parameter description struct */
677 {
678         char *v ;       /* points to VPD buffer */
679         int max;        /* Maximum Number of Iterations */
680
681         v = pAC->vpd.vpd_buf;
682         max = 128;
683
684         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
685                 ("VPD find para %s .. ",key));
686
687         /* check mandatory resource type ID string (Product Name) */
688         if (*v != (char)RES_ID) {
689                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
690                         ("Error: 0x%x missing\n", RES_ID));
691                 return(0);
692         }
693
694         if (strcmp(key, VPD_NAME) == 0) {
695                 p->p_len = VPD_GET_RES_LEN(v);
696                 p->p_val = VPD_GET_VAL(v);
697                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
698                         ("found, len = %d\n", p->p_len));
699                 return(p);
700         }
701
702         v += 3 + VPD_GET_RES_LEN(v) + 3;
703         for (;; ) {
704                 if (SK_MEMCMP(key,v,2) == 0) {
705                         p->p_len = VPD_GET_VPD_LEN(v);
706                         p->p_val = VPD_GET_VAL(v);
707                         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
708                                 ("found, len = %d\n",p->p_len));
709                         return(p);
710                 }
711
712                 /* exit when reaching the "RW" Tag or the maximum of itera. */
713                 max--;
714                 if (SK_MEMCMP(VPD_RW,v,2) == 0 || max == 0) {
715                         break;
716                 }
717
718                 if (SK_MEMCMP(VPD_RV,v,2) == 0) {
719                         v += 3 + VPD_GET_VPD_LEN(v) + 3;        /* skip VPD-W */
720                 }
721                 else {
722                         v += 3 + VPD_GET_VPD_LEN(v);
723                 }
724                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
725                         ("scanning '%c%c' len = %d\n",v[0],v[1],v[2]));
726         }
727
728 #ifdef DEBUG
729         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, ("not found\n"));
730         if (max == 0) {
731                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
732                         ("Key/Len Encoding error\n"));
733         }
734 #endif /* DEBUG */
735         return(0);
736 }
737
738 /*
739  *      Move 'n' bytes. Begin with the last byte if 'n' is > 0,
740  *      Start with the last byte if n is < 0.
741  *
742  * returns nothing
743  */
744 static void vpd_move_para(
745 char    *start,         /* start of memory block */
746 char    *end,           /* end of memory block to move */
747 int             n)                      /* number of bytes the memory block has to be moved */
748 {
749         char *p;
750         int i;          /* number of byte copied */
751
752         if (n == 0)
753                 return;
754
755         i = (int) (end - start + 1);
756         if (n < 0) {
757                 p = start + n;
758                 while (i != 0) {
759                         *p++ = *start++;
760                         i--;
761                 }
762         }
763         else {
764                 p = end + n;
765                 while (i != 0) {
766                         *p-- = *end--;
767                         i--;
768                 }
769         }
770 }
771
772 /*
773  *      setup the VPD keyword 'key' at 'ip'.
774  *
775  * returns nothing
776  */
777 static void vpd_insert_key(
778 const char      *key,   /* keyword to insert */
779 const char      *buf,   /* buffer with the keyword value */
780 int             len,            /* length of the value string */
781 char    *ip)            /* inseration point */
782 {
783         SK_VPD_KEY *p;
784
785         p = (SK_VPD_KEY *) ip;
786         p->p_key[0] = key[0];
787         p->p_key[1] = key[1];
788         p->p_len = (unsigned char) len;
789         SK_MEMCPY(&p->p_val,buf,len);
790 }
791
792 /*
793  *      Setup the VPD end tag "RV" / "RW".
794  *      Also correct the remaining space variables vpd_free_ro / vpd_free_rw.
795  *
796  * returns      0:      success
797  *              1:      encoding error
798  */
799 static int vpd_mod_endtag(
800 SK_AC   *pAC,           /* common data base */
801 char    *etp)           /* end pointer input position */
802 {
803         SK_VPD_KEY *p;
804         unsigned char   x;
805         int     i;
806         int     vpd_size;
807
808         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
809                 ("VPD modify endtag at 0x%x = '%c%c'\n",etp,etp[0],etp[1]));
810
811         vpd_size = pAC->vpd.vpd_size;
812
813         p = (SK_VPD_KEY *) etp;
814
815         if (p->p_key[0] != 'R' || (p->p_key[1] != 'V' && p->p_key[1] != 'W')) {
816                 /* something wrong here, encoding error */
817                 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
818                         ("Encoding Error: invalid end tag\n"));
819                 return(1);
820         }
821         if (etp > pAC->vpd.vpd_buf + vpd_size/2) {
822                 /* create "RW" tag */
823                 p->p_len = (unsigned char)(pAC->vpd.vpd_buf+vpd_size-etp-3-1);
824                 pAC->vpd.v.vpd_free_rw = (int) p->p_len;
825                 i = pAC->vpd.v.vpd_free_rw;
826                 etp += 3;
827         }
828         else {
829                 /* create "RV" tag */
830                 p->p_len = (unsigned char)(pAC->vpd.vpd_buf+vpd_size/2-etp-3);
831                 pAC->vpd.v.vpd_free_ro = (int) p->p_len - 1;
832
833                 /* setup checksum */
834                 for (i = 0, x = 0; i < vpd_size/2 - p->p_len; i++) {
835                         x += pAC->vpd.vpd_buf[i];
836                 }
837                 p->p_val = (char) 0 - x;
838                 i = pAC->vpd.v.vpd_free_ro;
839                 etp += 4;
840         }
841         while (i) {
842                 *etp++ = 0x00;
843                 i--;
844         }
845
846         return(0);
847 }
848
849 /*
850  *      Insert a VPD keyword into the VPD buffer.
851  *
852  *      The keyword 'key' is inserted at the position 'ip' in the
853  *      VPD buffer.
854  *      The keywords behind the input position will
855  *      be moved. The VPD end tag "RV" or "RW" is generated again.
856  *
857  * returns      0:      success
858  *              2:      value string was cut
859  *              4:      VPD full, keyword was not written
860  *              6:      fatal VPD error
861  *
862  */
863 int     VpdSetupPara(
864 SK_AC   *pAC,           /* common data base */
865 const char      *key,   /* keyword to insert */
866 const char      *buf,   /* buffer with the keyword value */
867 int             len,            /* length of the keyword value */
868 int             type,           /* VPD_RO_KEY or VPD_RW_KEY */
869 int             op)                     /* operation to do: ADD_KEY or OWR_KEY */
870 {
871         SK_VPD_PARA vp;
872         char    *etp;           /* end tag position */
873         int     free;           /* remaining space in selected area */
874         char    *ip;            /* input position inside the VPD buffer */
875         int     rtv;            /* return code */
876         int     head;           /* additional haeder bytes to move */
877         int     found;          /* additinoal bytes if the keyword was found */
878         int vpd_size;
879
880         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
881                 ("VPD setup para key = %s, val = %s\n",key,buf));
882
883         vpd_size = pAC->vpd.vpd_size;
884
885         rtv = 0;
886         ip = 0;
887         if (type == VPD_RW_KEY) {
888                 /* end tag is "RW" */
889                 free = pAC->vpd.v.vpd_free_rw;
890                 etp = pAC->vpd.vpd_buf + (vpd_size - free - 1 - 3);
891         }
892         else {
893                 /* end tag is "RV" */
894                 free = pAC->vpd.v.vpd_free_ro;
895                 etp = pAC->vpd.vpd_buf + (vpd_size/2 - free - 4);
896         }
897         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
898                 ("Free RO = %d, Free RW = %d\n",
899                 pAC->vpd.v.vpd_free_ro, pAC->vpd.v.vpd_free_rw));
900
901         head = 0;
902         found = 0;
903         if (op == OWR_KEY) {
904                 if (vpd_find_para(pAC, key, &vp)) {
905                         found = 3;
906                         ip = vp.p_val - 3;
907                         free += vp.p_len + 3;
908                         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
909                                 ("Overwrite Key\n"));
910                 }
911                 else {
912                         op = ADD_KEY;
913                         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
914                                 ("Add Key\n"));
915                 }
916         }
917         if (op == ADD_KEY) {
918                 ip = etp;
919                 vp.p_len = 0;
920                 head = 3;
921         }
922
923         if (len + 3 > free) {
924                 if (free < 7) {
925                         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
926                                 ("VPD Buffer Overflow, keyword not written\n"));
927                         return(4);
928                 }
929                 /* cut it again */
930                 len = free - 3;
931                 rtv = 2;
932                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
933                         ("VPD Buffer Full, Keyword was cut\n"));
934         }
935
936         vpd_move_para(ip + vp.p_len + found, etp+2, len-vp.p_len+head);
937         vpd_insert_key(key, buf, len, ip);
938         if (vpd_mod_endtag(pAC, etp + len - vp.p_len + head)) {
939                 pAC->vpd.v.vpd_status &= ~VPD_VALID;
940                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
941                         ("VPD Encoding Error\n"));
942                 return(6);
943         }
944
945         return(rtv);
946 }
947
948
949 /*
950  *      Read the contents of the VPD EEPROM and copy it to the
951  *      VPD buffer if not already done.
952  *
953  * return:      A pointer to the vpd_status structure. The structure contains
954  *              this fields.
955  */
956 SK_VPD_STATUS *VpdStat(
957 SK_AC   *pAC,   /* Adapters context */
958 SK_IOC  IoC)    /* IO Context */
959 {
960         if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
961                 (void)VpdInit(pAC, IoC);
962         }
963         return(&pAC->vpd.v);
964 }
965
966
967 /*
968  *      Read the contents of the VPD EEPROM and copy it to the VPD
969  *      buffer if not already done.
970  *      Scan the VPD buffer for VPD keywords and create the VPD
971  *      keyword list by copying the keywords to 'buf', all after
972  *      each other and terminated with a '\0'.
973  *
974  * Exceptions:  o The Resource Type ID String (product name) is called "Name"
975  *              o The VPD end tags 'RV' and 'RW' are not listed
976  *
977  *      The number of copied keywords is counted in 'elements'.
978  *
979  * returns      0:      success
980  *              2:      buffer overfull, one or more keywords are missing
981  *              6:      fatal VPD error
982  *
983  *      example values after returning:
984  *
985  *              buf =   "Name\0PN\0EC\0MN\0SN\0CP\0VF\0VL\0YA\0"
986  *              *len =          30
987  *              *elements =      9
988  */
989 int VpdKeys(
990 SK_AC   *pAC,           /* common data base */
991 SK_IOC  IoC,            /* IO Context */
992 char    *buf,           /* buffer where to copy the keywords */
993 int             *len,           /* buffer length */
994 int             *elements)      /* number of keywords returned */
995 {
996         char *v;
997         int n;
998
999         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("list VPD keys .. "));
1000         *elements = 0;
1001         if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
1002                 if (VpdInit(pAC, IoC) != 0) {
1003                         *len = 0;
1004                         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
1005                                 ("VPD Init Error, terminated\n"));
1006                         return(6);
1007                 }
1008         }
1009
1010         if ((signed)strlen(VPD_NAME) + 1 <= *len) {
1011                 v = pAC->vpd.vpd_buf;
1012                 strcpy(buf,VPD_NAME);
1013                 n = strlen(VPD_NAME) + 1;
1014                 buf += n;
1015                 *elements = 1;
1016                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX,
1017                         ("'%c%c' ",v[0],v[1]));
1018         }
1019         else {
1020                 *len = 0;
1021                 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
1022                         ("buffer overflow\n"));
1023                 return(2);
1024         }
1025
1026         v += 3 + VPD_GET_RES_LEN(v) + 3;
1027         for (;; ) {
1028                 /* exit when reaching the "RW" Tag */
1029                 if (SK_MEMCMP(VPD_RW,v,2) == 0) {
1030                         break;
1031                 }
1032
1033                 if (SK_MEMCMP(VPD_RV,v,2) == 0) {
1034                         v += 3 + VPD_GET_VPD_LEN(v) + 3;        /* skip VPD-W */
1035                         continue;
1036                 }
1037
1038                 if (n+3 <= *len) {
1039                         SK_MEMCPY(buf,v,2);
1040                         buf += 2;
1041                         *buf++ = '\0';
1042                         n += 3;
1043                         v += 3 + VPD_GET_VPD_LEN(v);
1044                         *elements += 1;
1045                         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX,
1046                                 ("'%c%c' ",v[0],v[1]));
1047                 }
1048                 else {
1049                         *len = n;
1050                         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
1051                                 ("buffer overflow\n"));
1052                         return(2);
1053                 }
1054         }
1055
1056         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("\n"));
1057         *len = n;
1058         return(0);
1059 }
1060
1061
1062 /*
1063  *      Read the contents of the VPD EEPROM and copy it to the
1064  *      VPD buffer if not already done. Search for the VPD keyword
1065  *      'key' and copy its value to 'buf'. Add a terminating '\0'.
1066  *      If the value does not fit into the buffer cut it after
1067  *      'len' - 1 bytes.
1068  *
1069  * returns      0:      success
1070  *              1:      keyword not found
1071  *              2:      value string was cut
1072  *              3:      VPD transfer timeout
1073  *              6:      fatal VPD error
1074  */
1075 int VpdRead(
1076 SK_AC           *pAC,   /* common data base */
1077 SK_IOC          IoC,    /* IO Context */
1078 const char      *key,   /* keyword to read (e.g. "MN") */
1079 char            *buf,   /* buffer where to copy the keyword value */
1080 int                     *len)   /* buffer length */
1081 {
1082         SK_VPD_PARA *p, vp;
1083
1084         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("VPD read %s .. ", key));
1085         if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
1086                 if (VpdInit(pAC, IoC) != 0) {
1087                         *len = 0;
1088                         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
1089                                 ("VPD init error\n"));
1090                         return(6);
1091                 }
1092         }
1093
1094         if ((p = vpd_find_para(pAC, key, &vp)) != NULL) {
1095                 if (p->p_len > (*(unsigned *)len)-1) {
1096                         p->p_len = *len - 1;
1097                 }
1098                 SK_MEMCPY(buf, p->p_val, p->p_len);
1099                 buf[p->p_len] = '\0';
1100                 *len = p->p_len;
1101                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX,
1102                         ("%c%c%c%c.., len = %d\n",
1103                         buf[0],buf[1],buf[2],buf[3],*len));
1104         }
1105         else {
1106                 *len = 0;
1107                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, ("not found\n"));
1108                 return(1);
1109         }
1110         return(0);
1111 }
1112
1113
1114 /*
1115  *      Check whether a given key may be written
1116  *
1117  * returns
1118  *      SK_TRUE         Yes it may be written
1119  *      SK_FALSE        No it may be written
1120  */
1121 SK_BOOL VpdMayWrite(
1122 char    *key)   /* keyword to write (allowed values "Yx", "Vx") */
1123 {
1124         if ((*key != 'Y' && *key != 'V') ||
1125                 key[1] < '0' || key[1] > 'Z' ||
1126                 (key[1] > '9' && key[1] < 'A') || strlen(key) != 2) {
1127
1128                 return(SK_FALSE);
1129         }
1130         return(SK_TRUE);
1131 }
1132
1133 /*
1134  *      Read the contents of the VPD EEPROM and copy it to the VPD
1135  *      buffer if not already done. Insert/overwrite the keyword 'key'
1136  *      in the VPD buffer. Cut the keyword value if it does not fit
1137  *      into the VPD read / write area.
1138  *
1139  * returns      0:      success
1140  *              2:      value string was cut
1141  *              3:      VPD transfer timeout
1142  *              4:      VPD full, keyword was not written
1143  *              5:      keyword cannot be written
1144  *              6:      fatal VPD error
1145  */
1146 int VpdWrite(
1147 SK_AC           *pAC,   /* common data base */
1148 SK_IOC          IoC,    /* IO Context */
1149 const char      *key,   /* keyword to write (allowed values "Yx", "Vx") */
1150 const char      *buf)   /* buffer where the keyword value can be read from */
1151 {
1152         int len;                /* length of the keyword to write */
1153         int rtv;                /* return code */
1154         int rtv2;
1155
1156         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX,
1157                 ("VPD write %s = %s\n",key,buf));
1158
1159         if ((*key != 'Y' && *key != 'V') ||
1160                 key[1] < '0' || key[1] > 'Z' ||
1161                 (key[1] > '9' && key[1] < 'A') || strlen(key) != 2) {
1162
1163                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
1164                         ("illegal key tag, keyword not written\n"));
1165                 return(5);
1166         }
1167
1168         if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
1169                 if (VpdInit(pAC, IoC) != 0) {
1170                         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
1171                                 ("VPD init error\n"));
1172                         return(6);
1173                 }
1174         }
1175
1176         rtv = 0;
1177         len = strlen(buf);
1178         if (len > VPD_MAX_LEN) {
1179                 /* cut it */
1180                 len = VPD_MAX_LEN;
1181                 rtv = 2;
1182                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
1183                         ("keyword too long, cut after %d bytes\n",VPD_MAX_LEN));
1184         }
1185         if ((rtv2 = VpdSetupPara(pAC, key, buf, len, VPD_RW_KEY, OWR_KEY)) != 0) {
1186                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
1187                         ("VPD write error\n"));
1188                 return(rtv2);
1189         }
1190
1191         return(rtv);
1192 }
1193
1194 /*
1195  *      Read the contents of the VPD EEPROM and copy it to the
1196  *      VPD buffer if not already done. Remove the VPD keyword
1197  *      'key' from the VPD buffer.
1198  *      Only the keywords in the read/write area can be deleted.
1199  *      Keywords in the read only area cannot be deleted.
1200  *
1201  * returns      0:      success, keyword was removed
1202  *              1:      keyword not found
1203  *              5:      keyword cannot be deleted
1204  *              6:      fatal VPD error
1205  */
1206 int VpdDelete(
1207 SK_AC   *pAC,   /* common data base */
1208 SK_IOC  IoC,    /* IO Context */
1209 char    *key)   /* keyword to read (e.g. "MN") */
1210 {
1211         SK_VPD_PARA *p, vp;
1212         char *etp;
1213         int     vpd_size;
1214
1215         vpd_size = pAC->vpd.vpd_size;
1216
1217         SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_TX,("VPD delete key %s\n",key));
1218         if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
1219                 if (VpdInit(pAC, IoC) != 0) {
1220                         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
1221                                 ("VPD init error\n"));
1222                         return(6);
1223                 }
1224         }
1225
1226         if ((p = vpd_find_para(pAC, key, &vp)) != NULL) {
1227                 if (p->p_val < pAC->vpd.vpd_buf + vpd_size/2) {
1228                         /* try to delete read only keyword */
1229                         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
1230                                 ("cannot delete RO keyword\n"));
1231                         return(5);
1232                 }
1233
1234                 etp = pAC->vpd.vpd_buf + (vpd_size-pAC->vpd.v.vpd_free_rw-1-3);
1235
1236                 vpd_move_para(vp.p_val+vp.p_len, etp+2,
1237                         - ((int)(vp.p_len + 3)));
1238                 if (vpd_mod_endtag(pAC, etp - vp.p_len - 3)) {
1239                         pAC->vpd.v.vpd_status &= ~VPD_VALID;
1240                         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
1241                                 ("VPD encoding error\n"));
1242                         return(6);
1243                 }
1244         }
1245         else {
1246                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
1247                         ("keyword not found\n"));
1248                 return(1);
1249         }
1250
1251         return(0);
1252 }
1253
1254 /*
1255  *      If the VPD buffer contains valid data write the VPD
1256  *      read/write area back to the VPD EEPROM.
1257  *
1258  * returns      0:      success
1259  *              3:      VPD transfer timeout
1260  */
1261 int VpdUpdate(
1262 SK_AC   *pAC,   /* Adapters context */
1263 SK_IOC  IoC)    /* IO Context */
1264 {
1265         int vpd_size;
1266
1267         vpd_size = pAC->vpd.vpd_size;
1268
1269         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("VPD update .. "));
1270         if ((pAC->vpd.v.vpd_status & VPD_VALID) != 0) {
1271                 if (VpdTransferBlock(pAC, IoC, pAC->vpd.vpd_buf + vpd_size/2,
1272                         vpd_size/2, vpd_size/2, VPD_WRITE) != vpd_size/2) {
1273
1274                         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
1275                                 ("transfer timed out\n"));
1276                         return(3);
1277                 }
1278         }
1279         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("done\n"));
1280         return(0);
1281 }
1282
1283
1284 /*
1285  *      Read the contents of the VPD EEPROM and copy it to the VPD buffer
1286  *      if not already done. If the keyword "VF" is not present it will be
1287  *      created and the error log message will be stored to this keyword.
1288  *      If "VF" is not present the error log message will be stored to the
1289  *      keyword "VL". "VL" will created or overwritten if "VF" is present.
1290  *      The VPD read/write area is saved to the VPD EEPROM.
1291  *
1292  * returns nothing, errors will be ignored.
1293  */
1294 void VpdErrLog(
1295 SK_AC   *pAC,   /* common data base */
1296 SK_IOC  IoC,    /* IO Context */
1297 char    *msg)   /* error log message */
1298 {
1299         SK_VPD_PARA *v, vf;     /* VF */
1300         int len;
1301
1302         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX,
1303                 ("VPD error log msg %s\n", msg));
1304         if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
1305                 if (VpdInit(pAC, IoC) != 0) {
1306                         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
1307                                 ("VPD init error\n"));
1308                         return;
1309                 }
1310         }
1311
1312         len = strlen(msg);
1313         if (len > VPD_MAX_LEN) {
1314                 /* cut it */
1315                 len = VPD_MAX_LEN;
1316         }
1317         if ((v = vpd_find_para(pAC, VPD_VF, &vf)) != NULL) {
1318                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("overwrite VL\n"));
1319                 (void)VpdSetupPara(pAC, VPD_VL, msg, len, VPD_RW_KEY, OWR_KEY);
1320         }
1321         else {
1322                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("write VF\n"));
1323                 (void)VpdSetupPara(pAC, VPD_VF, msg, len, VPD_RW_KEY, ADD_KEY);
1324         }
1325
1326         (void)VpdUpdate(pAC, IoC);
1327 }
1328
1329 #endif /* CONFIG_SK98 */