1 /******************************************************************************
 
   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
 
   9  ******************************************************************************/
 
  11 /******************************************************************************
 
  13  *      (C)Copyright 1998-2003 SysKonnect GmbH.
 
  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.
 
  20  *      The information in this file is provided "AS IS" without warranty.
 
  22  ******************************************************************************/
 
  25         Please refer skvpd.txt for infomation how to include this module
 
  27 static const char SysKonnectFileId[] =
 
  28         "@(#)$Id: skvpd.c,v 1.37 2003/01/13 10:42:45 rschmidt Exp $ (C) SK";
 
  30 #include "h/skdrv1st.h"
 
  31 #include "h/sktypes.h"
 
  32 #include "h/skdebug.h"
 
  33 #include "h/skdrv2nd.h"
 
  39 static SK_VPD_PARA      *vpd_find_para(
 
  43 #else   /* SK_KR_PROTO */
 
  44 static SK_VPD_PARA      *vpd_find_para();
 
  45 #endif  /* SK_KR_PROTO */
 
  48  * waits for a completion of a VPD transfer
 
  49  * The VPD transfer must complete within SK_TICKS_PER_SEC/16
 
  51  * returns      0:      success, transfer completes
 
  52  *              error   exit(9) with a error message
 
  55 SK_AC   *pAC,   /* Adapters context */
 
  56 SK_IOC  IoC,    /* IO Context */
 
  57 int             event)  /* event to wait for (VPD_READ / VPD_write) completion*/
 
  62         SK_DBG_MSG(pAC,SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
 
  63                 ("VPD wait for %s\n", event?"Write":"Read"));
 
  64         start_time = SkOsGetTime(pAC);
 
  66                 if (SkOsGetTime(pAC) - start_time > SK_TICKS_PER_SEC) {
 
  68                         /* Bug fix AF: Thu Mar 28 2002
 
  69                          * Do not call: VPD_STOP(pAC, IoC);
 
  70                          * A pending VPD read cycle can not be aborted by writing
 
  71                          * VPD_WRITE to the PCI_VPD_ADR_REG (VPD address register).
 
  72                          * Although the write threshold in the OUR-register protects
 
  73                          * VPD read only space from being overwritten this does not
 
  74                          * protect a VPD read from being `converted` into a VPD write
 
  75                          * operation (on the fly). As a consequence the VPD_STOP would
 
  76                          * delete VPD read only data. In case of any problems with the
 
  77                          * I2C bus we exit the loop here. The I2C read operation can
 
  78                          * not be aborted except by a reset (->LR).
 
  80                         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_FATAL | SK_DBGCAT_ERR,
 
  81                                 ("ERROR:VPD wait timeout\n"));
 
  85                 VPD_IN16(pAC, IoC, PCI_VPD_ADR_REG, &state);
 
  87                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
 
  88                         ("state = %x, event %x\n",state,event));
 
  89         } while((int)(state & PCI_VPD_FLAG) == event);
 
  97  * Read the dword at address 'addr' from the VPD EEPROM.
 
  99  * Needed Time: MIN 1,3 ms      MAX 2,6 ms
 
 101  * Note: The DWord is returned in the endianess of the machine the routine
 
 104  * Returns the data read.
 
 107 SK_AC   *pAC,   /* Adapters context */
 
 108 SK_IOC  IoC,    /* IO Context */
 
 109 int             addr)   /* VPD address */
 
 114         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
 
 115                 ("VPD read dword at 0x%x\n",addr));
 
 116         addr &= ~VPD_WRITE;             /* ensure the R/W bit is set to read */
 
 118         VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, (SK_U16)addr);
 
 120         /* ignore return code here */
 
 121         (void)VpdWait(pAC, IoC, VPD_READ);
 
 123         /* Don't swap here, it's a data stream of bytes */
 
 126         VPD_IN32(pAC, IoC, PCI_VPD_DAT_REG, &Rtv);
 
 128         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
 
 129                 ("VPD read dword data = 0x%x\n",Rtv));
 
 136  *      Read one Stream of 'len' bytes of VPD data, starting at 'addr' from
 
 137  *      or to the I2C EEPROM.
 
 139  * Returns number of bytes read / written.
 
 141 static int VpdWriteStream(
 
 142 SK_AC   *pAC,   /* Adapters context */
 
 143 SK_IOC  IoC,    /* IO Context */
 
 144 char    *buf,   /* data buffer */
 
 145 int             Addr,   /* VPD start address */
 
 146 int             Len)    /* number of bytes to read / to write */
 
 152         SK_U8   * pComp;        /* Compare pointer */
 
 153         SK_U8   Data;           /* Input Data for Compare */
 
 155         /* Init Compare Pointer */
 
 156         pComp = (SK_U8 *) buf;
 
 158         for (i = 0; i < Len; i++, buf++) {
 
 159                 if ((i%sizeof(SK_U32)) == 0) {
 
 161                          * At the begin of each cycle read the Data Reg
 
 162                          * So it is initialized even if only a few bytes
 
 165                         AdrReg = (SK_U16) Addr;
 
 166                         AdrReg &= ~VPD_WRITE;   /* READ operation */
 
 168                         VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
 
 170                         /* Wait for termination */
 
 171                         Rtv = VpdWait(pAC, IoC, VPD_READ);
 
 177                 /* Write current Byte */
 
 178                 VPD_OUT8(pAC, IoC, PCI_VPD_DAT_REG + (i%sizeof(SK_U32)),
 
 181                 if (((i%sizeof(SK_U32)) == 3) || (i == (Len - 1))) {
 
 182                         /* New Address needs to be written to VPD_ADDR reg */
 
 183                         AdrReg = (SK_U16) Addr;
 
 184                         Addr += sizeof(SK_U32);
 
 185                         AdrReg |= VPD_WRITE;    /* WRITE operation */
 
 187                         VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
 
 189                         /* Wait for termination */
 
 190                         Rtv = VpdWait(pAC, IoC, VPD_WRITE);
 
 192                                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
 
 193                                         ("Write Timed Out\n"));
 
 194                                 return(i - (i%sizeof(SK_U32)));
 
 198                          * Now re-read to verify
 
 200                         AdrReg &= ~VPD_WRITE;   /* READ operation */
 
 202                         VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
 
 204                         /* Wait for termination */
 
 205                         Rtv = VpdWait(pAC, IoC, VPD_READ);
 
 207                                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
 
 208                                         ("Verify Timed Out\n"));
 
 209                                 return(i - (i%sizeof(SK_U32)));
 
 212                         for (j = 0; j <= (int)(i%sizeof(SK_U32)); j++, pComp++) {
 
 214                                 VPD_IN8(pAC, IoC, PCI_VPD_DAT_REG + j, &Data);
 
 216                                 if (Data != *pComp) {
 
 218                                         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
 
 219                                                 ("WriteStream Verify Error\n"));
 
 220                                         return(i - (i%sizeof(SK_U32)) + j);
 
 231  *      Read one Stream of 'len' bytes of VPD data, starting at 'addr' from
 
 232  *      or to the I2C EEPROM.
 
 234  * Returns number of bytes read / written.
 
 236 static int VpdReadStream(
 
 237 SK_AC   *pAC,   /* Adapters context */
 
 238 SK_IOC  IoC,    /* IO Context */
 
 239 char    *buf,   /* data buffer */
 
 240 int             Addr,   /* VPD start address */
 
 241 int             Len)    /* number of bytes to read / to write */
 
 247         for (i = 0; i < Len; i++, buf++) {
 
 248                 if ((i%sizeof(SK_U32)) == 0) {
 
 249                         /* New Address needs to be written to VPD_ADDR reg */
 
 250                         AdrReg = (SK_U16) Addr;
 
 251                         Addr += sizeof(SK_U32);
 
 252                         AdrReg &= ~VPD_WRITE;   /* READ operation */
 
 254                         VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
 
 256                         /* Wait for termination */
 
 257                         Rtv = VpdWait(pAC, IoC, VPD_READ);
 
 262                 VPD_IN8(pAC, IoC, PCI_VPD_DAT_REG + (i%sizeof(SK_U32)),
 
 270  *      Read ore writes 'len' bytes of VPD data, starting at 'addr' from
 
 271  *      or to the I2C EEPROM.
 
 273  * Returns number of bytes read / written.
 
 275 static int VpdTransferBlock(
 
 276 SK_AC   *pAC,   /* Adapters context */
 
 277 SK_IOC  IoC,    /* IO Context */
 
 278 char    *buf,   /* data buffer */
 
 279 int             addr,   /* VPD start address */
 
 280 int             len,    /* number of bytes to read / to write */
 
 281 int             dir)    /* transfer direction may be VPD_READ or VPD_WRITE */
 
 283         int             Rtv;    /* Return value */
 
 286         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
 
 287                 ("VPD %s block, addr = 0x%x, len = %d\n",
 
 288                 dir ? "write" : "read", addr, len));
 
 293         vpd_rom_size = pAC->vpd.rom_size;
 
 295         if (addr > vpd_rom_size - 4) {
 
 296                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
 
 297                         ("Address error: 0x%x, exp. < 0x%x\n",
 
 298                         addr, vpd_rom_size - 4));
 
 302         if (addr + len > vpd_rom_size) {
 
 303                 len = vpd_rom_size - addr;
 
 304                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
 
 305                         ("Warning: len was cut to %d\n", len));
 
 308         if (dir == VPD_READ) {
 
 309                 Rtv = VpdReadStream(pAC, IoC, buf, addr, len);
 
 312                 Rtv = VpdWriteStream(pAC, IoC, buf, addr, len);
 
 321  *      Read 'len' bytes of VPD data, starting at 'addr'.
 
 323  * Returns number of bytes read.
 
 326 SK_AC   *pAC,   /* pAC pointer */
 
 327 SK_IOC  IoC,    /* IO Context */
 
 328 char    *buf,   /* buffer were the data should be stored */
 
 329 int             addr,   /* start reading at the VPD address */
 
 330 int             len)    /* number of bytes to read */
 
 332         return(VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_READ));
 
 336  *      Write 'len' bytes of *but to the VPD EEPROM, starting at 'addr'.
 
 338  * Returns number of bytes writes.
 
 341 SK_AC   *pAC,   /* pAC pointer */
 
 342 SK_IOC  IoC,    /* IO Context */
 
 343 char    *buf,   /* buffer, holds the data to write */
 
 344 int             addr,   /* start writing at the VPD address */
 
 345 int             len)    /* number of bytes to write */
 
 347         return(VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_WRITE));
 
 352  * (re)initialize the VPD buffer
 
 354  * Reads the VPD data from the EEPROM into the VPD buffer.
 
 355  * Get the remaining read only and read / write space.
 
 361 SK_AC   *pAC,   /* Adapters context */
 
 362 SK_IOC  IoC)    /* IO Context */
 
 364         SK_VPD_PARA *r, rp;     /* RW or RV */
 
 371         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT, ("VpdInit .. "));
 
 373         VPD_IN16(pAC, IoC, PCI_DEVICE_ID, &dev_id);
 
 375         VPD_IN32(pAC, IoC, PCI_OUR_REG_2, &our_reg2);
 
 377         pAC->vpd.rom_size = 256 << ((our_reg2 & PCI_VPD_ROM_SZ) >> 14);
 
 380          * this function might get used before the hardware is initialized
 
 381          * therefore we cannot always trust in GIChipId
 
 383         if (((pAC->vpd.v.vpd_status & VPD_VALID) == 0 &&
 
 384                 dev_id != VPD_DEV_ID_GENESIS) ||
 
 385                 ((pAC->vpd.v.vpd_status & VPD_VALID) != 0 &&
 
 386                 !pAC->GIni.GIGenesis)) {
 
 388                 /* for Yukon the VPD size is always 256 */
 
 389                 vpd_size = VPD_SIZE_YUKON;
 
 392                 /* Genesis uses the maximum ROM size up to 512 for VPD */
 
 393                 if (pAC->vpd.rom_size > VPD_SIZE_GENESIS) {
 
 394                         vpd_size = VPD_SIZE_GENESIS;
 
 397                         vpd_size = pAC->vpd.rom_size;
 
 401         /* read the VPD data into the VPD buffer */
 
 402         if (VpdTransferBlock(pAC, IoC, pAC->vpd.vpd_buf, 0, vpd_size, VPD_READ)
 
 405                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
 
 406                         ("Block Read Error\n"));
 
 410         pAC->vpd.vpd_size = vpd_size;
 
 412         /* Asus K8V Se Deluxe bugfix. Correct VPD content */
 
 414         if (((unsigned char)pAC->vpd.vpd_buf[0x3f] == 0x38) &&
 
 415             ((unsigned char)pAC->vpd.vpd_buf[0x40] == 0x3c) &&
 
 416             ((unsigned char)pAC->vpd.vpd_buf[0x41] == 0x45)) {
 
 417                 printk("sk98lin: Asus mainboard with buggy VPD? "
 
 418                                 "Correcting data.\n");
 
 419                 pAC->vpd.vpd_buf[0x40] = 0x38;
 
 423         /* find the end tag of the RO area */
 
 424         if (!(r = vpd_find_para(pAC, VPD_RV, &rp))) {
 
 425                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
 
 426                         ("Encoding Error: RV Tag not found\n"));
 
 430         if (r->p_val + r->p_len > pAC->vpd.vpd_buf + vpd_size/2) {
 
 431                 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
 
 432                         ("Encoding Error: Invalid VPD struct size\n"));
 
 435         pAC->vpd.v.vpd_free_ro = r->p_len - 1;
 
 437         /* test the checksum */
 
 438         for (i = 0, x = 0; (unsigned)i <= (unsigned)vpd_size/2 - r->p_len; i++) {
 
 439                 x += pAC->vpd.vpd_buf[i];
 
 444                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
 
 445                         ("VPD Checksum Error\n"));
 
 449         /* find and check the end tag of the RW area */
 
 450         if (!(r = vpd_find_para(pAC, VPD_RW, &rp))) {
 
 451                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
 
 452                         ("Encoding Error: RV Tag not found\n"));
 
 456         if (r->p_val < pAC->vpd.vpd_buf + vpd_size/2) {
 
 457                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
 
 458                         ("Encoding Error: Invalid VPD struct size\n"));
 
 461         pAC->vpd.v.vpd_free_rw = r->p_len;
 
 463         /* everything seems to be ok */
 
 464         if (pAC->GIni.GIChipId != 0) {
 
 465                 pAC->vpd.v.vpd_status |= VPD_VALID;
 
 468         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT,
 
 469                 ("done. Free RO = %d, Free RW = %d\n",
 
 470                 pAC->vpd.v.vpd_free_ro, pAC->vpd.v.vpd_free_rw));
 
 476  *      find the Keyword 'key' in the VPD buffer and fills the
 
 477  *      parameter struct 'p' with it's values
 
 480  *              0:      parameter was not found or VPD encoding error
 
 482 static SK_VPD_PARA *vpd_find_para(
 
 483 SK_AC           *pAC,   /* common data base */
 
 484 const char      *key,   /* keyword to find (e.g. "MN") */
 
 485 SK_VPD_PARA *p)         /* parameter description struct */
 
 487         char *v ;       /* points to VPD buffer */
 
 488         int max;        /* Maximum Number of Iterations */
 
 490         v = pAC->vpd.vpd_buf;
 
 493         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
 
 494                 ("VPD find para %s .. ",key));
 
 496         /* check mandatory resource type ID string (Product Name) */
 
 497         if (*v != (char)RES_ID) {
 
 498                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
 
 499                         ("Error: 0x%x missing\n", RES_ID));
 
 503         if (strcmp(key, VPD_NAME) == 0) {
 
 504                 p->p_len = VPD_GET_RES_LEN(v);
 
 505                 p->p_val = VPD_GET_VAL(v);
 
 506                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
 
 507                         ("found, len = %d\n", p->p_len));
 
 511         v += 3 + VPD_GET_RES_LEN(v) + 3;
 
 513                 if (SK_MEMCMP(key,v,2) == 0) {
 
 514                         p->p_len = VPD_GET_VPD_LEN(v);
 
 515                         p->p_val = VPD_GET_VAL(v);
 
 516                         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
 
 517                                 ("found, len = %d\n",p->p_len));
 
 521                 /* exit when reaching the "RW" Tag or the maximum of itera. */
 
 523                 if (SK_MEMCMP(VPD_RW,v,2) == 0 || max == 0) {
 
 527                 if (SK_MEMCMP(VPD_RV,v,2) == 0) {
 
 528                         v += 3 + VPD_GET_VPD_LEN(v) + 3;        /* skip VPD-W */
 
 531                         v += 3 + VPD_GET_VPD_LEN(v);
 
 533                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
 
 534                         ("scanning '%c%c' len = %d\n",v[0],v[1],v[2]));
 
 538         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, ("not found\n"));
 
 540                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
 
 541                         ("Key/Len Encoding error\n"));
 
 548  *      Move 'n' bytes. Begin with the last byte if 'n' is > 0,
 
 549  *      Start with the last byte if n is < 0.
 
 553 static void vpd_move_para(
 
 554 char    *start,         /* start of memory block */
 
 555 char    *end,           /* end of memory block to move */
 
 556 int             n)                      /* number of bytes the memory block has to be moved */
 
 559         int i;          /* number of byte copied */
 
 564         i = (int) (end - start + 1);
 
 582  *      setup the VPD keyword 'key' at 'ip'.
 
 586 static void vpd_insert_key(
 
 587 const char      *key,   /* keyword to insert */
 
 588 const char      *buf,   /* buffer with the keyword value */
 
 589 int             len,            /* length of the value string */
 
 590 char    *ip)            /* inseration point */
 
 594         p = (SK_VPD_KEY *) ip;
 
 595         p->p_key[0] = key[0];
 
 596         p->p_key[1] = key[1];
 
 597         p->p_len = (unsigned char) len;
 
 598         SK_MEMCPY(&p->p_val,buf,len);
 
 602  *      Setup the VPD end tag "RV" / "RW".
 
 603  *      Also correct the remaining space variables vpd_free_ro / vpd_free_rw.
 
 608 static int vpd_mod_endtag(
 
 609 SK_AC   *pAC,           /* common data base */
 
 610 char    *etp)           /* end pointer input position */
 
 617         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
 
 618                 ("VPD modify endtag at 0x%x = '%c%c'\n",etp,etp[0],etp[1]));
 
 620         vpd_size = pAC->vpd.vpd_size;
 
 622         p = (SK_VPD_KEY *) etp;
 
 624         if (p->p_key[0] != 'R' || (p->p_key[1] != 'V' && p->p_key[1] != 'W')) {
 
 625                 /* something wrong here, encoding error */
 
 626                 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
 
 627                         ("Encoding Error: invalid end tag\n"));
 
 630         if (etp > pAC->vpd.vpd_buf + vpd_size/2) {
 
 631                 /* create "RW" tag */
 
 632                 p->p_len = (unsigned char)(pAC->vpd.vpd_buf+vpd_size-etp-3-1);
 
 633                 pAC->vpd.v.vpd_free_rw = (int) p->p_len;
 
 634                 i = pAC->vpd.v.vpd_free_rw;
 
 638                 /* create "RV" tag */
 
 639                 p->p_len = (unsigned char)(pAC->vpd.vpd_buf+vpd_size/2-etp-3);
 
 640                 pAC->vpd.v.vpd_free_ro = (int) p->p_len - 1;
 
 643                 for (i = 0, x = 0; i < vpd_size/2 - p->p_len; i++) {
 
 644                         x += pAC->vpd.vpd_buf[i];
 
 646                 p->p_val = (char) 0 - x;
 
 647                 i = pAC->vpd.v.vpd_free_ro;
 
 659  *      Insert a VPD keyword into the VPD buffer.
 
 661  *      The keyword 'key' is inserted at the position 'ip' in the
 
 663  *      The keywords behind the input position will
 
 664  *      be moved. The VPD end tag "RV" or "RW" is generated again.
 
 667  *              2:      value string was cut
 
 668  *              4:      VPD full, keyword was not written
 
 672 static int      VpdSetupPara(
 
 673 SK_AC   *pAC,           /* common data base */
 
 674 const char      *key,   /* keyword to insert */
 
 675 const char      *buf,   /* buffer with the keyword value */
 
 676 int             len,            /* length of the keyword value */
 
 677 int             type,           /* VPD_RO_KEY or VPD_RW_KEY */
 
 678 int             op)                     /* operation to do: ADD_KEY or OWR_KEY */
 
 681         char    *etp;           /* end tag position */
 
 682         int     free;           /* remaining space in selected area */
 
 683         char    *ip;            /* input position inside the VPD buffer */
 
 684         int     rtv;            /* return code */
 
 685         int     head;           /* additional haeder bytes to move */
 
 686         int     found;          /* additinoal bytes if the keyword was found */
 
 689         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
 
 690                 ("VPD setup para key = %s, val = %s\n",key,buf));
 
 692         vpd_size = pAC->vpd.vpd_size;
 
 696         if (type == VPD_RW_KEY) {
 
 697                 /* end tag is "RW" */
 
 698                 free = pAC->vpd.v.vpd_free_rw;
 
 699                 etp = pAC->vpd.vpd_buf + (vpd_size - free - 1 - 3);
 
 702                 /* end tag is "RV" */
 
 703                 free = pAC->vpd.v.vpd_free_ro;
 
 704                 etp = pAC->vpd.vpd_buf + (vpd_size/2 - free - 4);
 
 706         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
 
 707                 ("Free RO = %d, Free RW = %d\n",
 
 708                 pAC->vpd.v.vpd_free_ro, pAC->vpd.v.vpd_free_rw));
 
 713                 if (vpd_find_para(pAC, key, &vp)) {
 
 716                         free += vp.p_len + 3;
 
 717                         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
 
 718                                 ("Overwrite Key\n"));
 
 722                         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
 
 732         if (len + 3 > free) {
 
 734                         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
 
 735                                 ("VPD Buffer Overflow, keyword not written\n"));
 
 741                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
 
 742                         ("VPD Buffer Full, Keyword was cut\n"));
 
 745         vpd_move_para(ip + vp.p_len + found, etp+2, len-vp.p_len+head);
 
 746         vpd_insert_key(key, buf, len, ip);
 
 747         if (vpd_mod_endtag(pAC, etp + len - vp.p_len + head)) {
 
 748                 pAC->vpd.v.vpd_status &= ~VPD_VALID;
 
 749                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
 
 750                         ("VPD Encoding Error\n"));
 
 759  *      Read the contents of the VPD EEPROM and copy it to the
 
 760  *      VPD buffer if not already done.
 
 762  * return:      A pointer to the vpd_status structure. The structure contains
 
 765 SK_VPD_STATUS *VpdStat(
 
 766 SK_AC   *pAC,   /* Adapters context */
 
 767 SK_IOC  IoC)    /* IO Context */
 
 769         if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
 
 770                 (void)VpdInit(pAC, IoC);
 
 777  *      Read the contents of the VPD EEPROM and copy it to the VPD
 
 778  *      buffer if not already done.
 
 779  *      Scan the VPD buffer for VPD keywords and create the VPD
 
 780  *      keyword list by copying the keywords to 'buf', all after
 
 781  *      each other and terminated with a '\0'.
 
 783  * Exceptions:  o The Resource Type ID String (product name) is called "Name"
 
 784  *              o The VPD end tags 'RV' and 'RW' are not listed
 
 786  *      The number of copied keywords is counted in 'elements'.
 
 789  *              2:      buffer overfull, one or more keywords are missing
 
 792  *      example values after returning:
 
 794  *              buf =   "Name\0PN\0EC\0MN\0SN\0CP\0VF\0VL\0YA\0"
 
 799 SK_AC   *pAC,           /* common data base */
 
 800 SK_IOC  IoC,            /* IO Context */
 
 801 char    *buf,           /* buffer where to copy the keywords */
 
 802 int             *len,           /* buffer length */
 
 803 int             *elements)      /* number of keywords returned */
 
 808         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("list VPD keys .. "));
 
 810         if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
 
 811                 if (VpdInit(pAC, IoC) != 0) {
 
 813                         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
 
 814                                 ("VPD Init Error, terminated\n"));
 
 819         if ((signed)strlen(VPD_NAME) + 1 <= *len) {
 
 820                 v = pAC->vpd.vpd_buf;
 
 821                 strcpy(buf,VPD_NAME);
 
 822                 n = strlen(VPD_NAME) + 1;
 
 825                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX,
 
 826                         ("'%c%c' ",v[0],v[1]));
 
 830                 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
 
 831                         ("buffer overflow\n"));
 
 835         v += 3 + VPD_GET_RES_LEN(v) + 3;
 
 837                 /* exit when reaching the "RW" Tag */
 
 838                 if (SK_MEMCMP(VPD_RW,v,2) == 0) {
 
 842                 if (SK_MEMCMP(VPD_RV,v,2) == 0) {
 
 843                         v += 3 + VPD_GET_VPD_LEN(v) + 3;        /* skip VPD-W */
 
 852                         v += 3 + VPD_GET_VPD_LEN(v);
 
 854                         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX,
 
 855                                 ("'%c%c' ",v[0],v[1]));
 
 859                         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
 
 860                                 ("buffer overflow\n"));
 
 865         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("\n"));
 
 872  *      Read the contents of the VPD EEPROM and copy it to the
 
 873  *      VPD buffer if not already done. Search for the VPD keyword
 
 874  *      'key' and copy its value to 'buf'. Add a terminating '\0'.
 
 875  *      If the value does not fit into the buffer cut it after
 
 879  *              1:      keyword not found
 
 880  *              2:      value string was cut
 
 881  *              3:      VPD transfer timeout
 
 885 SK_AC           *pAC,   /* common data base */
 
 886 SK_IOC          IoC,    /* IO Context */
 
 887 const char      *key,   /* keyword to read (e.g. "MN") */
 
 888 char            *buf,   /* buffer where to copy the keyword value */
 
 889 int                     *len)   /* buffer length */
 
 893         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("VPD read %s .. ", key));
 
 894         if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
 
 895                 if (VpdInit(pAC, IoC) != 0) {
 
 897                         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
 
 898                                 ("VPD init error\n"));
 
 903         if ((p = vpd_find_para(pAC, key, &vp)) != NULL) {
 
 904                 if (p->p_len > (*(unsigned *)len)-1) {
 
 907                 SK_MEMCPY(buf, p->p_val, p->p_len);
 
 908                 buf[p->p_len] = '\0';
 
 910                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX,
 
 911                         ("%c%c%c%c.., len = %d\n",
 
 912                         buf[0],buf[1],buf[2],buf[3],*len));
 
 916                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, ("not found\n"));
 
 924  *      Check whether a given key may be written
 
 927  *      SK_TRUE         Yes it may be written
 
 928  *      SK_FALSE        No it may be written
 
 931 char    *key)   /* keyword to write (allowed values "Yx", "Vx") */
 
 933         if ((*key != 'Y' && *key != 'V') ||
 
 934                 key[1] < '0' || key[1] > 'Z' ||
 
 935                 (key[1] > '9' && key[1] < 'A') || strlen(key) != 2) {
 
 943  *      Read the contents of the VPD EEPROM and copy it to the VPD
 
 944  *      buffer if not already done. Insert/overwrite the keyword 'key'
 
 945  *      in the VPD buffer. Cut the keyword value if it does not fit
 
 946  *      into the VPD read / write area.
 
 949  *              2:      value string was cut
 
 950  *              3:      VPD transfer timeout
 
 951  *              4:      VPD full, keyword was not written
 
 952  *              5:      keyword cannot be written
 
 956 SK_AC           *pAC,   /* common data base */
 
 957 SK_IOC          IoC,    /* IO Context */
 
 958 const char      *key,   /* keyword to write (allowed values "Yx", "Vx") */
 
 959 const char      *buf)   /* buffer where the keyword value can be read from */
 
 961         int len;                /* length of the keyword to write */
 
 962         int rtv;                /* return code */
 
 965         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX,
 
 966                 ("VPD write %s = %s\n",key,buf));
 
 968         if ((*key != 'Y' && *key != 'V') ||
 
 969                 key[1] < '0' || key[1] > 'Z' ||
 
 970                 (key[1] > '9' && key[1] < 'A') || strlen(key) != 2) {
 
 972                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
 
 973                         ("illegal key tag, keyword not written\n"));
 
 977         if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
 
 978                 if (VpdInit(pAC, IoC) != 0) {
 
 979                         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
 
 980                                 ("VPD init error\n"));
 
 987         if (len > VPD_MAX_LEN) {
 
 991                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
 
 992                         ("keyword too long, cut after %d bytes\n",VPD_MAX_LEN));
 
 994         if ((rtv2 = VpdSetupPara(pAC, key, buf, len, VPD_RW_KEY, OWR_KEY)) != 0) {
 
 995                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
 
 996                         ("VPD write error\n"));
 
