Port-i386 archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Sensors on Asus P2B-F?



Just curious, can you try 'mbmon -S' to see if that's how it is getting its data?

I'm suspecting that there's some contention between the piixpm i2c driver and ACPI's SMBus accessing the same bus. This can cause all sorts of issues.

I've written a ACPI SMBus i2c driver to use ACPI access directly, but it requires manually disabling the "native" i2c drivers since there's no clean way to prevent simultaneous access. Perhaps you might want to try my driver to see if you get more consistent and reliable results? (See attachment.)


On Tue, 3 Nov 2009, Hauke Fath wrote:

At 15:48 Uhr +0100 03.11.2009, Hauke Fath wrote:
I noted that taking out the DEBUG* options keeps the kernel from
recognizing the device?

Just leaving in

options I2C_SCAN
lm* at iic? addr 0x2d

results in

[...]
piixpm0: interrupting at SMI, polling
iic0 at piixpm0: I2C bus
iic0: devices at 0x09 0x2d
lm0 at iic0 addr 0x2d
lm0: Winbond AS99127F Hardware monitor
[...]

and

# envstat
             Current  CritMax  CritMin  CritCap     Unit
[lm0]
 VCore A:      2.064                                   V
 VCore B:      2.512                                   V
   +3.3V:      3.648                                   V
     +5V:      5.053                                   V
    +12V:     11.856                                   V
    -12V:    -11.126                                   V
     -5V:     -5.153                                   V
   Temp0:     33.000                                degC
   Temp1:      0.000                                degC
   Temp2:      0.000                                degC
    Fan0:       3341                                 RPM
    Fan1:        N/A
    Fan2:        N/A
#

        hauke

--
    The ASCII Ribbon Campaign                    Hauke Fath
()     No HTML/RTF in email            Institut für Nachrichtentechnik
/\     No Word docs in email                     TU Darmstadt
    Respect for open standards              Ruf +49-6151-16-3281


-------------------------------------------------------------------------
|   Paul Goyette   | PGP DSS Key fingerprint: |  E-mail addresses:      |
| Customer Service | FA29 0E3B 35AF E8AE 6651 |  paul at whooppee.com   |
| Network Engineer | 0786 F758 55DE 53BA 7731 | pgoyette at juniper.net |
| Kernel Developer |                          | pgoyette at netbsd.org  |
-------------------------------------------------------------------------
Index: distrib/sets/lists/man/mi
===================================================================
RCS file: /cvsroot/src/distrib/sets/lists/man/mi,v
retrieving revision 1.1165
diff -u -p -r1.1165 mi
--- distrib/sets/lists/man/mi   11 Oct 2009 12:47:38 -0000      1.1165
+++ distrib/sets/lists/man/mi   14 Oct 2009 21:43:43 -0000
@@ -614,6 +614,7 @@
 ./usr/share/man/cat4/acpidalb.0                        man-sys-catman          
.cat
 ./usr/share/man/cat4/acpiec.0                  man-sys-catman          .cat
 ./usr/share/man/cat4/acpilid.0                 man-sys-catman          .cat
+./usr/share/man/cat4/acpismbus.0               man-sys-catman          .cat
 ./usr/share/man/cat4/acpitz.0                  man-sys-catman          .cat
 ./usr/share/man/cat4/adb.0                     man-sys-catman          .cat
 ./usr/share/man/cat4/adbbt.0                   man-sys-catman          .cat
@@ -3278,6 +3279,7 @@
 ./usr/share/man/html4/acpidalb.html            man-sys-htmlman         html
 ./usr/share/man/html4/acpiec.html              man-sys-htmlman         html
 ./usr/share/man/html4/acpilid.html             man-sys-htmlman         html
+./usr/share/man/html4/acpismbus.html           man-sys-htmlman         html
 ./usr/share/man/html4/acpitz.html              man-sys-htmlman         html
 ./usr/share/man/html4/adb.html                 man-sys-htmlman         html
 ./usr/share/man/html4/adbbt.html               man-sys-htmlman         html
@@ -5642,6 +5644,7 @@
 ./usr/share/man/man4/acpidalb.4                        man-sys-man             
