static int spdmem_match(device_t parent, cfdata_t match, void *aux) { struct i2c_attach_args *ia = aux; struct spdmem_softc sc; int cksum = 0; uint8_t i, val, spd_type; int spd_len, spd_crc_cover; uint16_t crc_calc, crc_spd; if ((ia->ia_addr & SPDMEM_ADDRMASK) != SPDMEM_ADDR) return 0; sc.sc_tag = ia->ia_tag; sc.sc_addr = ia->ia_addr; spd_type = spdmem_read(&sc, 2); /* For older memory types, validate the checksum over 1st 63 bytes */ if (spd_type <= SPDMEM_MEMTYPE_DDR2SDRAM) { for (i = 0; i < 63; i++) cksum += spdmem_read(&sc, i); val = spdmem_read(&sc, 63); if (cksum == 0 || (cksum & 0xff) != val) { aprint_debug("spd addr 0x%2x: ", sc.sc_addr); aprint_debug("spd checksum failed, calc = 0x%02x, " "spd = 0x%02x\n", cksum, val); return 0; } else return 1; } /* For DDR3 and FBDIMM, verify the CRC */ else if (spd_type <= SPDMEM_MEMTYPE_DDR3SDRAM) { spd_len = spdmem_read(&sc, 0); if (spd_len && SPDMEM_SPDCRC_116) spd_crc_cover = 116; else spd_crc_cover = 125; switch (spd_len & SPDMEM_SPDLEN_MASK) { case SPDMEM_SPDLEN_128: spd_len = 128; break; case SPDMEM_SPDLEN_176: spd_len = 176; break; case SPDMEM_SPDLEN_256: spd_len = 256; break; default: return 0; } if (spd_crc_cover > spd_len) return 0; crc_calc = spdcrc16(&sc, spd_crc_cover); crc_spd = spdmem_read(&sc, 127) << 8; crc_spd |= spdmem_read(&sc, 126); if (crc_calc != crc_spd) { aprint_debug("spd addr 0x%2x: ", sc.sc_addr); aprint_debug("crc16 failed, covers %d bytes, " "calc = 0x%04x, spd = 0x%04x\n", spd_crc_cover, crc_calc, crc_spd); return 0; } return 1; } /* For unrecognized memory types, don't match at all */ return 0; }
int spdmem_common_probe(struct spdmem_softc *sc) { int cksum = 0; uint8_t i, val, spd_type; int spd_len, spd_crc_cover; uint16_t crc_calc, crc_spd; spd_type = (sc->sc_read)(sc, 2); /* For older memory types, validate the checksum over 1st 63 bytes */ if (spd_type <= SPDMEM_MEMTYPE_DDR2SDRAM) { for (i = 0; i < 63; i++) cksum += (sc->sc_read)(sc, i); val = (sc->sc_read)(sc, 63); if (cksum == 0 || (cksum & 0xff) != val) { aprint_debug("spd checksum failed, calc = 0x%02x, " "spd = 0x%02x\n", cksum, val); return 0; } else return 1; } /* For DDR3 and FBDIMM, verify the CRC */ else if (spd_type <= SPDMEM_MEMTYPE_DDR3SDRAM) { spd_len = (sc->sc_read)(sc, 0); if (spd_len & SPDMEM_SPDCRC_116) spd_crc_cover = 116; else spd_crc_cover = 125; switch (spd_len & SPDMEM_SPDLEN_MASK) { case SPDMEM_SPDLEN_128: spd_len = 128; break; case SPDMEM_SPDLEN_176: spd_len = 176; break; case SPDMEM_SPDLEN_256: spd_len = 256; break; default: return 0; } if (spd_crc_cover > spd_len) return 0; crc_calc = spdcrc16(sc, spd_crc_cover); crc_spd = (sc->sc_read)(sc, 127) << 8; crc_spd |= (sc->sc_read)(sc, 126); if (crc_calc != crc_spd) { aprint_debug("crc16 failed, covers %d bytes, " "calc = 0x%04x, spd = 0x%04x\n", spd_crc_cover, crc_calc, crc_spd); return 0; } return 1; } /* For unrecognized memory types, don't match at all */ return 0; }