PERFORCE change 34326 for review

Marcel Moolenaar marcel at FreeBSD.org
Thu Jul 10 18:11:08 PDT 2003


http://perforce.freebsd.org/chv.cgi?CH=34326

Change 34326 by marcel at marcel_nfs on 2003/07/10 18:10:27

	IFC @34325

Affected files ...

.. //depot/projects/ia64/Makefile.inc1#73 integrate
.. //depot/projects/ia64/bin/ls/ls.1#17 integrate
.. //depot/projects/ia64/etc/sendmail/Makefile#11 integrate
.. //depot/projects/ia64/share/man/man4/dc.4#5 integrate
.. //depot/projects/ia64/share/man/man4/rl.4#6 integrate
.. //depot/projects/ia64/sys/contrib/ia64/libuwx/src/Makefile#2 integrate
.. //depot/projects/ia64/sys/contrib/ia64/libuwx/src/uwx_trace.c#2 integrate
.. //depot/projects/ia64/sys/contrib/ia64/libuwx/src/uwx_trace.h#2 integrate
.. //depot/projects/ia64/sys/dev/acpica/acpi_ec.c#10 integrate
.. //depot/projects/ia64/sys/dev/hatm/if_hatm.c#3 integrate
.. //depot/projects/ia64/sys/dev/hatm/if_hatm_intr.c#2 integrate
.. //depot/projects/ia64/sys/dev/hatm/if_hatm_ioctl.c#2 integrate
.. //depot/projects/ia64/sys/dev/hatm/if_hatm_rx.c#2 integrate
.. //depot/projects/ia64/sys/dev/hatm/if_hatm_tx.c#2 integrate
.. //depot/projects/ia64/sys/dev/usb/if_aue.c#20 integrate
.. //depot/projects/ia64/sys/dev/usb/usbdevs#41 integrate
.. //depot/projects/ia64/sys/dev/usb/usbdevs.h#39 integrate
.. //depot/projects/ia64/sys/dev/usb/usbdevs_data.h#39 integrate
.. //depot/projects/ia64/sys/i386/i386/mp_machdep.c#25 integrate
.. //depot/projects/ia64/sys/kern/kern_malloc.c#24 integrate
.. //depot/projects/ia64/sys/kern/subr_param.c#10 integrate
.. //depot/projects/ia64/sys/modules/mii/Makefile#6 integrate
.. //depot/projects/ia64/sys/pci/if_dc.c#41 integrate
.. //depot/projects/ia64/sys/pci/if_dcreg.h#15 integrate
.. //depot/projects/ia64/sys/pci/if_rl.c#36 integrate
.. //depot/projects/ia64/sys/pci/if_rlreg.h#10 integrate
.. //depot/projects/ia64/sys/pci/if_xl.c#36 integrate
.. //depot/projects/ia64/sys/pci/if_xlreg.h#11 integrate
.. //depot/projects/ia64/sys/sparc64/include/bus.h#19 integrate
.. //depot/projects/ia64/sys/sparc64/include/bus_private.h#5 integrate
.. //depot/projects/ia64/sys/sparc64/include/iommuvar.h#13 integrate
.. //depot/projects/ia64/sys/sparc64/sparc64/bus_machdep.c#20 integrate
.. //depot/projects/ia64/sys/sparc64/sparc64/iommu.c#21 integrate
.. //depot/projects/ia64/sys/sys/systm.h#27 integrate

Differences ...

==== //depot/projects/ia64/Makefile.inc1#73 (text+ko) ====

@@ -1,5 +1,5 @@
 #
-# $FreeBSD: src/Makefile.inc1,v 1.377 2003/07/08 01:24:21 obrien Exp $
+# $FreeBSD: src/Makefile.inc1,v 1.378 2003/07/10 05:29:56 kris Exp $
 #
 # Make command line options:
 #	-DNO_KERBEROS Do not build Heimdal (Kerberos 5)
@@ -754,7 +754,7 @@
 
 .if (defined(RESCUE) || \
     defined(RELEASEDIR)) && \
-    (${TARGET_ARCH} != ${MACHINE_ARCH} || ${BOOTSTRAPPING} < 501101)
+    ( ${TARGET_ARCH} != ${MACHINE_ARCH} || ${BOOTSTRAPPING} < 501101 )
 _crunchide=	usr.sbin/crunch/crunchide
 .endif
 

==== //depot/projects/ia64/bin/ls/ls.1#17 (text+ko) ====

@@ -33,7 +33,7 @@
 .\" SUCH DAMAGE.
 .\"
 .\"     @(#)ls.1	8.7 (Berkeley) 7/29/94
-.\" $FreeBSD: src/bin/ls/ls.1,v 1.74 2003/05/06 21:54:46 trhodes Exp $
+.\" $FreeBSD: src/bin/ls/ls.1,v 1.75 2003/07/10 20:53:56 brueffer Exp $
 .\"
 .Dd May 19, 2002
 .Dt LS 1
@@ -334,7 +334,7 @@
 The file mode printed under the
 .Fl l
 option consists of the
-entry type, owner permissions, and group permissions.
+entry type and the permissions.
 The entry type character describes the type of file, as
 follows:
 .Pp

==== //depot/projects/ia64/etc/sendmail/Makefile#11 (text+ko) ====

