[Midnightbsd-cvs] src [8605] trunk: add device_identify method for wbwd(4), required on most recent supermicro motherboards.

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Sun Sep 25 13:28:11 EDT 2016


Revision: 8605
          http://svnweb.midnightbsd.org/src/?rev=8605
Author:   laffer1
Date:     2016-09-25 13:28:11 -0400 (Sun, 25 Sep 2016)
Log Message:
-----------
add device_identify method for wbwd(4), required on most recent supermicro motherboards.

Modified Paths:
--------------
    trunk/share/man/man4/wbwd.4
    trunk/sys/dev/wbwd/wbwd.c

Modified: trunk/share/man/man4/wbwd.4
===================================================================
--- trunk/share/man/man4/wbwd.4	2016-09-25 17:04:03 UTC (rev 8604)
+++ trunk/share/man/man4/wbwd.4	2016-09-25 17:28:11 UTC (rev 8605)
@@ -25,7 +25,7 @@
 .\"
 .\" $MidnightBSD$
 .\"
-.Dd March 6, 2012
+.Dd December 28, 2012
 .Dt wbwd 4
 .Os
 .Sh NAME
@@ -44,10 +44,6 @@
 .Bd -literal -offset indent
 wbwd_load="YES"
 .Ed
-.Pp
-In
-.Pa /boot/device.hints :
-.Cd hint.wbwd.0.at="isa"
 .Sh DESCRIPTION
 The
 .Nm

Modified: trunk/sys/dev/wbwd/wbwd.c
===================================================================
--- trunk/sys/dev/wbwd/wbwd.c	2016-09-25 17:04:03 UTC (rev 8604)
+++ trunk/sys/dev/wbwd/wbwd.c	2016-09-25 17:28:11 UTC (rev 8605)
@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 2011 Sandvine Incorporated ULC.
+ * Copyright (c) 2012 iXsystems, Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -93,15 +94,6 @@
 #define	WB_LDN8_CRF7_CLEAR_MASK	\
     (WB_LDN8_CRF7_MOUSE|WB_LDN8_CRF7_KEYB|WB_LDN8_CRF7_TS|WB_LDN8_CRF7_IRQS)
 
-#define	write_efir_1(sc, value)						\
-	bus_space_write_1((sc)->bst, (sc)->bsh, 0, (value))
-#define	read_efir_1(sc)							\
-	bus_space_read_1((sc)->bst, (sc)->bsh, 0)
-#define	write_efdr_1(sc, value)						\
-	bus_space_write_1((sc)->bst, (sc)->bsh, 1, (value))
-#define	read_efdr_1(sc)							\
-	bus_space_read_1((sc)->bst, (sc)->bsh, 1)
-
 struct wb_softc {
 	device_t		dev;
 	struct resource		*portres;
@@ -109,8 +101,8 @@
 	bus_space_handle_t	bsh;
 	int			rid;
 	eventhandler_tag	ev_tag;
-	int			(*ext_cfg_enter_f)(struct wb_softc *);
-	void			(*ext_cfg_exit_f)(struct wb_softc *);
+	int			(*ext_cfg_enter_f)(struct wb_softc *, u_short);
+	void			(*ext_cfg_exit_f)(struct wb_softc *, u_short);
 	int			debug_verbose;
 
 	/*
@@ -131,13 +123,13 @@
 	uint8_t			reg_2;
 };
 
-static int	ext_cfg_enter_0x87_0x87(struct wb_softc *);
-static void	ext_cfg_exit_0xaa(struct wb_softc *);
+static int	ext_cfg_enter_0x87_0x87(struct wb_softc *, u_short);
+static void	ext_cfg_exit_0xaa(struct wb_softc *, u_short);
 
 struct winbond_superio_cfg {
 	uint8_t			efer;	/* and efir */
-	int			(*ext_cfg_enter_f)(struct wb_softc *);
-	void			(*ext_cfg_exit_f)(struct wb_softc *);
+	int			(*ext_cfg_enter_f)(struct wb_softc *, u_short);
+	void			(*ext_cfg_exit_f)(struct wb_softc *, u_short);
 } probe_addrs[] = {
 	{
 		.efer			= 0x2e,
@@ -189,6 +181,50 @@
 	},
 };
 
