1 /******************************************************************************
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
9 ******************************************************************************/
11 /******************************************************************************
13 * (C)Copyright 1998,1999 SysKonnect,
14 * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
21 * The information in this file is provided "AS IS" without warranty.
23 ******************************************************************************/
25 /******************************************************************************
30 * Revision 1.26 2000/06/13 08:00:01 mkarl
31 * additional cast to avoid compile problems in 64 bit environment
33 * Revision 1.25 1999/11/22 13:39:32 cgoos
34 * Changed license header to GPL.
36 * Revision 1.24 1999/03/11 14:25:49 malthoff
37 * Replace __STDC__ with SK_KR_PROTO.
39 * Revision 1.23 1999/01/11 15:13:11 gklug
42 * Revision 1.22 1998/10/30 06:41:15 gklug
45 * Revision 1.21 1998/10/29 07:15:14 gklug
46 * fix: Write Stream function needs verify.
48 * Revision 1.20 1998/10/28 18:05:08 gklug
49 * chg: no DEBUG in VpdMayWrite
51 * Revision 1.19 1998/10/28 15:56:11 gklug
52 * fix: Return len at end of ReadStream
53 * fix: Write even less than 4 bytes correctly
55 * Revision 1.18 1998/10/28 09:00:47 gklug
56 * fix: unreferenced local vars
58 * Revision 1.17 1998/10/28 08:25:45 gklug
61 * Revision 1.16 1998/10/28 08:17:30 gklug
64 * Revision 1.15 1998/10/28 07:50:32 gklug
67 * Revision 1.14 1998/10/28 07:20:38 gklug
68 * chg: Interface functions to use IoC as parameter as well
69 * fix: VpdRead/WriteDWord now return SK_U32
70 * chg: VPD_IN/OUT names conform to SK_IN/OUT
71 * add: usage of VPD_IN/OUT8 macros
72 * add: VpdRead/Write Stream functions to r/w a stream of data
73 * fix: VpdTransferBlock swapped illeagal
76 * Revision 1.13 1998/10/22 10:02:37 gklug
77 * fix: SysKonnectFileId typo
79 * Revision 1.12 1998/10/20 10:01:01 gklug
80 * fix: parameter to SkOsGetTime
82 * Revision 1.11 1998/10/15 12:51:48 malthoff
83 * Remove unrequired parameter p in vpd_setup_para().
85 * Revision 1.10 1998/10/08 14:52:43 malthoff
86 * Remove CvsId by SysKonnectFileId.
88 * Revision 1.9 1998/09/16 07:33:52 malthoff
89 * remove memcmp() by SK_MEMCMP and
90 * memcpy() by SK_MEMCPY() to be
91 * independent from the 'C' Standard Library.
93 * Revision 1.8 1998/08/19 12:52:35 malthoff
94 * compiler fix: use SK_VPD_KEY instead of S_VPD.
96 * Revision 1.7 1998/08/19 08:14:01 gklug
97 * fix: remove struct keyword as much as possible from the c-code (see CCC)
99 * Revision 1.6 1998/08/18 13:03:58 gklug
100 * SkOsGetTime now returns SK_U64
102 * Revision 1.5 1998/08/18 08:17:29 malthoff
103 * Ensure we issue a VPD read in vpd_read_dword().
104 * Discard all VPD keywords other than Vx or Yx, where
105 * x is '0..9' or 'A..Z'.
107 * Revision 1.4 1998/07/03 14:52:19 malthoff
108 * Add category SK_DBGCAT_FATAL to some debug macros.
109 * bug fix: correct the keyword name check in vpd_write().
111 * Revision 1.3 1998/06/26 11:16:53 malthoff
112 * Correct the modified File Identifier.
114 * Revision 1.2 1998/06/26 11:13:43 malthoff
115 * Modify the File Identifier.
117 * Revision 1.1 1998/06/19 14:11:08 malthoff
118 * Created, Tests with AIX were performed successfully
121 ******************************************************************************/
124 Please refer skvpd.txt for information how to include this module
126 static const char SysKonnectFileId[] =
127 "@(#)$Id: skvpd.c,v 1.26 2000/06/13 08:00:01 mkarl Exp $ (C) SK" ;
129 #include "h/skdrv1st.h"
130 #include "h/sktypes.h"
131 #include "h/skdebug.h"
132 #include "h/skdrv2nd.h"
138 static SK_VPD_PARA *vpd_find_para(
142 #else /* SK_KR_PROTO */
143 static SK_VPD_PARA *vpd_find_para() ;
144 #endif /* SK_KR_PROTO */
147 * waits for a completetion of a VPD transfer
148 * The VPD transfer must complete within SK_TICKS_PER_SEC/16
150 * returns 0: success, transfer completes
151 * error exit(9) with a error message
154 SK_AC *pAC, /* Adapters context */
155 SK_IOC IoC, /* IO Context */
156 int event) /* event to wait for (VPD_READ / VPD_write) completion*/
161 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_CTRL,
162 ("vpd wait for %s\n",event?"Write":"Read")) ;
163 start_time = SkOsGetTime(pAC) ;
165 if (SkOsGetTime(pAC) - start_time > SK_TICKS_PER_SEC/16) {
167 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,
168 SK_DBGCAT_FATAL|SK_DBGCAT_ERR,
169 ("ERROR:vpd wait timeout\n")) ;
172 VPD_IN16(pAC,IoC,PCI_VPD_ADR_REG,&state) ;
173 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_CTRL,
174 ("state = %x, event %x\n",state,event)) ;
175 } while((int)(state & PCI_VPD_FLAG) == event) ;
182 * Read the dword at address 'addr' from the VPD EEPROM.
184 * Needed Time: MIN 1,3 ms MAX 2,6 ms
186 * Note: The DWord is returned in the endianess of the machine the routine
189 * Returns the data read.
192 SK_AC *pAC, /* Adapters context */
193 SK_IOC IoC, /* IO Context */
194 int addr) /* VPD address */
199 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_CTRL,
200 ("vpd read dword at 0x%x\n",addr)) ;
201 addr &= ~VPD_WRITE ; /* ensure the R/W bit is set to read */
203 VPD_OUT16(pAC,IoC,PCI_VPD_ADR_REG, (SK_U16) addr) ;
205 /* ignore return code here */
206 (void)VpdWait(pAC,IoC,VPD_READ) ;
208 /* Don't swap here, it's a data stream of bytes */
211 VPD_IN32(pAC,IoC,PCI_VPD_DAT_REG,&Rtv) ;
212 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_CTRL,
213 ("vpd read dword data = 0x%x\n",Rtv)) ;
218 Write the dword 'data' at address 'addr' into the VPD EEPROM, and
219 verify that the data is written.
224 . -------------------------------------------------------------------
225 . write 1.8 ms 3.6 ms
226 . internal write cyles 0.7 ms 7.0 ms
227 . -------------------------------------------------------------------
228 . over all program time 2.5 ms 10.6 ms
230 . -------------------------------------------------------------------
231 . over all 3.8 ms 13.2 ms
236 1: error, I2C transfer does not terminate
237 2: error, data verify error
240 #if 0 /* Unused at the moment */
241 static int VpdWriteDWord(
242 SK_AC *pAC, /* pAC pointer */
243 SK_IOC IoC, /* IO Context */
244 int addr, /* VPD address */
245 SK_U32 data) /* VPD data to write */
247 /* start VPD write */
248 /* Don't swap here, it's a data stream of bytes */
249 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_CTRL,
250 ("vpd write dword at addr 0x%x, data = 0x%x\n",addr,data)) ;
251 VPD_OUT32(pAC,IoC,PCI_VPD_DAT_REG, (SK_U32)data) ;
255 VPD_OUT16(pAC,IoC,PCI_VPD_ADR_REG, (SK_U16)(addr | VPD_WRITE)) ;
257 /* this may take up to 10,6 ms */
258 if (VpdWait(pAC,IoC,VPD_WRITE)) {
259 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
260 ("Write Timed Out\n")) ;
265 if (VpdReadDWord(pAC,IoC,addr) != data) {
266 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR|SK_DBGCAT_FATAL,
267 ("Data Verify Error\n")) ;
275 * Read one Stream of 'len' bytes of VPD data, starting at 'addr' from
276 * or to the I2C EEPROM.
278 * Returns number of bytes read / written.
280 static int VpdWriteStream(
281 SK_AC *pAC, /* Adapters context */
282 SK_IOC IoC, /* IO Context */
283 char *buf, /* data buffer */
284 int Addr, /* VPD start address */
285 int Len) /* number of bytes to read / to write */
291 SK_U8 * pComp; /* Compare pointer */
292 SK_U8 Data ; /* Input Data for Compare */
294 /* Init Compare Pointer */
295 pComp = (SK_U8 *) buf;
297 for (i=0; i < Len; i ++, buf++) {
298 if ((i%sizeof(SK_U32)) == 0) {
300 * At the begin of each cycle read the Data Reg
301 * So it is initialized even if only a few bytes
304 AdrReg = (SK_U16) Addr ;
305 AdrReg &= ~VPD_WRITE ; /* READ operation */
307 VPD_OUT16(pAC,IoC,PCI_VPD_ADR_REG, AdrReg) ;
309 /* ignore return code here */
310 Rtv = VpdWait(pAC,IoC,VPD_READ) ;
316 /* Write current Byte */
317 VPD_OUT8(pAC,IoC,PCI_VPD_DAT_REG+(i%sizeof(SK_U32)),
320 if (((i%sizeof(SK_U32)) == 3) || (i == (Len - 1))) {
321 /* New Address needs to be written to VPD_ADDR reg */
322 AdrReg = (SK_U16) Addr ;
323 Addr += sizeof(SK_U32);
324 AdrReg |= VPD_WRITE ; /* WRITE operation */
326 VPD_OUT16(pAC,IoC,PCI_VPD_ADR_REG, AdrReg) ;
328 /* Wait for termination */
329 Rtv = VpdWait(pAC,IoC,VPD_WRITE) ;
331 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
332 ("Write Timed Out\n")) ;
333 return(i - (i%sizeof(SK_U32))) ;
337 * Now re-read to verify
339 AdrReg &= ~VPD_WRITE ; /* READ operation */
341 VPD_OUT16(pAC,IoC,PCI_VPD_ADR_REG, AdrReg) ;
343 /* Wait for termination */
344 Rtv = VpdWait(pAC,IoC,VPD_READ) ;
346 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
347 ("Verify Timed Out\n")) ;
348 return(i - (i%sizeof(SK_U32))) ;
351 for (j = 0; j <= (int) (i%sizeof(SK_U32));
353 VPD_IN8(pAC,IoC,PCI_VPD_DAT_REG+j, &Data) ;
354 if (Data != *pComp) {
356 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,
358 ("WriteStream Verify Error\n"));
359 return(i - (i%sizeof(SK_U32)) + j);
371 * Read one Stream of 'len' bytes of VPD data, starting at 'addr' from
372 * or to the I2C EEPROM.
374 * Returns number of bytes read / written.
376 static int VpdReadStream(
377 SK_AC *pAC, /* Adapters context */
378 SK_IOC IoC, /* IO Context */
379 char *buf, /* data buffer */
380 int Addr, /* VPD start address */
381 int Len) /* number of bytes to read / to write */
387 for (i=0; i < Len; i ++, buf++) {
388 if ((i%sizeof(SK_U32)) == 0) {
389 /* New Address needs to be written to VPD_ADDR reg */
390 AdrReg = (SK_U16) Addr ;
391 Addr += sizeof(SK_U32);
392 AdrReg &= ~VPD_WRITE ; /* READ operation */
394 VPD_OUT16(pAC,IoC,PCI_VPD_ADR_REG, AdrReg) ;
396 /* ignore return code here */
397 Rtv = VpdWait(pAC,IoC,VPD_READ) ;
403 VPD_IN8(pAC,IoC,PCI_VPD_DAT_REG+(i%sizeof(SK_U32)),
411 * Read ore wirtes 'len' bytes of VPD data, starting at 'addr' from
412 * or to the I2C EEPROM.
414 * Returns number of bytes read / written.
416 static int VpdTransferBlock(
417 SK_AC *pAC, /* Adapters context */
418 SK_IOC IoC, /* IO Context */
419 char *buf, /* data buffer */
420 int addr, /* VPD start address */
421 int len, /* number of bytes to read / to write */
422 int dir) /* transfer direction may be VPD_READ or VPD_WRITE */
424 int Rtv ; /* Return value */
428 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_CTRL,
429 ("vpd %s block, addr = 0x%x, len = %d\n",
430 dir?"write":"read",addr,len)) ;
435 VPD_IN32(pAC,IoC,PCI_OUR_REG_2,&our_reg2) ;
436 vpd_rom_size = 256 << ((our_reg2 & PCI_VPD_ROM_SZ) >> 14);
437 if (addr > vpd_rom_size - 4) {
438 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR|SK_DBGCAT_FATAL,
439 ("Address error: 0x%x, exp. < 0x%x\n",
440 addr, vpd_rom_size - 4)) ;
443 if (addr + len > vpd_rom_size) {
444 len = vpd_rom_size - addr ;
445 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
446 ("Warning: len was cut to %d\n",len)) ;
449 if (dir == VPD_READ) {
450 Rtv = VpdReadStream(pAC, IoC, buf, addr, len);
452 Rtv = VpdWriteStream(pAC, IoC, buf, addr, len);
461 * Read 'len' bytes of VPD data, starting at 'addr'.
463 * Returns number of bytes read.
466 SK_AC *pAC, /* pAC pointer */
467 SK_IOC IoC, /* IO Context */
468 char *buf, /* buffer were the data should be stored */
469 int addr, /* start reading at the VPD address */
470 int len) /* number of bytes to read */
472 return (VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_READ)) ;
476 * Write 'len' bytes of *but to the VPD EEPROM, starting at 'addr'.
478 * Returns number of bytes writes.
481 SK_AC *pAC, /* pAC pointer */
482 SK_IOC IoC, /* IO Context */
483 char *buf, /* buffer, holds the data to write */
484 int addr, /* start writing at the VPD address */
485 int len) /* number of bytes to write */
487 return (VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_WRITE)) ;
492 * (re)initialize the VPD buffer
494 * Reads the VPD data from the EEPROM into the VPD buffer.
495 * Get the remaining read only and read / write space.
501 SK_AC *pAC, /* Adapters context */
502 SK_IOC IoC) /* IO Context */
504 SK_VPD_PARA *r, rp ; /* RW or RV */
508 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_INIT,("VpdInit .. ")) ;
509 /* read the VPD data into the VPD buffer */
510 if (VpdTransferBlock(pAC,IoC,pAC->vpd.vpd_buf,0,VPD_SIZE,VPD_READ)
513 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
514 ("Block Read Error\n")) ;
518 /* find the end tag of the RO area */
519 if (!(r = vpd_find_para(pAC,VPD_RV,&rp))) {
520 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
521 ("Encoding Error: RV Tag not found\n")) ;
524 if (r->p_val + r->p_len > pAC->vpd.vpd_buf + VPD_SIZE/2) {
525 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
526 ("Encoding Error: Invalid VPD struct size\n")) ;
529 pAC->vpd.v.vpd_free_ro = r->p_len - 1 ;
531 /* test the checksum */
532 for (i = 0, x = 0; (unsigned)i<=(unsigned)VPD_SIZE/2 - r->p_len; i++) {
533 x += pAC->vpd.vpd_buf[i] ;
537 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
538 ("VPD Checksum Error\n")) ;
542 /* find and check the end tag of the RW area */
543 if (!(r = vpd_find_para(pAC,VPD_RW,&rp))) {
544 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
545 ("Encoding Error: RV Tag not found\n")) ;
548 if (r->p_val < pAC->vpd.vpd_buf + VPD_SIZE/2) {
549 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
550 ("Encoding Error: Invalid VPD struct size\n")) ;
553 pAC->vpd.v.vpd_free_rw = r->p_len ;
555 /* everything seems to be ok */
556 pAC->vpd.v.vpd_status |= VPD_VALID ;
557 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_INIT,
558 ("done. Free RO = %d, Free RW = %d\n",
559 pAC->vpd.v.vpd_free_ro, pAC->vpd.v.vpd_free_rw)) ;
565 * find the Keyword 'key' in the VPD buffer and fills the
566 * parameter sturct 'p' with its values
569 * 0: parameter was not found or VPD encoding error
571 static SK_VPD_PARA *vpd_find_para(
572 SK_AC *pAC, /* common data base */
573 char *key, /* keyword to find (e.g. "MN") */
574 SK_VPD_PARA *p) /* parameter description struct */
576 char *v ; /* points to vpd buffer */
577 int max ; /* Maximum Number of Iterations */
579 v = pAC->vpd.vpd_buf ;
582 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_CTRL,
583 ("vpd find para %s .. ",key)) ;
585 /* check mandatory resource type ID string (Product Name) */
586 if (*v != (char) RES_ID) {
587 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
588 ("Error: 0x%x missing\n",RES_ID)) ;
592 if (strcmp(key,VPD_NAME) == 0) {
593 p->p_len = VPD_GET_RES_LEN(v) ;
594 p->p_val = VPD_GET_VAL(v) ;
595 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_CTRL,
596 ("found, len = %d\n",p->p_len)) ;
600 v += 3 + VPD_GET_RES_LEN(v) + 3 ;
602 if (SK_MEMCMP(key,v,2) == 0) {
603 p->p_len = VPD_GET_VPD_LEN(v) ;
604 p->p_val = VPD_GET_VAL(v) ;
605 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_CTRL,
606 ("found, len = %d\n",p->p_len)) ;
610 /* exit when reaching the "RW" Tag or the maximum of itera. */
612 if (SK_MEMCMP(VPD_RW,v,2) == 0 || max == 0) {
616 if (SK_MEMCMP(VPD_RV,v,2) == 0) {
617 v += 3 + VPD_GET_VPD_LEN(v) + 3 ; /* skip VPD-W */
619 v += 3 + VPD_GET_VPD_LEN(v) ;
621 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_CTRL,
622 ("scanning '%c%c' len = %d\n",v[0],v[1],v[2])) ;
626 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_CTRL,("not found\n")) ;
628 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
629 ("Key/Len Encoding error\n")) ;
636 * Move 'n' bytes. Begin with the last byte if 'n' is > 0,
637 * Start with the last byte if n is < 0.
641 static void vpd_move_para(
642 char *start, /* start of memory block */
643 char *end, /* end of memory block to move */
644 int n) /* number of bytes the memory block has to be moved */
647 int i ; /* number of byte copied */
652 i = (int) (end - start + 1) ;
669 * setup the VPD keyword 'key' at 'ip'.
673 static void vpd_insert_key(
674 char *key, /* keyword to insert */
675 char *buf, /* buffer with the keyword value */
676 int len, /* length of the value string */
677 char *ip) /* inseration point */
681 p = (SK_VPD_KEY *) ip ;
682 p->p_key[0] = key[0] ;
683 p->p_key[1] = key[1] ;
684 p->p_len = (unsigned char) len ;
685 SK_MEMCPY(&p->p_val,buf,len) ;
689 * Setup the VPD end tag "RV" / "RW".
690 * Also correct the remaining space variables vpd_free_ro / vpd_free_rw.
695 static int vpd_mod_endtag(
696 SK_AC *pAC, /* common data base */
697 char *etp) /* end pointer input position */
703 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_CTRL,
704 ("vpd modify endtag at 0x%x = '%c%c'\n",etp,etp[0],etp[1])) ;
706 p = (SK_VPD_KEY *) etp ;
708 if (p->p_key[0] != 'R' || (p->p_key[1] != 'V' && p->p_key[1] != 'W')) {
709 /* something wrong here, encoding error */
710 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
711 ("Encoding Error: invalid end tag\n")) ;
714 if (etp > pAC->vpd.vpd_buf + VPD_SIZE/2) {
715 /* create "RW" tag */
716 p->p_len = (unsigned char)(pAC->vpd.vpd_buf+VPD_SIZE-etp-3-1) ;
717 pAC->vpd.v.vpd_free_rw = (int) p->p_len ;
718 i = pAC->vpd.v.vpd_free_rw ;
721 /* create "RV" tag */
722 p->p_len = (unsigned char)(pAC->vpd.vpd_buf+VPD_SIZE/2-etp-3) ;
723 pAC->vpd.v.vpd_free_ro = (int) p->p_len - 1 ;
726 for (i = 0, x = 0; i < VPD_SIZE/2 - p->p_len; i++) {
727 x += pAC->vpd.vpd_buf[i] ;
729 p->p_val = (char) 0 - x ;
730 i = pAC->vpd.v.vpd_free_ro ;
742 * Insert a VPD keyword into the VPD buffer.
744 * The keyword 'key' is inserted at the position 'ip' in the
746 * The keywords behind the input position will
747 * be moved. The VPD end tag "RV" or "RW" is generated again.
750 * 2: value string was cut
751 * 4: VPD full, keyword was not written
756 SK_AC *pAC, /* common data base */
757 char *key, /* keyword to insert */
758 char *buf, /* buffer with the keyword value */
759 int len, /* length of the keyword value */
760 int type, /* VPD_RO_KEY or VPD_RW_KEY */
761 int op) /* operation to do: ADD_KEY or OWR_KEY */
764 char *etp ; /* end tag position */
765 int free ; /* remaining space in selected area */
766 char *ip ; /* input position inside the VPD buffer */
767 int rtv ; /* return code */
768 int head ; /* additional haeder bytes to move */
769 int found ; /* additinoal bytes if the keyword was found */
771 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_CTRL,
772 ("vpd setup para key = %s, val = %s\n",key,buf)) ;
776 if (type == VPD_RW_KEY) {
777 /* end tag is "RW" */
778 free = pAC->vpd.v.vpd_free_rw ;
779 etp = pAC->vpd.vpd_buf + (VPD_SIZE - free - 1 - 3) ;
781 /* end tag is "RV" */
782 free = pAC->vpd.v.vpd_free_ro ;
783 etp = pAC->vpd.vpd_buf + (VPD_SIZE/2 - free - 4) ;
785 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_CTRL,
786 ("Free RO = %d, Free RW = %d\n",
787 pAC->vpd.v.vpd_free_ro, pAC->vpd.v.vpd_free_rw)) ;
792 if (vpd_find_para(pAC,key,&vp)) {
795 free += vp.p_len + 3 ;
796 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_CTRL,
797 ("Overwrite Key\n")) ;
800 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_CTRL,
810 if (len + 3 > free) {
812 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
813 ("VPD Buffer Overflow, keyword not written\n"));
819 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
820 ("VPD Buffer Full, Keyword was cut\n")) ;
823 vpd_move_para(ip + vp.p_len + found, etp+2, len-vp.p_len+head) ;
824 vpd_insert_key(key, buf, len, ip) ;
825 if (vpd_mod_endtag(pAC, etp + len - vp.p_len + head)) {
826 pAC->vpd.v.vpd_status &= ~VPD_VALID ;
827 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
828 ("VPD Encoding Error\n")) ;
837 * Read the contents of the VPD EEPROM and copy it to the
838 * VPD buffer if not already done.
840 * return: A pointer to the vpd_status structure. The structure contain
843 SK_VPD_STATUS *VpdStat(
844 SK_AC *pAC, /* Adapters context */
845 SK_IOC IoC) /* IO Context */
847 if (!(pAC->vpd.v.vpd_status & VPD_VALID)) {
848 (void)VpdInit(pAC,IoC) ;
850 return(&pAC->vpd.v) ;
855 * Read the contents of the VPD EEPROM and copy it to the VPD
856 * buffer if not already done.
857 * Scan the VPD buffer for VPD keywords and create the VPD
858 * keyword list by copying the keywords to 'buf', all after
859 * each other and terminated with a '\0'.
861 * Exceptions: o The Resource Type ID String (product name) is called "Name"
862 * o The VPD end tags 'RV' and 'RW' are not listed
864 * The number of copied keywords is counted in 'elements'.
867 * 2: buffer overfull, one or more keywords are missing
870 * example values after returning:
872 * buf = "Name\0PN\0EC\0MN\0SN\0CP\0VF\0VL\0YA\0"
877 SK_AC *pAC, /* common data base */
878 SK_IOC IoC, /* IO Context */
879 char *buf, /* buffer where to copy the keywords */
880 int *len, /* buffer length */
881 int *elements) /* number of keywords returned */
886 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_RX,("list vpd keys .. ")) ;
888 if (!(pAC->vpd.v.vpd_status & VPD_VALID)) {
889 if (VpdInit(pAC,IoC) != 0 ) {
891 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
892 ("VPD Init Error, terminated\n")) ;
897 if ((signed)strlen(VPD_NAME) + 1 <= *len) {
898 v = pAC->vpd.vpd_buf ;
899 strcpy(buf,VPD_NAME) ;
900 n = strlen(VPD_NAME) + 1 ;
903 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_RX,
904 ("'%c%c' ",v[0],v[1])) ;
907 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
908 ("buffer overflow\n")) ;
912 v += 3 + VPD_GET_RES_LEN(v) + 3 ;
914 /* exit when reaching the "RW" Tag */
915 if (SK_MEMCMP(VPD_RW,v,2) == 0) {
919 if (SK_MEMCMP(VPD_RV,v,2) == 0) {
920 v += 3 + VPD_GET_VPD_LEN(v) + 3 ; /* skip VPD-W */
929 v += 3 + VPD_GET_VPD_LEN(v) ;
931 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_RX,
932 ("'%c%c' ",v[0],v[1])) ;
935 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
936 ("buffer overflow\n")) ;
941 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_RX,("\n")) ;
948 * Read the contents of the VPD EEPROM and copy it to the
949 * VPD buffer if not already done. Search for the VPD keyword
950 * 'key' and copy its value to 'buf'. Add a terminating '\0'.
951 * If the value does not fit into the buffer cut it after
955 * 1: keyword not found
956 * 2: value string was cut
957 * 3: VPD transfer timeout
961 SK_AC *pAC, /* common data base */
962 SK_IOC IoC, /* IO Context */
963 char *key, /* keyword to read (e.g. "MN") */
964 char *buf, /* buffer where to copy the keyword value */
965 int *len) /* buffer length */
969 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_RX,("vpd read %s .. ",key)) ;
970 if (!(pAC->vpd.v.vpd_status & VPD_VALID)) {
971 if (VpdInit(pAC,IoC) != 0 ) {
973 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
974 ("vpd init error\n")) ;
979 if ((p = vpd_find_para(pAC,key,&vp))) {
980 if (p->p_len > (*(unsigned *)len)-1) {
981 p->p_len = *len - 1 ;
983 SK_MEMCPY(buf,p->p_val,p->p_len) ;
984 buf[p->p_len] = '\0' ;
986 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_RX,
987 ("%c%c%c%c.., len = %d\n",
988 buf[0],buf[1],buf[2],buf[3],*len)) ;
991 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,("not found\n")) ;
999 * Check whether a given key may be written
1002 * SK_TRUE Yes it may be written
1003 * SK_FALSE No it may be written
1005 SK_BOOL VpdMayWrite(
1006 char *key) /* keyword to write (allowed values "Yx", "Vx") */
1008 if ((*key != 'Y' && *key != 'V') ||
1009 key[1] < '0' || key[1] > 'Z' ||
1010 (key[1] > '9' && key[1] < 'A') || strlen(key) != 2) {
1018 * Read the contents of the VPD EEPROM and copy it to the VPD
1019 * buffer if not already done. Insert/overwrite the keyword 'key'
1020 * in the VPD buffer. Cut the keyword value if it does not fit
1021 * into the VPD read / write area.
1023 * returns 0: success
1024 * 2: value string was cut
1025 * 3: VPD transfer timeout
1026 * 4: VPD full, keyword was not written
1027 * 5: keyword cannot be written
1028 * 6: fatal VPD error
1031 SK_AC *pAC, /* common data base */
1032 SK_IOC IoC, /* IO Context */
1033 char *key, /* keyword to write (allowed values "Yx", "Vx") */
1034 char *buf) /* buffer where the keyword value can be read from */
1036 int len ; /* lenght of the keyword to write */
1037 int rtv ; /* return code */
1040 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_TX,
1041 ("vpd write %s = %s\n",key,buf)) ;
1043 if ((*key != 'Y' && *key != 'V') ||
1044 key[1] < '0' || key[1] > 'Z' ||
1045 (key[1] > '9' && key[1] < 'A') || strlen(key) != 2) {
1047 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
1048 ("illegal key tag, keyword not written\n")) ;
1052 if (!(pAC->vpd.v.vpd_status & VPD_VALID)) {
1053 if (VpdInit(pAC,IoC) != 0 ) {
1054 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
1055 ("vpd init error\n")) ;
1062 if (len > VPD_MAX_LEN) {
1066 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
1067 ("keyword too long, cut after %d bytes\n",
1070 if ((rtv2 = VpdSetupPara(pAC,key,buf,len,VPD_RW_KEY,OWR_KEY)) != 0) {
1071 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
1072 ("vpd write error\n")) ;
1080 * Read the contents of the VPD EEPROM and copy it to the
1081 * VPD buffer if not already done. Remove the VPD keyword
1082 * 'key' from the VPD buffer.
1083 * Only the keywords in the read/write area can be deleted.
1084 * Keywords in the read only area cannot be deleted.
1086 * returns 0: success, keyword was removed
1087 * 1: keyword not found
1088 * 5: keyword cannot be deleted
1089 * 6: fatal VPD error
1092 SK_AC *pAC, /* common data base */
1093 SK_IOC IoC, /* IO Context */
1094 char *key) /* keyword to read (e.g. "MN") */
1096 SK_VPD_PARA *p, vp ;
1099 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_TX,("vpd delete key %s\n",key)) ;
1100 if (!(pAC->vpd.v.vpd_status & VPD_VALID)) {
1101 if (VpdInit(pAC,IoC) != 0 ) {
1102 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
1103 ("vpd init error\n")) ;
1108 if ((p = vpd_find_para(pAC,key,&vp))) {
1109 if (p->p_val < pAC->vpd.vpd_buf + VPD_SIZE/2) {
1110 /* try to delete read only keyword */
1111 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
1112 ("cannot delete RO keyword\n")) ;
1116 etp = pAC->vpd.vpd_buf + (VPD_SIZE-pAC->vpd.v.vpd_free_rw-1-3) ;
1118 vpd_move_para(vp.p_val+vp.p_len, etp+2,
1119 - ((int)(vp.p_len + 3))) ;
1120 if (vpd_mod_endtag(pAC, etp - vp.p_len - 3)) {
1121 pAC->vpd.v.vpd_status &= ~VPD_VALID ;
1122 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
1123 ("vpd encoding error\n")) ;
1127 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
1128 ("keyword not found\n")) ;
1136 * If the VPD buffer contains valid data write the VPD
1137 * read/write area back to the VPD EEPROM.
1139 * returns 0: success
1140 * 3: VPD transfer timeout
1143 SK_AC *pAC, /* Adapters context */
1144 SK_IOC IoC) /* IO Context */
1146 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_TX,("vpd update .. ")) ;
1147 if (pAC->vpd.v.vpd_status & VPD_VALID) {
1148 if (VpdTransferBlock(pAC,IoC,pAC->vpd.vpd_buf + VPD_SIZE/2,
1149 VPD_SIZE/2, VPD_SIZE/2, VPD_WRITE) != VPD_SIZE/2) {
1151 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
1152 ("transfer timed out\n")) ;
1156 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_TX,("done\n")) ;
1163 * Read the contents of the VPD EEPROM and copy it to the VPD buffer
1164 * if not already done. If the keyword "VF" is not present it will be
1165 * created and the error log message will be stored to this keyword.
1166 * If "VF" is not present the error log message will be stored to the
1167 * keyword "VL". "VL" will created or overwritten if "VF" is present.
1168 * The VPD read/write area is saved to the VPD EEPROM.
1170 * returns nothing, errors will be ignored.
1173 SK_AC *pAC, /* common data base */
1174 SK_IOC IoC, /* IO Context */
1175 char *msg) /* error log message */
1177 SK_VPD_PARA *v, vf ; /* VF */
1180 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_TX,
1181 ("vpd error log msg %s\n",msg)) ;
1182 if (!(pAC->vpd.v.vpd_status & VPD_VALID)) {
1183 if (VpdInit(pAC,IoC) != 0 ) {
1184 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
1185 ("vpd init error\n")) ;
1191 if (len > VPD_MAX_LEN) {
1195 if ((v = vpd_find_para(pAC,VPD_VF,&vf))) {
1196 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_TX,("overwrite VL\n")) ;
1197 (void)VpdSetupPara(pAC,VPD_VL,msg,len,VPD_RW_KEY,OWR_KEY) ;
1199 SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_TX,("write VF\n")) ;
1200 (void)VpdSetupPara(pAC,VPD_VF,msg,len,VPD_RW_KEY,ADD_KEY) ;
1203 (void)VpdUpdate(pAC,IoC) ;