123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113 |
- /* $OpenBSD: i2c_scan.c,v 1.145 2015/05/29 00:37:10 uebayasi Exp $ */
- /*
- * Copyright (c) 2005 Theo de Raadt <deraadt@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
- /*
- * I2C bus scanning. We apologize in advance for the massive overuse of 0x.
- */
- #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;
- };
- /*
- * Addresses at which to probe for sensors. Skip address 0x4f, since
- * probing it seems to crash at least one Sony VAIO laptop. Only a
- * few chips can actually sit at that address, and vendors seem to
- * place those at other addresses, so this isn't a big loss.
- */
- struct iicprobelist probe_addrs_sensor[] = {
- { 0x18, 0x1f },
- { 0x20, 0x2f },
- { 0x48, 0x4e },
- { 0, 0 }
- };
- /*
- * Addresses at which to probe for eeprom devices.
- */
- 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 }
- };
- /*
- * Some Maxim 1617 clones MAY NOT even read cmd 0xfc! When it is
- * read, they will power-on-reset. Their default condition
- * (control register bit 0x80) therefore will be that they assert
- * /ALERT for the 5 potential errors that may occur. One of those
- * errors is that the external temperature diode is missing. This
- * is unfortunately a common choice of system designers, except
- * suddenly now we get a /ALERT, which may on some chipsets cause
- * us to receive an entirely unexpected SMI .. and then an NMI.
- *
- * As we probe each device, if we hit something which looks suspiciously
- * like it may potentially be a 1617 or clone, we immediately set this
- * variable to avoid reading that register offset.
- */
- 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 we think we are talking to an evil Maxim 1617 or clone,
- * avoid accessing this register because it is death.
- */
- 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 we think we are talking to an evil Maxim 1617 or clone,
- * avoid accessing this register because it is death.
- */
- 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 /* 9 bits in temperature registers */
- #define LM77TMASK 0xfff8 /* 13 bits in temperature registers */
- /*
- * The LM75/LM75A/LM77 family are very hard to detect. Thus, we check
- * for all other possible chips first. These chips do not have an
- * ID register. They do have a few quirks though:
- * - on the LM75 and LM77, registers 0x06 and 0x07 return whatever
- * value was read before
- * - the LM75 lacks registers 0x04 and 0x05, so those act as above
- * - the LM75A returns 0xffff for registers 0x04, 0x05, 0x06 and 0x07
- * - the chip registers loop every 8 registers
- * The downside is that we must read almost every register to guess
- * if this is an LM75, LM75A or LM77.
- */
- 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);
- /*
- * Sometimes the other probes can upset the chip, if we get 0xffff
- * the first time, try it once more.
- */
- if (temp == 0xffff)
- temp = iicprobew(LM75TEMP);
- conf = iicprobenc(LM75CONF);
- thyst = iicprobew(LM75Thyst);
- tos = iicprobew(LM75Tos);
- /* totally bogus data */
- if (conf == 0xff && temp == 0xffff && thyst == 0xffff)
- return (NULL);
- temp &= mask;
- thyst &= mask;
- tos &= mask;
- /* All values the same? Very unlikely */
- if (temp == thyst && thyst == tos)
- return (NULL);
- #if notsure
- /* more register aliasing effects that indicate not a lm75 */
- if ((temp >> 8) == conf)
- return (NULL);
- #endif
- /*
- * LM77/LM75 registers 6, 7
- * echo whatever was read just before them from reg 0, 1, or 2
- *
- * LM75A doesn't appear to do this, but does appear to reliably
- * return 0xffff
- */
- 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++;
- }
- /* Make sure either both registers echo, or neither does */
- if (echocount == 1 || ffffcount == 1)
- return (NULL);
- echoreg67 = (echocount == 0) ? 0 : 1;
- ffffreg67 = (ffffcount == 0) ? 0 : 1;
- /*
- * LM75 has no registers 4 or 5, and they will act as echos too
- *
- * LM75A doesn't appear to do this either, but does appear to
- * reliably return 0xffff
- */
- 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++;
- }
- /* Make sure either both registers echo, or neither does */
- if (echocount == 1 || ffffcount == 1)
- return (NULL);
- echoreg45 = (echocount == 0) ? 0 : 1;
- ffffreg45 = (ffffcount == 0) ? 0 : 1;
- /*
- * If we find that 4 and 5 are not echos, and don't return 0xffff
- * then based on whether the echo test of registers 6 and 7
- * succeeded or not, we may have an LM77
- */
- if (echoreg45 == 0 && ffffreg45 == 0 && echoreg67 == 1) {
- mask = LM77TMASK;
- /* mask size changed, must re-read for the next checks */
- thyst = iicprobew(LM75Thyst) & mask;
- tos = iicprobew(LM75Tos) & mask;
- tlow = iicprobew(LM77Tlow) & mask;
- thigh = iicprobew(LM77Thigh) & mask;
- }
- /* a real LM75/LM75A/LM77 repeats its registers.... */
- for (i = 0x08; i <= 0xf8; i += 8) {
- if (conf != iicprobenc(LM75CONF + i) ||
- thyst != (iicprobew(LM75Thyst + i) & mask) ||
- tos != (iicprobew(LM75Tos + i) & mask))
- return (NULL);
- /*
- * Check that the repeated registers 0x06 and 0x07 still
- * either echo or return 0xffff
- */
- 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);
- /*
- * Check that the repeated registers 0x04 and 0x05 still
- * either echo or return 0xffff. If they do neither, and
- * registers 0x06 and 0x07 echo, then we will be probing
- * for an LM77, so make sure those still repeat
- */
- 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);
- }
- /*
- * Given that we now know how the first eight registers behave and
- * that this behaviour is consistently repeated, we can now use
- * the following table:
- *
- * echoreg67 | echoreg45 | ffffreg67 | ffffreg45 | chip
- * ----------+-----------+-----------+-----------+------
- * 1 | 1 | 0 | 0 | LM75
- * 1 | 0 | 0 | 0 | LM77
- * 0 | 0 | 1 | 1 | LM75A
- */
- /* Convert the various flags into a single score */
- 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 /* defined(I2C_DEBUG) */
- 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);
- }
- /* 0xfe may be Maxim, or some other vendor */
- if (iicprobe(0xfe) == 0x4d)
- return ("max1617");
- /*
- * "xeontemp" is the name we choose for clone chips
- * which have all sorts of buggy bus interactions, such
- * as those we just probed. Why?
- * Intel is partly to blame for this situation.
- */
- 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;
- /*
- * Don't bother printing the most often repeated register
- * value, since it is often weird devices that respond
- * incorrectly, busted controller driver, or in the worst
- * case, it in mosts cases, the value 0xff.
- */
- 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 /* I2C_VERBOSE */
- char *
- iic_probe_sensor(struct device *self, u_int8_t addr)
- {
- char *name = NULL;
- skip_fc = 0;
- /*
- * Many I2C/SMBus devices use register 0x3e as a vendor ID
- * register.
- */
- switch (iicprobe(0x3e)) {
- case 0x01: /* National Semiconductor */
- /*
- * Some newer National products use a vendor code at
- * 0x3e of 0x01, and then 0x3f contains a product code
- * But some older products are missing a product code,
- * and contain who knows what in that register. We assume
- * that some employee was smart enough to keep the numbers
- * unique.
- */
- if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) &&
- (iicprobe(0x3f) == 0x73 || iicprobe(0x3f) == 0x72) &&
- iicprobe(0x00) == 0x00)
- name = "lm93"; /* product 0x72 is the prototype */
- else if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) &&
- iicprobe(0x3f) == 0x68)
- name = "lm96000"; /* adt7460 compat? */
- else if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) &&
- (iicprobe(0x3f) == 0x60 || iicprobe(0x3f) == 0x62))
- name = "lm85"; /* lm85C/B == adt7460 compat */
- else if ((addr & 0x7c) == 0x2c && /* addr 0b01011xx */
- iicprobe(0x48) == addr &&
- (iicprobe(0x3f) == 0x03 || iicprobe(0x3f) == 0x04) &&
- (iicprobe(0x40) & 0x80) == 0x00)
- name = "lm81";
- break;
- case 0x02: /* National Semiconductor? */
- if ((iicprobe(0x3f) & 0xfc) == 0x04)
- name = "lm87"; /* complete check */
- break;
- case 0x23: /* Analog Devices? */
- if (iicprobe(0x48) == addr &&
- (iicprobe(0x40) & 0x80) == 0x00 &&
- (addr & 0x7c) == 0x2c)
- name = "adm9240"; /* lm87 clone */
- break;
- case 0x41: /* Analog Devices */
- /*
- * Newer chips have a valid 0x3d product number, while
- * older ones sometimes encoded the product into the
- * upper half of the "step register" at 0x3f.
- */
- 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"; /* or adt7476a */
- else if (addr == 0x2e && iicprobe(0x3d) == 0x75)
- name = "adt7475";
- else if (iicprobe(0x3d) == 0x27 &&
- (iicprobe(0x3f) == 0x60 || iicprobe(0x3f) == 0x6a))
- name = "adm1027"; /* or adt7463 */
- else if (iicprobe(0x3d) == 0x27 &&
- (iicprobe(0x3f) == 0x62 || iicprobe(0x3f) == 0x6a))
- name = "adt7460"; /* complete check */
- 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"; /* or adt7468 */
- 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)
- /*
- * Revision 3 seems to be an adm1031 with
- * remote diode 2 shorted. Therefore we
- * cannot assume the reserved/unused bits of
- * register 0x03 and 0x06 are set to zero.
- */
- name = "adm1030"; /* complete check */
- 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"; /* complete check */
- else if ((addr & 0x7c) == 0x2c && /* addr 0b01011xx */
- (iicprobe(0x3f) & 0xf0) == 0x20 &&
- (iicprobe(0x40) & 0x80) == 0x00 &&
- (iicprobe(0x41) & 0xc0) == 0x00 &&
- (iicprobe(0x42) & 0xbc) == 0x00)
- name = "adm1025"; /* complete check */
- else if ((addr & 0x7c) == 0x2c && /* addr 0b01011xx */
- (iicprobe(0x3f) & 0xf0) == 0x10 &&
- (iicprobe(0x40) & 0x80) == 0x00)
- name = "adm1024"; /* complete check */
- else if ((iicprobe(0xff) & 0xf0) == 0x30)
- name = "adm1023";
- else if (addr == 0x2e &&
- (iicprobe(0x3f) & 0xf0) == 0xd0 &&
- (iicprobe(0x40) & 0x80) == 0x00)
- name = "adm1028"; /* adm1022 clone? */
- else if ((addr == 0x2c || addr == 0x2e || addr == 0x2f) &&
- (iicprobe(0x3f) & 0xf0) == 0xc0 &&
- (iicprobe(0x40) & 0x80) == 0x00)
- name = "adm1022";
- break;
- case 0x49: /* Texas Instruments */
- if ((addr == 0x2c || addr == 0x2e || addr == 0x2f) &&
- (iicprobe(0x3f) & 0xf0) == 0xc0 &&
- (iicprobe(0x40) & 0x80) == 0x00)
- name = "thmc50"; /* adm1022 clone */
- break;
- case 0x55: /* SMSC */
- if ((addr & 0x7c) == 0x2c && /* addr 0b01011xx */
- iicprobe(0x3f) == 0x20 &&
- (iicprobe(0x47) & 0x70) == 0x00 &&
- (iicprobe(0x49) & 0xfe) == 0x80)
- name = "47m192"; /* adm1025 compat */
- break;
- case 0x5c: /* SMSC */
- 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"; /* emc6d101, emc6d102, emc6d103 */
- 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: /* Andigilog */
- if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) &&
- iicprobe(0x3f) == 0x69 &&
- iicprobe(0x22) >= 0xaf && /* Vdd */
- (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) /* Vdd */
- name = "asc7621";
- break;
- case 0xa1: /* Philips */
- if ((iicprobe(0x3f) & 0xf0) == 0x20 &&
- (iicprobe(0x40) & 0x80) == 0x00 &&
- (iicprobe(0x41) & 0xc0) == 0x00 &&
- (iicprobe(0x42) & 0xbc) == 0x00)
- name = "ne1619"; /* adm1025 compat */
- break;
- case 0xda: /* Dallas Semiconductor */
- if (iicprobe(0x3f) == 0x01 && iicprobe(0x48) == addr &&
- (iicprobe(0x40) & 0x80) == 0x00)
- name = "ds1780"; /* lm87 clones */
- break;
- }
- switch (iicprobe(0x4e)) {
- case 0x41: /* Analog Devices */
- if ((addr == 0x48 || addr == 0x4a || addr == 0x4b) &&
- (iicprobe(0x4d) == 0x03 || iicprobe(0x4d) == 0x08 ||
- iicprobe(0x4d) == 0x07))
- name = "adt7516"; /* adt7517, adt7519 */
- break;
- }
- switch (iicprobe(0xfe)) {
- case 0x01: /* National Semiconductor */
- 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"; /* or lm99 */
- else if (addr == 0x4d &&
- iicprobe(0xff) == 0x34 && (iicprobe(0x03) & 0x2a) == 0 &&
- iicprobe(0x04) <= 0x09 && (iicprobe(0xbf) & 0xf8) == 0)
- name = "lm89-1"; /* or lm99-1 */
- else if (addr == 0x4c &&
- iicprobe(0xff) == 0x21 && (iicprobe(0x03) & 0x2a) == 0 &&
- iicprobe(0x04) <= 0x09 && (iicprobe(0xbf) & 0xf8) == 0)
- name = "lm90";
- break;
- case 0x23: /* Genesys Logic? */
- if ((addr == 0x4c) &&
- (iicprobe(0x03) & 0x3f) == 0x00 && iicprobe(0x04) <= 0x08)
- /*
- * Genesys Logic doesn't make the datasheet
- * for the GL523SM publically available, so
- * the checks above are nothing more than a
- * (conservative) educated guess.
- */
- name = "gl523sm";
- break;
- case 0x41: /* Analog Devices */
- if ((addr == 0x4c || addr == 0x4d) &&
- iicprobe(0xff) == 0x51 &&
- (iicprobe(0x03) & 0x1f) == 0x04 &&
- iicprobe(0x04) <= 0x0a) {
- /* If not in adm1032 compatibility mode. */
- 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"; /* or adm1021a */
- skip_fc = 1;
- } else if ((addr == 0x4c || addr == 0x4d || addr == 0x4e) &&
- (iicprobe(0x03) & 0x3f) == 0x00 &&
- iicprobe(0x04) <= 0x0a) {
- name = "adm1032"; /* or adm1020 */
- skip_fc = 1;
- }
- break;
- case 0x47: /* Global Mixed-mode Technology */
- 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: /* Maxim */
- 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"; /* max6647/8/9, max6692 */
- else if ((addr == 0x4c || addr == 0x4d || addr == 0x4e) &&
- (iicprobe(0x02) & 0x2b) == 0 &&
- (iicprobe(0x03) & 0x0f) == 0 && iicprobe(0x04) <= 0x09) {
- name = "max6657"; /* max6658, max6659 */
- skip_fc = 1;
- } else if ((addr >= 0x48 && addr <= 0x4f) &&
- (iicprobe(0x02) & 0x2b) == 0 &&
- (iicprobe(0x03) & 0x0f) == 0)
- name = "max6642";
- break;
- case 0x55: /* Texas Instruments */
- 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"; /* NXP sa56004x */
- skip_fc = 1;
- }
- break;
- }
- if (addr == iicprobe(0x48) &&
- ((iicprobe(0x4f) == 0x5c && (iicprobe(0x4e) & 0x80)) ||
- (iicprobe(0x4f) == 0xa3 && !(iicprobe(0x4e) & 0x80)))) {
- /*
- * We could toggle 0x4e bit 0x80, then re-read 0x4f to
- * see if the value changes to 0xa3 (indicating Winbond).
- * But we are trying to avoid writes.
- */
- if ((iicprobe(0x4e) & 0x07) == 0) {
- switch (iicprobe(0x58)) {
- case 0x10:
- case 0x11: /* rev 2? */
- name = "w83781d";
- break;
- case 0x21:
- name = "w83627hf";
- break;
- case 0x30:
- name = "w83782d";
- break;
- case 0x31:
- name = "as99127f"; /* rev 2 */
- 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 {
- /*
- * The BIOS left the chip in a non-zero
- * register bank. Assume it's a W83781D and
- * let lm(4) sort out the real model.
- */
- 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)))) {
- /*
- * We could toggle 0x00 bit 0x80, then re-read 0xfd to
- * see if the value changes to 0xa3 (indicating Nuvoton).
- * But we are trying to avoid writes.
- */
- 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)) {
- /*
- * We could toggle 0x4e bit 0x80, then re-read 0x4f to
- * see if the value changes to 0xc3 (indicating ASUS).
- * But we are trying to avoid writes.
- */
- if (iicprobe(0x58) == 0x31)
- name = "as99127f"; /* rev 1 */
- } else if ((addr == 0x2d || addr == 0x2e) &&
- addr * 2 == iicprobe(0x04) &&
- iicprobe(0x5d) == 0x19 && iicprobe(0x5e) == 0x34 &&
- iicprobe(0x5a) == 0x03 && iicprobe(0x5b) == 0x06) {
- name = "f75375"; /* Fintek */
- } else if (addr == 0x2d &&
- ((iicprobe(0x4f) == 0x06 && (iicprobe(0x4e) & 0x80)) ||
- (iicprobe(0x4f) == 0x94 && !(iicprobe(0x4e) & 0x80)))) {
- /*
- * We could toggle 0x4e bit 0x80, then re-read 0x4f to
- * see if the value changes to 0x94 (indicating ASUS).
- * But we are trying to avoid writes.
- *
- * NB. we won't match if the BIOS has selected a non-zero
- * register bank (set via 0x4e). We could select bank 0 so
- * we see the right registers, but that would require a
- * write. In general though, we bet no BIOS would leave us
- * in the wrong state.
- */
- 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) {
- /*
- * The GL518SM is really crappy. It has both byte and
- * word registers, and reading a word register with a
- * byte read command will make the device crap out and
- * hang the bus. This has nasty consequences on some
- * machines, like preventing warm reboots. The word
- * registers are 0x07 through 0x0c, so make sure the
- * checks above don't access those registers. We
- * don't want to do this check right up front though
- * since this chip is somewhat hard to detect (which
- * is why we check for every single fixed bit it has).
- */
- 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"; /* or se97b */
- } 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"; /* or mcp9843 */
- } 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"; /* or cat6095, prod 0x0813 */
- } 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"; /* or tse2002b3 */
- } else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x00b3 &&
- (iicprobew(0x07) & 0xffff) == 0x2912 &&
- (iicprobew(0x00) == 0x006f)) {
- name = "ts3000gb2"; /* or tse2002gb2 */
- } 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"; /* or at30tse002 */
- } 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) && /* registers address is 7 bits */
- iicprobe(0x20) == iicprobe(0xa0) &&
- iicprobe(0x21) == iicprobe(0xa1) &&
- iicprobe(0x22) == iicprobe(0xa2) &&
- iicprobe(0x07) == 0x00) { /* 0x00 to 0x0e are reserved */
- name = "lis331dl";
- } else if (name == NULL &&
- (addr & 0x78) == 0x48) { /* addr 0b1001xxx */
- name = lm75probe();
- }
- #if 0
- /*
- * XXX This probe needs to be improved; the driver does some
- * dangerous writes.
- */
- if (name == NULL && (addr & 0x7c) == 0x48 && /* addr 0b1001xxx */
- (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"; /* terrible probe */
- else if ((iicprobe(0xac) & 0x2e) == 0x2e)
- name = "ds1721"; /* terrible probe */
- }
- #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"; /* sis950 too */
- }
- 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);
- /* limit to SPD types seen in the wild */
- if (type < 4 || type > 11)
- return (name);
- /* more matching in driver(s) */
- 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;
- /* Perform RECEIVE BYTE command */
- 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);
- /* Some device exists */
- iicprobeinit(iba, addr);
- name = (*probes[i].probe)(self, addr);
- #ifndef I2C_VERBOSE
- if (name == NULL)
- name = "unknown";
- #endif /* !I2C_VERBOSE */
- 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 /* I2C_VERBOSE */
- } else
- iic_release_bus(ic, 0);
- }
- }
- }
- }
|