+static void
+write_efir_1(struct wb_softc *sc, u_short baseport, uint8_t value)
+{
+
+	MPASS(sc != NULL || baseport != 0);
+	if (sc != NULL)
+		bus_space_write_1((sc)->bst, (sc)->bsh, 0, (value));
+	else
+		outb(baseport, value);
+}
+
+static uint8_t __unused
+read_efir_1(struct wb_softc *sc, u_short baseport)
+{
+
+	MPASS(sc != NULL || baseport != 0);
+	if (sc != NULL)
+		return (bus_space_read_1((sc)->bst, (sc)->bsh, 0));
+	else
+		return (inb(baseport));
+}
+
+static void
+write_efdr_1(struct wb_softc *sc, u_short baseport, uint8_t value)
+{
+
+	MPASS(sc != NULL || baseport != 0);
+	if (sc != NULL)
+		bus_space_write_1((sc)->bst, (sc)->bsh, 1, (value));
+	else
+		outb(baseport + 1, value);
+}
+
+static uint8_t
+read_efdr_1(struct wb_softc *sc, u_short baseport)
+{
+
+	MPASS(sc != NULL || baseport != 0);
+	if (sc != NULL)
+		return (bus_space_read_1((sc)->bst, (sc)->bsh, 1));
+	else
+		return (inb(baseport + 1));
+}
+
 /*
  * Return the watchdog related registers as we last read them.  This will
  * usually not give the current timeout or state on whether the watchdog
@@ -232,19 +268,19 @@
 	 * Enter extended function mode in case someone else has been
 	 * poking on the registers.  We will not leave it though.
 	 */
-	if ((*sc->ext_cfg_enter_f)(sc) != 0)
+	if ((*sc->ext_cfg_enter_f)(sc, 0) != 0)
 		return (ENXIO);
 
 	/* Watchdog is configured as part of LDN 8 (GPIO Port2, Watchdog). */
-	write_efir_1(sc, WB_LDN_REG);
-	write_efdr_1(sc, WB_LDN_REG_LDN8);
+	write_efir_1(sc, 0, WB_LDN_REG);
+	write_efdr_1(sc, 0, WB_LDN_REG_LDN8);
 
-	write_efir_1(sc, WB_LDN8_CRF5);
-	sc->reg_1 = read_efdr_1(sc);
-	write_efir_1(sc, WB_LDN8_CRF6);
-	sc->reg_timeout = read_efdr_1(sc);
-	write_efir_1(sc, WB_LDN8_CRF7);
-	sc->reg_2 = read_efdr_1(sc);
+	write_efir_1(sc, 0, WB_LDN8_CRF5);
+	sc->reg_1 = read_efdr_1(sc, 0);
+	write_efir_1(sc, 0, WB_LDN8_CRF6);
+	sc->reg_timeout = read_efdr_1(sc, 0);
+	write_efir_1(sc, 0, WB_LDN8_CRF7);
+	sc->reg_2 = read_efdr_1(sc, 0);
 
 	return (sysctl_wb_debug(oidp, arg1, arg2, req));
 }
@@ -289,7 +325,7 @@
 	 * Enter extended function mode in case someone else has been
 	 * poking on the registers.  We will not leave it though.
 	 */
-	if ((*sc->ext_cfg_enter_f)(sc) != 0)
+	if ((*sc->ext_cfg_enter_f)(sc, 0) != 0)
 		return (ENXIO);
 
 #ifdef notyet
@@ -302,16 +338,16 @@
 #endif
 
 	/* Watchdog is configured as part of LDN 8 (GPIO Port2, Watchdog). */
-	write_efir_1(sc, WB_LDN_REG);
-	write_efdr_1(sc, WB_LDN_REG_LDN8);
+	write_efir_1(sc, 0, WB_LDN_REG);
+	write_efdr_1(sc, 0, WB_LDN_REG_LDN8);
 
 	/* Force watchdog to fire. */
-	write_efir_1(sc, WB_LDN8_CRF7);
-	sc->reg_2 = read_efdr_1(sc);
+	write_efir_1(sc, 0, WB_LDN8_CRF7);
+	sc->reg_2 = read_efdr_1(sc, 0);
 	sc->reg_2 |= WB_LDN8_CRF7_FORCE;
 
-	write_efir_1(sc, WB_LDN8_CRF7);
-	write_efdr_1(sc, sc->reg_2);
+	write_efir_1(sc, 0, WB_LDN8_CRF7);
+	write_efdr_1(sc, 0, sc->reg_2);
 
 	return (0);
 }
@@ -345,7 +381,7 @@
  * between different chips.
  */
 static int
-ext_cfg_enter_0x87_0x87(struct wb_softc *sc)
+ext_cfg_enter_0x87_0x87(struct wb_softc *sc, u_short baseport)
 {
 
 	/*
@@ -352,17 +388,17 @@
 	 * Enable extended function mode.
 	 * Winbond does not allow us to validate so always return success.
 	 */
-	write_efir_1(sc, 0x87);
-	write_efir_1(sc, 0x87);
+	write_efir_1(sc, baseport, 0x87);
+	write_efir_1(sc, baseport, 0x87);
 
 	return (0);
 }
 
 static void
-ext_cfg_exit_0xaa(struct wb_softc *sc)
+ext_cfg_exit_0xaa(struct wb_softc *sc, u_short baseport)
 {
 
-	write_efir_1(sc, 0xaa);
+	write_efir_1(sc, baseport, 0xaa);
 }
 
 /*
@@ -380,22 +416,22 @@
 	 * Enter extended function mode in case someone else has been
 	 * poking on the registers.  We will not leave it though.
 	 */
-	if ((*sc->ext_cfg_enter_f)(sc) != 0)
+	if ((*sc->ext_cfg_enter_f)(sc, 0) != 0)
 		return (ENXIO);
 
 	/* Watchdog is configured as part of LDN 8 (GPIO Port2, Watchdog) */
-	write_efir_1(sc, WB_LDN_REG);
-	write_efdr_1(sc, WB_LDN_REG_LDN8);
+	write_efir_1(sc, 0, WB_LDN_REG);
+	write_efdr_1(sc, 0, WB_LDN_REG_LDN8);
 
 	/* Disable and validate or arm/reset watchdog. */
 	if (timeout == 0) {
 		/* Disable watchdog. */
-		write_efir_1(sc, WB_LDN8_CRF6);
-		write_efdr_1(sc, 0x00);
+		write_efir_1(sc, 0, WB_LDN8_CRF6);
+		write_efdr_1(sc, 0, 0x00);
 
 		/* Re-check. */
-		write_efir_1(sc, WB_LDN8_CRF6);
-		sc->reg_timeout = read_efdr_1(sc);
+		write_efir_1(sc, 0, WB_LDN8_CRF6);
+		sc->reg_timeout = read_efdr_1(sc, 0);
 		
 		if (sc->reg_timeout != 0x00) {
 			device_printf(sc->dev, "Failed to disable watchdog: "
@@ -416,8 +452,8 @@
 			return (EINVAL);
 
 		/* Read current scaling factor. */
-		write_efir_1(sc, WB_LDN8_CRF5);
-		sc->reg_1 = read_efdr_1(sc);
+		write_efir_1(sc, 0, WB_LDN8_CRF5);
+		sc->reg_1 = read_efdr_1(sc, 0);
 
 		if (timeout > 255) {
 			/* Set scaling factor to 60s. */
@@ -432,21 +468,21 @@
 		}
 
 		/* In case we fired before we need to clear to fire again. */
-		write_efir_1(sc, WB_LDN8_CRF7);
-		sc->reg_2 = read_efdr_1(sc);
+		write_efir_1(sc, 0, WB_LDN8_CRF7);
+		sc->reg_2 = read_efdr_1(sc, 0);
 		if (sc->reg_2 & WB_LDN8_CRF7_TS) {
 			sc->reg_2 &= ~WB_LDN8_CRF7_TS;
-			write_efir_1(sc, WB_LDN8_CRF7);
-			write_efdr_1(sc, sc->reg_2);
+			write_efir_1(sc, 0, WB_LDN8_CRF7);
+			write_efdr_1(sc, 0, sc->reg_2);
 		}
 
 		/* Write back scaling factor. */
-		write_efir_1(sc, WB_LDN8_CRF5);
-		write_efdr_1(sc, sc->reg_1);
+		write_efir_1(sc, 0, WB_LDN8_CRF5);
+		write_efdr_1(sc, 0, sc->reg_1);
 
 		/* Set timer and arm/reset the watchdog. */
-		write_efir_1(sc, WB_LDN8_CRF6);
-		write_efdr_1(sc, sc->reg_timeout);
+		write_efir_1(sc, 0, WB_LDN8_CRF6);
+		write_efdr_1(sc, 0, sc->reg_timeout);
 	}
 
 	if (sc->debug_verbose)
@@ -516,40 +552,48 @@
 	int error, found, i, j;
 	uint8_t dev_id, dev_rev, cr26;
 
-	sc = device_get_softc(dev);
-	bzero(sc, sizeof(*sc));
-	sc->dev = dev;
+	if (dev == NULL)
+		sc = NULL;
+	else {
+		sc = device_get_softc(dev);
+		bzero(sc, sizeof(*sc));
+		sc->dev = dev;
+	}
 
 	error = ENXIO;
 	for (i = 0; i < sizeof(probe_addrs) / sizeof(*probe_addrs); i++) {
 
-		/* Allocate bus resources for IO index/data register access. */
-		sc->portres = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->rid,
-		    probe_addrs[i].efer, probe_addrs[i].efer + 1, 2, RF_ACTIVE);
-		if (sc->portres == NULL)
-			continue;
-		sc->bst = rman_get_bustag(sc->portres);
-		sc->bsh = rman_get_bushandle(sc->portres);
+		if (sc != NULL) {
+			/* Allocate bus resources for IO index/data register access. */
+			sc->portres = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->rid,
+			    probe_addrs[i].efer, probe_addrs[i].efer + 1, 2, RF_ACTIVE);
+			if (sc->portres == NULL)
+				continue;
+			sc->bst = rman_get_bustag(sc->portres);
+			sc->bsh = rman_get_bushandle(sc->portres);
+		}
 
 		found = 0;
-		error = (*probe_addrs[i].ext_cfg_enter_f)(sc);
+		error = (*probe_addrs[i].ext_cfg_enter_f)(sc, probe_addrs[i].efer);
 		if (error != 0)
 			goto cleanup;
 
 		/* Identify the SuperIO chip. */
-		write_efir_1(sc, WB_DEVICE_ID_REG);
-		dev_id = read_efdr_1(sc);
-		write_efir_1(sc, WB_DEVICE_REV_REG);
-		dev_rev = read_efdr_1(sc);
-		write_efir_1(sc, WB_CR26);
-		cr26 = read_efdr_1(sc);
+		write_efir_1(sc, probe_addrs[i].efer, WB_DEVICE_ID_REG);
+		dev_id = read_efdr_1(sc, probe_addrs[i].efer);
+		write_efir_1(sc, probe_addrs[i].efer, WB_DEVICE_REV_REG);
+		dev_rev = read_efdr_1(sc, probe_addrs[i].efer);
+		write_efir_1(sc, probe_addrs[i].efer, WB_CR26);
+		cr26 = read_efdr_1(sc, probe_addrs[i].efer);
 
 		/* HEFRAS of 0 means EFER at 0x2e, 1 means EFER at 0x4e. */
 		if (((cr26 & 0x40) == 0x00 && probe_addrs[i].efer != 0x2e) ||
 		    ((cr26 & 0x40) == 0x40 && probe_addrs[i].efer != 0x4e)) {
-			device_printf(dev, "HEFRAS and EFER do not align: EFER "
-			    "0x%02x DevID 0x%02x DevRev 0x%02x CR26 0x%02x\n",
-			     probe_addrs[i].efer, dev_id, dev_rev, cr26);
+			if (dev != NULL)
+				device_printf(dev, "HEFRAS and EFER do not "
+				    "align: EFER 0x%02x DevID 0x%02x DevRev "
+				    "0x%02x CR26 0x%02x\n",
+				    probe_addrs[i].efer, dev_id, dev_rev, cr26);
 			goto cleanup;
 		}
 
@@ -556,22 +600,23 @@
 		for (j = 0; j < sizeof(wb_devs) / sizeof(*wb_devs); j++) {
 			if (wb_devs[j].device_id == dev_id &&
 			    wb_devs[j].device_rev == dev_rev) {
-				if (probe)
+				if (probe && dev != NULL)
 					device_set_desc(dev, wb_devs[j].descr);
 				found++;
 				break;
 			}
 		}
-		if (probe && found && bootverbose)
+		if (probe && found && bootverbose && dev != NULL)
 			device_printf(dev, "%s EFER 0x%02x ID 0x%02x Rev 0x%02x"
 			     " CR26 0x%02x (probing)\n", device_get_desc(dev),
 			     probe_addrs[i].efer, dev_id, dev_rev, cr26);
 cleanup:
 		if (probe || !found) {
-			(*probe_addrs[i].ext_cfg_exit_f)(sc);
+			(*probe_addrs[i].ext_cfg_exit_f)(sc, probe_addrs[i].efer);
 
-			(void) bus_release_resource(dev, SYS_RES_IOPORT, sc->rid,
-			    sc->portres);
+			if (sc != NULL)
+				(void) bus_release_resource(dev, SYS_RES_IOPORT,
+				    sc->rid, sc->portres);
 		}
 
 		/*
@@ -580,8 +625,10 @@
 		 * for operations.
 		 */
 		if (found) {
-			sc->ext_cfg_enter_f = probe_addrs[i].ext_cfg_enter_f;
-			sc->ext_cfg_exit_f = probe_addrs[i].ext_cfg_exit_f;
+			if (sc != NULL) {
+				sc->ext_cfg_enter_f = probe_addrs[i].ext_cfg_enter_f;
+				sc->ext_cfg_exit_f = probe_addrs[i].ext_cfg_exit_f;
+			}
 			error = BUS_PROBE_DEFAULT;
 			break;
 		} else
@@ -591,6 +638,21 @@
 	return (error);
 }
 