.man
 ./usr/share/man/man4/acpiec.4                  man-sys-man             .man
 ./usr/share/man/man4/acpilid.4                 man-sys-man             .man
+./usr/share/man/man4/acpismbus.4               man-sys-man             .man
 ./usr/share/man/man4/acpitz.4                  man-sys-man             .man
 ./usr/share/man/man4/adb.4                     man-sys-man             .man
 ./usr/share/man/man4/adbbt.4                   man-sys-man             .man
Index: share/man/man4/Makefile
===================================================================
RCS file: /cvsroot/src/share/man/man4/Makefile,v
retrieving revision 1.499
diff -u -p -r1.499 Makefile
--- share/man/man4/Makefile     30 Sep 2009 22:32:04 -0000      1.499
+++ share/man/man4/Makefile     14 Oct 2009 21:43:43 -0000
@@ -80,7 +80,7 @@ MAN+= irframe.4 cir.4 irframetty.4 oboe.
 
 # ACPI devices
 MAN+=  acpi.4 acpiacad.4 acpibat.4 acpibut.4 acpiec.4 acpilid.4 \
-       acpitz.4
+       acpismbus.4 acpitz.4
 
 # Radio devices
 MAN+=  radio.4 az.4 mr.4 rt.4 rtii.4 sf2r.4
Index: share/man/man4/acpi.4
===================================================================
RCS file: /cvsroot/src/share/man/man4/acpi.4,v
retrieving revision 1.30
diff -u -p -r1.30 acpi.4
--- share/man/man4/acpi.4       17 May 2009 00:37:53 -0000      1.30
+++ share/man/man4/acpi.4       14 Oct 2009 21:43:43 -0000
@@ -24,43 +24,44 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd May 16, 2009
+.Dd October XXX, 2009
 .Dt ACPI 4
 .Os
 .Sh NAME
 .Nm acpi
 .Nd Advanced Configuration and Power Interface
 .Sh SYNOPSIS
-.Cd "acpi0     at mainbus0"
-.Cd "acpiacad* at acpi?"
-.Cd "acpibat*  at acpi?"
-.Cd "acpibut*  at acpi?"
-.Cd "acpiec*   at acpi?"
-.Cd "acpilid*  at acpi?"
-.Cd "acpitz*   at acpi?"
-.Cd "attimer*  at acpi?"
-.Cd "aiboost*  at acpi?"
-.Cd "com*      at acpi?"
-.Cd "fdc*      at acpi?"
-.Cd "hpet*     at acpi?"
-.Cd "joy*      at acpi?"
-.Cd "lpt*      at acpi?"
-.Cd "mpu*      at acpi?"
-.Cd "npx*      at acpi?"
-.Cd "pckbc*    at acpi?"
-.Cd "pcppi*    at acpi?"
-.Cd "sony*     at acpi?"
-.Cd "spic*     at acpi?"
-.Cd "ug*       at acpi?"
-.Cd "vald*     at acpi?"
-.Cd "wss*      at acpi?"
-.Cd "ym*       at acpi?"
+.Cd "acpi0      at mainbus0"
+.Cd "acpiacad*  at acpi?"
+.Cd "acpibat*   at acpi?"
+.Cd "acpibut*   at acpi?"
+.Cd "acpiec*    at acpi?"
+.Cd "acpilid*   at acpi?"
+.Cd "acpismbus* at acpi?"
+.Cd "acpitz*    at acpi?"
+.Cd "attimer*   at acpi?"
+.Cd "aiboost*   at acpi?"
+.Cd "com*       at acpi?"
+.Cd "fdc*       at acpi?"
+.Cd "hpet*      at acpi?"
+.Cd "joy*       at acpi?"
+.Cd "lpt*       at acpi?"
+.Cd "mpu*       at acpi?"
+.Cd "npx*       at acpi?"
+.Cd "pckbc*     at acpi?"
+.Cd "pcppi*     at acpi?"
+.Cd "sony*      at acpi?"
+.Cd "spic*      at acpi?"
+.Cd "ug*        at acpi?"
+.Cd "vald*      at acpi?"
+.Cd "wss*       at acpi?"
+.Cd "ym*        at acpi?"
 .Pp
-.Cd "options   ACPI_DEBUG"
-.Cd "options   ACPIVERBOSE"
-.Cd "options   ACPI_ACTIVATE_DEV"
-.Cd "options   ACPICA_PEDANTIC"
-.Cd "options   ACPI_DSDT_OVERRIDE"
+.Cd "options    ACPI_DEBUG"
+.Cd "options    ACPIVERBOSE"
+.Cd "options    ACPI_ACTIVATE_DEV"
+.Cd "options    ACPICA_PEDANTIC"
+.Cd "options    ACPI_DSDT_OVERRIDE"
 .Sh DESCRIPTION
 .Nx
 provides machine-independent bus support for
@@ -187,6 +188,9 @@ Embedded Controllers.
 .It acpilid
 .Tn ACPI
 lid switches.
+.It acpismbus
+.Tn ACPI
+SMBus via Control Method Interface.
 .It acpitz
 .Tn ACPI
 thermal zones.
@@ -234,6 +238,7 @@ Toshiba Libretto device.
 .Xr acpibut 4 ,
 .Xr acpiec 4 ,
 .Xr acpilid 4 ,
+.Xr acpismbus 4 ,
 .Xr acpitz 4 ,
 .Xr aiboost 4 ,
 .Xr apm 4 ,
Index: share/man/man4/iic.4
===================================================================
RCS file: /cvsroot/src/share/man/man4/iic.4,v
retrieving revision 1.3
diff -u -p -r1.3 iic.4
--- share/man/man4/iic.4        22 Aug 2009 00:17:03 -0000      1.3
+++ share/man/man4/iic.4        14 Oct 2009 21:43:43 -0000
@@ -16,7 +16,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd June 4, 2009
+.Dd October XXX, 2009
 .Dt IIC 4
 .Os
 .Sh NAME
@@ -29,6 +29,7 @@
 .\" grep -h '^iic.*at' */conf/* | sort -u -k +3 | sed -e 's,[         ][      
]*, ,g' -e 's, *#.*,,' | sh -c 'while read iic at ic ; do printf ".Cd \"$iic 
$at %-20s # %s\"\n" "$ic" "`grep \"iic.*at.*$ic\" */conf/* | sed \"s,/.*,,\" | 
sort -u | tr \"\012\" \ `"  ; done' | uniq | tee /tmp/x
 .\" cat /tmp/x
 .\"
+.Cd "iic* at acpismbus?"
 .Cd "iic* at alipm?               # sparc64 "
 .Cd "iic* at amdpm?               # amd64 i386 "
 .Cd "iic* at armadillo9iic?       # evbarm "
@@ -96,6 +97,8 @@ are:
 .Bl -tag -width 18n -compact
 .It Xr alipm 4
 Acer Labs M7101 SMBus controller
+.It Xr acpismbus 4
+ACPI SMBus Control Method Interface
 .It Xr amdpm 4
 AMD768 Power Management Controller and AMD8111 System Management Controller
 .It Xr armadillo9iic 4
Index: share/man/man4/acpismbus.4
===================================================================
RCS file: share/man/man4/acpismbus.4
diff -N share/man/man4/acpismbus.4
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ share/man/man4/acpismbus.4  14 Oct 2009 21:43:43 -0000
@@ -0,0 +1,82 @@
+.\" $NetBSD$
+.\"
+.\" Copyright (c) 2009 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Paul Goyette
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd October XXX, 2009
+.Dt ACPISMBUS 4
+.Os
+.Sh NAME
+.Nm acpismbus
+.Nd ACPI SMBus Control Method Interface
+.Sh SYNOPSIS
+.Cd "acpismbus* at acpi?"
+.Cd "iic* at acpismbus?"
+.Sh DESCRIPTION
+The
+.Nm
+driver supports instances of the ACPI SMBus Control Method Interface.
+This enables i2c access to bus segments which might not otherwise be
+accessible due to missing "native" driver support.
+The SMBus Process Call protocol is not supported.
+All other SMBus protocols are supported to the extent that the underlying
+controller supports them.
+.Sh SEE ALSO
+.Xr acpi 4 ,
+.Xr iic 4
+.Sh HISTORY
+The
+.Nm
+driver
+appeared in
+.Nx 6.0 .
+.Sh BUGS
+Although
+.Nm
+SMBus Alerts can be associated with individual devices, this
+capability is ignored.
+When an
+.Nm
+SMBus Alert is generated, all devices on the i2c bus segment which have
+registered an interrupt routine are notified.
+.Pp
+The SMBus CMI protocol defines a method to provide a list of devices on an
+i2c bus segment and their addresses.
+The
+.Nm
+driver makes no attempt to retrieve or process this device list.
+.Pp
+There is currently no way to determine if the i2c controller managed by
+an instance of the ACPI SMBus CMI can also be accessed using a native
+device driver.
+Therefore, the
+.Nm
+driver should not be enabled by default.
+If both a native driver and the
+.Nm
+driver attempt to access the same i2c bus segment, the results are
+undefined.
Index: sys/dev/acpi/files.acpi
===================================================================
RCS file: /cvsroot/src/sys/dev/acpi/files.acpi,v
retrieving revision 1.60
diff -u -p -r1.60 files.acpi
--- sys/dev/acpi/files.acpi     2 Oct 2009 16:47:52 -0000       1.60
+++ sys/dev/acpi/files.acpi     14 Oct 2009 21:43:43 -0000
@@ -150,3 +150,8 @@ file        dev/acpi/wb_acpi.c              wb_acpi
 device acpiwmi
 attach acpiwmi at acpinodebus
 file   dev/acpi/wmi_acpi.c             acpiwmi
+
+# ACPI SMBus controller
+device acpismbus: i2cbus
+attach acpismbus at acpinodebus
+file   dev/acpi/smbus_acpi.c           acpismbus
Index: sys/dev/acpi/smbus_acpi.c
===================================================================
RCS file: sys/dev/acpi/smbus_acpi.c
diff -N sys/dev/acpi/smbus_acpi.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ sys/dev/acpi/smbus_acpi.c   14 Oct 2009 21:43:43 -0000
@@ -0,0 +1,503 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2009 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Paul Goyette
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * ACPI SMBus Controller driver
+ *
+ * See http://smbus.org/specs/smbus_cmi10.pdf for specifications
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/errno.h>
+#include <sys/ioctl.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+#include <sys/callout.h>
+#include <sys/proc.h>
+#include <sys/mutex.h>
+
+#include <dev/acpi/acpica.h>
+#include <dev/acpi/acpireg.h>
+#include <dev/acpi/acpivar.h>
+
+#include <dev/i2c/i2cvar.h>
+
+#define _COMPONENT          ACPI_SMBUS_COMPONENT
+ACPI_MODULE_NAME            ("acpi_smbus")
+
+/*
+ * ACPI SMBus CMI protocol codes
+ */
+#define        ACPI_SMBUS_RD_QUICK     0x03
+#define        ACPI_SMBUS_RCV_BYTE     0x05
+#define        ACPI_SMBUS_RD_BYTE      0x07
+#define        ACPI_SMBUS_RD_WORD      0x09
+#define        ACPI_SMBUS_RD_BLOCK     0x0B
+#define        ACPI_SMBUS_WR_QUICK     0x02
+#define        ACPI_SMBUS_SND_BYTE     0x04
+#define        ACPI_SMBUS_WR_BYTE      0x06
+#define        ACPI_SMBUS_WR_WORD      0x08
+#define        ACPI_SMBUS_WR_BLOCK     0x0A
+#define        ACPI_SMBUS_PROCESS_CALL 0x0C
+
+struct acpi_smbus_softc {
+       struct acpi_devnode     *sc_devnode;
+       struct callout          sc_callout;
+       struct i2c_controller   sc_i2c_tag;
+       device_t                sc_dv;
+       kmutex_t                sc_i2c_mutex;
+       int                     sc_poll_alert;
+};
+
+static int     acpi_smbus_match(device_t, cfdata_t, void *);
+static void    acpi_smbus_attach(device_t, device_t, void *);
+static int     acpi_smbus_detach(device_t, int); 
+static int     acpi_smbus_acquire_bus(void *, int);
+static void    acpi_smbus_release_bus(void *, int);
+static int     acpi_smbus_exec(void *, i2c_op_t, i2c_addr_t, const void *,
+                               size_t, void *, size_t, int);
+static void    acpi_smbus_alerts(struct acpi_smbus_softc *);
+static void    acpi_smbus_tick(void *);
+static void    acpi_smbus_notify_handler(ACPI_HANDLE, UINT32, void *);
+
+struct SMB_UDID {
+       uint8_t         dev_cap;
+       uint8_t         vers_rev;
+       uint16_t        vendor;
+       uint16_t        device;
+       uint16_t        interface;
+       uint16_t        subsys_vendor;
+       uint16_t        subsys_device;
+       uint8_t         reserved[4];
+};
+
+struct SMB_DEVICE {
+       uint8_t         slave_addr;
+       uint8_t         reserved;
+       struct SMB_UDID dev_id;
+};
+
+struct SMB_INFO {
+       uint8_t         struct_ver;
+       uint8_t         spec_ver;
+       uint8_t         hw_cap;
+       uint8_t         poll_int;
+       uint8_t         dev_count;
+       struct SMB_DEVICE device[1];
+};
+
+static const char * const smbus_acpi_ids[] = {
+       "SMBUS01",      /* SMBus CMI v1.0 */
+       NULL
+};
+
+static const char * const pcibus_acpi_ids[] = {
+       "PNP0A03",
+       "PNP0A08",
+       NULL
+};
+
+CFATTACH_DECL_NEW(acpismbus, sizeof(struct acpi_smbus_softc),
+    acpi_smbus_match, acpi_smbus_attach, acpi_smbus_detach, NULL);
+
+/*
+ * acpi_smbus_match: autoconf(9) match routine
+ */
+static int
+acpi_smbus_match(device_t parent, cfdata_t match, void *aux)
+{
+       struct acpi_attach_args *aa = aux;
+       int r = 0;
+       ACPI_STATUS rv;
+       ACPI_BUFFER smi_buf;
+       ACPI_OBJECT *e, *p;
+
+       if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE)
+               return 0;
+
+       if (acpi_match_hid(aa->aa_node->ad_devinfo, smbus_acpi_ids) == 0)
+               return 0;
+
+       /* Ensure that device's CMI version is supported */
+       smi_buf.Pointer = NULL;
+       smi_buf.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
+       rv = AcpiEvaluateObject(aa->aa_node->ad_handle, "_SBI", NULL,
+                               &smi_buf);
+       if (ACPI_FAILURE(rv))
+               goto done;
+
+       p = smi_buf.Pointer;
+       if (p != NULL && p->Type == ACPI_TYPE_PACKAGE &&
+           p->Package.Count >= 1) {
+               e = p->Package.Elements;
+               if (e[0].Type == ACPI_TYPE_INTEGER &&
+                   e[0].Integer.Value == 0x10)
+                       r = 1;
+       }
+done:
+       if (smi_buf.Pointer != NULL)
+               ACPI_FREE(smi_buf.Pointer);
+
+       return r;
+}
+
+/*
+ * acpitz_attach: autoconf(9) attach routine
+ */
+static void
+acpi_smbus_attach(device_t parent, device_t self, void *aux)
+{
+       struct acpi_smbus_softc *sc = device_private(self);
+       struct acpi_attach_args *aa = aux;
+       struct i2cbus_attach_args iba;
+       ACPI_STATUS rv;
+       ACPI_HANDLE native_dev, native_bus;
+       ACPI_DEVICE_INFO *native_dev_info, *native_bus_info;
+       ACPI_BUFFER smi_buf;
+       ACPI_OBJECT *e, *p;
+       struct SMB_INFO *info;
+       int pci_bus, pci_dev, pci_func;
+
+       aprint_naive("\n");
+
+       sc->sc_devnode = aa->aa_node;
+       sc->sc_dv = self;
+       sc->sc_poll_alert = 2;
+
+       /* Attach I2C bus */
+       mutex_init(&sc->sc_i2c_mutex, MUTEX_DEFAULT, IPL_NONE);
+       sc->sc_i2c_tag.ic_cookie = sc;
+       sc->sc_i2c_tag.ic_acquire_bus = acpi_smbus_acquire_bus;
+       sc->sc_i2c_tag.ic_release_bus = acpi_smbus_release_bus;
+       sc->sc_i2c_tag.ic_exec = acpi_smbus_exec;
+
+       /* Retrieve polling interval for SMBus Alerts */
+       smi_buf.Pointer = NULL;
+       smi_buf.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
+       rv = AcpiEvaluateObject(aa->aa_node->ad_handle, "_SBI", NULL,
+                               &smi_buf);
+       if (!ACPI_FAILURE(rv)) {
+               p = smi_buf.Pointer;
+               if (p != NULL && p->Type == ACPI_TYPE_PACKAGE &&
+                   p->Package.Count >= 2) {
+                       e = p->Package.Elements;
+                       if (e[1].Type == ACPI_TYPE_BUFFER) {
+                               info = (struct SMB_INFO *)(e[1].Buffer.Pointer);
+                               sc->sc_poll_alert = info->poll_int;
+                       }
+               }
+       }
+       if (smi_buf.Pointer != NULL)
+               ACPI_FREE(smi_buf.Pointer);
+
+       /* Install notify handler if possible */
+       rv = AcpiInstallNotifyHandler(sc->sc_devnode->ad_handle,
+               ACPI_DEVICE_NOTIFY, acpi_smbus_notify_handler, self);
+       if (ACPI_FAILURE(rv)) {
+               aprint_error(": unable to install DEVICE NOTIFY handler: %s\n",
+                   AcpiFormatException(rv));
+               sc->sc_poll_alert = 2;  /* If failed, fall-back to polling */
+       }
+
+       callout_init(&sc->sc_callout, 0);
+       callout_setfunc(&sc->sc_callout, acpi_smbus_tick, self);
+
+       if (!pmf_device_register(self, NULL, NULL))
+               aprint_error(": couldn't establish power handler\n");
+
+       if (sc->sc_poll_alert != 0) {
+               aprint_debug(" alert_poll %d sec", sc->sc_poll_alert);
+               callout_schedule(&sc->sc_callout, sc->sc_poll_alert * hz);
+       }
+       aprint_normal("\n");
+
+       /*
+        * Retrieve and display native controller info
+        */
+       rv = AcpiGetParent(sc->sc_devnode->ad_handle, &native_dev);
+       if (!ACPI_FAILURE(rv))
+               rv = AcpiGetParent(native_dev, &native_bus);
+       if (!ACPI_FAILURE(rv))
+               rv = AcpiGetObjectInfo(native_bus, &native_bus_info);
+       if (!ACPI_FAILURE(rv) &&
+           acpi_match_hid(native_bus_info, pcibus_acpi_ids) != 0) {
+               rv = AcpiGetObjectInfo(native_dev, &native_dev_info);
+               if (!ACPI_FAILURE(rv)) {
+                       pci_bus = native_bus_info->Address;
+                       pci_dev = (native_dev_info->Address >> 16) & 0xffff;
+                       pci_func = native_dev_info->Address & 0xffff;
+                       aprint_debug_dev(self, "Native i2c host controller"
+                           " is on PCI bus %d dev %d func %d\n",
+                           pci_bus, pci_dev, pci_func);
+                       /*
+                        * XXX We really need a mechanism to prevent the
+                        * XXX native controller from attaching
+                        */
+               }
+       }
+
+       memset(&iba, 0, sizeof(iba));
+       iba.iba_tag = &sc->sc_i2c_tag;
+       config_found_ia(self, "i2cbus", &iba, iicbus_print);
+}
+
+static int
+acpi_smbus_detach(device_t self, int flags) 
+{
+       struct acpi_smbus_softc *sc = device_private(self);
+       ACPI_STATUS rv;
+ 
+       pmf_device_deregister(self);
+
+       callout_halt(&sc->sc_callout, NULL);
+
+       rv = AcpiRemoveNotifyHandler(sc->sc_devnode->ad_handle,
+           ACPI_DEVICE_NOTIFY, acpi_smbus_notify_handler);
+       if (ACPI_FAILURE(rv)) {
+               aprint_error_dev(self,
+                   "unable to deregister DEVICE NOTIFY handler: %s\n",
+                   AcpiFormatException(rv));
+               return EBUSY;
+       }
+
+       mutex_destroy(&sc->sc_i2c_mutex);
+   
+       return 0;
+}
+
+static int
+acpi_smbus_acquire_bus(void *cookie, int flags)
+{
+        struct acpi_smbus_softc *sc = cookie;
+  
+        mutex_enter(&sc->sc_i2c_mutex);
+        return 0;
+}       
+                
+static void
+acpi_smbus_release_bus(void *cookie, int flags)
+{       
+        struct acpi_smbus_softc *sc = cookie;
+                                
+        mutex_exit(&sc->sc_i2c_mutex);
+}
+static int
+acpi_smbus_exec(void *cookie, i2c_op_t op, i2c_addr_t addr,
+       const void *cmdbuf, size_t cmdlen, void *buf, size_t len, int flags)
+{
+        struct acpi_smbus_softc *sc = cookie;
+       const uint8_t *c = cmdbuf;
+       uint8_t *b = buf, *xb;
+       int xlen;
+       int r = 0;
+       ACPI_BUFFER smbuf;
+       ACPI_STATUS rv;
+       ACPI_OBJECT_LIST args;
+       ACPI_OBJECT arg[5];
+       ACPI_OBJECT *p, *e;
+
+       smbuf.Pointer = NULL;
+       smbuf.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
+       args.Pointer = arg;
+       arg[0].Type = ACPI_TYPE_INTEGER;        /* Protocol */
+       arg[1].Type = ACPI_TYPE_INTEGER;        /* Slave Addr */
+       arg[1].Integer.Value = addr;
+       arg[2].Type = ACPI_TYPE_INTEGER;        /* Command */
+       if (I2C_OP_READ_P(op)) {
+               args.Count = 3;
+               if (len == 0) {
+                       arg[2].Integer.Value = 0;
+                       if (cmdlen == 0)
+                               arg[0].Integer.Value = ACPI_SMBUS_RD_QUICK;
+                       else
+                               arg[0].Integer.Value = ACPI_SMBUS_RCV_BYTE;
+               } else
+                       arg[2].Integer.Value = *c;
+               if (len == 1)
+                       arg[0].Integer.Value = ACPI_SMBUS_RD_BYTE;
+               else if (len == 2)
+                       arg[0].Integer.Value = ACPI_SMBUS_RD_WORD;
+               else if (len > 2)
+                       arg[0].Integer.Value = ACPI_SMBUS_RD_BLOCK;
+               rv = AcpiEvaluateObject(sc->sc_devnode->ad_handle, "_SBR",
+                                   &args, &smbuf);
+       } else {
+               args.Count = 5;
+               arg[3].Type = ACPI_TYPE_INTEGER;        /* Data Len */
+               arg[3].Integer.Value = len;
+               arg[4].Type = ACPI_TYPE_INTEGER;        /* Data */
+               if (len == 0) {
+                       arg[4].Integer.Value = 0;
+                       if (cmdlen == 0) {
+                               arg[2].Integer.Value = 0;
+                               arg[0].Integer.Value = ACPI_SMBUS_WR_QUICK;
+                       } else {
+                               arg[2].Integer.Value = *c;
+                               arg[0].Integer.Value = ACPI_SMBUS_SND_BYTE;
+                       }
+               } else
+                       arg[2].Integer.Value = *c;
+               if (len == 1) {
+                       arg[0].Integer.Value = ACPI_SMBUS_WR_BYTE;
+                       arg[4].Integer.Value = *b;
+               } else if (len == 2) {
+                       arg[0].Integer.Value = ACPI_SMBUS_WR_WORD;
+                       arg[4].Integer.Value = *b++;
+                       arg[4].Integer.Value += (*b--) << 8;
+               } else if (len > 2) {
+                       arg[0].Integer.Value = ACPI_SMBUS_WR_BLOCK;
+                       arg[4].Type = ACPI_TYPE_BUFFER;
+                       arg[4].Buffer.Pointer = buf;
+                       arg[4].Buffer.Length = (len < 32?len:32);
+               }
+               rv = AcpiEvaluateObject(sc->sc_devnode->ad_handle, "_SBW",
+                                   &args, &smbuf);
+       }
+       if (ACPI_FAILURE(rv))
+               r = 1;
+       else {
+               p = smbuf.Pointer;
+               if (p == NULL || p->Type != ACPI_TYPE_PACKAGE ||
+                   p->Package.Count < 1)
+                       r = 1;
+               else {
+                       e = p->Package.Elements;
+                       if (e->Type == ACPI_TYPE_INTEGER)
+                               r = e[0].Integer.Value;
+                       else
+                               r = 1;
+               }
+               if (r != 0)
+                       r = 1;
+
+               /* For read operations, copy data to user buffer */
+               if (r == 0 && I2C_OP_READ_P(op)) {
+                       if (p->Package.Count >= 3 &&
+                           e[1].Type == ACPI_TYPE_INTEGER) {
+                               xlen = e[1].Integer.Value;
+                               if (xlen > len)
+                                       xlen = len;
+                               if (xlen != 0 &&
+                                   e[2].Type == ACPI_TYPE_BUFFER) {
+                                       xb = e[2].Buffer.Pointer;
+                                       if (xb != NULL)
+                                               memcpy(b, xb, xlen);
+                                       else
+                                               r = 1;
+                               } else if (e[2].Type == ACPI_TYPE_INTEGER) {
+                                       if (xlen > 0)
+                                               *b++ = e[2].Integer.Value &
+                                                       0xff;
+                                       if (xlen > 1)
+                                               *b = (e[2].Integer.Value >> 8);
+                               } else
+                                       r = 1;
+                       } else
+                               r = 1;
+               }
+       }
+       if (smbuf.Pointer)
+               ACPI_FREE(smbuf.Pointer);
+
+       return r;
+}
+
+/*
+ * acpi_smbus_alerts
+ *
+ * Whether triggered by periodic polling or an AcpiNotify, retrieve
+ * all pending SMBus device alerts
+ */
+static void
+acpi_smbus_alerts(struct acpi_smbus_softc *sc)
+{
+       int status = 0;
+       uint8_t slave_addr;
+       ACPI_STATUS rv;
+       ACPI_BUFFER alert;
+       ACPI_OBJECT *e, *p;
+
+       do {
+               alert.Pointer = NULL;
+               alert.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
+               rv = AcpiEvaluateObject(sc->sc_devnode->ad_handle, "_SBA", NULL,
+                                       &alert);
+               if (ACPI_FAILURE(rv)) {
+                       status = 1;
+                       goto done;
+               }
+
+               p = alert.Pointer;
+               if (p != NULL && p->Type == ACPI_TYPE_PACKAGE &&
+                   p->Package.Count >= 2) {
+                       e = p->Package.Elements;
+                       if (e[0].Type == ACPI_TYPE_INTEGER)
+                               status = e[0].Integer.Value;
+                       else
+                               status = 1;
+                       if (status == 0x0 && e[1].Type == ACPI_TYPE_INTEGER) {
+                               slave_addr = e[1].Integer.Value;
+                               aprint_debug_dev(sc->sc_dv, "Alert for 0x%x\n",
+                                                slave_addr);
+                               (void)iic_smbus_intr(&sc->sc_i2c_tag);
+                       }
+               }
+done:
+               if (alert.Pointer != NULL)
+                       ACPI_FREE(alert.Pointer);
+       } while (status == 0);
+}
+
+static void
+acpi_smbus_tick(void *opaque)
+{
+       device_t dv = opaque;
+       struct acpi_smbus_softc *sc = device_private(dv);
+
+       acpi_smbus_alerts(sc);
+
+       callout_schedule(&sc->sc_callout, sc->sc_poll_alert * hz);
+}
+
+static void
+acpi_smbus_notify_handler(ACPI_HANDLE hdl, UINT32 notify, void *opaque)
+{
+       device_t dv = opaque;
+       struct acpi_smbus_softc *sc = device_private(dv);
+
+       aprint_debug_dev(dv, "received notify message 0x%x\n", notify);
+       acpi_smbus_alerts(sc);
+}


Home | Main Index | Thread Index | Old Index