@@ -1,5 +1,5 @@
 #	@(#)Makefile	8.19 (Berkeley) 1/14/97
-# $FreeBSD: src/etc/sendmail/Makefile,v 1.25 2003/07/07 03:19:46 gshapiro Exp $
+# $FreeBSD: src/etc/sendmail/Makefile,v 1.26 2003/07/10 04:53:32 gshapiro Exp $
 
 M4=		m4
 CHMOD=		chmod
@@ -25,6 +25,7 @@
 DEST_SUBMIT_CF=	${DESTDIR}/etc/mail/submit.cf
 
 ALL=		freebsd.cf
+CLEANFILES=	freebsd.cf
 
 # Local SENDMAIL_MC or SENDMAIL_CF may be set in /etc/make.conf.
 # Warning!  If set, this causes 'make install' to always copy it
@@ -33,14 +34,17 @@
 .if defined(SENDMAIL_MC)
 INSTALL_CF=	${SENDMAIL_MC:T:R}.cf
 ALL+=		${INSTALL_CF}
+CLEANFILES+=	${SENDMAIL_MC:T:R}.cf
 ${INSTALL_CF}: ${SENDMAIL_MC}
 .elif defined(SENDMAIL_CF)
+ALL+=		${SENDMAIL_CF}
 INSTALL_CF=	${SENDMAIL_CF}
 .endif
 
 .if !defined(SENDMAIL_SET_USER_ID) && defined(SENDMAIL_SUBMIT_MC)
 INSTALL_SUBMIT_CF= ${SENDMAIL_SUBMIT_MC:T:R}.cf
 ALL+=		${INSTALL_SUBMIT_CF}
+CLEANFILES+=	${INSTALL_SUBMIT_CF}
 ${INSTALL_SUBMIT_CF}: ${SENDMAIL_SUBMIT_MC}
 .endif
 
@@ -48,13 +52,12 @@
 .if defined(SENDMAIL_ADDITIONAL_MC)
 SENDMAIL_ADDITIONAL_CF= ${SENDMAIL_ADDITIONAL_MC:T:S/.mc$/.cf/}
 ALL+=		${SENDMAIL_ADDITIONAL_CF}
+CLEANFILES+=	${SENDMAIL_ADDITIONAL_CF}
 .for mc in ${SENDMAIL_ADDITIONAL_MC}
 ${mc:T:R}.cf: ${mc}
 .endfor
 .endif
 
-CLEANFILES=	${ALL}
-
 all: ${ALL}
 
 install distribution: ${ALL}

==== //depot/projects/ia64/share/man/man4/dc.4#5 (text+ko) ====

@@ -28,7 +28,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 .\" THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $FreeBSD: src/share/man/man4/dc.4,v 1.20 2003/05/12 19:50:21 mbr Exp $
+.\" $FreeBSD: src/share/man/man4/dc.4,v 1.21 2003/07/10 18:43:17 wpaul Exp $
 .\"
 .Dd November 20, 1999
 .Dt DC 4
@@ -145,6 +145,10 @@
 LinkSys LNE100TX v4.0/4.1 (ADMtek AN985 Centaur-P)
 .It
 3Com OfficeConnect 10/100B (ADMtek AN985 Centaur-P)
+.It
+Microsoft MN-120 10/100 CardBus (ADMTek Centaur-C)
+.It
+Microsoft MN-130 10/100 PCI (ADMTek Centaur-P)
 .El
 .Pp
 The

==== //depot/projects/ia64/share/man/man4/rl.4#6 (text+ko) ====

@@ -28,14 +28,14 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 .\" THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $FreeBSD: src/share/man/man4/rl.4,v 1.26 2003/02/15 17:12:53 trhodes Exp $
+.\" $FreeBSD: src/share/man/man4/rl.4,v 1.27 2003/07/10 18:43:17 wpaul Exp $
 .\"
 .Dd November 4, 1998
 .Dt RL 4
 .Os
 .Sh NAME
 .Nm rl
-.Nd RealTek 8129/8139 fast ethernet device driver
+.Nd RealTek 8129/8139/8139C+ fast ethernet device driver
 .Sh SYNOPSIS
 .Cd "device miibus"
 .Cd "device rl"
@@ -44,17 +44,64 @@
 .Nm
 driver provides support for PCI ethernet adapters and embedded
 controllers based on the RealTek 8129 and 8139 fast ethernet controller
-chips.
-This includes the Allied Telesyn AT2550, Farallon NetLINE 10/100 PCI,
+chips, including the following:
+.Pp
+.Bl -bullet -compact -offset indent
+.It
+Allied Telesyn AT2550
+.It
+Farallon NetLINE 10/100 PCI
+.It
 Genius GF100TXR,
