예제 #1
0
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;
}
예제 #2
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;
}