Module Name:    src
Committed By:   msaitoh
Date:           Fri Aug 18 04:07:51 UTC 2017

Modified Files:
        src/sys/dev/i2c: lm_i2c.c
        src/sys/dev/ic: nslm7x.c nslm7xvar.h
        src/sys/dev/isa: lm_isa_common.c wbsio.c wbsioreg.h

Log Message:
- WBSIO_ID_W83627DHG and newer devices have 12bit device ID. So, change sioid
  from 8bit to 16bit and check with it strictly.
- s/lm_match/nslm_match/
- split {wb,lm,def}_match() to XXX_match and XXX_attach().
- Rename lm_probe with lm_match and call {wb,nslm,def}_match() at the end of
  the function to check strictly.
- NCT610[246]D is different from otehrs, so add new nct6102d_sensors[] table.
- Register offsets of vendor ID and chip id of NCT610[246]D are different
  from others. When it failed reading vendor ID or chip ID, fallback to
  NCT610[246]D's register offsets.
- Add debug messages.


To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/sys/dev/i2c/lm_i2c.c
cvs rdiff -u -r1.69 -r1.70 src/sys/dev/ic/nslm7x.c
cvs rdiff -u -r1.32 -r1.33 src/sys/dev/ic/nslm7xvar.h
cvs rdiff -u -r1.5 -r1.6 src/sys/dev/isa/lm_isa_common.c
cvs rdiff -u -r1.14 -r1.15 src/sys/dev/isa/wbsio.c
cvs rdiff -u -r1.2 -r1.3 src/sys/dev/isa/wbsioreg.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/i2c/lm_i2c.c
diff -u src/sys/dev/i2c/lm_i2c.c:1.3 src/sys/dev/i2c/lm_i2c.c:1.4
--- src/sys/dev/i2c/lm_i2c.c:1.3	Thu Aug 17 05:27:48 2017
+++ src/sys/dev/i2c/lm_i2c.c	Fri Aug 18 04:07:51 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: lm_i2c.c,v 1.3 2017/08/17 05:27:48 msaitoh Exp $	*/
+/*	$NetBSD: lm_i2c.c,v 1.4 2017/08/18 04:07:51 msaitoh Exp $	*/
 
 /*-
  * Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lm_i2c.c,v 1.3 2017/08/17 05:27:48 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lm_i2c.c,v 1.4 2017/08/18 04:07:51 msaitoh Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -76,7 +76,7 @@ lm_i2c_match(device_t parent, cfdata_t m
 	sc.sc_lmsc.lm_readreg = lm_i2c_readreg;
 	sc.sc_tag = ia->ia_tag;
 	sc.sc_addr = ia->ia_addr;
-	rv = lm_probe(&sc.sc_lmsc);
+	rv = lm_match(&sc.sc_lmsc);
 
 	return rv;
 }

Index: src/sys/dev/ic/nslm7x.c
diff -u src/sys/dev/ic/nslm7x.c:1.69 src/sys/dev/ic/nslm7x.c:1.70
--- src/sys/dev/ic/nslm7x.c:1.69	Thu Aug 17 05:27:48 2017
+++ src/sys/dev/ic/nslm7x.c	Fri Aug 18 04:07:51 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: nslm7x.c,v 1.69 2017/08/17 05:27:48 msaitoh Exp $ */
+/*	$NetBSD: nslm7x.c,v 1.70 2017/08/18 04:07:51 msaitoh Exp $ */
 
 /*-
  * Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nslm7x.c,v 1.69 2017/08/17 05:27:48 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nslm7x.c,v 1.70 2017/08/18 04:07:51 msaitoh Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -72,10 +72,16 @@ __KERNEL_RCSID(0, "$NetBSD: nslm7x.c,v 1
 
 #define LM_REFRESH_TIMO	(2 * hz)	/* 2 seconds */
 
-static int lm_match(struct lm_softc *);
+static const struct wb_product *wb_lookup(struct lm_softc *,
+    const struct wb_product *, uint16_t);
 static int wb_match(struct lm_softc *);
+static int wb_attach(struct lm_softc *);
+static int nslm_match(struct lm_softc *);
+static int nslm_attach(struct lm_softc *);
 static int def_match(struct lm_softc *);
+static int def_attach(struct lm_softc *);
 static void wb_temp_diode_type(struct lm_softc *, int);
+static uint16_t wb_read_vendorid(struct lm_softc *);
 
 static void lm_refresh(void *);
 
@@ -94,32 +100,18 @@ static void wb_refresh_temp(struct lm_so
 static void wb_refresh_fanrpm(struct lm_softc *, int);
 static void wb_w83792d_refresh_fanrpm(struct lm_softc *, int);
 static void wb_nct6776f_refresh_fanrpm(struct lm_softc *, int);
-static const char * wb_nct67xx_id2str(uint8_t);
 
 static void as_refresh_temp(struct lm_softc *, int);
 
 struct lm_chip {
 	int (*chip_match)(struct lm_softc *);
+	int (*chip_attach)(struct lm_softc *);
 };
 
 static struct lm_chip lm_chips[] = {
-	{ wb_match },
-	{ lm_match },
-	{ def_match } /* Must be last */
-};
-
-static struct {
-	uint8_t id;
-	const char *str;
-} nct_chips[] = {
-	{WBSIO_ID_NCT6775F, "NCT6775F"},
-	{WBSIO_ID_NCT6776F, "NCT6776F"},
-	{WBSIO_ID_NCT5104D, "NCT5104D or 610[246]D"},
-	{WBSIO_ID_NCT6779D, "NCT6779D"},
-	{WBSIO_ID_NCT6791D, "NCT6791D"},
-	{WBSIO_ID_NCT6792D, "NCT6792D"},
-	{WBSIO_ID_NCT6793D, "NCT6793D"},
-	{WBSIO_ID_NCT6795D, "NCT6795D"},
+	{ wb_match,	wb_attach },
+	{ nslm_match,	nslm_attach },
+	{ def_match,	def_attach } /* Must be last */
 };
 
 /* LM78/78J/79/81 */
@@ -1784,6 +1776,137 @@ static const struct lm_sensor nct6776f_s
 	{ .desc = NULL }
 };
 
