Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 21 Aug 2004 18:43:17 -0700 (PDT)
From:      Dennis Holmes <dholmes@email.rahul.net>
To:        FreeBSD-gnats-submit@FreeBSD.org
Cc:        dholmes@liberator.dyndns.org
Subject:   i386/70810: [patch] Enable SMBus device on Asus P4B series motherboards
Message-ID:  <200408220143.i7M1hHYI020239@star-one.liberator.dyndns.org>
Resent-Message-ID: <200408220150.i7M1oMSA029947@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         70810
>Category:       i386
>Synopsis:       [patch] Enable SMBus device on Asus P4B series motherboards
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-i386
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Sun Aug 22 01:50:22 GMT 2004
>Closed-Date:
>Last-Modified:
>Originator:     Dennis Holmes
>Release:        FreeBSD 4.8-RELEASE-p13 i386
>Organization:
a little
>Environment:
Asus P4B266 with Intel 845D chipset
System: FreeBSD star-one.liberator.dyndns.org 4.8-RELEASE-p13 FreeBSD 4.8-RELEASE-p13 #14: Mon Aug 2 10:52:46 PDT 2004 dholmes at star-one.liberator.dyndns.org:/usr/obj/usr/src/sys/STAR-ONE i386

>Description:
On affected Asus motherboards, the smbus device in the chipset is
disabled by the BIOS with no setup option to enable it.  This prevents
hardware (temp/fan/voltage) monitoring since the monitoring chip is
only accessible via smbus.

Additional information regarding the nature of the problem and the fix
can be found on the following web pages:
	http://www.nt.phys.kyushu-u.ac.jp/shimizu/download/README-ASUS-P4motherboard.html
	http://www2.lm-sensors.nu/~lm78/cvs/lm_sensors2/prog/hotplug/README.p4b
Note that the Linux fix of enabling the smbus device after boot
requires that hot-pluggable device support be present in the kernel.
In Freebsd the device can be enabled while running by using pciconf or
pcitweak, but the kernel remains unaware of it.

>How-To-Repeat:
Observe via dmesg that the ichsmb and smbus devices are not found at boot
time even with the appropriate devices configured in the kernel.

>Fix:
The included patch turns on the smbus device as soon as the parent
chip is probed.  Then the device is detected as the device probing
sequence continues.

I now have healthd working on my system after applying the patch.
This adds a new PCI quirk and a kernel config option to activate the
quirk.  Now in dmesg I see:
ichsmb0: <Intel 82801BA (ICH2) SMBus controller> port 0xe800-0xe80f irq 0 at device 31.3 on pci0
pci_cfgintr_search: linked (61) to configured irq 11 at 1:0:0
pci_cfgintr: 0:31 INTB routed to irq 11
smbus1: <System Management Bus> on ichsmb0
smb1: <SMBus general purpose I/O> on smbus1
(It is assigned smbus1 since I also have a Bt848-based video capture
card which gets smbus0.  I also had to tweak healthd to get it to use
smbus1 and correct some of the monitoring values.  If anyone is
interested in those changes, let me know; some of it's not very pretty
but I'll share.)

The patch changes three files.  Prior to each diff is the CVS ID string
of the file against which the patch was generated.  I realize these
versions are a little old, but I don't have an installation of -current
to play with.  I did check to see that the files have not changed
substantially in newer releases.

I am also including a diff against the pci.c file from -current.  This
version had changed enough that the patch from my version didn't apply.
Also, it looks like the location or nature of LINT has changed in
-current, so I don't know how to handle updating it.

This is my first PR submission; if you have any advice (other than the
obvious of "upgrade!") or need additional info please let me know.


##########
# Version: $FreeBSD: src/sys/i386/conf/LINT,v 1.749.2.138.2.1 2003/03/28 20:05:39 scottl Exp $
##########
--- /usr/src/sys/i386/conf/LINT.dist	Fri Mar 28 12:05:39 2003
+++ /usr/src/sys/i386/conf/LINT	Thu Aug  5 10:50:24 2004
@@ -2153,6 +2153,15 @@
 device		amdpm
 
 device		smb
+
+# Some of the ASUS P-4 motherboard with ICH2(82801BA) and ICH4(82801DB)
+# chipsets switch off the SMBus PCI device in the BIOS.  Therefore, one
+# has to enable it explicitly in order to make hardware-monitoring possible.
+# For further details, see:
+# http://www.nt.phys.kyushu-u.ac.jp/shimizu/download/README-ASUS-P4motherboard.html
+# http://www2.lm-sensors.nu/~lm78/cvs/lm_sensors2/prog/hotplug/README.p4b
+
+options		ASUS_P4B	# Enable SMBus on Asus P4B series
 
 #
 # I2C Bus


##########
# Version: $FreeBSD: src/sys/conf/options.i386,v 1.132.2.18 2003/03/14 21:22:35 jhb Exp $
##########
--- /usr/src/sys/conf/options.i386.dist	Fri Mar 14 13:22:35 2003
+++ /usr/src/sys/conf/options.i386	Thu Jul 29 19:57:11 2004
@@ -214,6 +214,9 @@
 # SMB/CIFS filesystem
 SMBFS
 
+# Enable smbus device on Asus P4B
+ASUS_P4B		opt_pci.h
+
 # -------------------------------
 # EOF
 # -------------------------------

##########
# Version: $FreeBSD: src/sys/pci/pci.c,v 1.141.2.15 2002/04/30 17:48:18 tmm Exp $
##########
--- /usr/src/sys/pci/pci.c.dist	Tue Apr 30 10:48:18 2002
+++ /usr/src/sys/pci/pci.c	Mon Aug  2 10:50:31 2004
@@ -71,22 +71,26 @@
 static void		pci_read_extcap(pcicfgregs *cfg);
 
 struct pci_quirk {
 	u_int32_t devid;	/* Vendor/device of the card */
 	int	type;
 #define PCI_QUIRK_MAP_REG	1 /* PCI map register in wierd place */
+#define PCI_QUIRK_CLEAR_BITS	2 /* Enable function by clearing some bits */
 	int	arg1;
 	int	arg2;
 };
 
 struct pci_quirk pci_quirks[] = {
 	/*
 	 * The Intel 82371AB and 82443MX has a map register at offset 0x90.
 	 */
 	{ 0x71138086, PCI_QUIRK_MAP_REG,	0x90,	 0 },
 	{ 0x719b8086, PCI_QUIRK_MAP_REG,	0x90,	 0 },
+#ifdef ASUS_P4B
+	{ 0x24408086, PCI_QUIRK_CLEAR_BITS,	0xf2,	0x0108 },
+#endif
 
 	{ 0 }
 };
 
 /* map register information */
 #define PCI_MAPMEM	0x01	/* memory map */
@@ -1356,21 +1360,33 @@
 pci_add_resources(device_t dev, pcicfgregs* cfg)
 {
 	struct pci_devinfo *dinfo = device_get_ivars(dev);
 	struct resource_list *rl = &dinfo->resources;
 	struct pci_quirk *q;
 	int i;
+	u_int32_t	val;
 
 	for (i = 0; i < cfg->nummaps;) {
 		i += pci_add_map(dev, cfg, PCIR_MAPS + i*4);
 	}
 
 	for (q = &pci_quirks[0]; q->devid; q++) {
-		if (q->devid == ((cfg->device << 16) | cfg->vendor)
-		    && q->type == PCI_QUIRK_MAP_REG)
-			pci_add_map(dev, cfg, q->arg1);
+		if (q->devid == ((cfg->device << 16) | cfg->vendor)) {
+			switch (q->type) {
+			case PCI_QUIRK_MAP_REG:
+				pci_add_map(dev, cfg, q->arg1);
+				break;
+			case PCI_QUIRK_CLEAR_BITS:
+				val = pci_read_config(dev, q->arg1, 2);
+				if (val & q->arg2) {
+					val &= ~(q->arg2);
+					pci_write_config(dev, q->arg1, val, 2);
+				}
+				break;
+			}
+		}
 	}
 
 	if (cfg->intpin > 0 && cfg->intline != 255)
 		resource_list_add(rl, SYS_RES_IRQ, 0,
 				  cfg->intline, cfg->intline, 1);
 }


##########
# src/sys/dev/pci/pci.c from -current  NOTE THAT THIS IS NOT TESTED!
# Version: $FreeBSD: /repoman/r/ncvs/src/sys/dev/pci/pci.c,v 1.264 2004/07/02 13:42:36 imp Exp $
##########
--- pci.c.current	Fri Jul  2 06:42:36 2004
+++ pci.c	Thu Aug  5 13:01:36 2004
@@ -139,22 +139,26 @@
 
 
 struct pci_quirk {
 	uint32_t devid;	/* Vendor/device of the card */
 	int	type;
 #define PCI_QUIRK_MAP_REG	1 /* PCI map register in weird place */
+#define PCI_QUIRK_CLEAR_BITS	2 /* Enable function by clearing some bits */
 	int	arg1;
 	int	arg2;
 };
 
 struct pci_quirk pci_quirks[] = {
 	/* The Intel 82371AB and 82443MX has a map register at offset 0x90. */
 	{ 0x71138086, PCI_QUIRK_MAP_REG,	0x90,	 0 },
 	{ 0x719b8086, PCI_QUIRK_MAP_REG,	0x90,	 0 },
 	/* As does the Serverworks OSB4 (the SMBus mapping register) */
 	{ 0x02001166, PCI_QUIRK_MAP_REG,	0x90,	 0 },
+#ifdef ASUS_P4B
+	{ 0x24408086, PCI_QUIRK_CLEAR_BITS,	0xf2,	0x0108 },
+#endif
 
 	{ 0 }
 };
 
 /* map register information */
 #define PCI_MAPMEM	0x01	/* memory map */
@@ -894,12 +898,13 @@
 {
 	struct pci_devinfo *dinfo = device_get_ivars(dev);
 	pcicfgregs *cfg = &dinfo->cfg;
 	struct resource_list *rl = &dinfo->resources;
 	struct pci_quirk *q;
 	int b, i, irq, f, s;
+ 	u_int32_t	val;
 
 	b = cfg->bus;
 	s = cfg->slot;
 	f = cfg->func;
 
 	/* ATA devices needs special map treatment */
@@ -910,15 +915,26 @@
 	else
 		for (i = 0; i < cfg->nummaps;)
 			i += pci_add_map(pcib, bus, dev, b, s, f, PCIR_BAR(i),
 			    rl);
 
 	for (q = &pci_quirks[0]; q->devid; q++) {
-		if (q->devid == ((cfg->device << 16) | cfg->vendor)
-		    && q->type == PCI_QUIRK_MAP_REG)
-			pci_add_map(pcib, bus, dev, b, s, f, q->arg1, rl);
+		if (q->devid == ((cfg->device << 16) | cfg->vendor)) {
+			switch (q->type) {
+			case PCI_QUIRK_MAP_REG:
+				pci_add_map(pcib, bus, dev, b, s, f, q->arg1, rl);
+				break;
+			case PCI_QUIRK_CLEAR_BITS:
+				val = pci_read_config(dev, q->arg1, 2);
+				if (val & q->arg2) {
+					val &= ~(q->arg2);
+					pci_write_config(dev, q->arg1, val, 2);
+				}
+				break;
+			}
+		}
 	}
 
 	if (cfg->intpin > 0 && PCI_INTERRUPT_VALID(cfg->intline)) {
 #if defined(__ia64__) || defined(__i386__) || defined(__amd64__)
 		/*
 		 * Try to re-route interrupts. Sometimes the BIOS or


>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200408220143.i7M1hHYI020239>