-NDC Communications NE100TX-E, OvisLink LEF-8129TX, OvisLink LEF-8139TX,
-Netronix Inc. EA-1210 NetEther 10/100, KTX-9130TX 10/100 Fast Ethernet,
-Encore ENL832-TX 10/100 M PCI, Longshine LCS-8038TX-R, the
-SMC EZ Card 10/100 PCI 1211-TX, and various other cheap adapters.
-It also supports the Accton EN1207D which has a
-chip labeled MPX5030 (or MPX5038) which appears to be a RealTek workalike.
+.It
+NDC Communications NE100TX-E
+.It
+OvisLink LEF-8129TX
+.It
+OvisLink LEF-8139TX,
+.It
+Netronix Inc. EA-1210 NetEther 10/100
+.It
+KTX-9130TX 10/100 Fast Ethernet,
+.It
+Encore ENL832-TX 10/100 M PCI,
+.It
+Longshine LCS-8038TX-R
+.It
+SMC EZ Card 10/100 PCI 1211-TX
+.It
+Compaq HNE-300
+.It
+LevelOne FPC-0106TX
+.It
+Edimax EP-4103DL CardBus
+.It
+Nortel Networks 10/100BaseTX
+.It
+D-Link DFE-690TXD
+.It
+D-Link DFE-530TX+
+.It
+D-Link DFE-538TX (same as 530+?)
+.It
+Corega FEther CB-TXD
+.It
+Corega FEtherII CB-TXD
+.It
+Peppercon AG ROL-F
+.It
+Planex FNW-3800-TX
+.It
+Accton EN1207D
+.It
+GigaFast Ethernet EE100-AXP
+.It
+CompUSA no-name 10/100 PCI ethernet NIC
+.It
+Belkin F5D5000
+.El
 .Pp
-The RealTek controllers use bus master DMA but do not use a
+The RealTek 8129/8139 series controllers use bus master DMA but do not use a
 descriptor-based data transfer mechanism.
 The receiver uses a
 single fixed size ring buffer from which packets must be copied
@@ -73,6 +120,21 @@
 The 8129 can support the same speeds and modes given an appropriate
 PHY chip.
 .Pp
+Support is also provided for the special C+ mode of the 8139C+ chip.
+By default, the 8139C+ is back backwards compatible with the 8139, but
+in C+ mode it supports advanced features such as descriptor-based DMA,
+64-bit addressing, TCP/IP checksum offload on both receive and transmit,
+hardware VLAN tag insertion and extraction, and TCP large send.
+When used with an 8139C+ chip, the
+.Nm
+driver makes use of all of these features, except for TCP large send,
+since there is currently no OS support for it. Transmit interrupt
+moderation is also used to improve performance at high frame rates.
+The receive and transmit checksum offload capabilities are on by default
+but can be toggled off using the
+.Xr ifconfig 8
+command.
+.Pp
 The
 .Nm
 driver supports the following media types:
@@ -167,8 +229,8 @@
 .Xr ng_ether 4 ,
 .Xr ifconfig 8
 .Rs
-.%B The RealTek 8129 and 8139 datasheets
-.%O ftp.realtek.com.tw:/lancard/data sheet
+.%B The RealTek 8129, 8139 and 8139C+ datasheets
+.%O http://www.realtek.com.tw
 .Re
 .Sh HISTORY
 The

==== //depot/projects/ia64/sys/contrib/ia64/libuwx/src/Makefile#2 (text+ko) ====

@@ -8,7 +8,7 @@
 AR = ar
 RANLIB = :
 
-# OTHERCFLAGS = -DDISABLE_TRACE		# Disables trace output
+# OTHERCFLAGS = -DUWX_TRACE_ENABLE	# Enables trace output
 # OTHERCFLAGS = +DD64			# Builds 64-bit library
 OTHERCFLAGS =
 

==== //depot/projects/ia64/sys/contrib/ia64/libuwx/src/uwx_trace.c#2 (text+ko) ====

@@ -25,6 +25,8 @@
 #include "uwx_scoreboard.h"
 #include "uwx_trace.h"
 
+#ifdef UWX_TRACE_ENABLE
+
 void uwx_trace_init(struct uwx_env *env)
 {
     char *tstr;
@@ -136,3 +138,4 @@
 	uwx_dump_rstate(i, scoreboard->rstate[i]);
 }
 
+#endif /* UWX_TRACE_ENABLE */

==== //depot/projects/ia64/sys/contrib/ia64/libuwx/src/uwx_trace.h#2 (text+ko) ====

@@ -29,7 +29,7 @@
 #define UWX_TRACE_COPYIN	64	/* UWX_TRACE=C: copyin callback */
 #define UWX_TRACE_LOOKUPIP	128	/* UWX_TRACE=L: lookupip callback */
 
-#ifdef DISABLE_TRACE
+#ifndef UWX_TRACE_ENABLE
 
 #define TRACE_INIT
 #define TRACE_B_REUSE(id)
@@ -76,7 +76,7 @@
 #define TRACE_SELF_LOOKUP(ip)
 #define TRACE_SELF_LOOKUP_DESC(text_base, unwind_base)
 
-#else /* not TRACE_DISABLED */
+#else /* !UWX_TRACE_ENABLE */
 
 extern void uwx_trace_init(struct uwx_env *env);
 
@@ -344,5 +344,5 @@
 			(unsigned int) ((text_base)+(unwind_base)[2])); \
 	}
 
-#endif /* TRACE_DISABLED */
+#endif /* !UWX_TRACE_ENABLE */
 

==== //depot/projects/ia64/sys/dev/acpica/acpi_ec.c#10 (text+ko) ====

@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2003 Nate Lawson
  * Copyright (c) 2000 Michael Smith
  * Copyright (c) 2000 BSDi
  * All rights reserved.