+/* NCT610[246]D */
+static const struct lm_sensor nct6102d_sensors[] = {
+	/* Voltage */
+	{
+		.desc = "VCore",
+		.type = ENVSYS_SVOLTS_DC,
+		.bank = 0,
+		.reg = 0x00,
+		.refresh = lm_refresh_volt,
+		.rfact = RFACT_NONE
+	},
+	{
+		.desc = "VIN0",
+		.type = ENVSYS_SVOLTS_DC,
+		.bank = 0,
+		.reg = 0x01,
+		.refresh = lm_refresh_volt,
+		.rfact = RFACT_NONE
+	},
+	{
+		.desc = "AVCC",
+		.type = ENVSYS_SVOLTS_DC,
+		.bank = 0,
+		.reg = 0x02,
+		.refresh = lm_refresh_volt,
+		.rfact = RFACT(34, 34) / 2
+	},
+	{
+		.desc = "3VCC",
+		.type = ENVSYS_SVOLTS_DC,
+		.bank = 0,
+		.reg = 0x03,
+		.refresh = lm_refresh_volt,
+		.rfact = RFACT(34, 34) / 2
+	},
+	{
+		.desc = "VIN1",
+		.type = ENVSYS_SVOLTS_DC,
+		.bank = 0,
+		.reg = 0x04,
+		.refresh = lm_refresh_volt,
+		.rfact = RFACT_NONE
+	},
+	{
+		.desc = "VIN2",
+		.type = ENVSYS_SVOLTS_DC,
+		.bank = 0,
+		.reg = 0x05,
+		.refresh = lm_refresh_volt,
+		.rfact = RFACT(34, 34) / 2
+	},
+	{
+		.desc = "+3.3VSB",
+		.type = ENVSYS_SVOLTS_DC,
+		.bank = 0,
+		.reg = 0x07,
+		.refresh = lm_refresh_volt,
+		.rfact = RFACT(34, 34) / 2
+	},
+	{
+		.desc = "VBAT",
+		.type = ENVSYS_SVOLTS_DC,
+		.bank = 0,
+		.reg = 0x08,
+		.refresh = lm_refresh_volt,
+		.rfact = RFACT(34, 34) / 2
+	},
+	{
+		.desc = "VTT",
+		.type = ENVSYS_SVOLTS_DC,
+		.bank = 0,
+		.reg = 0x09,
+		.refresh = lm_refresh_volt,
+		.rfact = RFACT_NONE
+	},
+
+	/* Temperature */
+	{
+		.desc = "MB Temperature",
+		.type = ENVSYS_STEMP,
+		.bank = 0,
+		.reg = 0x18,
+		.refresh = lm_refresh_temp,
+		.rfact = 0
+	},
+	{
+		.desc = "CPU Temperature",
+		.type = ENVSYS_STEMP,
+		.bank = 0,
+		.reg = 0x19,
+		.refresh = lm_refresh_temp,
+		.rfact = 0
+	},
+	{
+		.desc = "Aux Temp",
+		.type = ENVSYS_STEMP,
+		.bank = 0,
+		.reg = 0x1a,
+		.refresh = lm_refresh_temp,
+		.rfact = 0
+	},
+
+	/* Fans */
+	{
+		.desc = "System Fan",
+		.type = ENVSYS_SFANRPM,
+		.bank = 0,
+		.reg = 0x30,
+		.refresh = wb_nct6776f_refresh_fanrpm,
+		.rfact = 0
+	},
+	{
+		.desc = "CPU Fan",
+		.type = ENVSYS_SFANRPM,
+		.bank = 0,
+		.reg = 0x32,
+		.refresh = wb_nct6776f_refresh_fanrpm,
+		.rfact = 0
+	},
+	{
+		.desc = "Aux Fan",
+		.type = ENVSYS_SFANRPM,
+		.bank = 0,
+		.reg = 0x34,
+		.refresh = wb_nct6776f_refresh_fanrpm,
+		.rfact = 0
+	},
+
+	{ .desc = NULL }
+};
+
 /* NCT6779D */
 static const struct lm_sensor nct6779d_sensors[] = {
 	/* Voltage */
@@ -2003,6 +2126,44 @@ static const struct lm_sensor nct6779d_s
 	{ .desc = NULL }
 };
 
+static const struct wb_product wb_products[] = {
+    { WB_CHIPID_W83627HF,   "W83627HF",	w83627hf_sensors, NULL },
+    { WB_CHIPID_W83627THF,  "W83627THF",w83637hf_sensors, NULL },
+    { WB_CHIPID_W83627EHF_A,"W83627EHF-A",w83627ehf_sensors,NULL },
+    { WB_CHIPID_W83627EHF,  "W83627EHF",w83627ehf_sensors,NULL },
+    { WB_CHIPID_W83627DHG,  NULL,	NULL,   NULL },
+    { WB_CHIPID_W83637HF,   "W83637HF",	w83637hf_sensors, NULL },
+    { WB_CHIPID_W83697HF,   "W83697HF",	w83697hf_sensors, NULL },
+    { WB_CHIPID_W83781D,    "W83781D",	w83781d_sensors,  NULL },
+    { WB_CHIPID_W83781D_2,  "W83781D",	w83781d_sensors,  NULL },
+    { WB_CHIPID_W83782D,    "W83782D",	w83782d_sensors,  NULL },
+    { WB_CHIPID_W83783S,    "W83783S",	w83783s_sensors,  NULL },
+    { WB_CHIPID_W83791D,    "W83791D",	w83791d_sensors,  NULL },
+    { WB_CHIPID_W83791SD,   "W83791SD",	NULL,		  NULL },
+    { WB_CHIPID_W83792D,    "W83792D",	w83792d_sensors,  NULL },
+    { WB_CHIPID_AS99127F,   NULL,	NULL,  NULL },
+    { 0, NULL, NULL, NULL }
+};
+
+static const struct wb_product wbsio_products[] = {
+    { WBSIO_ID_W83627DHG,   "W83627DHG",w83627dhg_sensors,NULL },
+    { WBSIO_ID_NCT6775F,    "NCT6775F", nct6776f_sensors, NULL },
+    { WBSIO_ID_NCT6776F,    "NCT6776F", nct6776f_sensors, NULL },
+    { WBSIO_ID_NCT5104D,    "NCT5104D or 610[246]D",nct6102d_sensors,NULL },
+    { WBSIO_ID_NCT6779D,    "NCT6779D", nct6779d_sensors, NULL },
+    { WBSIO_ID_NCT6791D,    "NCT6791D", nct6779d_sensors, NULL },
+    { WBSIO_ID_NCT6792D,    "NCT6792D", nct6779d_sensors, NULL },
+    { WBSIO_ID_NCT6793D,    "NCT6793D", nct6779d_sensors, NULL },
+    { WBSIO_ID_NCT6795D,    "NCT6795D", nct6779d_sensors, NULL },
+    { 0, NULL, NULL, NULL }
+};
+
+static const struct wb_product as99127f_products[] = {
+    { WB_VENDID_ASUS,       "AS99127F", w83781d_sensors,  NULL },
+    { WB_VENDID_WINBOND,    "AS99127F rev 2",as99127f_sensors,NULL },
+    { 0, NULL, NULL, NULL }
+};
+
 static void
 lm_generic_banksel(struct lm_softc *lmsc, uint8_t bank)
 {
@@ -2010,16 +2171,16 @@ lm_generic_banksel(struct lm_softc *lmsc
 }
 
 /*
- * bus independent probe
+ * bus independent match
  *
  * prerequisites:  lmsc contains valid lm_{read,write}reg() routines
  * and associated bus access data is present in attachment's softc
  */
 int
-lm_probe(struct lm_softc *lmsc)
+lm_match(struct lm_softc *lmsc)
 {
 	uint8_t cr;
-	int rv;
+	int i, rv;
 
 	/* Perform LM78 reset */
 	/*(*lmsc->lm_writereg)(lmsc, LMD_CONFIG, 0x80); */
@@ -2027,24 +2188,52 @@ lm_probe(struct lm_softc *lmsc)
 	cr = (*lmsc->lm_readreg)(lmsc, LMD_CONFIG);
 
 	/* XXX - spec says *only* 0x08! */
-	if ((cr == 0x08) || (cr == 0x01) || (cr == 0x03) || (cr == 0x06))
-		rv = 1;
-	else
-		rv = 0;
+	if ((cr != 0x08) && (cr != 0x01) && (cr != 0x03) && (cr != 0x06))
+		return 0;
+
+	DPRINTF(("%s: 0x80 check: cr = %x\n", __func__, cr));
 
-	DPRINTF(("%s: rv = %d, cr = %x\n", __func__, rv, cr));
+	for (i = 0; i < __arraycount(lm_chips); i++)
+		if ((rv = lm_chips[i].chip_match(lmsc)) != 0)
+			return rv;
 
-	return rv;
+	return 0;
+}
+
+int
+nslm_match(struct lm_softc *sc)
+{
+	uint8_t chipid;
+
+	/* See if we have an LM78/LM78J/LM79 or LM81 */
+	chipid = (*sc->lm_readreg)(sc, LMD_CHIPID) & LM_ID_MASK;
+	switch(chipid) {
+	case LM_ID_LM78:
+	case LM_ID_LM78J:
+	case LM_ID_LM79:
+	case LM_ID_LM81:
+		break;
+	default:
+		return 0;
+	}
+	DPRINTF(("%s: chipid %x\n", __func__, chipid));
+	return 1;
 }
 
 void
 lm_attach(struct lm_softc *lmsc)
 {
 	uint32_t i;
+	int rv;
 
-	for (i = 0; i < __arraycount(lm_chips); i++)
-		if (lm_chips[i].chip_match(lmsc))
-			break;
+	for (i = 0; i < __arraycount(lm_chips); i++) {
+		if (lm_chips[i].chip_match(lmsc) != 0) {
+			if (lm_chips[i].chip_attach(lmsc) == 0)
+				break;
+			else
+				return;
+		}
+	}
 
 	/* Start the monitoring loop */
 	(*lmsc->lm_writereg)(lmsc, LMD_CONFIG, 0x01);
@@ -2053,9 +2242,11 @@ lm_attach(struct lm_softc *lmsc)
 	/* Initialize sensors */
 	for (i = 0; i < lmsc->numsensors; i++) {
 		lmsc->sensors[i].state = ENVSYS_SINVALID;
-		if (sysmon_envsys_sensor_attach(lmsc->sc_sme,
-						&lmsc->sensors[i])) {
+		if ((rv = sysmon_envsys_sensor_attach(lmsc->sc_sme,
+			    &lmsc->sensors[i])) != 0) {
 			sysmon_envsys_destroy(lmsc->sc_sme);
+			aprint_error_dev(lmsc->sc_dev,
+			    "sysmon_envsys_sensor_attach() returned %d\n", rv);
 			return;
 		}
 	}
@@ -2102,7 +2293,7 @@ lm_refresh(void *arg)
 }
 
 static int
-lm_match(struct lm_softc *sc)
+nslm_attach(struct lm_softc *sc)
 {
 	const char *model = NULL;
 	uint8_t chipid;
@@ -2123,7 +2314,7 @@ lm_match(struct lm_softc *sc)
 		model = "LM81";
 		break;
 	default:
-		return 0;
+		return -1;
 	}
 
 	aprint_naive("\n");
@@ -2133,22 +2324,29 @@ lm_match(struct lm_softc *sc)
 
 	lm_setup_sensors(sc, lm78_sensors);
 	sc->refresh_sensor_data = lm_refresh_sensor_data;
-	return 1;
+	return 0;
 }
 
 static int
 def_match(struct lm_softc *sc)
 {
+
+	return 1;
+}
+
+static int
+def_attach(struct lm_softc *sc)
+{
 	uint8_t chipid;
 
 	chipid = (*sc->lm_readreg)(sc, LMD_CHIPID) & LM_ID_MASK;
 	aprint_naive("\n");
 	aprint_normal("\n");
-	aprint_error_dev(sc->sc_dev, "Unknown chip (ID %02x)\n", chipid);
+	aprint_error_dev(sc->sc_dev, "Unknown chip (ID 0x%02x)\n", chipid);
 
 	lm_setup_sensors(sc, lm78_sensors);
 	sc->refresh_sensor_data = lm_refresh_sensor_data;
-	return 1;
+	return 0;
 }
 
 static void
@@ -2199,152 +2397,236 @@ wb_temp_diode_type(struct lm_softc *sc, 
 	}
 }
 
