📄 skvpd.c
字号:
SK_IN32(IoC, SPI_CTRL, &SpiCtrlReg); SpiCtrlReg &= ~SPI_Y2_CMD_MASK; SpiCtrlReg |= SPI_Y2_RD; SK_OUT32(IoC, SPI_CTRL, SpiCtrlReg); /* wait for the SPI to finish RD operation */ if (SpiWait(pAC, IoC)) {; break; } /* read the returned data */ SK_IN32(IoC, SPI_DATA, &uBuf.RegVal); addr += 4; } *buf = uBuf.Byte[i % SZ_LONG]; } return(i);}#endif /* !SK_SLIM || EFI_UNDI *//****************************************************************************** * * VpdReadBlock() - Read a Block of Configuration Data * * Description: * Read 'len' bytes of configuraiton data, starting at 'addr'. * VpdInit() needs to be run prior calling this function. * * Returns number of bytes read. */int VpdReadBlock(SK_AC *pAC, /* Adapters Context */SK_IOC IoC, /* IO Context */char *buf, /* buffer were the data should be stored */int addr, /* start reading at the VPD address */int len) /* number of bytes to read */{ int n; /* number of read bytes */ if (pAC->GIni.GIChipId >= CHIP_ID_YUKON_FE_P) { SK_TST_MODE_ON(IoC); } if (pAC->vpd.CfgInSpi) { n = SpiReadBlock(pAC, IoC, buf, addr, len); } else { n = VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_READ); } if (pAC->GIni.GIChipId >= CHIP_ID_YUKON_FE_P) { SK_TST_MODE_OFF(IoC); } return (n);}/****************************************************************************** * * VpdWriteBlock() - Writes a block of config data to the EEPROM * * Description: * Write 'len' bytes of *buf to the VPD EEPROM, starting at 'addr'. * VpdInit() needs to be run prior calling this function. * * Returns number of bytes writes. */int VpdWriteBlock(SK_AC *pAC, /* Adapters Context */SK_IOC IoC, /* IO Context */char *buf, /* buffer, holds the data to write */int addr, /* start writing at the VPD address */int len) /* number of bytes to write */{ int n; /* number of written bytes */ if (pAC->GIni.GIChipId >= CHIP_ID_YUKON_FE_P) { SK_TST_MODE_ON(IoC); } if (pAC->vpd.CfgInSpi) { n = 0; } else { n = VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_WRITE); } if (pAC->GIni.GIChipId >= CHIP_ID_YUKON_FE_P) { SK_TST_MODE_OFF(IoC); } return(n);}/****************************************************************************** * * VpdInit() - (re)initialize the VPD buffer * * Description: * Reads the VPD data from the EEPROM into the VPD buffer. * Get the remaining read only and read / write space. * * Returns: * 0: success * 1: fatal VPD error */int VpdInit(SK_AC *pAC, /* Adapters Context */SK_IOC IoC) /* IO Context */{ SK_VPD_PARA *r, rp; /* RW or RV */ int i; int vpd_size; int vpd_ro_size; SK_U8 x; SK_U16 dev_id; SK_U32 our_reg2; SK_U32 vpd_ctrl_add_reg; SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT, ("VpdInit ... ")); /* Reset VPD status */ pAC->vpd.v.vpd_status = 0; if (pAC->GIni.GILevel < SK_INIT_IO) { SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, ("Wrong Init Level")); return(1); } if (!HW_SUP_VPD(pAC)) { SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT, ("VPD not supported")); return(1); } VPD_IN16(pAC, IoC, PCI_DEVICE_ID, &dev_id); VPD_IN8(pAC, IoC, PCI_PM_NITEM, &x);#ifndef SK_SLIM /* needs to be enabled for ASF w/o EEPROM */ pAC->vpd.CfgInSpi = (x != PCI_VPD_CAP_ID && pAC->GIni.GIYukon2) ? SK_TRUE : SK_FALSE;#endif /* !SK_SLIM */ VPD_IN32(pAC, IoC, PCI_OUR_REG_2, &our_reg2); pAC->vpd.rom_size = 256 << ((our_reg2 & PCI_VPD_ROM_SZ) >> 14); /* * this function might get used before the hardware is initialized * therefore we cannot always trust in GIChipId */ /* for Yukon the VPD size is always 256 */ vpd_size = VPD_SIZE_YUKON; vpd_ro_size = vpd_size / 2; if (pAC->GIni.GIChipId >= CHIP_ID_YUKON_SUPR) { /* * Supreme: VPD data may be in parallel flash or EEPROM * Ultra-II: VPD data only in EEPROM * * Read VPD_CTRL_ADD to get length for VPD RO and RW section. */ SK_IN32(IoC, PCI_C(pAC, VPD_CTRL_ADD), &vpd_ctrl_add_reg); if ( pAC->GIni.GIChipId == CHIP_ID_YUKON_SUPR || (pAC->GIni.GIChipId == CHIP_ID_YUKON_UL_2 && (vpd_ctrl_add_reg & VPD_CTRL_ADD_VPD_SEL))) { vpd_size = (vpd_ctrl_add_reg & 0xff000000) >> 24; vpd_size = ((vpd_size + 1) - ((vpd_ctrl_add_reg & 0x0000ff00) >> 8)) * 4; vpd_ro_size = (vpd_ctrl_add_reg & 0x00ff0000) >> 16; vpd_ro_size = (vpd_ro_size - ((vpd_ctrl_add_reg & 0x0000ff00) >> 8)) * 4; } else { SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT, ("VPD not supported")); return(1); } } i = 0; if (vpd_ro_size == 0) { SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, ("Error: VPD R/O size is 0\n")); i = 1; } if (vpd_size > VPD_SIZE) { SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, ("Error: Too many VPD data (%u)\n", vpd_size)); i = 1; } if (i != 0) { return(1); } /* read the VPD data into the VPD buffer */ if (VpdReadBlock(pAC, IoC, pAC->vpd.vpd_buf, 0, vpd_size) != vpd_size) { SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, ("Block Read Error\n")); return(1); } pAC->vpd.vpd_size = vpd_size;#ifndef SK_SLIM /* Asus K8V Se Deluxe bugfix. Correct VPD content */ i = 62; if (!SK_STRNCMP(pAC->vpd.vpd_buf + i, " 8<E", 4)) { pAC->vpd.vpd_buf[i + 2] = '8'; }#endif /* !SK_SLIM */ /* find the end tag of the RO area */ if (!(r = vpd_find_para(pAC, VPD_RV, &rp))) { SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, ("Encoding Error: RV Tag not found\n")); return(1); } if (r->p_val + r->p_len > pAC->vpd.vpd_buf + vpd_ro_size) { SK_DBG_MSG(pAC, SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL, ("Encoding Error: Invalid VPD struct size\n")); return(1); } pAC->vpd.v.vpd_free_ro = r->p_len - 1; /* test the checksum */ for (i = 0, x = 0; (unsigned)i <= (unsigned)vpd_ro_size - r->p_len; i++) { x += pAC->vpd.vpd_buf[i]; } if (x != 0) { /* checksum error */ SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, ("VPD Checksum Error\n")); return(1); }#ifndef SK_SLIM /* needs to be enabled for ASF w/o EEPROM */ if (pAC->vpd.CfgInSpi) { pAC->vpd.v.vpd_free_rw = 0; pAC->vpd.v.vpd_status |= VPD_NO_RW; } else {#endif /* !SK_SLIM */ /* find and check the end tag of the RW area */ if (!(r = vpd_find_para(pAC, VPD_RW, &rp))) { SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, ("Encoding Error: RW Tag not found\n")); return(1); } if (r->p_val < pAC->vpd.vpd_buf + vpd_ro_size) { SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, ("Encoding Error: Invalid VPD struct size\n")); return(1); } pAC->vpd.v.vpd_free_rw = r->p_len;#ifndef SK_SLIM /* needs to be enabled for ASF w/o EEPROM */ if ((pAC->vpd.v.vpd_free_rw < 3) && (r->p_val == pAC->vpd.vpd_buf + vpd_ro_size + 6)) { pAC->vpd.v.vpd_status |= VPD_NO_RW; } }#endif /* !SK_SLIM */ /* everything seems to be ok */ if (pAC->GIni.GIChipId != 0) { pAC->vpd.v.vpd_status |= VPD_VALID; } SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT, ("done. Free RO = %d, Free RW = %d\n", pAC->vpd.v.vpd_free_ro, pAC->vpd.v.vpd_free_rw)); return(0);}/* * find the Keyword 'key' in the VPD buffer and fills the * parameter struct 'p' with it's values * * returns *p success * 0: parameter was not found or VPD encoding error */static SK_VPD_PARA *vpd_find_para(SK_AC *pAC, /* Adapters Context */const char *key, /* keyword to find (e.g. "MN") */SK_VPD_PARA *p) /* parameter description struct */{ char *v ; /* points to VPD buffer */ int max; /* Maximum Number of Iterations */ int len; v = pAC->vpd.vpd_buf; max = 128; SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, ("VPD find para %s .. ", key)); /* check mandatory resource type ID string (Product Name) */ if (*v != (char)RES_ID) { SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, ("Error: 0x%x missing\n", RES_ID)); return(0); } len = VPD_GET_RES_LEN(v); if (SK_STRCMP(key, VPD_NAME) == 0) { p->p_len = len; p->p_val = VPD_GET_VAL(v); SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, ("found, len = %d\n", len)); return(p); } v += 3 + len + 3; for ( ; ; ) { if (SK_MEMCMP(key, v, 2) == 0) { p->p_len = VPD_GET_VPD_LEN(v); p->p_val = VPD_GET_VAL(v); SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, ("found, len = %d\n", p->p_len)); return(p); } /* exit when reaching the "RW" Tag or the maximum of itera. */ max--; if (SK_MEMCMP(VPD_RW, v, 2) == 0 || max == 0) { break; } len = 3 + VPD_GET_VPD_LEN(v); if (SK_MEMCMP(VPD_RV, v, 2) == 0) { len += 3; /* skip VPD-W */ } v += len; SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, ("scanning '%c%c' len = %d\n", v[0], v[1], v[2])); }#ifdef DEBUG SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, ("not found\n")); if (max == 0) { SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, ("Key/Len Encoding error\n")); }#endif /* DEBUG */ return(0);}/* * Move 'n' bytes. Begin with the last byte if 'n' is > 0, * Start with the last byte if n is < 0. * * returns nothing */static void vpd_move_para(char *start, /* start of memory block */char *end, /* end of memory block to move */int n) /* number of bytes the memory block has to be moved */{ char *p; int i; /* number of byte copied */ if (n == 0) { return; } i = (int) (end - start + 1); if (n < 0) { p = start + n; while (i != 0) { *p++ = *start++; i--; } } else { p = end + n; while (i != 0) { *p-- = *end--; i--; } }}/* * setup the VPD keyword 'key' at 'ip'. * * returns nothing */static void vpd_insert_key(const char *key, /* keyword to insert */const char *buf, /* buffer with the keyword value */int len, /* length of the value string */char *ip) /* inseration point */{ SK_VPD_KEY *p; p = (SK_VPD_KEY *) ip; p->p_key[0] = key[0]; p->p_key[1] = key[1]; p->p_len = (unsigned char)len; SK_MEMCPY(&p->p_val, buf, len);}/* * Setup the VPD end tag "RV" / "RW". * Also correct the remaining space variables vpd_free_ro / vpd_free_rw. * * returns 0: success * 1: encoding error */static int vpd_mod_endtag(SK_AC *pAC, /* Adapters Context */char *etp) /* end pointer input position */{ SK_VPD_KEY *p; unsigned char x; int i; int vpd_size; SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, ("VPD modify endtag at 0x%x = '%c%c'\n", etp, etp[0], etp[1])); vpd_size = pAC->vpd.vpd_size; p = (SK_VPD_KEY *) etp; if (p->p_key[0] != 'R' || (p->p_key[1] != 'V' && p->p_key[1] != 'W')) { /* something wrong here, encoding error */ SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, ("Encoding Error: invalid end tag\n")); return(1); } if (etp > pAC->vpd.vpd_buf + vpd_size/2) { /* create "RW" tag */ p->p_len = (unsigned char)(pAC->vpd.vpd_buf+vpd_size-etp-3-1); pAC->vpd.v.vpd_free_rw = (int) p->p_len; i = pAC->vpd.v.vpd_free_rw; etp += 3; } else { /* create "RV" tag */ p->p_len = (unsigned char)(pAC->vpd.vpd_buf+vpd_size/2-etp-3); pAC->vpd.v.vpd_free_ro = (int) p->p_len - 1; /* setup checksum */ for (i = 0, x = 0; i < vpd_size/2 - p->p_len; i++) { x += pAC->vpd.vpd_buf[i]; } p->p_val = (char) 0 - x; i = pAC->vpd.v.vpd_free_ro; etp += 4; } while (i) { *etp++ = 0x00; i--; } return(0);}/* * Insert a VPD keyword into the VPD buffer. * * The keyword 'key' is inserted at the position 'ip' in the * VPD buffer. * The keywords behind the input position will * be moved. The VPD end tag "RV" or "RW" is generated again.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -