Date: Thu, 10 Jul 2003 18:11:05 -0700 (PDT) From: Marcel Moolenaar <marcel@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 34326 for review Message-ID: <200307110111.h6B1B5pE073524@repoman.freebsd.org>
index | next in thread | raw e-mail
http://perforce.freebsd.org/chv.cgi?CH=34326 Change 34326 by marcel@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) <<<home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200307110111.h6B1B5pE073524>
