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