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