+static const struct wb_product *
+wb_lookup(struct lm_softc *sc, const struct wb_product *products, uint16_t id)
+{
+	const struct wb_product *prod = products;
+	int i = 0;
+
+	while (prod[i].id != 0) {
+		if (prod[i].id != id) {
+			i++;
+			continue;
+		}
+		if (prod[i].str == NULL) {
+			if (products == wb_products) {
+				if (id == WB_CHIPID_W83627DHG) {
+					/*
+					 *  Lookup wbsio_products
+					 * with WBSIO_ID.
+					 */
+					return wb_lookup(sc, wbsio_products,
+					    sc->sioid);
+				} else if (id == WB_CHIPID_AS99127F) {
+					/*
+					 *  Lookup as99127f_products
+					 * with WB_VENDID.
+					 */
+					return wb_lookup(sc, as99127f_products,
+					    wb_read_vendorid(sc));
+				} else
+					return NULL; /* not occur */
+			}
+			return NULL; /* not occur */
+		}
+		return &prod[i];
+	}
+
+	/* Not found */
+	return NULL;
+}
+
+static uint16_t
+wb_read_vendorid(struct lm_softc *sc)
+{
+	uint16_t vendid;
+	uint8_t vendidreg;
+	uint8_t banksel;
+
+	/* Save bank */
+	banksel = (*sc->lm_readreg)(sc, WB_BANKSEL);
+
+	/* Check default vendor ID register first */
+	vendidreg = WB_VENDID;
+
+retry:
+	/* Read vendor ID */
+	lm_generic_banksel(sc, WB_BANKSEL_HBAC);
+	vendid = (*sc->lm_readreg)(sc, vendidreg) << 8;
+	lm_generic_banksel(sc, 0);
+	vendid |= (*sc->lm_readreg)(sc, vendidreg);
+
+	if ((vendidreg == WB_VENDID)
+	    &&  (vendid != WB_VENDID_WINBOND && vendid != WB_VENDID_ASUS)) {
+		/* If it failed, try NCT6102 vendor ID register */
+		vendidreg = WB_NCT6102_VENDID;
+		goto retry;
+	} else if ((vendidreg == WB_NCT6102_VENDID)
+	    && (vendid != WB_VENDID_WINBOND))
+		vendid = 0; /* XXX */
+	
+	/* Restore bank */
+	lm_generic_banksel(sc, banksel);
+
+	return vendid;
+}
+
+static uint8_t
+wb_read_chipid(struct lm_softc *sc)
+{
+	const struct wb_product *prod;
+	uint8_t chipidreg, chipid, banksel;
+
+	/* Save bank */
+	banksel = (*sc->lm_readreg)(sc, WB_BANKSEL);
+
+	/* Check default vendor ID register first */
+	chipidreg = WB_BANK0_CHIPID;
+	lm_generic_banksel(sc, WB_BANKSEL_B0);
+
+retry:
+	(void)(*sc->lm_readreg)(sc, LMD_CHIPID);
+	chipid = (*sc->lm_readreg)(sc, chipidreg);
+	prod = wb_lookup(sc, wb_products, chipid);
+	if (prod == NULL) {
+		if (chipidreg == WB_BANK0_CHIPID) {
+			chipidreg = WB_BANK0_NCT6102_CHIPID;
+			goto retry;
+		} else
+			chipid = 0;
+	}
+	/* Restore bank */
+	lm_generic_banksel(sc, banksel);
+
+	return chipid;
+}
+
 static int
 wb_match(struct lm_softc *sc)
 {
+	const struct wb_product *prod;
+	uint16_t vendid;
+	uint8_t chipid;
+
+	/* Read vendor ID */
+	vendid = wb_read_vendorid(sc);
+	DPRINTF(("%s: winbond vend id 0x%x\n", __func__, vendid));
+	if ((vendid != WB_VENDID_WINBOND && vendid != WB_VENDID_ASUS))
+		return 0;
+
+	/* Read device/chip ID */
+	chipid = wb_read_chipid(sc);
+	DPRINTF(("%s: winbond chip id 0x%x\n", __func__, chipid));
+	prod = wb_lookup(sc, wb_products, chipid);
+
+	if (prod == NULL) {
+		if (vendid == WB_VENDID_WINBOND)
+			return 1; /* Generic match */
+		else
+			return 0;
+	}
+	DPRINTF(("%s: chipid %02x, sioid = %04x\n", __func__, chipid,
+		sc->sioid));
+
+	return 10; /* found */
+}
+
+static int
+wb_attach(struct lm_softc *sc)
+{
+	device_t dev = sc->sc_dev;
+	const struct wb_product *prod;
 	const char *model = NULL;
 	const char *vendor = "Winbond";
+	const struct lm_sensor *sensors;
 	uint16_t vendid;
 	uint8_t banksel;
 	int cf_flags;
 
 	aprint_naive("\n");
 	aprint_normal("\n");
-	/* Read vendor ID */
-	banksel = (*sc->lm_readreg)(sc, WB_BANKSEL);
-	lm_generic_banksel(sc, WB_BANKSEL_HBAC);
-	vendid = (*sc->lm_readreg)(sc, WB_VENDID) << 8;
-	lm_generic_banksel(sc, 0);
-	vendid |= (*sc->lm_readreg)(sc, WB_VENDID);
-	DPRINTF(("%s: winbond vend id 0x%x\n", __func__, vendid));
-	if (vendid != WB_VENDID_WINBOND && vendid != WB_VENDID_ASUS)
-		return 0;
-
 	/* Read device/chip ID */
-	lm_generic_banksel(sc, WB_BANKSEL_B0);
-	(void)(*sc->lm_readreg)(sc, LMD_CHIPID);
-	sc->chipid = (*sc->lm_readreg)(sc, WB_BANK0_CHIPID);
-	lm_generic_banksel(sc, banksel);
-	cf_flags = device_cfdata(sc->sc_dev)->cf_flags;
+	sc->chipid = wb_read_chipid(sc);
 	DPRINTF(("%s: winbond chip id 0x%x\n", __func__, sc->chipid));
 
+	if ((prod = wb_lookup(sc, wb_products, sc->chipid)) != NULL) {
+		switch (prod->str[0]) {
+		case 'W':
+			vendor = "Winbond";
+			break;
+		case 'A':
+			vendor = "ASUS";
+			break;
+		case 'N':
+			vendor = "Nuvoton";
+			break;
+		default:
+			aprint_error_dev(dev, "Unknown model (%s)\n", model);
+			return -1;
+		}
+		model = prod->str;
+		sensors = prod->sensors;
+		sc->refresh_sensor_data = wb_refresh_sensor_data;
+		if (prod->extattach != NULL)
+			prod->extattach(sc);
+	} else {
+		vendid = wb_read_vendorid(sc);
+		if (vendid == WB_VENDID_WINBOND) {
+			vendor = "Winbond";
+			model = "unknown-model";
+
+			/* Handle as a standard LM78. */
+			sensors = lm78_sensors;
+			sc->refresh_sensor_data = lm_refresh_sensor_data;
+		} else {
+			aprint_error_dev(dev, "Unknown chip (ID %02x)\n",
+			    sc->chipid);
+			return -1;
+		}
+	}
+	
+	cf_flags = device_cfdata(dev)->cf_flags;
+
+	if (sensors != NULL) {
+		lm_setup_sensors(sc, sensors);
+
+		/* XXX Is this correct? Check all datasheets. */
+		switch (sc->chipid) {
+		case WB_CHIPID_W83627EHF_A:
+		case WB_CHIPID_W83781D:
+		case WB_CHIPID_W83781D_2:
+		case WB_CHIPID_W83791SD:
+		case WB_CHIPID_W83792D:
+		case WB_CHIPID_AS99127F:
+			break;
+		default:
+			wb_temp_diode_type(sc, cf_flags);
+			break;
+		}
+	}
+
+	/* XXX Is this correct? Check all datasheets. */
+	banksel = (*sc->lm_readreg)(sc, WB_BANKSEL);
 	switch(sc->chipid) {
-	case WB_CHIPID_W83627HF:
-		model = "W83627HF";
-		lm_setup_sensors(sc, w83627hf_sensors);
-		wb_temp_diode_type(sc, cf_flags);
-		break;
 	case WB_CHIPID_W83627THF:
-		model = "W83627THF";
 		lm_generic_banksel(sc, WB_BANKSEL_B0);
 		if ((*sc->lm_readreg)(sc, WB_BANK0_CONFIG) & WB_CONFIG_VMR9)
 			sc->vrm9 = 1;
 		lm_generic_banksel(sc, banksel);
-		lm_setup_sensors(sc, w83637hf_sensors);
-		wb_temp_diode_type(sc, cf_flags);
-		break;
-	case WB_CHIPID_W83627EHF_A:
-		model = "W83627EHF-A";
-		lm_setup_sensors(sc, w83627ehf_sensors);
-		break;
-	case WB_CHIPID_W83627EHF:
-		model = "W83627EHF";
-		lm_setup_sensors(sc, w83627ehf_sensors);
-		wb_temp_diode_type(sc, cf_flags);
-		break;
-	case WB_CHIPID_W83627DHG:
-		model = wb_nct67xx_id2str(sc->sioid);
-		if (model != NULL) {
-			vendor = "Nuvoton";
-			switch (sc->sioid) {
-			case WBSIO_ID_NCT6775F:
-			case WBSIO_ID_NCT6776F:
-			case WBSIO_ID_NCT5104D:
-				lm_setup_sensors(sc, nct6776f_sensors);
-				break;
-			case WBSIO_ID_NCT6779D:
-			case WBSIO_ID_NCT6791D:
-			case WBSIO_ID_NCT6792D:
-			case WBSIO_ID_NCT6793D:
-			case WBSIO_ID_NCT6795D:
-				lm_setup_sensors(sc, nct6779d_sensors);
-				break;
-			default:
-				panic("%s: unknown id (%02x)", __func__,
-				      sc->sioid);
-				break;
-			}
-		} else {
-			model = "W83627DHG";
-			lm_setup_sensors(sc, w83627dhg_sensors);
-			break;
-		}
-		wb_temp_diode_type(sc, cf_flags);
 		break;
 	case WB_CHIPID_W83637HF:
-		model = "W83637HF";
 		lm_generic_banksel(sc, WB_BANKSEL_B0);
 		if ((*sc->lm_readreg)(sc, WB_BANK0_CONFIG) & WB_CONFIG_VMR9)
 			sc->vrm9 = 1;
 		lm_generic_banksel(sc, banksel);
-		lm_setup_sensors(sc, w83637hf_sensors);
-		wb_temp_diode_type(sc, cf_flags);
-		break;
-	case WB_CHIPID_W83697HF:
-		model = "W83697HF";
-		lm_setup_sensors(sc, w83697hf_sensors);
-		wb_temp_diode_type(sc, cf_flags);
-		break;
-	case WB_CHIPID_W83781D:
-	case WB_CHIPID_W83781D_2:
-		model = "W83781D";
-		lm_setup_sensors(sc, w83781d_sensors);
-		break;
-	case WB_CHIPID_W83782D:
-		model = "W83782D";
-		lm_setup_sensors(sc, w83782d_sensors);
-		wb_temp_diode_type(sc, cf_flags);
-		break;
-	case WB_CHIPID_W83783S:
-		model = "W83783S";
-		lm_setup_sensors(sc, w83783s_sensors);
-		wb_temp_diode_type(sc, cf_flags);
-		break;
-	case WB_CHIPID_W83791D:
-		model = "W83791D";
-		lm_setup_sensors(sc, w83791d_sensors);
-		wb_temp_diode_type(sc, cf_flags);
-		break;
-	case WB_CHIPID_W83791SD:
-		model = "W83791SD";
-		break;
-	case WB_CHIPID_W83792D:
-		model = "W83792D";
-		lm_setup_sensors(sc, w83792d_sensors);
-		break;
-	case WB_CHIPID_AS99127F:
-		vendor = "ASUS";
-		if (vendid == WB_VENDID_ASUS) {
-			model = "AS99127F";
-			lm_setup_sensors(sc, w83781d_sensors);
-		} else {
-			model = "AS99127F rev 2";
-			lm_setup_sensors(sc, as99127f_sensors);
-		}
 		break;
 	default:
-		aprint_normal_dev(sc->sc_dev,
-		    "unknown Winbond chip (ID 0x%x)\n", sc->chipid);
-		/* Handle as a standard LM78. */
-		lm_setup_sensors(sc, lm78_sensors);
-		sc->refresh_sensor_data = lm_refresh_sensor_data;
-		return 1;
+		break;
 	}
 
-	aprint_normal_dev(sc->sc_dev, "%s %s Hardware monitor\n", vendor, model);
+	aprint_normal_dev(dev, "%s %s Hardware monitor\n", vendor, model);
 
-	sc->refresh_sensor_data = wb_refresh_sensor_data;
-	return 1;
+	return 0;
 }
 
 static void
