skvpd.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:30k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /******************************************************************************
  2.  *
  3.  * Name: skvpd.c
  4.  * Project: GEnesis, PCI Gigabit Ethernet Adapter
  5.  * Version: $Revision: 1.26 $
  6.  * Date: $Date: 2000/06/13 08:00:01 $
  7.  * Purpose: Shared software to read and write VPD data
  8.  *
  9.  ******************************************************************************/
  10. /******************************************************************************
  11.  *
  12.  * (C)Copyright 1998,1999 SysKonnect,
  13.  * a business unit of Schneider & Koch & Co. Datensysteme 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.  * History:
  26.  *
  27.  * $Log: skvpd.c,v $
  28.  * Revision 1.26  2000/06/13 08:00:01  mkarl
  29.  * additional cast to avoid compile problems in 64 bit environment
  30.  *
  31.  * Revision 1.25  1999/11/22 13:39:32  cgoos
  32.  * Changed license header to GPL.
  33.  *
  34.  * Revision 1.24  1999/03/11 14:25:49  malthoff
  35.  * Replace __STDC__ with SK_KR_PROTO.
  36.  *
  37.  * Revision 1.23  1999/01/11 15:13:11  gklug
  38.  * fix: syntax error
  39.  *
  40.  * Revision 1.22  1998/10/30 06:41:15  gklug
  41.  * rmv: WARNING
  42.  *
  43.  * Revision 1.21  1998/10/29 07:15:14  gklug
  44.  * fix: Write Stream function needs verify.
  45.  *
  46.  * Revision 1.20  1998/10/28 18:05:08  gklug
  47.  * chg: no DEBUG in VpdMayWrite
  48.  *
  49.  * Revision 1.19  1998/10/28 15:56:11  gklug
  50.  * fix: Return len at end of ReadStream
  51.  * fix: Write even less than 4 bytes correctly
  52.  *
  53.  * Revision 1.18  1998/10/28 09:00:47  gklug
  54.  * fix: unreferenced local vars
  55.  *
  56.  * Revision 1.17  1998/10/28 08:25:45  gklug
  57.  * fix: WARNING
  58.  *
  59.  * Revision 1.16  1998/10/28 08:17:30  gklug
  60.  * fix: typo
  61.  *
  62.  * Revision 1.15  1998/10/28 07:50:32  gklug
  63.  * fix: typo
  64.  *
  65.  * Revision 1.14  1998/10/28 07:20:38  gklug
  66.  * chg: Interface functions to use IoC as parameter as well
  67.  * fix: VpdRead/WriteDWord now return SK_U32
  68.  * chg: VPD_IN/OUT names conform to SK_IN/OUT
  69.  * add: usage of VPD_IN/OUT8 macros
  70.  * add: VpdRead/Write Stream functions to r/w a stream of data
  71.  * fix: VpdTransferBlock swapped illeagal
  72.  * add: VpdMayWrite
  73.  *
  74.  * Revision 1.13  1998/10/22 10:02:37  gklug
  75.  * fix: SysKonnectFileId typo
  76.  *
  77.  * Revision 1.12  1998/10/20 10:01:01  gklug
  78.  * fix: parameter to SkOsGetTime
  79.  *
  80.  * Revision 1.11  1998/10/15 12:51:48  malthoff
  81.  * Remove unrequired parameter p in vpd_setup_para().
  82.  *
  83.  * Revision 1.10  1998/10/08 14:52:43  malthoff
  84.  * Remove CvsId by SysKonnectFileId.
  85.  *
  86.  * Revision 1.9  1998/09/16 07:33:52  malthoff
  87.  * remove memcmp() by SK_MEMCMP and
  88.  * memcpy() by SK_MEMCPY() to be
  89.  * independant from the 'C' Standard Library.
  90.  *
  91.  * Revision 1.8  1998/08/19 12:52:35  malthoff
  92.  * compiler fix: use SK_VPD_KEY instead of S_VPD.
  93.  *
  94.  * Revision 1.7  1998/08/19 08:14:01  gklug
  95.  * fix: remove struct keyword as much as possible from the c-code (see CCC)
  96.  *
  97.  * Revision 1.6  1998/08/18 13:03:58  gklug
  98.  * SkOsGetTime now returns SK_U64
  99.  *
  100.  * Revision 1.5  1998/08/18 08:17:29  malthoff
  101.  * Ensure we issue a VPD read in vpd_read_dword().
  102.  * Discard all VPD keywords other than Vx or Yx, where
  103.  * x is '0..9' or 'A..Z'.
  104.  *
  105.  * Revision 1.4  1998/07/03 14:52:19  malthoff
  106.  * Add category SK_DBGCAT_FATAL to some debug macros.
  107.  * bug fix: correct the keyword name check in vpd_write().
  108.  *
  109.  * Revision 1.3  1998/06/26 11:16:53  malthoff
  110.  * Correct the modified File Identifier.
  111.  *
  112.  * Revision 1.2  1998/06/26 11:13:43  malthoff
  113.  * Modify the File Identifier.
  114.  *
  115.  * Revision 1.1  1998/06/19 14:11:08  malthoff
  116.  * Created, Tests with AIX were performed successfully
  117.  *
  118.  *
  119.  ******************************************************************************/
  120. /*
  121. Please refer skvpd.txt for infomation how to include this module
  122.  */
  123. static const char SysKonnectFileId[] =
  124. "@(#)$Id: skvpd.c,v 1.26 2000/06/13 08:00:01 mkarl Exp $ (C) SK" ;
  125. #include "h/skdrv1st.h"
  126. #include "h/sktypes.h"
  127. #include "h/skdebug.h"
  128. #include "h/skdrv2nd.h"
  129. /*
  130.  * Static functions
  131.  */
  132. #ifndef SK_KR_PROTO
  133. static SK_VPD_PARA *vpd_find_para(
  134. SK_AC *pAC,
  135. char *key,
  136. SK_VPD_PARA *p) ;
  137. #else /* SK_KR_PROTO */
  138. static SK_VPD_PARA *vpd_find_para() ;
  139. #endif /* SK_KR_PROTO */
  140. /*
  141.  * waits for a completetion of a VPD transfer
  142.  * The VPD transfer must complete within SK_TICKS_PER_SEC/16
  143.  *
  144.  * returns 0: success, transfer completes
  145.  * error exit(9) with a error message
  146.  */
  147. static int VpdWait(
  148. SK_AC *pAC, /* Adapters context */
  149. SK_IOC IoC, /* IO Context */
  150. int event) /* event to wait for (VPD_READ / VPD_write) completion*/
  151. {
  152. SK_U64 start_time ;
  153. SK_U16 state ;
  154. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_CTRL,
  155. ("vpd wait for %sn",event?"Write":"Read")) ;
  156. start_time = SkOsGetTime(pAC) ;
  157. do {
  158. if (SkOsGetTime(pAC) - start_time > SK_TICKS_PER_SEC/16) {
  159. VPD_STOP(pAC,IoC) ;
  160. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,
  161. SK_DBGCAT_FATAL|SK_DBGCAT_ERR,
  162. ("ERROR:vpd wait timeoutn")) ;
  163. return(1) ;
  164. }
  165. VPD_IN16(pAC,IoC,PCI_VPD_ADR_REG,&state) ;
  166. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_CTRL,
  167. ("state = %x, event %xn",state,event)) ;
  168. } while((int)(state & PCI_VPD_FLAG) == event) ;
  169. return(0) ;
  170. }
  171. /*
  172.  * Read the dword at address 'addr' from the VPD EEPROM.
  173.  *
  174.  * Needed Time: MIN 1,3 ms MAX 2,6 ms
  175.  *
  176.  * Note: The DWord is returned in the endianess of the machine the routine
  177.  *       is running on.
  178.  *
  179.  * Returns the data read.
  180.  */
  181. SK_U32 VpdReadDWord(
  182. SK_AC *pAC, /* Adapters context */
  183. SK_IOC IoC, /* IO Context */
  184. int addr) /* VPD address */
  185. {
  186. SK_U32 Rtv ;
  187. /* start VPD read */
  188. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_CTRL,
  189. ("vpd read dword at 0x%xn",addr)) ;
  190. addr &= ~VPD_WRITE ; /* ensure the R/W bit is set to read */
  191. VPD_OUT16(pAC,IoC,PCI_VPD_ADR_REG, (SK_U16) addr) ;
  192. /* ignore return code here */
  193. (void)VpdWait(pAC,IoC,VPD_READ) ;
  194. /* Don't swap here, it's a data stream of bytes */
  195. Rtv = 0 ;
  196. VPD_IN32(pAC,IoC,PCI_VPD_DAT_REG,&Rtv) ;
  197. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_CTRL,
  198. ("vpd read dword data = 0x%xn",Rtv)) ;
  199. return (Rtv) ;
  200. }
  201. /*
  202. Write the dword 'data' at address 'addr' into the VPD EEPROM, and
  203. verify that the data is written.
  204.  Needed Time:
  205. . MIN MAX
  206. . -------------------------------------------------------------------
  207. . write 1.8 ms 3.6 ms
  208. . internal write cyles 0.7 ms 7.0 ms
  209. . -------------------------------------------------------------------
  210. . over all program time   2.5 ms 10.6 ms
  211. . read 1.3 ms 2.6 ms
  212. . -------------------------------------------------------------------
  213. . over all  3.8 ms 13.2 ms
  214. .
  215.  Returns 0: success
  216. 1: error, I2C transfer does not terminate
  217. 2: error, data verify error
  218.  */
  219. #if 0 /* Unused at the moment */
  220. static int VpdWriteDWord(
  221. SK_AC *pAC, /* pAC pointer */
  222. SK_IOC IoC, /* IO Context */
  223. int addr, /* VPD address */
  224. SK_U32 data) /* VPD data to write */
  225. {
  226. /* start VPD write */
  227. /* Don't swap here, it's a data stream of bytes */
  228. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_CTRL,
  229. ("vpd write dword at addr 0x%x, data = 0x%xn",addr,data)) ;
  230. VPD_OUT32(pAC,IoC,PCI_VPD_DAT_REG, (SK_U32)data) ;
  231. /* But do it here */
  232. addr |= VPD_WRITE ;
  233. VPD_OUT16(pAC,IoC,PCI_VPD_ADR_REG, (SK_U16)(addr | VPD_WRITE)) ;
  234. /* this may take up to 10,6 ms */
  235. if (VpdWait(pAC,IoC,VPD_WRITE)) {
  236. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
  237. ("Write Timed Outn")) ;
  238. return(1) ;
  239. } ;
  240. /* verify data */
  241. if (VpdReadDWord(pAC,IoC,addr) != data) {
  242. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR|SK_DBGCAT_FATAL,
  243. ("Data Verify Errorn")) ;
  244. return(2) ;
  245. }
  246. return(0) ;
  247. }
  248. #endif
  249. /*
  250.  * Read one Stream of 'len' bytes of VPD data, starting at 'addr' from
  251.  * or to the I2C EEPROM.
  252.  *
  253.  * Returns number of bytes read / written.
  254.  */
  255. static int VpdWriteStream(
  256. SK_AC *pAC, /* Adapters context */
  257. SK_IOC IoC, /* IO Context */
  258. char *buf, /* data buffer */
  259. int Addr, /* VPD start address */
  260. int Len) /* number of bytes to read / to write */
  261. {
  262. int i ;
  263. int j ;
  264. SK_U16 AdrReg ;
  265. int Rtv ;
  266. SK_U8 * pComp; /* Compare pointer */
  267. SK_U8 Data ; /* Input Data for Compare */
  268. /* Init Compare Pointer */
  269. pComp = (SK_U8 *) buf;
  270. for (i=0; i < Len; i ++, buf++) {
  271. if ((i%sizeof(SK_U32)) == 0) {
  272. /*
  273.  * At the begin of each cycle read the Data Reg
  274.  * So it is initialized even if only a few bytes
  275.  * are written.
  276.  */
  277. AdrReg = (SK_U16) Addr ;
  278. AdrReg &= ~VPD_WRITE ; /* READ operation */
  279. VPD_OUT16(pAC,IoC,PCI_VPD_ADR_REG, AdrReg) ;
  280. /* ignore return code here */
  281. Rtv = VpdWait(pAC,IoC,VPD_READ) ;
  282. if (Rtv != 0) {
  283. return(i) ;
  284. }
  285. }
  286. /* Write current Byte */
  287. VPD_OUT8(pAC,IoC,PCI_VPD_DAT_REG+(i%sizeof(SK_U32)),
  288. *(SK_U8*)buf) ;
  289. if (((i%sizeof(SK_U32)) == 3) || (i == (Len - 1))) {
  290. /* New Address needs to be written to VPD_ADDR reg */
  291. AdrReg = (SK_U16) Addr ;
  292. Addr += sizeof(SK_U32);
  293. AdrReg |= VPD_WRITE ; /* WRITE operation */
  294. VPD_OUT16(pAC,IoC,PCI_VPD_ADR_REG, AdrReg) ;
  295. /* Wait for termination */
  296. Rtv = VpdWait(pAC,IoC,VPD_WRITE) ;
  297. if (Rtv != 0) {
  298. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
  299. ("Write Timed Outn")) ;
  300. return(i - (i%sizeof(SK_U32))) ;
  301. }
  302. /*
  303.  * Now re-read to verify
  304.  */
  305. AdrReg &= ~VPD_WRITE ; /* READ operation */
  306. VPD_OUT16(pAC,IoC,PCI_VPD_ADR_REG, AdrReg) ;
  307. /* Wait for termination */
  308. Rtv = VpdWait(pAC,IoC,VPD_READ) ;
  309. if (Rtv != 0) {
  310. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
  311. ("Verify Timed Outn")) ;
  312. return(i - (i%sizeof(SK_U32))) ;
  313. }
  314. for (j = 0; j <= (int) (i%sizeof(SK_U32));
  315. j ++, pComp ++ ) {
  316. VPD_IN8(pAC,IoC,PCI_VPD_DAT_REG+j, &Data) ;
  317. if (Data != *pComp) {
  318. /* Verify Error */
  319. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,
  320. SK_DBGCAT_ERR,
  321. ("WriteStream Verify Errorn"));
  322. return(i - (i%sizeof(SK_U32)) + j);
  323. }
  324. }
  325. }
  326. }
  327. return(Len);
  328. }
  329. /*
  330.  * Read one Stream of 'len' bytes of VPD data, starting at 'addr' from
  331.  * or to the I2C EEPROM.
  332.  *
  333.  * Returns number of bytes read / written.
  334.  */
  335. static int VpdReadStream(
  336. SK_AC *pAC, /* Adapters context */
  337. SK_IOC IoC, /* IO Context */
  338. char *buf, /* data buffer */
  339. int Addr, /* VPD start address */
  340. int Len) /* number of bytes to read / to write */
  341. {
  342. int i ;
  343. SK_U16 AdrReg ;
  344. int Rtv ;
  345. for (i=0; i < Len; i ++, buf++) {
  346. if ((i%sizeof(SK_U32)) == 0) {
  347. /* New Address needs to be written to VPD_ADDR reg */
  348. AdrReg = (SK_U16) Addr ;
  349. Addr += sizeof(SK_U32);
  350. AdrReg &= ~VPD_WRITE ; /* READ operation */
  351. VPD_OUT16(pAC,IoC,PCI_VPD_ADR_REG, AdrReg) ;
  352. /* ignore return code here */
  353. Rtv = VpdWait(pAC,IoC,VPD_READ) ;
  354. if (Rtv != 0) {
  355. return(i) ;
  356. }
  357. }
  358. VPD_IN8(pAC,IoC,PCI_VPD_DAT_REG+(i%sizeof(SK_U32)),
  359. (SK_U8 *)buf) ;
  360. }
  361. return(Len) ;
  362. }
  363. /*
  364.  * Read ore wirtes 'len' bytes of VPD data, starting at 'addr' from
  365.  * or to the I2C EEPROM.
  366.  *
  367.  * Returns number of bytes read / written.
  368.  */
  369. static int VpdTransferBlock(
  370. SK_AC *pAC, /* Adapters context */
  371. SK_IOC IoC, /* IO Context */
  372. char *buf, /* data buffer */
  373. int addr, /* VPD start address */
  374. int len, /* number of bytes to read / to write */
  375. int dir) /* transfer direction may be VPD_READ or VPD_WRITE */
  376. {
  377. int Rtv ; /* Return value */
  378. int vpd_rom_size ;
  379. SK_U32 our_reg2 ;
  380. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_CTRL,
  381. ("vpd %s block, addr = 0x%x, len = %dn",
  382. dir?"write":"read",addr,len)) ;
  383. if (len == 0)
  384. return (0) ;
  385. VPD_IN32(pAC,IoC,PCI_OUR_REG_2,&our_reg2) ;
  386. vpd_rom_size = 256 << ((our_reg2 & PCI_VPD_ROM_SZ) >> 14);
  387. if (addr > vpd_rom_size - 4) {
  388. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR|SK_DBGCAT_FATAL,
  389. ("Address error: 0x%x, exp. < 0x%xn",
  390. addr, vpd_rom_size - 4)) ;
  391. return (0) ;
  392. }
  393. if (addr + len > vpd_rom_size) {
  394. len = vpd_rom_size - addr ;
  395. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
  396. ("Warning: len was cut to %dn",len)) ;
  397. }
  398. if (dir == VPD_READ) {
  399. Rtv = VpdReadStream(pAC, IoC, buf, addr, len);
  400. } else {
  401. Rtv = VpdWriteStream(pAC, IoC, buf, addr, len);
  402. }
  403. return (Rtv) ;
  404. }
  405. #ifdef SKDIAG
  406. /*
  407.  * Read 'len' bytes of VPD data, starting at 'addr'.
  408.  *
  409.  * Returns number of bytes read.
  410.  */
  411. int VpdReadBlock(
  412. SK_AC *pAC, /* pAC pointer */
  413. SK_IOC IoC, /* IO Context */
  414. char *buf, /* buffer were the data should be stored */
  415. int addr, /* start reading at the VPD address */
  416. int len) /* number of bytes to read */
  417. {
  418. return (VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_READ)) ;
  419. }
  420. /*
  421.  * Write 'len' bytes of *but to the VPD EEPROM, starting at 'addr'.
  422.  *
  423.  * Returns number of bytes writes.
  424.  */
  425. int VpdWriteBlock(
  426. SK_AC *pAC, /* pAC pointer */
  427. SK_IOC IoC, /* IO Context */
  428. char *buf, /* buffer, holds the data to write */
  429. int addr, /* start writing at the VPD address */
  430. int len) /* number of bytes to write */
  431. {
  432. return (VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_WRITE)) ;
  433. }
  434. #endif /* SKDIAG */
  435. /*
  436.  * (re)initialize the VPD buffer
  437.  *
  438.  * Reads the VPD data from the EEPROM into the VPD buffer.
  439.  * Get the remaining read only and read / write space.
  440.  *
  441.  * return 0: success
  442.  * 1: fatal VPD error
  443.  */
  444. static int VpdInit(
  445. SK_AC *pAC, /* Adapters context */
  446. SK_IOC IoC) /* IO Context */
  447. {
  448. SK_VPD_PARA *r, rp ; /* RW or RV */
  449. int i ;
  450. unsigned char x ;
  451. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_INIT,("VpdInit .. ")) ;
  452. /* read the VPD data into the VPD buffer */
  453. if (VpdTransferBlock(pAC,IoC,pAC->vpd.vpd_buf,0,VPD_SIZE,VPD_READ)
  454. != VPD_SIZE) {
  455. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
  456. ("Block Read Errorn")) ;
  457. return(1) ;
  458. }
  459. /* find the end tag of the RO area */
  460. if (!(r = vpd_find_para(pAC,VPD_RV,&rp))) {
  461. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
  462. ("Encoding Error: RV Tag not foundn")) ;
  463. return (1) ;
  464. }
  465. if (r->p_val + r->p_len > pAC->vpd.vpd_buf + VPD_SIZE/2) {
  466. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
  467. ("Encoding Error: Invalid VPD struct sizen")) ;
  468. return (1) ;
  469. }
  470. pAC->vpd.v.vpd_free_ro = r->p_len - 1 ;
  471. /* test the checksum */
  472. for (i = 0, x = 0; (unsigned)i<=(unsigned)VPD_SIZE/2 - r->p_len; i++) {
  473. x += pAC->vpd.vpd_buf[i] ;
  474. }
  475. if (x != 0) {
  476. /* checksum error */
  477. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
  478. ("VPD Checksum Errorn")) ;
  479. return (1) ;
  480. }
  481. /* find and check the end tag of the RW area */
  482. if (!(r = vpd_find_para(pAC,VPD_RW,&rp))) {
  483. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
  484. ("Encoding Error: RV Tag not foundn")) ;
  485. return (1) ;
  486. }
  487. if (r->p_val < pAC->vpd.vpd_buf + VPD_SIZE/2) {
  488. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
  489. ("Encoding Error: Invalid VPD struct sizen")) ;
  490. return (1) ;
  491. }
  492. pAC->vpd.v.vpd_free_rw = r->p_len ;
  493. /* everything seems to be ok */
  494. pAC->vpd.v.vpd_status |= VPD_VALID ;
  495. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_INIT,
  496. ("done. Free RO = %d, Free RW = %dn",
  497. pAC->vpd.v.vpd_free_ro, pAC->vpd.v.vpd_free_rw)) ;
  498. return(0) ;
  499. }
  500. /*
  501.  * find the Keyword 'key' in the VPD buffer and fills the
  502.  * parameter sturct 'p' with it's values
  503.  *
  504.  * returns *p success
  505.  * 0: parameter was not found or VPD encoding error
  506.  */
  507. static SK_VPD_PARA *vpd_find_para(
  508. SK_AC *pAC, /* common data base */
  509. char *key, /* keyword to find (e.g. "MN") */
  510. SK_VPD_PARA *p) /* parameter description struct */
  511. {
  512. char *v ; /* points to vpd buffer */
  513. int max ; /* Maximum Number of Iterations */
  514. v = pAC->vpd.vpd_buf ;
  515. max = 128 ;
  516. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_CTRL,
  517. ("vpd find para %s .. ",key)) ;
  518. /* check mandatory resource type ID string (Product Name) */
  519. if (*v != (char) RES_ID) {
  520. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
  521. ("Error: 0x%x missingn",RES_ID)) ;
  522. return (0) ;
  523. }
  524. if (strcmp(key,VPD_NAME) == 0) {
  525. p->p_len = VPD_GET_RES_LEN(v) ;
  526. p->p_val = VPD_GET_VAL(v) ;
  527. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_CTRL,
  528. ("found, len = %dn",p->p_len)) ;
  529. return(p) ;
  530. }
  531. v += 3 + VPD_GET_RES_LEN(v) + 3 ;
  532. for ( ; ; ) {
  533. if (SK_MEMCMP(key,v,2) == 0) {
  534. p->p_len = VPD_GET_VPD_LEN(v) ;
  535. p->p_val = VPD_GET_VAL(v) ;
  536. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_CTRL,
  537. ("found, len = %dn",p->p_len)) ;
  538. return (p) ;
  539. }
  540. /* exit when reaching the "RW" Tag or the maximum of itera. */
  541. max-- ;
  542. if (SK_MEMCMP(VPD_RW,v,2) == 0 || max == 0) {
  543. break ;
  544. }
  545. if (SK_MEMCMP(VPD_RV,v,2) == 0) {
  546. v += 3 + VPD_GET_VPD_LEN(v) + 3 ; /* skip VPD-W */
  547. } else {
  548. v += 3 + VPD_GET_VPD_LEN(v) ;
  549. }
  550. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_CTRL,
  551. ("scanning '%c%c' len = %dn",v[0],v[1],v[2])) ;
  552. }
  553. #ifdef DEBUG
  554. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_CTRL,("not foundn")) ;
  555. if (max == 0) {
  556. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
  557. ("Key/Len Encoding errorn")) ;
  558. }
  559. #endif
  560. return (0) ;
  561. }
  562. /*
  563.  * Move 'n' bytes. Begin with the last byte if 'n' is > 0,
  564.  * Start with the last byte if n is < 0.
  565.  *
  566.  * returns nothing
  567.  */
  568. static void vpd_move_para(
  569. char *start, /* start of memory block */
  570. char *end, /* end of memory block to move */
  571. int n) /* number of bytes the memory block has to be moved */
  572. {
  573. char *p ;
  574. int i ; /* number of byte copied */
  575. if (n == 0)
  576. return ;
  577. i = (int) (end - start + 1) ;
  578. if (n < 0) {
  579. p = start + n ;
  580. while (i != 0) {
  581. *p++ = *start++ ;
  582. i-- ;
  583. }
  584. } else {
  585. p = end + n ;
  586. while (i != 0) {
  587. *p-- = *end-- ;
  588. i-- ;
  589. }
  590. }
  591. }
  592. /*
  593.  * setup the VPD keyword 'key' at 'ip'.
  594.  *
  595.  * returns nothing
  596.  */
  597. static void vpd_insert_key(
  598. char *key, /* keyword to insert */
  599. char *buf, /* buffer with the keyword value */
  600. int len, /* length of the value string */
  601. char *ip) /* inseration point */
  602. {
  603. SK_VPD_KEY *p ;
  604. p = (SK_VPD_KEY *) ip ;
  605. p->p_key[0] = key[0] ;
  606. p->p_key[1] = key[1] ;
  607. p->p_len = (unsigned char) len ;
  608. SK_MEMCPY(&p->p_val,buf,len) ;
  609. }
  610. /*
  611.  * Setup the VPD end tag "RV" / "RW".
  612.  * Also correct the remaining space variables vpd_free_ro / vpd_free_rw.
  613.  *
  614.  * returns 0: success
  615.  * 1: encoding error
  616.  */
  617. static int vpd_mod_endtag(
  618. SK_AC *pAC, /* common data base */
  619. char *etp) /* end pointer input position */
  620. {
  621. SK_VPD_KEY *p ;
  622. unsigned char x ;
  623. int i ;
  624. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_CTRL,
  625. ("vpd modify endtag at 0x%x = '%c%c'n",etp,etp[0],etp[1])) ;
  626. p = (SK_VPD_KEY *) etp ;
  627. if (p->p_key[0] != 'R' || (p->p_key[1] != 'V' && p->p_key[1] != 'W')) {
  628. /* something wrong here, encoding error */
  629. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
  630. ("Encoding Error: invalid end tagn")) ;
  631. return(1) ;
  632. }
  633. if (etp > pAC->vpd.vpd_buf + VPD_SIZE/2) {
  634. /* create "RW" tag */
  635. p->p_len = (unsigned char)(pAC->vpd.vpd_buf+VPD_SIZE-etp-3-1) ;
  636. pAC->vpd.v.vpd_free_rw = (int) p->p_len ;
  637. i = pAC->vpd.v.vpd_free_rw ;
  638. etp += 3 ;
  639. } else {
  640. /* create "RV" tag */
  641. p->p_len = (unsigned char)(pAC->vpd.vpd_buf+VPD_SIZE/2-etp-3) ;
  642. pAC->vpd.v.vpd_free_ro = (int) p->p_len - 1 ;
  643. /* setup checksum */
  644. for (i = 0, x = 0; i < VPD_SIZE/2 - p->p_len; i++) {
  645. x += pAC->vpd.vpd_buf[i] ;
  646. }
  647. p->p_val = (char) 0 - x ;
  648. i = pAC->vpd.v.vpd_free_ro ;
  649. etp += 4 ;
  650. }
  651. while (i) {
  652. *etp++ = 0x00 ;
  653. i-- ;
  654. }
  655. return (0) ;
  656. }
  657. /*
  658.  * Insert a VPD keyword into the VPD buffer.
  659.  *
  660.  * The keyword 'key' is inserted at the position 'ip' in the
  661.  * VPD buffer.
  662.  * The keywords behind the input position will
  663.  * be moved. The VPD end tag "RV" or "RW" is generated again.
  664.  *
  665.  * returns 0: success
  666.  * 2: value string was cut
  667.  * 4: VPD full, keyword was not written
  668.  * 6: fatal VPD error
  669.  *
  670.  */
  671. int VpdSetupPara(
  672. SK_AC *pAC, /* common data base */
  673. char *key, /* keyword to insert */
  674. char *buf, /* buffer with the keyword value */
  675. int len, /* length of the keyword value */
  676. int type, /* VPD_RO_KEY or VPD_RW_KEY */
  677. int op) /* operation to do: ADD_KEY or OWR_KEY */
  678. {
  679. SK_VPD_PARA vp ;
  680. char *etp ; /* end tag position */
  681. int free ; /* remaining space in selected area */
  682. char *ip ; /* input position inside the VPD buffer */
  683. int rtv ; /* return code */
  684. int head ; /* additional haeder bytes to move */
  685. int found ; /* additinoal bytes if the keyword was found */
  686. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_CTRL,
  687. ("vpd setup para key = %s, val = %sn",key,buf)) ;
  688. rtv = 0 ;
  689. ip = 0 ;
  690. if (type == VPD_RW_KEY) {
  691. /* end tag is "RW" */
  692. free = pAC->vpd.v.vpd_free_rw ;
  693. etp = pAC->vpd.vpd_buf + (VPD_SIZE - free - 1 - 3) ;
  694. } else {
  695. /* end tag is "RV" */
  696. free = pAC->vpd.v.vpd_free_ro ;
  697. etp = pAC->vpd.vpd_buf + (VPD_SIZE/2 - free - 4) ;
  698. }
  699. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_CTRL,
  700. ("Free RO = %d, Free RW = %dn",
  701. pAC->vpd.v.vpd_free_ro, pAC->vpd.v.vpd_free_rw)) ;
  702. head = 0 ;
  703. found = 0 ;
  704. if (op == OWR_KEY) {
  705. if (vpd_find_para(pAC,key,&vp)) {
  706. found = 3 ;
  707. ip = vp.p_val - 3 ;
  708. free += vp.p_len + 3 ;
  709. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_CTRL,
  710. ("Overwrite Keyn")) ;
  711. } else {
  712. op = ADD_KEY ;
  713. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_CTRL,
  714. ("Add Keyn")) ;
  715. }
  716. }
  717. if (op == ADD_KEY) {
  718. ip = etp ;
  719. vp.p_len = 0 ;
  720. head = 3 ;
  721. }
  722. if (len + 3 > free) {
  723. if (free < 7) {
  724. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
  725. ("VPD Buffer Overflow, keyword not writtenn"));
  726. return (4) ;
  727. }
  728. /* cut it again */
  729. len = free - 3 ;
  730. rtv = 2 ;
  731. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
  732. ("VPD Buffer Full, Keyword was cutn")) ;
  733. }
  734. vpd_move_para(ip + vp.p_len + found, etp+2, len-vp.p_len+head) ;
  735. vpd_insert_key(key, buf, len, ip) ;
  736. if (vpd_mod_endtag(pAC, etp + len - vp.p_len + head)) {
  737. pAC->vpd.v.vpd_status &= ~VPD_VALID ;
  738. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
  739. ("VPD Encoding Errorn")) ;
  740. return(6) ;
  741. }
  742. return (rtv) ;
  743. }
  744. /*
  745.  * Read the contents of the VPD EEPROM and copy it to the
  746.  * VPD buffer if not already done.
  747.  *
  748.  * return: A pointer to the vpd_status structure. The structure contain
  749.  * this fields.
  750.  */
  751. SK_VPD_STATUS *VpdStat(
  752. SK_AC *pAC, /* Adapters context */
  753. SK_IOC IoC) /* IO Context */
  754. {
  755. if (!(pAC->vpd.v.vpd_status & VPD_VALID)) {
  756. (void)VpdInit(pAC,IoC) ;
  757. }
  758. return(&pAC->vpd.v) ;
  759. }
  760. /*
  761.  * Read the contents of the VPD EEPROM and copy it to the VPD
  762.  * buffer if not already done.
  763.  * Scan the VPD buffer for VPD keywords and create the VPD
  764.  * keyword list by copying the keywords to 'buf', all after
  765.  * each other and terminated with a ''.
  766.  *
  767.  * Exceptions: o The Resource Type ID String (product name) is called "Name"
  768.  * o The VPD end tags 'RV' and 'RW' are not listed
  769.  *
  770.  * The number of copied keywords is counted in 'elements'.
  771.  *
  772.  * returns 0: success
  773.  * 2: buffer overfull, one or more keywords are missing
  774.  * 6: fatal VPD error
  775.  *
  776.  * example values after returning:
  777.  *
  778.  * buf = "NamePNECMNSNCPVFVLYA"
  779.  * *len = 30
  780.  * *elements =  9
  781.  */
  782. int VpdKeys(
  783. SK_AC *pAC, /* common data base */
  784. SK_IOC IoC, /* IO Context */
  785. char *buf, /* buffer where to copy the keywords */
  786. int *len, /* buffer length */
  787. int *elements) /* number of keywords returned */
  788. {
  789. char *v ;
  790. int n ;
  791. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_RX,("list vpd keys .. ")) ;
  792. *elements = 0 ;
  793. if (!(pAC->vpd.v.vpd_status & VPD_VALID)) {
  794. if (VpdInit(pAC,IoC) != 0 ) {
  795. *len = 0 ;
  796. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
  797. ("VPD Init Error, terminatedn")) ;
  798. return(6) ;
  799. }
  800. }
  801. if ((signed)strlen(VPD_NAME) + 1 <= *len) {
  802. v = pAC->vpd.vpd_buf ;
  803. strcpy(buf,VPD_NAME) ;
  804. n = strlen(VPD_NAME) + 1 ;
  805. buf += n ;
  806. *elements = 1 ;
  807. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_RX,
  808. ("'%c%c' ",v[0],v[1])) ;
  809. } else {
  810. *len = 0 ;
  811. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
  812. ("buffer overflown")) ;
  813. return(2) ;
  814. }
  815. v += 3 + VPD_GET_RES_LEN(v) + 3 ;
  816. for ( ; ; ) {
  817. /* exit when reaching the "RW" Tag */
  818. if (SK_MEMCMP(VPD_RW,v,2) == 0) {
  819. break ;
  820. }
  821. if (SK_MEMCMP(VPD_RV,v,2) == 0) {
  822. v += 3 + VPD_GET_VPD_LEN(v) + 3 ; /* skip VPD-W */
  823. continue ;
  824. }
  825. if (n+3 <= *len) {
  826. SK_MEMCPY(buf,v,2) ;
  827. buf += 2 ;
  828. *buf++ = '' ;
  829. n += 3 ;
  830. v += 3 + VPD_GET_VPD_LEN(v) ;
  831. *elements += 1 ;
  832. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_RX,
  833. ("'%c%c' ",v[0],v[1])) ;
  834. } else {
  835. *len = n ;
  836. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
  837. ("buffer overflown")) ;
  838. return (2) ;
  839. }
  840. }
  841. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_RX,("n")) ;
  842. *len = n ;
  843. return(0) ;
  844. }
  845. /*
  846.  * Read the contents of the VPD EEPROM and copy it to the
  847.  * VPD buffer if not already done. Search for the VPD keyword
  848.  * 'key' and copy its value to 'buf'. Add a terminating ''.
  849.  * If the value does not fit into the buffer cut it after
  850.  * 'len' - 1 bytes.
  851.  *
  852.  * returns 0: success
  853.  * 1: keyword not found
  854.  * 2: value string was cut
  855.  * 3: VPD transfer timeout
  856.  * 6: fatal VPD error
  857.  */
  858. int VpdRead(
  859. SK_AC *pAC, /* common data base */
  860. SK_IOC IoC, /* IO Context */
  861. char *key, /* keyword to read (e.g. "MN") */
  862. char *buf, /* buffer where to copy the keyword value */
  863. int *len) /* buffer length */
  864. {
  865. SK_VPD_PARA *p, vp ;
  866. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_RX,("vpd read %s .. ",key)) ;
  867. if (!(pAC->vpd.v.vpd_status & VPD_VALID)) {
  868. if (VpdInit(pAC,IoC) != 0 ) {
  869. *len = 0 ;
  870. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
  871. ("vpd init errorn")) ;
  872. return(6) ;
  873. }
  874. }
  875. if ((p = vpd_find_para(pAC,key,&vp))) {
  876. if (p->p_len > (*(unsigned *)len)-1) {
  877. p->p_len = *len - 1 ;
  878. }
  879. SK_MEMCPY(buf,p->p_val,p->p_len) ;
  880. buf[p->p_len] = '' ;
  881. *len = p->p_len ;
  882. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_RX,
  883. ("%c%c%c%c.., len = %dn",
  884. buf[0],buf[1],buf[2],buf[3],*len)) ;
  885. } else {
  886. *len = 0 ;
  887. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,("not foundn")) ;
  888. return (1) ;
  889. }
  890. return (0) ;
  891. }
  892. /*
  893.  * Check whether a given key may be written
  894.  *
  895.  * returns
  896.  * SK_TRUE Yes it may be written
  897.  * SK_FALSE No it may be written
  898.  */
  899. SK_BOOL VpdMayWrite(
  900. char *key) /* keyword to write (allowed values "Yx", "Vx") */
  901. {
  902. if ((*key != 'Y' && *key != 'V') ||
  903. key[1] < '0' || key[1] > 'Z' ||
  904. (key[1] > '9' && key[1] < 'A') || strlen(key) != 2) {
  905. return (SK_FALSE) ;
  906. }
  907. return (SK_TRUE) ;
  908. }
  909. /*
  910.  * Read the contents of the VPD EEPROM and copy it to the VPD
  911.  * buffer if not already done. Insert/overwrite the keyword 'key'
  912.  * in the VPD buffer. Cut the keyword value if it does not fit
  913.  * into the VPD read / write area.
  914.  *
  915.  * returns 0: success
  916.  * 2: value string was cut
  917.  * 3: VPD transfer timeout
  918.  * 4: VPD full, keyword was not written
  919.  * 5: keyword cannot be written
  920.  * 6: fatal VPD error
  921.  */
  922. int VpdWrite(
  923. SK_AC *pAC, /* common data base */
  924. SK_IOC IoC, /* IO Context */
  925. char *key, /* keyword to write (allowed values "Yx", "Vx") */
  926. char *buf) /* buffer where the keyword value can be read from */
  927. {
  928. int len ; /* lenght of the keyword to write */
  929. int rtv ; /* return code */
  930. int rtv2 ;
  931. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_TX,
  932. ("vpd write %s = %sn",key,buf)) ;
  933. if ((*key != 'Y' && *key != 'V') ||
  934. key[1] < '0' || key[1] > 'Z' ||
  935. (key[1] > '9' && key[1] < 'A') || strlen(key) != 2) {
  936. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
  937. ("illegal key tag, keyword not writtenn")) ;
  938. return (5) ;
  939. }
  940. if (!(pAC->vpd.v.vpd_status & VPD_VALID)) {
  941. if (VpdInit(pAC,IoC) != 0 ) {
  942. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
  943. ("vpd init errorn")) ;
  944. return(6) ;
  945. }
  946. }
  947. rtv = 0 ;
  948. len = strlen(buf) ;
  949. if (len > VPD_MAX_LEN) {
  950. /* cut it */
  951. len = VPD_MAX_LEN ;
  952. rtv = 2 ;
  953. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
  954. ("keyword to long, cut after %d bytesn",VPD_MAX_LEN)) ;
  955. }
  956. if ((rtv2 = VpdSetupPara(pAC,key,buf,len,VPD_RW_KEY,OWR_KEY)) != 0) {
  957. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
  958. ("vpd write errorn")) ;
  959. return(rtv2) ;
  960. }
  961. return (rtv) ;
  962. }
  963. /*
  964.  * Read the contents of the VPD EEPROM and copy it to the
  965.  * VPD buffer if not already done. Remove the VPD keyword
  966.  * 'key' from the VPD buffer.
  967.  * Only the keywords in the read/write area can be deleted.
  968.  * Keywords in the read only area cannot be deleted.
  969.  *
  970.  * returns 0: success, keyword was removed
  971.  * 1: keyword not found
  972.  * 5: keyword cannot be deleted
  973.  * 6: fatal VPD error
  974.  */
  975. int VpdDelete(
  976. SK_AC *pAC, /* common data base */
  977. SK_IOC IoC, /* IO Context */
  978. char *key) /* keyword to read (e.g. "MN") */
  979. {
  980. SK_VPD_PARA *p, vp ;
  981. char *etp ;
  982. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_TX,("vpd delete key %sn",key)) ;
  983. if (!(pAC->vpd.v.vpd_status & VPD_VALID)) {
  984. if (VpdInit(pAC,IoC) != 0 ) {
  985. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
  986. ("vpd init errorn")) ;
  987. return(6) ;
  988. }
  989. }
  990. if ((p = vpd_find_para(pAC,key,&vp))) {
  991. if (p->p_val < pAC->vpd.vpd_buf + VPD_SIZE/2) {
  992. /* try to delete read only keyword */
  993. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
  994. ("cannot delete RO keywordn")) ;
  995. return (5) ;
  996. }
  997. etp = pAC->vpd.vpd_buf + (VPD_SIZE-pAC->vpd.v.vpd_free_rw-1-3) ;
  998. vpd_move_para(vp.p_val+vp.p_len, etp+2,
  999. - ((int)(vp.p_len + 3))) ;
  1000. if (vpd_mod_endtag(pAC, etp - vp.p_len - 3)) {
  1001. pAC->vpd.v.vpd_status &= ~VPD_VALID ;
  1002. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
  1003. ("vpd encoding errorn")) ;
  1004. return(6) ;
  1005. }
  1006. } else {
  1007. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
  1008. ("keyword not foundn")) ;
  1009. return (1) ;
  1010. }
  1011. return (0) ;
  1012. }
  1013. /*
  1014.  * If the VPD buffer contains valid data write the VPD
  1015.  * read/write area back to the VPD EEPROM.
  1016.  *
  1017.  * returns 0: success
  1018.  * 3: VPD transfer timeout
  1019.  */
  1020. int VpdUpdate(
  1021. SK_AC *pAC, /* Adapters context */
  1022. SK_IOC IoC) /* IO Context */
  1023. {
  1024. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_TX,("vpd update .. ")) ;
  1025. if (pAC->vpd.v.vpd_status & VPD_VALID) {
  1026. if (VpdTransferBlock(pAC,IoC,pAC->vpd.vpd_buf + VPD_SIZE/2,
  1027. VPD_SIZE/2, VPD_SIZE/2, VPD_WRITE) != VPD_SIZE/2) {
  1028. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
  1029. ("transfer timed outn")) ;
  1030. return(3) ;
  1031. }
  1032. }
  1033. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_TX,("donen")) ;
  1034. return (0) ;
  1035. }
  1036. /*
  1037.  * Read the contents of the VPD EEPROM and copy it to the VPD buffer
  1038.  * if not already done. If the keyword "VF" is not present it will be
  1039.  * created and the error log message will be stored to this keyword.
  1040.  * If "VF" is not present the error log message will be stored to the
  1041.  * keyword "VL". "VL" will created or overwritten if "VF" is present.
  1042.  * The VPD read/write area is saved to the VPD EEPROM.
  1043.  *
  1044.  * returns nothing, errors will be ignored.
  1045.  */
  1046. void VpdErrLog(
  1047. SK_AC *pAC, /* common data base */
  1048. SK_IOC IoC, /* IO Context */
  1049. char *msg) /* error log message */
  1050. {
  1051. SK_VPD_PARA *v, vf ; /* VF */
  1052. int len ;
  1053. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_TX,
  1054. ("vpd error log msg %sn",msg)) ;
  1055. if (!(pAC->vpd.v.vpd_status & VPD_VALID)) {
  1056. if (VpdInit(pAC,IoC) != 0 ) {
  1057. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
  1058. ("vpd init errorn")) ;
  1059. return ;
  1060. }
  1061. }
  1062. len = strlen(msg) ;
  1063. if (len > VPD_MAX_LEN) {
  1064. /* cut it */
  1065. len = VPD_MAX_LEN ;
  1066. }
  1067. if ((v = vpd_find_para(pAC,VPD_VF,&vf))) {
  1068. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_TX,("overwrite VLn")) ;
  1069. (void)VpdSetupPara(pAC,VPD_VL,msg,len,VPD_RW_KEY,OWR_KEY) ;
  1070. } else {
  1071. SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_TX,("write VFn")) ;
  1072. (void)VpdSetupPara(pAC,VPD_VF,msg,len,VPD_RW_KEY,ADD_KEY) ;
  1073. }
  1074. (void)VpdUpdate(pAC,IoC) ;
  1075. }