@@ -24,7 +25,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	$FreeBSD: src/sys/dev/acpica/acpi_ec.c,v 1.30 2003/06/27 21:57:42 njl Exp $
+ *	$FreeBSD: src/sys/dev/acpica/acpi_ec.c,v 1.31 2003/07/10 17:22:46 njl Exp $
  */
 /******************************************************************************
  *
@@ -238,26 +239,42 @@
     bus_space_tag_t	ec_csr_tag;
     bus_space_handle_t	ec_csr_handle;
 
-    int			ec_locked;
-    int			ec_lockhandle;
-    int			ec_pendquery;
-    int			ec_csrvalue;
+    int			ec_glk;
+    int			ec_glkhandle;
+    struct mtx		ec_mtx;
+    UINT32		ec_polldelay;
 };
 
-static int		acpi_ec_event_driven = 0;
-TUNABLE_INT("hw.acpi.ec.event_driven", &acpi_ec_event_driven);
+/*
+ * XXX
+ * I couldn't find it in the spec but other implementations also use a
+ * value of 1 ms for the time to acquire global lock.
+ */
+#define EC_LOCK_TIMEOUT	1000
+
+/*
+ * Start with an interval of 1 us for status poll loop.  This delay
+ * will be dynamically adjusted based on the actual time waited.
+ */
+#define EC_POLL_DELAY	1
 
-#define EC_LOCK_TIMEOUT	1000	/* 1ms */
+/* Total time in ms spent in the poll loop waiting for a response. */
+#define EC_POLL_TIMEOUT	50
 
 static __inline ACPI_STATUS
 EcLock(struct acpi_ec_softc *sc)
 {
-    ACPI_STATUS	status;
+    ACPI_STATUS	status = AE_OK;
+
+    /* Always acquire this EC's mutex. */
+    mtx_lock(&sc->ec_mtx);
 
-    /* XXX ACPI_WAIT_FOREVER is probably a bad idea, what is a better time? */
-    status = AcpiAcquireGlobalLock(ACPI_WAIT_FOREVER, &sc->ec_lockhandle);
-    if (ACPI_SUCCESS(status))
-	sc->ec_locked = 1;
+    /* If _GLK is non-zero, also acquire the global lock. */
+    if (sc->ec_glk) {
+	status = AcpiAcquireGlobalLock(EC_LOCK_TIMEOUT, &sc->ec_glkhandle);
+	if (ACPI_FAILURE(status))
+	    mtx_unlock(&sc->ec_mtx);
+    }
 
     return (status);
 }
@@ -265,23 +282,11 @@
 static __inline void
 EcUnlock(struct acpi_ec_softc *sc)
 {
-    sc->ec_locked = 0; 
-    AcpiReleaseGlobalLock(sc->ec_lockhandle);
-}
-
-static __inline int
-EcIsLocked(struct acpi_ec_softc *sc)
-{
-    return (sc->ec_locked != 0);
+    if (sc->ec_glk)
+	AcpiReleaseGlobalLock(sc->ec_glkhandle);
+    mtx_unlock(&sc->ec_mtx);
 }
 
-typedef struct
-{
-    EC_COMMAND		Command;
-    UINT8		Address;
-    UINT8		Data;
-} EC_REQUEST;
-
 static void		EcGpeHandler(void *Context);
 static ACPI_STATUS	EcSpaceSetup(ACPI_HANDLE Region, UINT32 Function, 
 				void *Context, void **return_Context);
@@ -291,8 +296,7 @@
 				void *Context, void *RegionContext);
 static ACPI_STATUS	EcWaitEvent(struct acpi_ec_softc *sc, EC_EVENT Event);
 static ACPI_STATUS	EcQuery(struct acpi_ec_softc *sc, UINT8 *Data);
-static ACPI_STATUS	EcTransaction(struct acpi_ec_softc *sc,
-				EC_REQUEST *EcRequest);
+static ACPI_STATUS	EcCommand(struct acpi_ec_softc *sc, EC_COMMAND cmd);
 static ACPI_STATUS	EcRead(struct acpi_ec_softc *sc, UINT8 Address,
 				UINT8 *Data);
 static ACPI_STATUS	EcWrite(struct acpi_ec_softc *sc, UINT8 Address,
@@ -341,6 +345,7 @@
 static int
 acpi_ec_probe(device_t dev)
 {
+    int ret = ENXIO;
 
     if (acpi_get_type(dev) == ACPI_TYPE_DEVICE && !acpi_disabled("ec") &&
 	acpi_MatchHid(dev, "PNP0C09")) {
@@ -349,9 +354,10 @@
 	 * Set device description 
 	 */
 	device_set_desc(dev, "embedded controller");
-	return (0);
+	ret = 0;
     }
-    return (ENXIO);
+
+    return (ret);
 }
 
 static int
@@ -363,17 +369,14 @@
 
     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
 
-    /*
-     * Fetch/initialise softc
-     */
+    /* Fetch/initialize softc (assumes softc is pre-zeroed). */
     sc = device_get_softc(dev);
-    bzero(sc, sizeof(*sc));
     sc->ec_dev = dev;
     sc->ec_handle = acpi_get_handle(dev);
+    sc->ec_polldelay = EC_POLL_DELAY;
+    mtx_init(&sc->ec_mtx, "ACPI embedded controller", NULL, MTX_DEF);
 
-    /* 
-     * Attach bus resources
-     */
+    /* Attach bus resources for data and command/status ports. */
     sc->ec_data_rid = 0;
     sc->ec_data_res = bus_alloc_resource(sc->ec_dev, SYS_RES_IOPORT,
 			&sc->ec_data_rid, 0, ~0, 1, RF_ACTIVE);
@@ -396,13 +399,15 @@
     sc->ec_csr_tag = rman_get_bustag(sc->ec_csr_res);
     sc->ec_csr_handle = rman_get_bushandle(sc->ec_csr_res);
 
+    /* Check if global lock should be used.  If not, leave flag as 0. */
+    acpi_EvaluateInteger(sc->ec_handle, "_GLK", &sc->ec_glk);
+
     /*
-     * Install GPE handler
-     *
      * Evaluate the _GPE method to find the GPE bit used by the EC to signal
-     * status (SCI).
+     * status (SCI).  Note that we don't handle the case where it can
+     * return a package instead of an int.
      */
-    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "attaching GPE\n"));
+    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "querying GPE\n"));
     Status = acpi_EvaluateInteger(sc->ec_handle, "_GPE", &sc->ec_gpebit);
     if (ACPI_FAILURE(Status)) {
 	device_printf(dev, "can't evaluate _GPE - %s\n",
@@ -412,16 +417,12 @@
     }
 
     /*
-     * Install a handler for this EC's GPE bit.  Note that EC SCIs are 
-     * treated as both edge- and level-triggered interrupts; in other words
-     * we clear the status bit immediately after getting an EC-SCI, then
-     * again after we're done processing the event.  This guarantees that
-     * events we cause while performing a transaction (e.g. IBE/OBF) get 
-     * cleared before re-enabling the GPE.
+     * Install a handler for this EC's GPE bit.  We want edge-triggered
+     * behavior.
      */
-    Status = AcpiInstallGpeHandler(sc->ec_gpebit,
-		ACPI_EVENT_LEVEL_TRIGGERED | ACPI_EVENT_EDGE_TRIGGERED, 
-		EcGpeHandler, sc);
+    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "attaching GPE handler\n"));
+    Status = AcpiInstallGpeHandler(sc->ec_gpebit, ACPI_EVENT_EDGE_TRIGGERED, 
+		&EcGpeHandler, sc);
     if (ACPI_FAILURE(Status)) {
 	device_printf(dev, "can't install GPE handler for %s - %s\n",
 		      acpi_name(sc->ec_handle), AcpiFormatException(Status));
@@ -434,117 +435,138 @@
      */
     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "attaching address space handler\n"));
     Status = AcpiInstallAddressSpaceHandler(sc->ec_handle, ACPI_ADR_SPACE_EC,
-		EcSpaceHandler, EcSpaceSetup, sc);
+		&EcSpaceHandler, &EcSpaceSetup, sc);
     if (ACPI_FAILURE(Status)) {
 	device_printf(dev, "can't install address space handler for %s - %s\n",
 		      acpi_name(sc->ec_handle), AcpiFormatException(Status));
-	panic("very suck");
+	Status = AcpiRemoveGpeHandler(sc->ec_gpebit, &EcGpeHandler);
+	if (ACPI_FAILURE(Status))
+	    panic("Added GPE handler but can't remove it");
 	errval = ENXIO;
 	goto out;
     }
-    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "attach complete\n"));
-    return_VALUE (0);
+
+    ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
+		"GPE bit is %#x, %susing global lock\n", sc->ec_gpebit,
+		sc->ec_glk == 0 ? "not " : "");
+
+    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "acpi_ec_attach complete\n"));
+    return (0);
 
  out:
     if (sc->ec_csr_res)
 	bus_release_resource(sc->ec_dev, SYS_RES_IOPORT, sc->ec_csr_rid, 
 			     sc->ec_csr_res);
     if (sc->ec_data_res)
-        bus_release_resource(sc->ec_dev, SYS_RES_IOPORT, sc->ec_data_rid,
+	bus_release_resource(sc->ec_dev, SYS_RES_IOPORT, sc->ec_data_rid,
 			     sc->ec_data_res);
-    return_VALUE (errval);
+    return (errval);
 }
 