+static void
+wb_identify(driver_t *driver, device_t parent)
+{
+	device_t dev;
+
+	if ((dev = device_find_child(parent, driver->name, 0)) == NULL) {
+		if (wb_probe_enable(dev, 1) != BUS_PROBE_DEFAULT) {
+			if (bootverbose)
+				device_printf(dev, "can not find compatible Winbond chip.\n");
+		} else
+			dev = BUS_ADD_CHILD(parent, 0, driver->name, 0);
+		return;
+	}
+}
+
 static int
 wb_probe(device_t dev)
 {
@@ -620,20 +682,20 @@
 	    ("%s: successfull probe result but not setup correctly", __func__));
 
 	/* Watchdog is configured as part of LDN 8 (GPIO Port2, Watchdog). */
-	write_efir_1(sc, WB_LDN_REG);
-	write_efdr_1(sc, WB_LDN_REG_LDN8);
+	write_efir_1(sc, 0, WB_LDN_REG);
+	write_efdr_1(sc, 0, WB_LDN_REG_LDN8);
 
 	/* Make sure LDN8 is enabled (Do we need to? Also affects GPIO). */
-	write_efir_1(sc, WB_LDN8_CR30);
-	write_efdr_1(sc, WB_LDN8_CR30_ACTIVE);
+	write_efir_1(sc, 0, WB_LDN8_CR30);
+	write_efdr_1(sc, 0, WB_LDN8_CR30_ACTIVE);
 
 	/* Read the current watchdog configuration. */
