#include "ipmi.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#define _I2C_PRIVATE
#include <dev/i2c/i2cvar.h>
#undef I2C_DEBUG
#define I2C_VERBOSE
#define MAX_IGNORE 8
u_int8_t ignore_addrs[MAX_IGNORE];
struct iicprobelist {
u_int8_t start, end;
};
struct iicprobelist probe_addrs_sensor[] = {
{ 0x18, 0x1f },
{ 0x20, 0x2f },
{ 0x48, 0x4e },
{ 0, 0 }
};
struct iicprobelist probe_addrs_eeprom[] = {
{ 0x50, 0x57 },
{ 0, 0 }
};
char *iic_probe_sensor(struct device *, u_int8_t);
char *iic_probe_eeprom(struct device *, u_int8_t);
#define PFLAG_SENSOR 1
static struct {
struct iicprobelist *pl;
char *(*probe)(struct device *, u_int8_t);
int flags;
} probes[] = {
{ probe_addrs_sensor, iic_probe_sensor, PFLAG_SENSOR },
{ probe_addrs_eeprom, iic_probe_eeprom, 0 },
{ NULL, NULL }
};
int skip_fc;
static i2c_tag_t probe_ic;
static u_int8_t probe_addr;
static u_int8_t probe_val[256];
void iicprobeinit(struct i2cbus_attach_args *, u_int8_t);
u_int8_t iicprobenc(u_int8_t);
u_int8_t iicprobe(u_int8_t);
u_int16_t iicprobew(u_int8_t);
char *lm75probe(void);
char *adm1032cloneprobe(u_int8_t);
void iic_dump(struct device *, u_int8_t, char *);
void
iicprobeinit(struct i2cbus_attach_args *iba, u_int8_t addr)
{
probe_ic = iba->iba_tag;
probe_addr = addr;
memset(probe_val, 0xff, sizeof probe_val);
}
u_int8_t
iicprobenc(u_int8_t cmd)
{
u_int8_t data;
if (skip_fc && cmd == 0xfc)
return (0xff);
iic_acquire_bus(probe_ic, 0);
if (iic_exec(probe_ic, I2C_OP_READ_WITH_STOP,
probe_addr, &cmd, sizeof cmd, &data, sizeof data, 0) != 0)
data = 0xff;
iic_release_bus(probe_ic, 0);
return (data);
}
u_int16_t
iicprobew(u_int8_t cmd)
{
u_int16_t data;
if (skip_fc && cmd == 0xfc)
return (0xffff);
iic_acquire_bus(probe_ic, 0);
if (iic_exec(probe_ic, I2C_OP_READ_WITH_STOP,
probe_addr, &cmd, sizeof cmd, &data, sizeof data, 0) != 0)
data = 0xffff;
iic_release_bus(probe_ic, 0);
return betoh16(data);
}
u_int8_t
iicprobe(u_int8_t cmd)
{
if (probe_val[cmd] != 0xff)
return probe_val[cmd];
probe_val[cmd] = iicprobenc(cmd);
return (probe_val[cmd]);
}
#define LM75TEMP 0x00
#define LM75CONF 0x01
#define LM75Thyst 0x02
#define LM75Tos 0x03
#define LM77Tlow 0x04
#define LM77Thigh 0x05
#define LM75TMASK 0xff80
#define LM77TMASK 0xfff8
char *
lm75probe(void)
{
u_int16_t temp, thyst, tos, tlow, thigh, mask = LM75TMASK;
u_int8_t conf;
int i, echocount, ffffcount, score;
int echoreg67, echoreg45, ffffreg67, ffffreg45;
temp = iicprobew(LM75TEMP);
if (temp == 0xffff)
temp = iicprobew(LM75TEMP);
conf = iicprobenc(LM75CONF);
thyst = iicprobew(LM75Thyst);
tos = iicprobew(LM75Tos);
if (conf == 0xff && temp == 0xffff && thyst == 0xffff)
return (NULL);
temp &= mask;
thyst &= mask;
tos &= mask;
if (temp == thyst && thyst == tos)
return (NULL);
#if notsure
if ((temp >> 8) == conf)
return (NULL);
#endif
for (i = 6, echocount = 2, ffffcount = 0; i <= 7; i++) {
if ((iicprobew(LM75TEMP) & mask) != (iicprobew(i) & mask) ||
(iicprobew(LM75Thyst) & mask) != (iicprobew(i) & mask) ||
(iicprobew(LM75Tos) & mask) != (iicprobew(i) & mask))
echocount--;
if (iicprobew(i) == 0xffff)
ffffcount++;
}
if (echocount == 1 || ffffcount == 1)
return (NULL);
echoreg67 = (echocount == 0) ? 0 : 1;
ffffreg67 = (ffffcount == 0) ? 0 : 1;
for (i = 4, echocount = 2, ffffcount = 0; i <= 5; i++) {
if ((iicprobew(LM75TEMP) & mask) != (iicprobew(i) & mask) ||
(iicprobew(LM75Thyst) & mask) != (iicprobew(i) & mask) ||
(iicprobew(LM75Tos) & mask) != (iicprobew(i) & mask))
echocount--;
if (iicprobew(i) == 0xffff)
ffffcount++;
}
if (echocount == 1 || ffffcount == 1)
return (NULL);
echoreg45 = (echocount == 0) ? 0 : 1;
ffffreg45 = (ffffcount == 0) ? 0 : 1;
if (echoreg45 == 0 && ffffreg45 == 0 && echoreg67 == 1) {
mask = LM77TMASK;
thyst = iicprobew(LM75Thyst) & mask;
tos = iicprobew(LM75Tos) & mask;
tlow = iicprobew(LM77Tlow) & mask;
thigh = iicprobew(LM77Thigh) & mask;
}
for (i = 0x08; i <= 0xf8; i += 8) {
if (conf != iicprobenc(LM75CONF + i) ||
thyst != (iicprobew(LM75Thyst + i) & mask) ||
tos != (iicprobew(LM75Tos + i) & mask))
return (NULL);
if (echoreg67 == 1) {
tos = iicprobew(LM75Tos) & mask;
if (tos != (iicprobew(0x06 + i) & mask) ||
tos != (iicprobew(0x07 + i) & mask))
return (NULL);
} else if (ffffreg67 == 1)
if (iicprobew(0x06 + i) != 0xffff ||
iicprobew(0x07 + i) != 0xffff)
return (NULL);
if (echoreg45 == 1) {
tos = iicprobew(LM75Tos) & mask;
if (tos != (iicprobew(LM77Tlow + i) & mask) ||
tos != (iicprobew(LM77Thigh + i) & mask))
return (NULL);
} else if (ffffreg45 == 1) {
if (iicprobew(LM77Tlow + i) != 0xffff ||
iicprobew(LM77Thigh + i) != 0xffff)
return (NULL);
} else if (echoreg67 == 1)
if (tlow != (iicprobew(LM77Tlow + i) & mask) ||
thigh != (iicprobew(LM77Thigh + i) & mask))
return (NULL);
}
score = (echoreg67 << 3) + (echoreg45 << 2) + (ffffreg67 << 1) +
ffffreg45;
switch (score) {
case 12:
return ("lm75");
case 8:
return ("lm77");
case 3:
return ("lm75a");
default:
#if defined(I2C_DEBUG)
printf("lm75probe: unknown chip, scored %d\n", score);
#endif
return (NULL);
}
}
char *
adm1032cloneprobe(u_int8_t addr)
{
if (addr == 0x18 || addr == 0x1a || addr == 0x29 ||
addr == 0x2b || addr == 0x4c || addr == 0x4e) {
u_int8_t reg, val;
int zero = 0, copy = 0;
val = iicprobe(0x00);
for (reg = 0x00; reg < 0x09; reg++) {
if (iicprobe(reg) == 0xff)
return (NULL);
if (iicprobe(reg) == 0x00)
zero++;
if (val == iicprobe(reg))
copy++;
}
if (zero > 6 || copy > 6)
return (NULL);
val = iicprobe(0x09);
for (reg = 0x0a; reg < 0xfc; reg++) {
if (iicprobe(reg) != val)
return (NULL);
}
if (iicprobe(0xfe) == 0x4d)
return ("max1617");
return ("xeontemp");
}
return (NULL);
}
void
iic_ignore_addr(u_int8_t addr)
{
int i;
for (i = 0; i < sizeof(ignore_addrs); i++)
if (ignore_addrs[i] == 0) {
ignore_addrs[i] = addr;
return;
}
}
#ifdef I2C_VERBOSE
void
iic_dump(struct device *dv, u_int8_t addr, char *name)
{
static u_int8_t iicvalcnt[256];
u_int8_t val, val2, max;
int i, cnt = 0;
bzero(iicvalcnt, sizeof iicvalcnt);
val = iicprobe(0);
iicvalcnt[val]++;
for (i = 1; i <= 0xff; i++) {
val2 = iicprobe(i);
iicvalcnt[val2]++;
if (val == val2)
cnt++;
}
for (val = max = i = 0; i <= 0xff; i++)
if (max < iicvalcnt[i]) {
max = iicvalcnt[i];
val = i;
}
if (cnt == 255)
return;
printf("%s: addr 0x%x", dv->dv_xname, addr);
for (i = 0; i <= 0xff; i++) {
if (iicprobe(i) != val)
printf(" %02x=%02x", i, iicprobe(i));
}
printf(" words");
for (i = 0; i < 8; i++)
printf(" %02x=%04x", i, iicprobew(i));
if (name)
printf(": %s", name);
printf("\n");
}
#endif
char *
iic_probe_sensor(struct device *self, u_int8_t addr)
{
char *name = NULL;
skip_fc = 0;
switch (iicprobe(0x3e)) {
case 0x01:
if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) &&
(iicprobe(0x3f) == 0x73 || iicprobe(0x3f) == 0x72) &&
iicprobe(0x00) == 0x00)
name = "lm93";
else if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) &&
iicprobe(0x3f) == 0x68)
name = "lm96000";
else if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) &&
(iicprobe(0x3f) == 0x60 || iicprobe(0x3f) == 0x62))
name = "lm85";
else if ((addr & 0x7c) == 0x2c &&
iicprobe(0x48) == addr &&
(iicprobe(0x3f) == 0x03 || iicprobe(0x3f) == 0x04) &&
(iicprobe(0x40) & 0x80) == 0x00)
name = "lm81";
break;
case 0x02:
if ((iicprobe(0x3f) & 0xfc) == 0x04)
name = "lm87";
break;
case 0x23:
if (iicprobe(0x48) == addr &&
(iicprobe(0x40) & 0x80) == 0x00 &&
(addr & 0x7c) == 0x2c)
name = "adm9240";
break;
case 0x41:
if ((addr == 0x2c || addr == 0x2e || addr == 0x2f) &&
iicprobe(0x3d) == 0x70)
name = "adt7470";
else if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) &&
iicprobe(0x3d) == 0x76)
name = "adt7476";
else if (addr == 0x2e && iicprobe(0x3d) == 0x75)
name = "adt7475";
else if (iicprobe(0x3d) == 0x27 &&
(iicprobe(0x3f) == 0x60 || iicprobe(0x3f) == 0x6a))
name = "adm1027";
else if (iicprobe(0x3d) == 0x27 &&
(iicprobe(0x3f) == 0x62 || iicprobe(0x3f) == 0x6a))
name = "adt7460";
else if ((addr == 0x2c || addr == 0x2e) &&
iicprobe(0x3d) == 0x62 && iicprobe(0x3f) == 0x04)
name = "adt7462";
else if (addr == 0x4c &&
iicprobe(0x3d) == 0x66 && iicprobe(0x3f) == 0x02)
name = "adt7466";
else if (addr == 0x2e &&
iicprobe(0x3d) == 0x68 && (iicprobe(0x3f) & 0xf0) == 0x70)
name = "adt7467";
else if (iicprobe(0x3d) == 0x33 && iicprobe(0x3f) == 0x02)
name = "adm1033";
else if (iicprobe(0x3d) == 0x34 && iicprobe(0x3f) == 0x02)
name = "adm1034";
else if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) &&
iicprobe(0x3d) == 0x30 &&
(iicprobe(0x01) & 0x80) == 0x00 &&
(iicprobe(0x0d) & 0x70) == 0x00 &&
(iicprobe(0x0e) & 0x70) == 0x00)
name = "adm1030";
else if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) &&
iicprobe(0x3d) == 0x31 &&
(iicprobe(0x01) & 0x80) == 0x00 &&
(iicprobe(0x0d) & 0x70) == 0x00 &&
(iicprobe(0x0e) & 0x70) == 0x00 &&
(iicprobe(0x0f) & 0x70) == 0x00)
name = "adm1031";
else if ((addr & 0x7c) == 0x2c &&
(iicprobe(0x3f) & 0xf0) == 0x20 &&
(iicprobe(0x40) & 0x80) == 0x00 &&
(iicprobe(0x41) & 0xc0) == 0x00 &&
(iicprobe(0x42) & 0xbc) == 0x00)
name = "adm1025";
else if ((addr & 0x7c) == 0x2c &&
(iicprobe(0x3f) & 0xf0) == 0x10 &&
(iicprobe(0x40) & 0x80) == 0x00)
name = "adm1024";
else if ((iicprobe(0xff) & 0xf0) == 0x30)
name = "adm1023";
else if (addr == 0x2e &&
(iicprobe(0x3f) & 0xf0) == 0xd0 &&
(iicprobe(0x40) & 0x80) == 0x00)
name = "adm1028";
else if ((addr == 0x2c || addr == 0x2e || addr == 0x2f) &&
(iicprobe(0x3f) & 0xf0) == 0xc0 &&
(iicprobe(0x40) & 0x80) == 0x00)
name = "adm1022";
break;
case 0x49:
if ((addr == 0x2c || addr == 0x2e || addr == 0x2f) &&
(iicprobe(0x3f) & 0xf0) == 0xc0 &&
(iicprobe(0x40) & 0x80) == 0x00)
name = "thmc50";
break;
case 0x55:
if ((addr & 0x7c) == 0x2c &&
iicprobe(0x3f) == 0x20 &&
(iicprobe(0x47) & 0x70) == 0x00 &&
(iicprobe(0x49) & 0xfe) == 0x80)
name = "47m192";
break;
case 0x5c:
if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) &&
(iicprobe(0x3f) == 0x69))
name = "sch5027";
else if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) &&
(iicprobe(0x3f) & 0xf0) == 0x60)
name = "emc6d100";
else if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) &&
(iicprobe(0x3f) & 0xf0) == 0x80)
name = "sch5017";
else if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) &&
(iicprobe(0x3f) & 0xf0) == 0xb0)
name = "emc6w201";
break;
case 0x61:
if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) &&
iicprobe(0x3f) == 0x69 &&
iicprobe(0x22) >= 0xaf &&
(iicprobe(0x09) & 0xbf) == 0x00 && iicprobe(0x0f) == 0x00 &&
(iicprobe(0x40) & 0xf0) == 0x00)
name = "asc7611";
else if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) &&
iicprobe(0x3f) == 0x6c &&
iicprobe(0x22) >= 0xae)
name = "asc7621";
break;
case 0xa1:
if ((iicprobe(0x3f) & 0xf0) == 0x20 &&
(iicprobe(0x40) & 0x80) == 0x00 &&
(iicprobe(0x41) & 0xc0) == 0x00 &&
(iicprobe(0x42) & 0xbc) == 0x00)
name = "ne1619";
break;
case 0xda:
if (iicprobe(0x3f) == 0x01 && iicprobe(0x48) == addr &&
(iicprobe(0x40) & 0x80) == 0x00)
name = "ds1780";
break;
}
switch (iicprobe(0x4e)) {
case 0x41:
if ((addr == 0x48 || addr == 0x4a || addr == 0x4b) &&
(iicprobe(0x4d) == 0x03 || iicprobe(0x4d) == 0x08 ||
iicprobe(0x4d) == 0x07))
name = "adt7516";
break;
}
switch (iicprobe(0xfe)) {
case 0x01:
if (addr == 0x4c &&
iicprobe(0xff) == 0x41 && (iicprobe(0x03) & 0x18) == 0 &&
iicprobe(0x04) <= 0x0f && (iicprobe(0xbf) & 0xf8) == 0)
name = "lm63";
else if (addr == 0x4c &&
iicprobe(0xff) == 0x11 && (iicprobe(0x03) & 0x2a) == 0 &&
iicprobe(0x04) <= 0x09 && (iicprobe(0xbf) & 0xf8) == 0)
name = "lm86";
else if (addr == 0x4c &&
iicprobe(0xff) == 0x31 && (iicprobe(0x03) & 0x2a) == 0 &&
iicprobe(0x04) <= 0x09 && (iicprobe(0xbf) & 0xf8) == 0)
name = "lm89";
else if (addr == 0x4d &&
iicprobe(0xff) == 0x34 && (iicprobe(0x03) & 0x2a) == 0 &&
iicprobe(0x04) <= 0x09 && (iicprobe(0xbf) & 0xf8) == 0)
name = "lm89-1";
else if (addr == 0x4c &&
iicprobe(0xff) == 0x21 && (iicprobe(0x03) & 0x2a) == 0 &&
iicprobe(0x04) <= 0x09 && (iicprobe(0xbf) & 0xf8) == 0)
name = "lm90";
break;
case 0x23:
if ((addr == 0x4c) &&
(iicprobe(0x03) & 0x3f) == 0x00 && iicprobe(0x04) <= 0x08)
name = "gl523sm";
break;
case 0x41:
if ((addr == 0x4c || addr == 0x4d) &&
iicprobe(0xff) == 0x51 &&
(iicprobe(0x03) & 0x1f) == 0x04 &&
iicprobe(0x04) <= 0x0a) {
name = "adt7461";
} else if ((addr == 0x18 || addr == 0x19 || addr == 0x1a ||
addr == 0x29 || addr == 0x2a || addr == 0x2b ||
addr == 0x4c || addr == 0x4d || addr == 0x4e) &&
(iicprobe(0xff) & 0xf0) == 0x00 &&
(iicprobe(0x03) & 0x3f) == 0x00 &&
iicprobe(0x04) <= 0x07) {
name = "adm1021";
skip_fc = 1;
} else if ((addr == 0x18 || addr == 0x19 || addr == 0x1a ||
addr == 0x29 || addr == 0x2a || addr == 0x2b ||
addr == 0x4c || addr == 0x4d || addr == 0x4e) &&
(iicprobe(0xff) & 0xf0) == 0x30 &&
(iicprobe(0x03) & 0x3f) == 0x00 &&
iicprobe(0x04) <= 0x07) {
name = "adm1023";
skip_fc = 1;
} else if ((addr == 0x4c || addr == 0x4d || addr == 0x4e) &&
(iicprobe(0x03) & 0x3f) == 0x00 &&
iicprobe(0x04) <= 0x0a) {
name = "adm1032";
skip_fc = 1;
}
break;
case 0x47:
if (addr == 0x4c && iicprobe(0xff) == 0x01 &&
(iicprobe(0x03) & 0x3f) == 0x00 && iicprobe(0x04) <= 0x08)
name = "g781";
if (addr == 0x4d && iicprobe(0xff) == 0x03 &&
(iicprobe(0x03) & 0x3f) == 0x00 && iicprobe(0x04) <= 0x08)
name = "g781-1";
break;
case 0x4d:
if ((addr == 0x18 || addr == 0x19 || addr == 0x1a ||
addr == 0x29 || addr == 0x2a || addr == 0x2b ||
addr == 0x4c || addr == 0x4d || addr == 0x4e) &&
iicprobe(0xff) == 0x08 && (iicprobe(0x02) & 0x03) == 0 &&
(iicprobe(0x03) & 0x07) == 0 && iicprobe(0x04) <= 0x08)
name = "max6690";
else if ((addr == 0x4c || addr == 0x4d || addr == 0x4e) &&
iicprobe(0xff) == 0x59 && (iicprobe(0x03) & 0x1f) == 0 &&
iicprobe(0x04) <= 0x07)
name = "max6646";
else if ((addr == 0x4c || addr == 0x4d || addr == 0x4e) &&
(iicprobe(0x02) & 0x2b) == 0 &&
(iicprobe(0x03) & 0x0f) == 0 && iicprobe(0x04) <= 0x09) {
name = "max6657";
skip_fc = 1;
} else if ((addr >= 0x48 && addr <= 0x4f) &&
(iicprobe(0x02) & 0x2b) == 0 &&
(iicprobe(0x03) & 0x0f) == 0)
name = "max6642";
break;
case 0x55:
if (addr == 0x4c && iicprobe(0xff) == 0x11 &&
(iicprobe(0x03) & 0x1b) == 0x00 &&
(iicprobe(0x04) & 0xf0) == 0x00 &&
(iicprobe(0x10) & 0x0f) == 0x00 &&
(iicprobe(0x13) & 0x0f) == 0x00 &&
(iicprobe(0x14) & 0x0f) == 0x00 &&
(iicprobe(0x15) & 0x0f) == 0x00 &&
(iicprobe(0x16) & 0x0f) == 0x00 &&
(iicprobe(0x17) & 0x0f) == 0x00)
name = "tmp401";
break;
case 0xa1:
if ((addr >= 0x48 && addr <= 0x4f) &&
iicprobe(0xff) == 0x00 &&
(iicprobe(0x03) & 0xf8) == 0x00 &&
iicprobe(0x04) <= 0x09) {
name = "sa56004x";
skip_fc = 1;
}
break;
}
if (addr == iicprobe(0x48) &&
((iicprobe(0x4f) == 0x5c && (iicprobe(0x4e) & 0x80)) ||
(iicprobe(0x4f) == 0xa3 && !(iicprobe(0x4e) & 0x80)))) {
if ((iicprobe(0x4e) & 0x07) == 0) {
switch (iicprobe(0x58)) {
case 0x10:
case 0x11:
name = "w83781d";
break;
case 0x21:
name = "w83627hf";
break;
case 0x30:
name = "w83782d";
break;
case 0x31:
name = "as99127f";
break;
case 0x40:
name = "w83783s";
break;
case 0x71:
name = "w83791d";
break;
case 0x72:
name = "w83791sd";
break;
case 0x7a:
name = "w83792d";
break;
case 0xc1:
name = "w83627dhg";
break;
}
} else {
name = "w83781d";
}
} else if (addr == (iicprobe(0xfc) & 0x7f) &&
iicprobe(0xfe) == 0x79 && iicprobe(0xfb) == 0x51 &&
((iicprobe(0xfd) == 0x5c && (iicprobe(0x00) & 0x80)) ||
(iicprobe(0xfd) == 0xa3 && !(iicprobe(0x00) & 0x80)))) {
name = "w83795g";
} else if (addr == iicprobe(0x4a) && iicprobe(0x4e) == 0x50 &&
iicprobe(0x4c) == 0xa3 && iicprobe(0x4d) == 0x5c) {
name = "w83l784r";
} else if (addr == 0x2d && iicprobe(0x4e) == 0x60 &&
iicprobe(0x4c) == 0xa3 && iicprobe(0x4d) == 0x5c) {
name = "w83l785r";
} else if (addr == 0x2e && iicprobe(0x4e) == 0x70 &&
iicprobe(0x4c) == 0xa3 && iicprobe(0x4d) == 0x5c) {
name = "w83l785ts-l";
} else if (addr >= 0x2c && addr <= 0x2f &&
((iicprobe(0x00) & 0x07) != 0x0 ||
((iicprobe(0x00) & 0x07) == 0x0 && addr * 2 == iicprobe(0x0b) &&
(iicprobe(0x0c) & 0x40) && !(iicprobe(0x0c) & 0x04))) &&
iicprobe(0x0e) == 0x7b &&
(iicprobe(0x0f) & 0xf0) == 0x10 &&
((iicprobe(0x0d) == 0x5c && (iicprobe(0x00) & 0x80)) ||
(iicprobe(0x0d) == 0xa3 && !(iicprobe(0x00) & 0x80)))) {
name = "w83793g";
} else if (addr >= 0x28 && addr <= 0x2f &&
iicprobe(0x4f) == 0x12 && (iicprobe(0x4e) & 0x80)) {
if (iicprobe(0x58) == 0x31)
name = "as99127f";
} else if ((addr == 0x2d || addr == 0x2e) &&
addr * 2 == iicprobe(0x04) &&
iicprobe(0x5d) == 0x19 && iicprobe(0x5e) == 0x34 &&
iicprobe(0x5a) == 0x03 && iicprobe(0x5b) == 0x06) {
name = "f75375";
} else if (addr == 0x2d &&
((iicprobe(0x4f) == 0x06 && (iicprobe(0x4e) & 0x80)) ||
(iicprobe(0x4f) == 0x94 && !(iicprobe(0x4e) & 0x80)))) {
if ((iicprobe(0x58) & 0x7f) == 0x31 &&
(iicprobe(0x4e) & 0xf) == 0x00)
name = "asb100";
} else if ((addr == 0x2c || addr == 0x2d) &&
iicprobe(0x00) == 0x80 &&
(iicprobe(0x01) == 0x00 || iicprobe(0x01) == 0x80) &&
iicprobe(0x02) == 0x00 && (iicprobe(0x03) & 0x83) == 0x00 &&
(iicprobe(0x0f) & 0x07) == 0x00 &&
(iicprobe(0x11) & 0x80) == 0x00 &&
(iicprobe(0x12) & 0x80) == 0x00) {
name = "gl518sm";
} else if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) &&
iicprobe(0x16) == 0x41 && ((iicprobe(0x17) & 0xf0) == 0x40)) {
name = "adm1026";
} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x1131 &&
(iicprobew(0x07) & 0xfffc) == 0xa200) {
name = "se97";
} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x1131 &&
(iicprobew(0x07) & 0xfffc) == 0xa100 &&
(iicprobew(0x00) & 0xfff0) == 0x0010) {
name = "se98";
} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x004d &&
iicprobew(0x07) == 0x3e00 &&
(iicprobew(0x00) & 0xffe0) == 0x0000) {
name = "max6604";
} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x0054 &&
(iicprobew(0x07) & 0xfffc) == 0x0200 &&
(iicprobew(0x00) & 0xffe0) == 0x0000) {
name = "mcp9804";
} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x0054 &&
(iicprobew(0x07) & 0xff00) == 0x0000 &&
(iicprobew(0x00) & 0xffe0) == 0x0000) {
name = "mcp9805";
} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x0054 &&
(iicprobew(0x07) & 0xfffc) == 0x2000 &&
(iicprobew(0x00) & 0xffe0) == 0x0000) {
name = "mcp98242";
} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x0054 &&
(iicprobew(0x07) & 0xff00) == 0x2100 &&
(iicprobew(0x00) & 0xff00) == 0x0000) {
name = "mcp98243";
} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x0054 &&
(iicprobew(0x07) & 0xfffc) == 0x2200 &&
(iicprobew(0x00) & 0xff00) == 0x0000) {
name = "mcp98244";
} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x11d4 &&
iicprobew(0x07) == 0x0800 &&
iicprobew(0x00) == 0x001d) {
name = "adt7408";
} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x104a &&
(iicprobew(0x07) & 0xfffe) == 0x0000 &&
(iicprobew(0x00) == 0x002d || iicprobew(0x00) == 0x002f)) {
name = "stts424e02";
} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x104a &&
(iicprobew(0x07) & 0xfffe) == 0x0300 &&
(iicprobew(0x00) == 0x006f)) {
name = "stts2002";
} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x104a &&
(iicprobew(0x07) & 0xffff) == 0x2201 &&
(iicprobew(0x00) == 0x00ef)) {
name = "stts2004";
} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x104a &&
(iicprobew(0x07) & 0xffff) == 0x0200 &&
(iicprobew(0x00) == 0x006f)) {
name = "stts3000";
} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x104a &&
(iicprobew(0x07) & 0xffff) == 0x0101 &&
(iicprobew(0x00) == 0x002d || iicprobew(0x00) == 0x002f)) {
name = "stts424";
} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x1b09 &&
(iicprobew(0x07) & 0xffe0) == 0x0800 &&
(iicprobew(0x00) & 0x001f) == 0x001f) {
name = "cat34ts02";
} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x1b09 &&
(iicprobew(0x07) & 0xffff) == 0x0a00 &&
(iicprobew(0x00) & 0x001f) == 0x001f) {
name = "cat34ts02c";
} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x1b09 &&
(iicprobew(0x07) & 0xffff) == 0x2200 &&
(iicprobew(0x00) == 0x007f)) {
name = "cat34ts04";
} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x00b3 &&
(iicprobew(0x07) & 0xffff) == 0x2903 &&
(iicprobew(0x00) == 0x004f)) {
name = "ts3000b3";
} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x00b3 &&
(iicprobew(0x07) & 0xffff) == 0x2912 &&
(iicprobew(0x00) == 0x006f)) {
name = "ts3000gb2";
} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x00b3 &&
(iicprobew(0x07) & 0xffff) == 0x2913 &&
(iicprobew(0x00) == 0x0077)) {
name = "ts3000gb0";
} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x00b3 &&
(iicprobew(0x07) & 0xffff) == 0x3001 &&
(iicprobew(0x00) == 0x006f)) {
name = "ts3001gb2";
} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x00b3 &&
(iicprobew(0x07) & 0xffff) == 0x2214 &&
(iicprobew(0x00) == 0x00ff)) {
name = "tse2004gb2";
} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x001f &&
(iicprobew(0x07) & 0xffff) == 0x8201 &&
(iicprobew(0x00) & 0xff00) == 0x0000) {
name = "at30ts00";
} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x1114 &&
(iicprobew(0x07) & 0xffff) == 0x2200 &&
(iicprobew(0x00) & 0xff00) == 0x0000) {
name = "at30tse004";
} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x1c68 &&
(iicprobew(0x07) & 0xffff) == 0x2201 &&
(iicprobew(0x00) & 0xff00) == 0x0000) {
name = "gt30ts00";
} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x132d &&
(iicprobew(0x07) & 0xffff) == 0x3300 &&
(iicprobew(0x00) & 0x001f) == 0x001f) {
name = "gt34ts02";
} else if ((addr & 0x7e) == 0x1c && iicprobe(0x0f) == 0x3b &&
(iicprobe(0x21) & 0x60) == 0x00 &&
iicprobe(0x0f) == iicprobe(0x8f) &&
iicprobe(0x20) == iicprobe(0xa0) &&
iicprobe(0x21) == iicprobe(0xa1) &&
iicprobe(0x22) == iicprobe(0xa2) &&
iicprobe(0x07) == 0x00) {
name = "lis331dl";
} else if (name == NULL &&
(addr & 0x78) == 0x48) {
name = lm75probe();
}
#if 0
if (name == NULL && (addr & 0x7c) == 0x48 &&
(iicprobew(0xaa) & 0x0007) == 0x0000 &&
(iicprobew(0xa1) & 0x0007) == 0x0000 &&
(iicprobew(0xa2) & 0x0007) == 0x0000 &&
(iicprobe(0xac) & 0x10) == 0x00) {
if ((iicprobe(0xac) & 0x7e) == 0x0a &&
iicprobe(0xab) == 0x00 && iicprobe(0xa8) == 0x00)
name = "ds1624";
else if ((iicprobe(0xac) & 0x7e) == 0x0c)
name = "ds1631";
else if ((iicprobe(0xac) & 0x2e) == 0x2e)
name = "ds1721";
}
#endif
if (name == NULL && (addr & 0xf8) == 0x28 && iicprobe(0x48) == addr &&
(iicprobe(0x00) & 0x90) == 0x10 && iicprobe(0x58) == 0x90) {
if (iicprobe(0x5b) == 0x12)
name = "it8712";
else if (iicprobe(0x5b) == 0x00)
name = "it8712f-a";
}
if (name == NULL && iicprobe(0x48) == addr &&
(iicprobe(0x40) & 0x80) == 0x00 && iicprobe(0x58) == 0xac)
name = "mtp008";
if (name == NULL) {
name = adm1032cloneprobe(addr);
if (name)
skip_fc = 1;
}
return (name);
}
char *
iic_probe_eeprom(struct device *self, u_int8_t addr)
{
u_int8_t type;
char *name = NULL;
type = iicprobe(0x02);
if (type < 4 || type > 16)
return (name);
name = "eeprom";
return (name);
}
void
iic_scan(struct device *self, struct i2cbus_attach_args *iba)
{
i2c_tag_t ic = iba->iba_tag;
struct i2c_attach_args ia;
struct iicprobelist *pl;
u_int8_t cmd = 0, addr;
char *name;
int i, j, k;
bzero(ignore_addrs, sizeof(ignore_addrs));
for (i = 0; probes[i].probe; i++) {
#if NIPMI > 0
extern int ipmi_enabled;
if ((probes[i].flags & PFLAG_SENSOR) && ipmi_enabled) {
printf("%s: skipping sensors to avoid ipmi0 interactions\n",
self->dv_xname);
continue;
}
#endif
pl = probes[i].pl;
for (j = 0; pl[j].start && pl[j].end; j++) {
for (addr = pl[j].start; addr <= pl[j].end; addr++) {
for (k = 0; k < sizeof(ignore_addrs); k++)
if (ignore_addrs[k] == addr)
break;
if (k < sizeof(ignore_addrs))
continue;
iic_acquire_bus(ic, 0);
if (iic_exec(ic, I2C_OP_READ_WITH_STOP, addr,
&cmd, sizeof cmd, NULL, 0, 0) == 0) {
iic_release_bus(ic, 0);
iicprobeinit(iba, addr);
name = (*probes[i].probe)(self, addr);
#ifndef I2C_VERBOSE
if (name == NULL)
name = "unknown";
#endif
if (name) {
memset(&ia, 0, sizeof(ia));
ia.ia_tag = iba->iba_tag;
ia.ia_addr = addr;
ia.ia_size = 1;
ia.ia_name = name;
if (config_found(self,
&ia, iic_print))
continue;
}
#ifdef I2C_VERBOSE
if ((probes[i].flags & PFLAG_SENSOR))
iic_dump(self, addr, name);
#endif
} else
iic_release_bus(ic, 0);
}
}
}
}