+static ACPI_STATUS
+EcQuery(struct acpi_ec_softc *sc, UINT8 *Data)
+{
+    ACPI_STATUS	Status;
+
+    Status = EcLock(sc);
+    if (ACPI_FAILURE(Status))
+	return (Status);
+
+    /*
+     * Send a query command to the EC to find out which _Qxx call it
+     * wants to make.  This command clears the SCI bit and also the
+     * interrupt source since we are edge-triggered.
+     */
+    Status = EcCommand(sc, EC_COMMAND_QUERY);
+    if (ACPI_SUCCESS(Status))
+	*Data = EC_GET_DATA(sc);
+
+    EcUnlock(sc);
+
+    return (Status);
+}    
+
 static void
 EcGpeQueryHandler(void *Context)
 {
     struct acpi_ec_softc	*sc = (struct acpi_ec_softc *)Context;
     UINT8			Data;
     ACPI_STATUS			Status;
+    EC_STATUS			EcStatus;
     char			qxx[5];
 
     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
+    KASSERT(Context != NULL, ("EcGpeQueryHandler called with NULL"));
 
-    for (;;) {
+    /*
+     * Check status for EC_SCI.
+     * 
+     * Bail out if the EC_SCI bit of the status register is not set.
+     * Note that this function should only be called when
+     * this bit is set (polling is used to detect IBE/OBF events).
+     *
+     * We don't acquire the global lock here but do protect against other
+     * running commands (read/write/query) by grabbing ec_mtx.
+     */
+    mtx_lock(&sc->ec_mtx);
+    EcStatus = EC_GET_CSR(sc);
+    mtx_unlock(&sc->ec_mtx);
+    if ((EcStatus & EC_EVENT_SCI) == 0)
+	goto re_enable;
 
-	/*
-	 * Check EC_SCI.
-	 * 
-	 * Bail out if the EC_SCI bit of the status register is not set.
-	 * Note that this function should only be called when
-	 * this bit is set (polling is used to detect IBE/OBF events).
-	 *
-	 * It is safe to do this without locking the controller, as it's
-	 * OK to call EcQuery when there's no data ready; in the worst
-	 * case we should just find nothing waiting for us and bail.
-	 */
-	if ((EC_GET_CSR(sc) & EC_EVENT_SCI) == 0)
-	    break;
+    /* Find out why the EC is signaling us. */
+    Status = EcQuery(sc, &Data);
+    if (ACPI_FAILURE(Status)) {
+	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
+		    "GPE query failed - %s\n", AcpiFormatException(Status));
+	goto re_enable;
+    }
 
-	/*
-	 * Find out why the EC is signalling us
-	 */
-	Status = EcQuery(sc, &Data);
-	    
-	/*
-	 * If we failed to get anything from the EC, give up
-	 */
-	if (ACPI_FAILURE(Status)) {
-	    ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
-		"GPE query failed - %s\n", AcpiFormatException(Status));
-	    break;
-	}
+    /* Ignore the value for "no outstanding event". (13.3.5) */
+    if (Data == 0)
+	goto re_enable;
 
-	/*
-	 * Evaluate _Qxx to respond to the controller.
-	 */
-	sprintf(qxx, "_Q%02x", Data);
-	strupr(qxx);
-	Status = AcpiEvaluateObject(sc->ec_handle, qxx, NULL, NULL);
-	/*
-	 * Ignore spurious query requests.
-	 */
-	if (ACPI_FAILURE(Status) && (Data != 0 || Status != AE_NOT_FOUND)) {
-	    ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
-	    	"evaluation of GPE query method %s failed - %s\n", 
-		qxx, AcpiFormatException(Status));
-	}
+    /* Evaluate _Qxx to respond to the controller. */
+    sprintf(qxx, "_Q%02x", Data);
+    strupr(qxx);
+    Status = AcpiEvaluateObject(sc->ec_handle, qxx, NULL, NULL);
+    if (ACPI_FAILURE(Status) && Status != AE_NOT_FOUND) {
+	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
+		    "evaluation of GPE query method %s failed - %s\n", 
+		    qxx, AcpiFormatException(Status));
     }
