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