skvpd.c 27 KB

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