-        /* I know I request Level trigger cleanup */
-    if (ACPI_FAILURE(AcpiClearEvent(sc->ec_gpebit, ACPI_EVENT_GPE)))
-	printf("EcGpeQueryHandler:ClearEvent Failed\n");
-    if (ACPI_FAILURE(AcpiEnableEvent(sc->ec_gpebit, ACPI_EVENT_GPE, 0)))
-	printf("EcGpeQueryHandler:EnableEvent Failed\n");
+
+re_enable:
+    /* Re-enable the GPE event so we'll get future requests. */
+    Status = AcpiEnableEvent(sc->ec_gpebit, ACPI_EVENT_GPE, 0);
+    if (ACPI_FAILURE(Status))
+	printf("EcGpeQueryHandler: AcpiEnableEvent failed\n");
 }
 
 /*
- * Handle a GPE sent to us.
+ * Handle a GPE.  Currently we only handle SCI events as others must
+ * be handled by polling in EcWaitEvent().  This is because some ECs
+ * treat events as level when they should be edge-triggered.
  */
 static void
 EcGpeHandler(void *Context)
 {
     struct acpi_ec_softc *sc = Context;
-    int csrvalue;
+    ACPI_STATUS		       Status;
+
+    KASSERT(Context != NULL, ("EcGpeHandler called with NULL"));
+
+    /* Disable further GPEs while we handle this one. */
+    AcpiDisableEvent(sc->ec_gpebit, ACPI_EVENT_GPE, 0);
 
-    /* 
-     * If EC is locked, the intr must process EcRead/Write wait only.
-     * Query request must be pending.
-     */
-    if (EcIsLocked(sc)) {
-	csrvalue = EC_GET_CSR(sc);
-	if (csrvalue & EC_EVENT_SCI)
-	    sc->ec_pendquery = 1;
-	if ((csrvalue & EC_FLAG_OUTPUT_BUFFER) != 0 ||
-	    (csrvalue & EC_FLAG_INPUT_BUFFER) == 0) {
-	    sc->ec_csrvalue = csrvalue;
-	    wakeup(&sc->ec_csrvalue);
-	}
-    } else {
-	/* Queue GpeQuery Handler */
-	if (ACPI_FAILURE(AcpiOsQueueForExecution(OSD_PRIORITY_HIGH,
-				    EcGpeQueryHandler,Context))) {
-	    printf("QueryHandler Queuing Failed\n");
-	}
+    /* Schedule the GPE query handler. */
+    Status = AcpiOsQueueForExecution(OSD_PRIORITY_GPE, EcGpeQueryHandler,
+		Context);
+    if (ACPI_FAILURE(Status)) {
+	printf("Queuing GPE query handler failed.\n");
+	Status = AcpiEnableEvent(sc->ec_gpebit, ACPI_EVENT_GPE, 0);
+	if (ACPI_FAILURE(Status))
+	    printf("EcGpeHandler: AcpiEnableEvent failed\n");
     }
 }
 
@@ -569,249 +591,177 @@
 {
     struct acpi_ec_softc	*sc = (struct acpi_ec_softc *)Context;
     ACPI_STATUS			Status = AE_OK;
-    EC_REQUEST			EcRequest;
+    UINT8			EcAddr, EcData;
     int				i;
 
     ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, (UINT32)Address);
 
     if (Address > 0xFF || width % 8 != 0 || Value == NULL || Context == NULL)
-        return_ACPI_STATUS (AE_BAD_PARAMETER);
-
-    switch (Function) {
-    case ACPI_READ:
-        EcRequest.Command = EC_COMMAND_READ;
-        EcRequest.Address = Address;
-	(*Value) = 0;
-        break;
-    case ACPI_WRITE:
-        EcRequest.Command = EC_COMMAND_WRITE;
-        EcRequest.Address = Address;
-        break;
-    default:
-	device_printf(sc->ec_dev, "invalid Address Space function %d\n",
-		      Function);
-        return_ACPI_STATUS (AE_BAD_PARAMETER);
-    }
+	return_ACPI_STATUS (AE_BAD_PARAMETER);
 
     /*
      * Perform the transaction.
      */
+    EcAddr = Address;
     for (i = 0; i < width; i += 8) {
-	if (Function == ACPI_READ)
-	    EcRequest.Data = 0;
-	else
-	    EcRequest.Data = (UINT8)((*Value) >> i);
-	Status = EcTransaction(sc, &EcRequest);
+	Status = EcLock(sc);
 	if (ACPI_FAILURE(Status))
+	    return (Status);
+
+	switch (Function) {
+	case ACPI_READ:
+	    EcData = 0;
+	    Status = EcRead(sc, EcAddr, &EcData);
+	    break;
+	case ACPI_WRITE:
+	    EcData = (UINT8)((*Value) >> i);
+	    Status = EcWrite(sc, EcAddr, &EcData);
 	    break;
-        *Value |= (ACPI_INTEGER)EcRequest.Data << i;
-	if (++EcRequest.Address == 0)
-            return_ACPI_STATUS (AE_BAD_PARAMETER);
-    }
-    return_ACPI_STATUS (Status);
-}
+	default:
+	    device_printf(sc->ec_dev, "invalid EcSpaceHandler function %d\n",
+			  Function);
+	    Status = AE_BAD_PARAMETER;
+	    break;
+	}
 
-/*
- * Wait for an event interrupt for a specific condition.
- */
-static ACPI_STATUS
-EcWaitEventIntr(struct acpi_ec_softc *sc, EC_EVENT Event)
-{
-    EC_STATUS	EcStatus;
-    int		i;
+	EcUnlock(sc);
+	if (ACPI_FAILURE(Status))
+	    return (Status);
 
-    ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, (UINT32)Event);
-
-    /* XXX this should test whether interrupts are available some other way */
-    if (cold || acpi_ec_event_driven)
-	return_ACPI_STATUS (EcWaitEvent(sc, Event));
-
-    if (!EcIsLocked(sc)) {
-	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
-	    "EcWaitEventIntr called without EC lock!\n");
+	*Value |= (ACPI_INTEGER)EcData << i;
+	if (++EcAddr == 0)
+	    return_ACPI_STATUS (AE_BAD_PARAMETER);
     }
-
-    EcStatus = EC_GET_CSR(sc);
-
-    /* XXX waiting too long? */
-    for (i = 0; i < 10; i++) {
-	/*
-	 * Check EC status against the desired event.
-	 */
-    	if ((Event == EC_EVENT_OUTPUT_BUFFER_FULL) &&
-	    (EcStatus & EC_FLAG_OUTPUT_BUFFER) != 0)
-	    return_ACPI_STATUS (AE_OK);
-      
-	if ((Event == EC_EVENT_INPUT_BUFFER_EMPTY) && 
-	    (EcStatus & EC_FLAG_INPUT_BUFFER) == 0)
-	    return_ACPI_STATUS (AE_OK);
-	
-	sc->ec_csrvalue = 0;
-	/* XXX sleeping with Acpi Global Lock held */
-	if (tsleep(&sc->ec_csrvalue, PZERO, "EcWait", 1) != EWOULDBLOCK) {
-	    EcStatus = sc->ec_csrvalue;
-	} else {
-	    EcStatus = EC_GET_CSR(sc);
-	}
-    }
-    return_ACPI_STATUS (AE_ERROR);
+    return_ACPI_STATUS (Status);
 }
 
 static ACPI_STATUS
 EcWaitEvent(struct acpi_ec_softc *sc, EC_EVENT Event)
 {
     EC_STATUS	EcStatus;
-    UINT32	i = 0;
+    ACPI_STATUS	Status;
+    UINT32	i, period;
 
-    if (!EcIsLocked(sc)) {
-	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
-	    "EcWaitEvent called without EC lock!\n");
-    }
+    mtx_assert(&sc->ec_mtx, MA_OWNED);
+    Status = AE_NO_HARDWARE_RESPONSE;
 