1004  *      Read the contents of the VPD EEPROM and copy it to the
 
1005  *      VPD buffer if not already done. Remove the VPD keyword
 
1006  *      'key' from the VPD buffer.
 
1007  *      Only the keywords in the read/write area can be deleted.
 
1008  *      Keywords in the read only area cannot be deleted.
 
1010  * returns      0:      success, keyword was removed
 
1011  *              1:      keyword not found
 
1012  *              5:      keyword cannot be deleted
 
1013  *              6:      fatal VPD error
 
1016 SK_AC   *pAC,   /* common data base */
 
1017 SK_IOC  IoC,    /* IO Context */
 
1018 char    *key)   /* keyword to read (e.g. "MN") */
 
1024         vpd_size = pAC->vpd.vpd_size;
 
1026         SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_TX,("VPD delete key %s\n",key));
 
1027         if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
 
1028                 if (VpdInit(pAC, IoC) != 0) {
 
1029                         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
 
1030                                 ("VPD init error\n"));
 
1035         if ((p = vpd_find_para(pAC, key, &vp)) != NULL) {
 
1036                 if (p->p_val < pAC->vpd.vpd_buf + vpd_size/2) {
 
1037                         /* try to delete read only keyword */
 
1038                         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
 
1039                                 ("cannot delete RO keyword\n"));
 
1043                 etp = pAC->vpd.vpd_buf + (vpd_size-pAC->vpd.v.vpd_free_rw-1-3);
 
1045                 vpd_move_para(vp.p_val+vp.p_len, etp+2,
 
1046                         - ((int)(vp.p_len + 3)));
 
1047                 if (vpd_mod_endtag(pAC, etp - vp.p_len - 3)) {
 
1048                         pAC->vpd.v.vpd_status &= ~VPD_VALID;
 
1049                         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
 
1050                                 ("VPD encoding error\n"));
 
1055                 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
 
1056                         ("keyword not found\n"));
 
1064  *      If the VPD buffer contains valid data write the VPD
 
1065  *      read/write area back to the VPD EEPROM.
 
1067  * returns      0:      success
 
1068  *              3:      VPD transfer timeout
 
1071 SK_AC   *pAC,   /* Adapters context */
 
1072 SK_IOC  IoC)    /* IO Context */
 
1076         vpd_size = pAC->vpd.vpd_size;
 
1078         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("VPD update .. "));
 
1079         if ((pAC->vpd.v.vpd_status & VPD_VALID) != 0) {
 
1080                 if (VpdTransferBlock(pAC, IoC, pAC->vpd.vpd_buf + vpd_size/2,
 
1081                         vpd_size/2, vpd_size/2, VPD_WRITE) != vpd_size/2) {
 
1083                         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
 
1084                                 ("transfer timed out\n"));
 
1088         SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("done\n"));