1/****************************************************************************** 2 * 3 * Name: skvpd.c 4 * Project: GEnesis, PCI Gigabit Ethernet Adapter 5 * Version: $Revision: 1.1.1.1 $ 6 * Date: $Date: 2007/08/03 18:52:48 $ 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 Please refer skvpd.txt for information how to include this module 26 */ 27static const char SysKonnectFileId[] = 28 "@(#)$Id: skvpd.c,v 1.1.1.1 2007/08/03 18:52:48 Exp $ (C) SK"; 29 30#include "h/skdrv1st.h" 31#include "h/sktypes.h" 32#include "h/skdebug.h" 33#include "h/skdrv2nd.h" 34 35/* 36 * Static functions 37 */ 38#ifndef SK_KR_PROTO 39static SK_VPD_PARA *vpd_find_para( 40 SK_AC *pAC, 41 const char *key, 42 SK_VPD_PARA *p); 43#else /* SK_KR_PROTO */ 44static SK_VPD_PARA *vpd_find_para(); 45#endif /* SK_KR_PROTO */ 46 47/* 48 * waits for a completion of a VPD transfer 49 * The VPD transfer must complete within SK_TICKS_PER_SEC/16 50 * 51 * returns 0: success, transfer completes 52 * error exit(9) with a error message 53 */ 54static int VpdWait( 55SK_AC *pAC, /* Adapters context */ 56SK_IOC IoC, /* IO Context */ 57int event) /* event to wait for (VPD_READ / VPD_write) completion*/ 58{ 59 SK_U64 start_time; 60 SK_U16 state; 61 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); 65 do { 66 if (SkOsGetTime(pAC) - start_time > SK_TICKS_PER_SEC) { 67 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). 79 */ 80 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_FATAL | SK_DBGCAT_ERR, 81 ("ERROR:VPD wait timeout\n")); 82 return(1); 83 } 84 85 VPD_IN16(pAC, IoC, PCI_VPD_ADR_REG, &state); 86 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); 90 91 return(0); 92} 93 94#ifdef SKDIAG 95 96/* 97 * Read the dword at address 'addr' from the VPD EEPROM. 98 * 99 * Needed Time: MIN 1,3 ms MAX 2,6 ms 100 * 101 * Note: The DWord is returned in the endianess of the machine the routine 102 * is running on. 103 * 104 * Returns the data read. 105 */ 106SK_U32 VpdReadDWord( 107SK_AC *pAC, /* Adapters context */ 108SK_IOC IoC, /* IO Context */ 109int addr) /* VPD address */ 110{ 111 SK_U32 Rtv; 112 113 /* start VPD read */ 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 */ 117 118 VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, (SK_U16)addr); 119 120 /* ignore return code here */ 121 (void)VpdWait(pAC, IoC, VPD_READ); 122 123 /* Don't swap here, it's a data stream of bytes */ 124 Rtv = 0; 125 126 VPD_IN32(pAC, IoC, PCI_VPD_DAT_REG, &Rtv); 127 128 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, 129 ("VPD read dword data = 0x%x\n",Rtv)); 130 return(Rtv); 131} 132 133#endif /* SKDIAG */ 134 135/* 136 * Read one Stream of 'len' bytes of VPD data, starting at 'addr' from 137 * or to the I2C EEPROM. 138 * 139 * Returns number of bytes read / written. 140 */ 141static int VpdWriteStream( 142SK_AC *pAC, /* Adapters context */ 143SK_IOC IoC, /* IO Context */ 144char *buf, /* data buffer */ 145int Addr, /* VPD start address */ 146int Len) /* number of bytes to read / to write */ 147{ 148 int i; 149 int j; 150 SK_U16 AdrReg; 151 int Rtv; 152 SK_U8 * pComp; /* Compare pointer */ 153 SK_U8 Data; /* Input Data for Compare */ 154 155 /* Init Compare Pointer */ 156 pComp = (SK_U8 *) buf; 157 158 for (i = 0; i < Len; i++, buf++) { 159 if ((i%sizeof(SK_U32)) == 0) { 160 /* 161 * At the begin of each cycle read the Data Reg 162 * So it is initialized even if only a few bytes 163 * are written. 164 */ 165 AdrReg = (SK_U16) Addr; 166 AdrReg &= ~VPD_WRITE; /* READ operation */ 167 168 VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg); 169 170 /* Wait for termination */ 171 Rtv = VpdWait(pAC, IoC, VPD_READ); 172 if (Rtv != 0) { 173 return(i); 174 } 175 } 176 177 /* Write current Byte */ 178 VPD_OUT8(pAC, IoC, PCI_VPD_DAT_REG + (i%sizeof(SK_U32)), 179 *(SK_U8*)buf); 180 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 */ 186 187 VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg); 188 189 /* Wait for termination */ 190 Rtv = VpdWait(pAC, IoC, VPD_WRITE); 191 if (Rtv != 0) { 192 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, 193 ("Write Timed Out\n")); 194 return(i - (i%sizeof(SK_U32))); 195 } 196 197 /* 198 * Now re-read to verify 199 */ 200 AdrReg &= ~VPD_WRITE; /* READ operation */ 201 202 VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg); 203 204 /* Wait for termination */ 205 Rtv = VpdWait(pAC, IoC, VPD_READ); 206 if (Rtv != 0) { 207 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, 208 ("Verify Timed Out\n")); 209 return(i - (i%sizeof(SK_U32))); 210 } 211 212 for (j = 0; j <= (int)(i%sizeof(SK_U32)); j++, pComp++) { 213 214 VPD_IN8(pAC, IoC, PCI_VPD_DAT_REG + j, &Data); 215 216 if (Data != *pComp) { 217 /* Verify Error */ 218 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, 219 ("WriteStream Verify Error\n")); 220 return(i - (i%sizeof(SK_U32)) + j); 221 } 222 } 223 } 224 } 225 226 return(Len); 227} 228 229 230/* 231 * Read one Stream of 'len' bytes of VPD data, starting at 'addr' from 232 * or to the I2C EEPROM. 233 * 234 * Returns number of bytes read / written. 235 */ 236static int VpdReadStream( 237SK_AC *pAC, /* Adapters context */ 238SK_IOC IoC, /* IO Context */ 239char *buf, /* data buffer */ 240int Addr, /* VPD start address */ 241int Len) /* number of bytes to read / to write */ 242{ 243 int i; 244 SK_U16 AdrReg; 245 int Rtv; 246 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 */ 253 254 VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg); 255 256 /* Wait for termination */ 257 Rtv = VpdWait(pAC, IoC, VPD_READ); 258 if (Rtv != 0) { 259 return(i); 260 } 261 } 262 VPD_IN8(pAC, IoC, PCI_VPD_DAT_REG + (i%sizeof(SK_U32)), 263 (SK_U8 *)buf); 264 } 265 266 return(Len); 267} 268 269/* 270 * Read ore writes 'len' bytes of VPD data, starting at 'addr' from 271 * or to the I2C EEPROM. 272 * 273 * Returns number of bytes read / written. 274 */ 275static int VpdTransferBlock( 276SK_AC *pAC, /* Adapters context */ 277SK_IOC IoC, /* IO Context */ 278char *buf, /* data buffer */ 279int addr, /* VPD start address */ 280int len, /* number of bytes to read / to write */ 281int dir) /* transfer direction may be VPD_READ or VPD_WRITE */ 282{ 283 int Rtv; /* Return value */ 284 int vpd_rom_size; 285 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)); 289 290 if (len == 0) 291 return(0); 292 293 vpd_rom_size = pAC->vpd.rom_size; 294 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)); 299 return(0); 300 } 301 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)); 306 } 307 308 if (dir == VPD_READ) { 309 Rtv = VpdReadStream(pAC, IoC, buf, addr, len); 310 } 311 else { 312 Rtv = VpdWriteStream(pAC, IoC, buf, addr, len); 313 } 314 315 return(Rtv); 316} 317 318#ifdef SKDIAG 319 320/* 321 * Read 'len' bytes of VPD data, starting at 'addr'. 322 * 323 * Returns number of bytes read. 324 */ 325int VpdReadBlock( 326SK_AC *pAC, /* pAC pointer */ 327SK_IOC IoC, /* IO Context */ 328char *buf, /* buffer were the data should be stored */ 329int addr, /* start reading at the VPD address */ 330int len) /* number of bytes to read */ 331{ 332 return(VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_READ)); 333} 334 335/* 336 * Write 'len' bytes of *but to the VPD EEPROM, starting at 'addr'. 337 * 338 * Returns number of bytes writes. 339 */ 340int VpdWriteBlock( 341SK_AC *pAC, /* pAC pointer */ 342SK_IOC IoC, /* IO Context */ 343char *buf, /* buffer, holds the data to write */ 344int addr, /* start writing at the VPD address */ 345int len) /* number of bytes to write */ 346{ 347 return(VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_WRITE)); 348} 349#endif /* SKDIAG */ 350 351/* 352 * (re)initialize the VPD buffer 353 * 354 * Reads the VPD data from the EEPROM into the VPD buffer. 355 * Get the remaining read only and read / write space. 356 * 357 * return 0: success 358 * 1: fatal VPD error 359 */ 360static int VpdInit( 361SK_AC *pAC, /* Adapters context */ 362SK_IOC IoC) /* IO Context */ 363{ 364 SK_VPD_PARA *r, rp; /* RW or RV */ 365 int i; 366 unsigned char x; 367 int vpd_size; 368 SK_U16 dev_id; 369 SK_U32 our_reg2; 370 371 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT, ("VpdInit .. ")); 372 373 VPD_IN16(pAC, IoC, PCI_DEVICE_ID, &dev_id); 374 375 VPD_IN32(pAC, IoC, PCI_OUR_REG_2, &our_reg2); 376 377 pAC->vpd.rom_size = 256 << ((our_reg2 & PCI_VPD_ROM_SZ) >> 14); 378 379 /* 380 * this function might get used before the hardware is initialized 381 * therefore we cannot always trust in GIChipId 382 */ 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)) { 387 388 /* for Yukon the VPD size is always 256 */ 389 vpd_size = VPD_SIZE_YUKON; 390 } 391 else { 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; 395 } 396 else { 397 vpd_size = pAC->vpd.rom_size; 398 } 399 } 400 401 /* read the VPD data into the VPD buffer */ 402 if (VpdTransferBlock(pAC, IoC, pAC->vpd.vpd_buf, 0, vpd_size, VPD_READ) 403 != vpd_size) { 404 405 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, 406 ("Block Read Error\n")); 407 return(1); 408 } 409 410 pAC->vpd.vpd_size = vpd_size; 411 412 /* Asus K8V Se Deluxe bugfix. Correct VPD content */ 413 /* MBo April 2004 */ 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; 420 } 421 422 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")); 427 return(1); 428 } 429 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")); 433 return(1); 434 } 435 pAC->vpd.v.vpd_free_ro = r->p_len - 1; 436 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]; 440 } 441 442 if (x != 0) { 443 /* checksum error */ 444 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, 445 ("VPD Checksum Error\n")); 446 return(1); 447 } 448 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")); 453 return(1); 454 } 455 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")); 459 return(1); 460 } 461 pAC->vpd.v.vpd_free_rw = r->p_len; 462 463 /* everything seems to be ok */ 464 if (pAC->GIni.GIChipId != 0) { 465 pAC->vpd.v.vpd_status |= VPD_VALID; 466 } 467 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)); 471 472 return(0); 473} 474 475/* 476 * find the Keyword 'key' in the VPD buffer and fills the 477 * parameter struct 'p' with it's values 478 * 479 * returns *p success 480 * 0: parameter was not found or VPD encoding error 481 */ 482static SK_VPD_PARA *vpd_find_para( 483SK_AC *pAC, /* common data base */ 484const char *key, /* keyword to find (e.g. "MN") */ 485SK_VPD_PARA *p) /* parameter description struct */ 486{ 487 char *v ; /* points to VPD buffer */ 488 int max; /* Maximum Number of Iterations */ 489 490 v = pAC->vpd.vpd_buf; 491 max = 128; 492 493 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, 494 ("VPD find para %s .. ",key)); 495 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)); 500 return NULL; 501 } 502 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)); 508 return(p); 509 } 510 511 v += 3 + VPD_GET_RES_LEN(v) + 3; 512 for (;; ) { 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)); 518 return(p); 519 } 520 521 /* exit when reaching the "RW" Tag or the maximum of itera. */ 522 max--; 523 if (SK_MEMCMP(VPD_RW,v,2) == 0 || max == 0) { 524 break; 525 } 526 527 if (SK_MEMCMP(VPD_RV,v,2) == 0) { 528 v += 3 + VPD_GET_VPD_LEN(v) + 3; /* skip VPD-W */ 529 } 530 else { 531 v += 3 + VPD_GET_VPD_LEN(v); 532 } 533 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, 534 ("scanning '%c%c' len = %d\n",v[0],v[1],v[2])); 535 } 536 537#ifdef DEBUG 538 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, ("not found\n")); 539 if (max == 0) { 540 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, 541 ("Key/Len Encoding error\n")); 542 } 543#endif /* DEBUG */ 544 return NULL; 545} 546 547/* 548 * Move 'n' bytes. Begin with the last byte if 'n' is > 0, 549 * Start with the last byte if n is < 0. 550 * 551 * returns nothing 552 */ 553static void vpd_move_para( 554char *start, /* start of memory block */ 555char *end, /* end of memory block to move */ 556int n) /* number of bytes the memory block has to be moved */ 557{ 558 char *p; 559 int i; /* number of byte copied */ 560 561 if (n == 0) 562 return; 563 564 i = (int) (end - start + 1); 565 if (n < 0) { 566 p = start + n; 567 while (i != 0) { 568 *p++ = *start++; 569 i--; 570 } 571 } 572 else { 573 p = end + n; 574 while (i != 0) { 575 *p-- = *end--; 576 i--; 577 } 578 } 579} 580 581/* 582 * setup the VPD keyword 'key' at 'ip'. 583 * 584 * returns nothing 585 */ 586static void vpd_insert_key( 587const char *key, /* keyword to insert */ 588const char *buf, /* buffer with the keyword value */ 589int len, /* length of the value string */ 590char *ip) /* inseration point */ 591{ 592 SK_VPD_KEY *p; 593 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); 599} 600 601/* 602 * Setup the VPD end tag "RV" / "RW". 603 * Also correct the remaining space variables vpd_free_ro / vpd_free_rw. 604 * 605 * returns 0: success 606 * 1: encoding error 607 */ 608static int vpd_mod_endtag( 609SK_AC *pAC, /* common data base */ 610char *etp) /* end pointer input position */ 611{ 612 SK_VPD_KEY *p; 613 unsigned char x; 614 int i; 615 int vpd_size; 616 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])); 619 620 vpd_size = pAC->vpd.vpd_size; 621 622 p = (SK_VPD_KEY *) etp; 623 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")); 628 return(1); 629 } 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; 635 etp += 3; 636 } 637 else { 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; 641 642 /* setup checksum */ 643 for (i = 0, x = 0; i < vpd_size/2 - p->p_len; i++) { 644 x += pAC->vpd.vpd_buf[i]; 645 } 646 p->p_val = (char) 0 - x; 647 i = pAC->vpd.v.vpd_free_ro; 648 etp += 4; 649 } 650 while (i) { 651 *etp++ = 0x00; 652 i--; 653 } 654 655 return(0); 656} 657 658/* 659 * Insert a VPD keyword into the VPD buffer. 660 * 661 * The keyword 'key' is inserted at the position 'ip' in the 662 * VPD buffer. 663 * The keywords behind the input position will 664 * be moved. The VPD end tag "RV" or "RW" is generated again. 665 * 666 * returns 0: success 667 * 2: value string was cut 668 * 4: VPD full, keyword was not written 669 * 6: fatal VPD error 670 * 671 */ 672static int VpdSetupPara( 673SK_AC *pAC, /* common data base */ 674const char *key, /* keyword to insert */ 675const char *buf, /* buffer with the keyword value */ 676int len, /* length of the keyword value */ 677int type, /* VPD_RO_KEY or VPD_RW_KEY */ 678int op) /* operation to do: ADD_KEY or OWR_KEY */ 679{ 680 SK_VPD_PARA vp; 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 */ 687 int vpd_size; 688 689 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, 690 ("VPD setup para key = %s, val = %s\n",key,buf)); 691 692 vpd_size = pAC->vpd.vpd_size; 693 694 rtv = 0; 695 ip = NULL; 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); 700 } 701 else { 702 /* end tag is "RV" */ 703 free = pAC->vpd.v.vpd_free_ro; 704 etp = pAC->vpd.vpd_buf + (vpd_size/2 - free - 4); 705 } 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)); 709 710 head = 0; 711 found = 0; 712 if (op == OWR_KEY) { 713 if (vpd_find_para(pAC, key, &vp)) { 714 found = 3; 715 ip = vp.p_val - 3; 716 free += vp.p_len + 3; 717 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, 718 ("Overwrite Key\n")); 719 } 720 else { 721 op = ADD_KEY; 722 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, 723 ("Add Key\n")); 724 } 725 } 726 if (op == ADD_KEY) { 727 ip = etp; 728 vp.p_len = 0; 729 head = 3; 730 } 731 732 if (len + 3 > free) { 733 if (free < 7) { 734 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, 735 ("VPD Buffer Overflow, keyword not written\n")); 736 return(4); 737 } 738 /* cut it again */ 739 len = free - 3; 740 rtv = 2; 741 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, 742 ("VPD Buffer Full, Keyword was cut\n")); 743 } 744 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")); 751 return(6); 752 } 753 754 return(rtv); 755} 756 757 758/* 759 * Read the contents of the VPD EEPROM and copy it to the 760 * VPD buffer if not already done. 761 * 762 * return: A pointer to the vpd_status structure. The structure contains 763 * this fields. 764 */ 765SK_VPD_STATUS *VpdStat( 766SK_AC *pAC, /* Adapters context */ 767SK_IOC IoC) /* IO Context */ 768{ 769 if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) { 770 (void)VpdInit(pAC, IoC); 771 } 772 return(&pAC->vpd.v); 773} 774 775 776/* 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'. 782 * 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 785 * 786 * The number of copied keywords is counted in 'elements'. 787 * 788 * returns 0: success 789 * 2: buffer overfull, one or more keywords are missing 790 * 6: fatal VPD error 791 * 792 * example values after returning: 793 * 794 * buf = "Name\0PN\0EC\0MN\0SN\0CP\0VF\0VL\0YA\0" 795 * *len = 30 796 * *elements = 9 797 */ 798int VpdKeys( 799SK_AC *pAC, /* common data base */ 800SK_IOC IoC, /* IO Context */ 801char *buf, /* buffer where to copy the keywords */ 802int *len, /* buffer length */ 803int *elements) /* number of keywords returned */ 804{ 805 char *v; 806 int n; 807 808 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("list VPD keys .. ")); 809 *elements = 0; 810 if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) { 811 if (VpdInit(pAC, IoC) != 0) { 812 *len = 0; 813 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, 814 ("VPD Init Error, terminated\n")); 815 return(6); 816 } 817 } 818 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; 823 buf += n; 824 *elements = 1; 825 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, 826 ("'%c%c' ",v[0],v[1])); 827 } 828 else { 829 *len = 0; 830 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR, 831 ("buffer overflow\n")); 832 return(2); 833 } 834 835 v += 3 + VPD_GET_RES_LEN(v) + 3; 836 for (;; ) { 837 /* exit when reaching the "RW" Tag */ 838 if (SK_MEMCMP(VPD_RW,v,2) == 0) { 839 break; 840 } 841 842 if (SK_MEMCMP(VPD_RV,v,2) == 0) { 843 v += 3 + VPD_GET_VPD_LEN(v) + 3; /* skip VPD-W */ 844 continue; 845 } 846 847 if (n+3 <= *len) { 848 SK_MEMCPY(buf,v,2); 849 buf += 2; 850 *buf++ = '\0'; 851 n += 3; 852 v += 3 + VPD_GET_VPD_LEN(v); 853 *elements += 1; 854 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, 855 ("'%c%c' ",v[0],v[1])); 856 } 857 else { 858 *len = n; 859 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, 860 ("buffer overflow\n")); 861 return(2); 862 } 863 } 864 865 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("\n")); 866 *len = n; 867 return(0); 868} 869 870 871/* 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 876 * 'len' - 1 bytes. 877 * 878 * returns 0: success 879 * 1: keyword not found 880 * 2: value string was cut 881 * 3: VPD transfer timeout 882 * 6: fatal VPD error 883 */ 884int VpdRead( 885SK_AC *pAC, /* common data base */ 886SK_IOC IoC, /* IO Context */ 887const char *key, /* keyword to read (e.g. "MN") */ 888char *buf, /* buffer where to copy the keyword value */ 889int *len) /* buffer length */ 890{ 891 SK_VPD_PARA *p, vp; 892 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) { 896 *len = 0; 897 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, 898 ("VPD init error\n")); 899 return(6); 900 } 901 } 902 903 if ((p = vpd_find_para(pAC, key, &vp)) != NULL) { 904 if (p->p_len > (*(unsigned *)len)-1) { 905 p->p_len = *len - 1; 906 } 907 SK_MEMCPY(buf, p->p_val, p->p_len); 908 buf[p->p_len] = '\0'; 909 *len = p->p_len; 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)); 913 } 914 else { 915 *len = 0; 916 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, ("not found\n")); 917 return(1); 918 } 919 return(0); 920} 921 922 923/* 924 * Check whether a given key may be written 925 * 926 * returns 927 * SK_TRUE Yes it may be written 928 * SK_FALSE No it may be written 929 */ 930SK_BOOL VpdMayWrite( 931char *key) /* keyword to write (allowed values "Yx", "Vx") */ 932{ 933 if ((*key != 'Y' && *key != 'V') || 934 key[1] < '0' || key[1] > 'Z' || 935 (key[1] > '9' && key[1] < 'A') || strlen(key) != 2) { 936 937 return(SK_FALSE); 938 } 939 return(SK_TRUE); 940} 941 942/* 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. 947 * 948 * returns 0: success 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 953 * 6: fatal VPD error 954 */ 955int VpdWrite( 956SK_AC *pAC, /* common data base */ 957SK_IOC IoC, /* IO Context */ 958const char *key, /* keyword to write (allowed values "Yx", "Vx") */ 959const char *buf) /* buffer where the keyword value can be read from */ 960{ 961 int len; /* length of the keyword to write */ 962 int rtv; /* return code */ 963 int rtv2; 964 965 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, 966 ("VPD write %s = %s\n",key,buf)); 967 968 if ((*key != 'Y' && *key != 'V') || 969 key[1] < '0' || key[1] > 'Z' || 970 (key[1] > '9' && key[1] < 'A') || strlen(key) != 2) { 971 972 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, 973 ("illegal key tag, keyword not written\n")); 974 return(5); 975 } 976 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")); 981 return(6); 982 } 983 } 984 985 rtv = 0; 986 len = strlen(buf); 987 if (len > VPD_MAX_LEN) { 988 /* cut it */ 989 len = VPD_MAX_LEN; 990 rtv = 2; 991 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, 992 ("keyword too long, cut after %d bytes\n",VPD_MAX_LEN)); 993 } 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")); 997 return(rtv2); 998 } 999 1000 return(rtv); 1001} 1002 1003/* 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. 1009 * 1010 * returns 0: success, keyword was removed 1011 * 1: keyword not found 1012 * 5: keyword cannot be deleted 1013 * 6: fatal VPD error 1014 */ 1015int VpdDelete( 1016SK_AC *pAC, /* common data base */ 1017SK_IOC IoC, /* IO Context */ 1018char *key) /* keyword to read (e.g. "MN") */ 1019{ 1020 SK_VPD_PARA *p, vp; 1021 char *etp; 1022 int vpd_size; 1023 1024 vpd_size = pAC->vpd.vpd_size; 1025 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")); 1031 return(6); 1032 } 1033 } 1034 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")); 1040 return(5); 1041 } 1042 1043 etp = pAC->vpd.vpd_buf + (vpd_size-pAC->vpd.v.vpd_free_rw-1-3); 1044 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")); 1051 return(6); 1052 } 1053 } 1054 else { 1055 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, 1056 ("keyword not found\n")); 1057 return(1); 1058 } 1059 1060 return(0); 1061} 1062 1063/* 1064 * If the VPD buffer contains valid data write the VPD 1065 * read/write area back to the VPD EEPROM. 1066 * 1067 * returns 0: success 1068 * 3: VPD transfer timeout 1069 */ 1070int VpdUpdate( 1071SK_AC *pAC, /* Adapters context */ 1072SK_IOC IoC) /* IO Context */ 1073{ 1074 int vpd_size; 1075 1076 vpd_size = pAC->vpd.vpd_size; 1077 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) { 1082 1083 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, 1084 ("transfer timed out\n")); 1085 return(3); 1086 } 1087 } 1088 SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("done\n")); 1089 return(0); 1090} 1091