-    /*
-     * Stall 1us:
-     * ----------
-     * Stall for 1 microsecond before reading the status register
-     * for the first time.  This allows the EC to set the IBF/OBF
-     * bit to its proper state.
-     *
-     * XXX it is not clear why we read the CSR twice.
+    /* 
+     * Wait for 1 us before checking the CSR.  Testing shows about
+     * 50% of requests complete in 1 us and 90% of them complete
+     * in 5 us or less.
      */
     AcpiOsStall(1);
-    EcStatus = EC_GET_CSR(sc);
 
     /*
-     * Wait For Event:
-     * ---------------
      * Poll the EC status register to detect completion of the last
-     * command.  Wait up to 10ms (in 10us chunks) for this to occur.
+     * command.  Wait up to 50 ms (in chunks of sc->ec_polldelay
+     * microseconds for the first 1 ms, in 1 ms chunks for the remainder
+     * of the period) for this to occur.
      */
-    for (i = 0; i < 1000; i++) {
+    for (i = 0; i < (1000 / sc->ec_polldelay) + EC_POLL_TIMEOUT; i++) {
 	EcStatus = EC_GET_CSR(sc);
 
-        if (Event == EC_EVENT_OUTPUT_BUFFER_FULL &&
-            (EcStatus & EC_FLAG_OUTPUT_BUFFER) != 0)
-	    return (AE_OK);
+	/* Check if the user's event occurred. */
+	if ((Event == EC_EVENT_OUTPUT_BUFFER_FULL &&
+	    (EcStatus & EC_FLAG_OUTPUT_BUFFER) != 0) ||
+	    (Event == EC_EVENT_INPUT_BUFFER_EMPTY && 
+	    (EcStatus & EC_FLAG_INPUT_BUFFER) == 0)) {
+		Status = AE_OK;
+		break;
+	}
 
-	if (Event == EC_EVENT_INPUT_BUFFER_EMPTY && 
-            (EcStatus & EC_FLAG_INPUT_BUFFER) == 0)
-	    return(AE_OK);
-	
-	AcpiOsStall(10);
+	/* For the first 1 ms, DELAY, after that, msleep. */
+	if (i < 1000)
+	    AcpiOsStall(sc->ec_polldelay);
+	else
+	    msleep(&sc->ec_polldelay, &sc->ec_mtx, PZERO, "ecpoll", 1/*ms*/);
     }
 
-    return (AE_ERROR);
-}    
-
-static ACPI_STATUS
-EcQuery(struct acpi_ec_softc *sc, UINT8 *Data)
-{
-    ACPI_STATUS	Status;
-
-    Status = EcLock(sc);
-    if (ACPI_FAILURE(Status))
-	return (Status);
-
-    EC_SET_CSR(sc, EC_COMMAND_QUERY);
-    Status = EcWaitEvent(sc, EC_EVENT_OUTPUT_BUFFER_FULL);
-    if (ACPI_SUCCESS(Status))
-	*Data = EC_GET_DATA(sc);
-
-    EcUnlock(sc);
+    /* Scale poll delay by the amount of time actually waited. */
+    if (Status == AE_OK) {
+	period = i * sc->ec_polldelay;
+	if (period <= 5)
+	    sc->ec_polldelay = 1;
+	else if (period <= 20)
+	    sc->ec_polldelay = 5;
+	else if (period <= 100)
+	    sc->ec_polldelay = 10;
+	else
+	    sc->ec_polldelay = 100;
+    }
 
-    if (ACPI_FAILURE(Status)) {
-	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
-	    "timeout waiting for EC to respond to EC_COMMAND_QUERY\n");
-    }
     return (Status);
 }    
 
 static ACPI_STATUS
-EcTransaction(struct acpi_ec_softc *sc, EC_REQUEST *EcRequest)
+EcCommand(struct acpi_ec_softc *sc, EC_COMMAND cmd)
 {
     ACPI_STATUS	Status;
+    EC_EVENT	Event;
 
-    Status = EcLock(sc);
-    if (ACPI_FAILURE(Status))
-	return (Status);
+    mtx_assert(&sc->ec_mtx, MA_OWNED);
 
-    /*
-     * Perform the transaction.
-     */
-    switch (EcRequest->Command) {
+    /* Decide what to wait for based on command type. */
+    switch (cmd) {
     case EC_COMMAND_READ:
-	Status = EcRead(sc, EcRequest->Address, &EcRequest->Data);
+    case EC_COMMAND_WRITE:
+    case EC_COMMAND_BURST_DISABLE:
+	Event = EC_EVENT_INPUT_BUFFER_EMPTY;
 	break;
-    case EC_COMMAND_WRITE:
-	Status = EcWrite(sc, EcRequest->Address, &EcRequest->Data);
+    case EC_COMMAND_QUERY:
+    case EC_COMMAND_BURST_ENABLE:

>>> TRUNCATED FOR MAIL (1000 lines) <<<


More information about the p4-projects mailing list