@@ -2621,20 +2903,6 @@ wb_nct6776f_refresh_fanrpm(struct lm_sof
 	}
 }
 
-static const char *
-wb_nct67xx_id2str(uint8_t id)
-{
-	int i;
-
-	for (i = 0; i < __arraycount(nct_chips); i++) {
-		if (nct_chips[i].id == id)
-		    return nct_chips[i].str;
-	}
-
-	/* Not Found */
-	return NULL;
-}
-
 static void
 wb_w83792d_refresh_fanrpm(struct lm_softc *sc, int n)
 {

Index: src/sys/dev/ic/nslm7xvar.h
diff -u src/sys/dev/ic/nslm7xvar.h:1.32 src/sys/dev/ic/nslm7xvar.h:1.33
--- src/sys/dev/ic/nslm7xvar.h:1.32	Thu Aug 17 05:27:48 2017
+++ src/sys/dev/ic/nslm7xvar.h	Fri Aug 18 04:07:51 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: nslm7xvar.h,v 1.32 2017/08/17 05:27:48 msaitoh Exp $ */
+/*	$NetBSD: nslm7xvar.h,v 1.33 2017/08/18 04:07:51 msaitoh Exp $ */
 
 /*-
  * Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -86,6 +86,7 @@
 #define WB_PIN		0x4b	/* Pin Control */
 #define WB_BANKSEL	0x4e	/* Bank Select */
 #define WB_VENDID	0x4f	/* Vendor ID */
+#define WB_NCT6102_VENDID 0xfe	/* Vendor ID for NCT610[246] */
 
 /* Bank 0 regs */
 #define WB_BANK0_CHIPID	0x58	/* Chip ID */
@@ -96,6 +97,7 @@
 #define WB_BANK0_FAN5	0xbb	/* Fan 5 reading (W83791D only) */
 
 #define WB_BANK0_CONFIG	0x18	/* VRM & OVT Config (W83627THF/W83637HF) */
+#define WB_BANK0_NCT6102_CHIPID	0xff /* Chip ID for NCT610[246] */
 
 /* Bank 1 registers */
 #define WB_BANK1_T2H	0x50	/* Temperature 2 High Byte */
@@ -170,7 +172,7 @@ struct lm_softc {
 	const struct lm_sensor *lm_sensors;
 	uint8_t	chipid;
 	uint8_t	vrm9;
-	uint8_t sioid;
+	uint16_t sioid;
 };
 
 struct lm_sensor {
@@ -182,8 +184,15 @@ struct lm_sensor {
 	int rfact;
 };
 
+struct wb_product {
+	uint16_t id; /* WB_CHIPID(8b) or WBSIO_ID(16b) or WB_VENDID(16b) */
+	const char *str;
+	const struct lm_sensor *sensors;
+	void (*extattach)(struct lm_softc *);
+};
+
+int 	lm_match(struct lm_softc *);
 void 	lm_attach(struct lm_softc *);
 void	lm_detach(struct lm_softc *);
-int 	lm_probe(struct lm_softc *);
 
 #endif /* _DEV_ISA_NSLM7XVAR_H_ */

Index: src/sys/dev/isa/lm_isa_common.c
diff -u src/sys/dev/isa/lm_isa_common.c:1.5 src/sys/dev/isa/lm_isa_common.c:1.6
--- src/sys/dev/isa/lm_isa_common.c:1.5	Thu Aug 17 05:27:48 2017
+++ src/sys/dev/isa/lm_isa_common.c	Fri Aug 18 04:07:51 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: lm_isa_common.c,v 1.5 2017/08/17 05:27:48 msaitoh Exp $ */
+/*	$NetBSD: lm_isa_common.c,v 1.6 2017/08/18 04:07:51 msaitoh Exp $ */
 
 /*-
  * Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lm_isa_common.c,v 1.5 2017/08/17 05:27:48 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lm_isa_common.c,v 1.6 2017/08/18 04:07:51 msaitoh Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -80,13 +80,12 @@ lm_isa_match(device_t parent, cfdata_t m
 	if (bus_space_map(ia->ia_iot, ia->ia_io[0].ir_addr, 8, 0, &ioh))
 		return 0;
 
-
 	/* Bus independent probe */
 	sc.lm_iot = ia->ia_iot;
 	sc.lm_ioh = ioh;
 	sc.lmsc.lm_writereg = lm_isa_writereg;
 	sc.lmsc.lm_readreg = lm_isa_readreg;
-	rv = lm_probe(&sc.lmsc);
+	rv = lm_match(&sc.lmsc);
 
 	bus_space_unmap(ia->ia_iot, ioh, 8);
 
@@ -122,7 +121,7 @@ lm_isa_attach(device_t parent, device_t 
 	sc->lmsc.lm_writereg = lm_isa_writereg;
 	sc->lmsc.lm_readreg = lm_isa_readreg;
 	/* pass wbsio Device ID */
-	sc->lmsc.sioid = (uint8_t)(uintptr_t)ia->ia_aux;
+	sc->lmsc.sioid = (uint16_t)(uintptr_t)ia->ia_aux;
 
 	lm_attach(&sc->lmsc);
 }

Index: src/sys/dev/isa/wbsio.c
diff -u src/sys/dev/isa/wbsio.c:1.14 src/sys/dev/isa/wbsio.c:1.15
--- src/sys/dev/isa/wbsio.c:1.14	Thu Aug 17 05:32:04 2017
+++ src/sys/dev/isa/wbsio.c	Fri Aug 18 04:07:51 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: wbsio.c,v 1.14 2017/08/17 05:32:04 msaitoh Exp $	*/
+/*	$NetBSD: wbsio.c,v 1.15 2017/08/18 04:07:51 msaitoh Exp $	*/
 /*	$OpenBSD: wbsio.c,v 1.10 2015/03/14 03:38:47 jsg Exp $	*/
 /*
  * Copyright (c) 2008 Mark Kettenis <kette...@openbsd.org>
@@ -43,7 +43,36 @@ struct wbsio_softc {
 	struct isa_io		sc_io;
 };
 
-static int	wbsio_probe(device_t, cfdata_t, void *);
+static const struct wbsio_product {
+	uint16_t id;
+	bool	idis12bits;
+	const char *str;
+} wbsio_products[] = {
+	{ WBSIO_ID_W83627HF,	false,	"W83627HF" },
+	{ WBSIO_ID_W83697HF,	false,	"W83697HF" },
+	{ WBSIO_ID_W83637HF,	false,	"W83637HF" },
+	{ WBSIO_ID_W83627THF,	false,	"W83627THF" },
+	{ WBSIO_ID_W83687THF,	false,	"W83687THF" },
+	{ WBSIO_ID_W83627DHG,	true,	"W83627DHG" },
+	{ WBSIO_ID_W83627DHGP,	true,	"W83627DHG-P" },
+	{ WBSIO_ID_W83627EHF,	true,	"W83627EHF" },
+	{ WBSIO_ID_W83627SF,	true,	"W83627SF" },
+	{ WBSIO_ID_W83627UHG,	true,	"W83627UHG" },
+	{ WBSIO_ID_W83667HG,	true,	"W83667HG" },
+	{ WBSIO_ID_W83667HGB,	true,	"W83667HGB" },
+	{ WBSIO_ID_W83697UG,	true,	"W83697UG" },
+	{ WBSIO_ID_NCT6775F,	true,	"NCT6775F" },
+	{ WBSIO_ID_NCT6776F,	true,	"NCT6776F" },
+	{ WBSIO_ID_NCT5104D,	true,	"NCT5104D or 610[246]D" },
+	{ WBSIO_ID_NCT6779D,	true,	"NCT6779D" },
+	{ WBSIO_ID_NCT6791D,	true,	"NCT6791D" },
+	{ WBSIO_ID_NCT6792D,	true,	"NCT6792D" },
+	{ WBSIO_ID_NCT6793D,	true,	"NCT6793D" },
+	{ WBSIO_ID_NCT6795D,	true,	"NCT6795D" },
+};
+
+static const struct wbsio_product *wbsio_lookup(uint8_t id, uint8_t rev);
+static int	wbsio_match(device_t, cfdata_t, void *);
 static void	wbsio_attach(device_t, device_t, void *);
 static int	wbsio_detach(device_t, int);
 static int	wbsio_rescan(device_t, const char *, const int *);
@@ -52,7 +81,7 @@ static int	wbsio_print(void *, const cha
 static int	wbsio_search(device_t, cfdata_t, const int *, void *);
 
 CFATTACH_DECL2_NEW(wbsio, sizeof(struct wbsio_softc),
-    wbsio_probe, wbsio_attach, wbsio_detach, NULL,
+    wbsio_match, wbsio_attach, wbsio_detach, NULL,
     wbsio_rescan, wbsio_childdet);
 
 static __inline void
@@ -83,13 +112,34 @@ wbsio_conf_write(bus_space_tag_t iot, bu
 	bus_space_write_1(iot, ioh, WBSIO_DATA, data);
 }
 
+static const struct wbsio_product *
+wbsio_lookup(uint8_t id, uint8_t rev)
+{
+	uint16_t wid = ((uint16_t)id << 4) | (rev >> 4);
+	int i;
+
+	for (i = 0; i < __arraycount(wbsio_products); i++) {
+		if (wbsio_products[i].idis12bits) {
+			if (wbsio_products[i].id == wid)
+				return &wbsio_products[i];
+		} else {
+			if (wbsio_products[i].id == id)
+				return &wbsio_products[i];
+		}
+	}
+
+	/* Not found */
+	return NULL;
+}
+
 int
-wbsio_probe(device_t parent, cfdata_t match, void *aux)
+wbsio_match(device_t parent, cfdata_t match, void *aux)
 {
 	struct isa_attach_args *ia = aux;
+	const struct wbsio_product *product;
 	bus_space_tag_t iot;
 	bus_space_handle_t ioh;
-	uint8_t reg;
+	uint8_t id, rev;
 
 	/* Must supply an address */
 	if (ia->ia_nio < 1)
@@ -106,39 +156,21 @@ wbsio_probe(device_t parent, cfdata_t ma
 	if (bus_space_map(iot, ia->ia_io[0].ir_addr, WBSIO_IOSIZE, 0, &ioh))
 		return 0;
 	wbsio_conf_enable(iot, ioh);
-	reg = wbsio_conf_read(iot, ioh, WBSIO_ID);
-	aprint_debug("wbsio_probe: id 0x%02x\n", reg);
+	id = wbsio_conf_read(iot, ioh, WBSIO_ID);
+	rev = wbsio_conf_read(iot, ioh, WBSIO_REV);
+	aprint_debug("wbsio_probe: id 0x%02x, rev 0x%02x\n", id, rev);
 	wbsio_conf_disable(iot, ioh);
 	bus_space_unmap(iot, ioh, WBSIO_IOSIZE);
-	switch (reg) {
-	case WBSIO_ID_W83627HF:
-	case WBSIO_ID_W83627DHG:
-	case WBSIO_ID_W83627DHGP:
-	case WBSIO_ID_W83627EHF:
-	case WBSIO_ID_W83627SF:
-	case WBSIO_ID_W83627THF:
-	case WBSIO_ID_W83627UHG:
-	case WBSIO_ID_W83637HF:
-	case WBSIO_ID_W83667HG:
-	case WBSIO_ID_W83667HGB:
-	case WBSIO_ID_W83687THF:
-	case WBSIO_ID_W83697HF:
-	case WBSIO_ID_W83697UG:
-	case WBSIO_ID_NCT5104D:
-	case WBSIO_ID_NCT6775F:
-	case WBSIO_ID_NCT6776F:
-	case WBSIO_ID_NCT6779D:
-	case WBSIO_ID_NCT6791D:
-	case WBSIO_ID_NCT6792D:
-		ia->ia_nio = 1;
-		ia->ia_io[0].ir_size = WBSIO_IOSIZE;
-		ia->ia_niomem = 0;
-		ia->ia_nirq = 0;
-		ia->ia_ndrq = 0;
-		return 1;
-	}
 
-	return 0;
+	if ((product = wbsio_lookup(id, rev)) == NULL)
+		return 0;
+
+	ia->ia_nio = 1;
+	ia->ia_io[0].ir_size = WBSIO_IOSIZE;
+	ia->ia_niomem = 0;
+	ia->ia_nirq = 0;
+	ia->ia_ndrq = 0;
+	return 1;
 }
 
 void
@@ -146,9 +178,10 @@ wbsio_attach(device_t parent, device_t s
 {
 	struct wbsio_softc *sc = device_private(self);
 	struct isa_attach_args *ia = aux;
-	const char *desc = NULL;
-	const char *vendor = "Winbond";
-	uint8_t reg;
+	const struct wbsio_product *product;
+	const char *desc;
+	const char *vendor;
+	uint8_t id, rev;
 
 	sc->sc_dev = self;
 
@@ -166,89 +199,33 @@ wbsio_attach(device_t parent, device_t s
 	wbsio_conf_enable(sc->sc_iot, sc->sc_ioh);
 
 	/* Read device ID */
-	reg = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_ID);
-	switch (reg) {
-	case WBSIO_ID_W83627HF:
-		desc = "W83627HF";
-		break;
-	case WBSIO_ID_W83627DHG:
-		desc = "W83627DHG";
-		break;
-	case WBSIO_ID_W83627DHGP:
-		desc = "W83627DHG-P";
-		break;
-	case WBSIO_ID_W83627EHF:
-		desc = "W83627EHF";
-		break;
-	case WBSIO_ID_W83627SF:
-		desc = "W83627SF";
-		break;
-	case WBSIO_ID_W83627THF:
-		desc = "W83627THF";
-		break;
-	case WBSIO_ID_W83627UHG:
-		desc = "W83627UHG";
-		break;
-	case WBSIO_ID_W83637HF:
-		desc = "W83637HF";
-		break;
-	case WBSIO_ID_W83667HG:
-		desc = "W83667HG";
-		break;
-	case WBSIO_ID_W83667HGB:
-		desc = "W83667HGB";
-		break;
-	case WBSIO_ID_W83687THF:
-		desc = "W83687THF";
-		break;
-	case WBSIO_ID_W83697HF:
-		desc = "W83697HF";
-		break;
-	case WBSIO_ID_W83697UG:
-		desc = "W83697UG";
-		break;
-	case WBSIO_ID_NCT5104D:
-		vendor = "Nuvoton";
-		desc = "NCT5104D";
-		break;
-	case WBSIO_ID_NCT6775F:
-		vendor = "Nuvoton";
-		desc = "NCT6775F";
-		break;
-	case WBSIO_ID_NCT6776F:
-		vendor = "Nuvoton";
-		desc = "NCT6776F";
-		break;
-	case WBSIO_ID_NCT6779D:
-		vendor = "Nuvoton";
-		desc = "NCT6779D";
-		break;
-	case WBSIO_ID_NCT6791D:
-		vendor = "Nuvoton";
-		desc = "NCT6791D";
-		break;
-	case WBSIO_ID_NCT6792D:
-		vendor = "Nuvoton";
-		desc = "NCT6792D";
-		break;
-	case WBSIO_ID_NCT6793D:
-		vendor = "Nuvoton";
-		desc = "NCT6793D";
-		break;
-	case WBSIO_ID_NCT6795D:
-		vendor = "Nuvoton";
-		desc = "NCT6795D";
-		break;
-	}
+	id = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_ID);
 	/* Read device revision */
-	reg = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_REV);
-
-	aprint_naive("\n");
-	aprint_normal(": %s LPC Super I/O %s rev 0x%02x\n", vendor, desc, reg);
+	rev = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_REV);
 
 	/* Escape from configuration mode */
 	wbsio_conf_disable(sc->sc_iot, sc->sc_ioh);
 
+	if ((product = wbsio_lookup(id, rev)) == NULL) {
+		aprint_error_dev(self, "Unknown device. Failed to attach\n");
+		return;
+	}
+	if (product->idis12bits)
+		rev &= 0x0f; /* Revision is low 4bits */
+
+	desc = product->str;
+	if (desc[0] == 'W')
+		vendor = "Winbond";
+	else
+		vendor = "Nuvoton";
+	aprint_naive("\n");
+	aprint_normal(": %s LPC Super I/O %s rev ", vendor, desc);
+	if (product->idis12bits) {
+		/* Revision filed is 4bit only */
+		aprint_normal("%c\n", 'A' + rev);
+	} else
+		aprint_normal("0x%02x\n", rev);
+
 	if (!pmf_device_register(self, NULL, NULL))
 		aprint_error_dev(self, "couldn't establish power handler\n");
 	wbsio_rescan(self, "wbsio", NULL);
@@ -289,8 +266,10 @@ static int
 wbsio_search(device_t parent, cfdata_t cf, const int *slocs, void *aux)
 {
 	struct wbsio_softc *sc = device_private(parent);
+	const struct wbsio_product *product;
 	uint16_t iobase;
-	uint8_t reg0, reg1, devid;
+	uint16_t devid;
+	uint8_t reg0, reg1, rev;
 
 	/* Enter configuration mode */
 	wbsio_conf_enable(sc->sc_iot, sc->sc_ioh);
@@ -317,11 +296,19 @@ wbsio_search(device_t parent, cfdata_t c
 
 	/* Enter configuration mode */
 	wbsio_conf_enable(sc->sc_iot, sc->sc_ioh);
-	/* Read device ID */
+	/* Read device ID and revision */
 	devid = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_ID);
+	rev = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_REV);
 	/* Escape from configuration mode */
 	wbsio_conf_disable(sc->sc_iot, sc->sc_ioh);
 
+	if ((product = wbsio_lookup(devid, rev)) == NULL) {
+		aprint_error_dev(parent, "%s: Unknown device.\n", __func__);
+		return -1;
+	}
+	if (product->idis12bits)
+		devid = (devid << 4) | (rev >> 4);
+
 	sc->sc_ia.ia_nio = 1;
 	sc->sc_ia.ia_io = &sc->sc_io;
 	sc->sc_ia.ia_io[0].ir_addr = iobase;

Index: src/sys/dev/isa/wbsioreg.h
diff -u src/sys/dev/isa/wbsioreg.h:1.2 src/sys/dev/isa/wbsioreg.h:1.3
--- src/sys/dev/isa/wbsioreg.h:1.2	Tue Jul 11 10:10:51 2017
+++ src/sys/dev/isa/wbsioreg.h	Fri Aug 18 04:07:51 2017
@@ -34,26 +34,27 @@
 #define WBSIO_REV		0x21	/* Device Revision */
 
 #define WBSIO_ID_W83627HF	0x52
-#define WBSIO_ID_W83627SF	0x59
 #define WBSIO_ID_W83697HF	0x60
-#define WBSIO_ID_W83697UG	0x68
 #define WBSIO_ID_W83637HF	0x70
 #define WBSIO_ID_W83627THF	0x82
 #define WBSIO_ID_W83687THF	0x85
-#define WBSIO_ID_W83627EHF	0x88
-#define WBSIO_ID_W83627DHG	0xa0
-#define WBSIO_ID_W83627UHG	0xa2
-#define WBSIO_ID_W83667HG	0xa5
-#define WBSIO_ID_W83627DHGP	0xb0
-#define WBSIO_ID_W83667HGB	0xb3
-#define WBSIO_ID_NCT6775F	0xb4
-#define WBSIO_ID_NCT6776F	0xc3
-#define WBSIO_ID_NCT5104D	0xc4 /* 610[246]D */
-#define WBSIO_ID_NCT6779D	0xc5
-#define WBSIO_ID_NCT6791D	0xc8
-#define WBSIO_ID_NCT6792D	0xc9
-#define WBSIO_ID_NCT6793D	0xd1
-#define WBSIO_ID_NCT6795D	0xd3
+#define WBSIO_ID_W83627SF	0x595
+#define WBSIO_ID_W83697UG	0x681
+#define WBSIO_ID_W83627EHF_A	0x885
+#define WBSIO_ID_W83627EHF	0x886
+#define WBSIO_ID_W83627DHG	0xa02
+#define WBSIO_ID_W83627UHG	0xa23
+#define WBSIO_ID_W83667HG	0xa51
+#define WBSIO_ID_W83627DHGP	0xb07
+#define WBSIO_ID_W83667HGB	0xb35
+#define WBSIO_ID_NCT6775F	0xb47
+#define WBSIO_ID_NCT6776F	0xc33
+#define WBSIO_ID_NCT5104D	0xc45	/* 610[246]D */
+#define WBSIO_ID_NCT6779D	0xc56
+#define WBSIO_ID_NCT6791D	0xc80
+#define WBSIO_ID_NCT6792D	0xc91
+#define WBSIO_ID_NCT6793D	0xd12
+#define WBSIO_ID_NCT6795D	0xd35
 
 /* Logical Device Number (LDN) Assignments */
 #define WBSIO_LDN_HM		0x0b

Reply via email to