-	write_efir_1(sc, WB_LDN8_CRF5);
-	sc->reg_1 = read_efdr_1(sc);
-	write_efir_1(sc, WB_LDN8_CRF6);
-	sc->reg_timeout = read_efdr_1(sc);
-	write_efir_1(sc, WB_LDN8_CRF7);
-	sc->reg_2 = read_efdr_1(sc);
+	write_efir_1(sc, 0, WB_LDN8_CRF5);
+	sc->reg_1 = read_efdr_1(sc, 0);
+	write_efir_1(sc, 0, WB_LDN8_CRF6);
+	sc->reg_timeout = read_efdr_1(sc, 0);
+	write_efir_1(sc, 0, WB_LDN8_CRF7);
+	sc->reg_2 = read_efdr_1(sc, 0);
 
 	/* Print current state if bootverbose or watchdog already enabled. */
 	if (bootverbose || (sc->reg_timeout > 0x00))
@@ -645,12 +707,12 @@
 	 */
 	sc->reg_1 &= ~(WB_LDN8_CRF5_KEYB_P20);
 	sc->reg_1 |= WB_LDN8_CRF5_KBRST;
-	write_efir_1(sc, WB_LDN8_CRF5);
-	write_efdr_1(sc, sc->reg_1);
+	write_efir_1(sc, 0, WB_LDN8_CRF5);
+	write_efdr_1(sc, 0, sc->reg_1);
 
 	sc->reg_2 &= ~WB_LDN8_CRF7_CLEAR_MASK;
-	write_efir_1(sc, WB_LDN8_CRF7);
-	write_efdr_1(sc, sc->reg_2);
+	write_efir_1(sc, 0, WB_LDN8_CRF7);
+	write_efdr_1(sc, 0, sc->reg_2);
 
 	/* Read global timeout override tunable, Add per device sysctls. */
 	if (TUNABLE_ULONG_FETCH("hw.wbwd.timeout_override", &timeout)) {
@@ -699,7 +761,7 @@
 	wb_set_watchdog(sc, 0);
 
 	/* Disable extended function mode. */
-	(*sc->ext_cfg_exit_f)(sc);
+	(*sc->ext_cfg_exit_f)(sc, 0);
 
 	/* Cleanup resources. */
 	(void) bus_release_resource(dev, SYS_RES_IOPORT, sc->rid, sc->portres);
@@ -711,6 +773,7 @@
 
 static device_method_t wb_methods[] = {
 	/* Device interface */
+	DEVMETHOD(device_identify,	wb_identify),
 	DEVMETHOD(device_probe,		wb_probe),
 	DEVMETHOD(device_attach,	wb_attach),
 	DEVMETHOD(device_detach,	wb_detach),



More information about the Midnightbsd-cvs mailing list