Date: Thu, 14 Jun 2007 01:21:03 +0200 From: Stefan Sperling <stsp@stsp.name> To: Edwin Mons <freebsd@edwinm.ik.nu>, bug-followup@FreeBSD.org, freebsd-hackers@FreeBSD.org Subject: Re: kern/83807: [sis] [patch] if_sis: Wake On Lan support for FreeBSD Message-ID: <20070613232103.GA53373@ted.stsp.lan> In-Reply-To: <20070610144504.GA7129@ted.stsp.lan> References: <466A6DF1.3020306@edwinm.ik.nu> <20070609103848.GA1465@ted.stsp.lan> <466AC23B.4040601@edwinm.ik.nu> <20070610144504.GA7129@ted.stsp.lan>
next in thread | previous in thread | raw e-mail | index | archive | help
--s2ZSL+KKDSLx8OML Content-Type: multipart/mixed; boundary="X1bOJ3K7DJ5YkBrT" Content-Disposition: inline --X1bOJ3K7DJ5YkBrT Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Sun, Jun 10, 2007 at 04:45:04PM +0200, Stefan Sperling wrote: > > I usually use either if_em or if_xl chipsets, so I hoped landing this = code=20 > > in at least -CURRENT (should go there first, I guess) would result in = more=20 > > chipsets supported ;) >=20 > There is code for enabling wake on lan in the Linux drivers for both > if_xl and if_em cards. See drivers/net/3c59x.c and > drivers/net/e1000/e1000_ethtool.c in the linux source tree. >=20 > So I don't think adding support for these cards is a problem. > Just need to find some time to do it... Updated patch attached. Also available at http://stsp.name/wol/ Now contains untested support for if_xl. Please test. I have no such card so I cannot test this myself. Note that apparently only 3C905B type cards support wake on lan. And they only support magic packet events, no unicast, broadcast or multicast events. The patch is against RELENG_6_2. Sorry I have no -CURRENT system set up at the moment. I don't know if the patch even applies to -CURRENT. Once if_xl is working I'll look into getting if_em supported. If any nve users are reading this, I still need feedback on if_nve as well. I cannot test nve myself either. Thanks, --=20 stefan http://stsp.name PGP Key: 0xF59D25F0 --X1bOJ3K7DJ5YkBrT Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="FreeBSD-6.2-wol-2007-06-14.diff" Content-Transfer-Encoding: quoted-printable Index: sbin/ifconfig/Makefile =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /usr/local/ncvs/src/sbin/ifconfig/Makefile,v retrieving revision 1.29 diff -u -u -r1.29 Makefile --- sbin/ifconfig/Makefile 5 Jun 2005 03:32:51 -0000 1.29 +++ sbin/ifconfig/Makefile 6 May 2006 11:08:41 -0000 @@ -28,6 +28,8 @@ =20 SRCS+=3D ifbridge.c # bridge support =20 +SRCS+=3D ifwol.c # wake on lan support + .if !defined(RELEASE_CRUNCH) SRCS+=3D af_ipx.c # IPX support DPADD=3D ${LIBIPX} Index: sbin/ifconfig/ifconfig.8 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /usr/local/ncvs/src/sbin/ifconfig/ifconfig.8,v retrieving revision 1.95.2.17 diff -u -u -r1.95.2.17 ifconfig.8 --- sbin/ifconfig/ifconfig.8 3 Nov 2006 09:14:24 -0000 1.95.2.17 +++ sbin/ifconfig/ifconfig.8 13 Jan 2007 12:18:33 -0000 @@ -939,6 +939,27 @@ If that is the case, then the first four keys (1-4) will be the standard temporary keys and any others will be adaptor specific keys such as permanent keys stored in NVRAM. +.It Cm wakeon Ar events +Enable Wake On Lan support, if available. The=20 +.Ar events +argument is a comma seperated list of package types that shall +trigger wake events. The set of valid package types is +.Dq Li unicast , +.Dq Li multicast , +.Dq Li broadcast , +and +.Dq Li magic . +These enable wake on unicast, multicast, broadcast and Magic Packet(tm), +respectively. +A SecureOn password, if supported, can be be enabled using the +.Dq Li sopasswd:<password>=20 +event. +SecureOn passwords only work in combination with +.Dq Li magic . +The password must consist of 12 hexadecimal digits. +.It Fl wakeon +Disable Wake On Lan. +.Pp .It Cm wme Enable Wireless Multimedia Extensions (WME) support, if available, for the specified interface. @@ -946,7 +967,6 @@ efficient communication of realtime and multimedia data. To disable WME support, use .Fl wme . -.Pp The following parameters are meaningful only when WME support is in use. Parameters are specified per-AC (Access Category) and split into those that are used by a station when acting Index: sbin/ifconfig/ifwol.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: sbin/ifconfig/ifwol.c diff -N sbin/ifconfig/ifwol.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sbin/ifconfig/ifwol.c 20 Oct 2006 10:29:10 -0000 @@ -0,0 +1,229 @@ +/* $Id$ */ + +/* + * Copyright (c) 2005 Stefan Sperling. + * All rights reserved. + * + * 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTI= ES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR 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. + */ + +#include <sys/param.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <sys/sysctl.h> +#include <sys/time.h> + +#include <net/if.h> +#include <net/if_dl.h> +#include <net/if_types.h> +#include <net/if_media.h> +#include <net/route.h> + +#include <ctype.h> +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sysexits.h> + +#include "ifconfig.h" + +static void wol_status(int s); +static void setwol(const char *, int, int, const struct afswtch *); +static void parse_args(const char *, struct if_wolopts *); +static void parse_sopasswd(const char *, u_char *); +static void unsetwol(const char *, int, int, const struct afswtch *); +static void print_wol_events(uint32_t events); + +/* + * Print wake on lan capabilities and events the device currently heeds. + */ +static void +wol_status(int s) +{ + struct ifreq ifr; + + memset(&ifr, 0, sizeof(ifr)); + strlcpy(ifr.ifr_name, name, IFNAMSIZ); + + if (ioctl(s, SIOCGIFWOLSUPP, &ifr) < 0) + /* Device does not support wake on lan */ + return; + + printf("\tsupported wake events:"); + print_wol_events(ifr.ifr_wolopts.ifwol_supported); + printf("\n"); + + if (ioctl(s, SIOCGIFWOLOPTS, &ifr) < 0) + err(EX_USAGE, "SIOCGIFWOLOPTS"); + + if (ifr.ifr_wolopts.ifwol_events =3D=3D 0) + return; + + printf("\twill wake on:"); + print_wol_events(ifr.ifr_wolopts.ifwol_events); + printf("\n"); +} + +static void +print_wol_events(uint32_t events) +{ + if (events & IFWOL_WAKE_ON_UNICAST) + printf(" unicast"); + if (events & IFWOL_WAKE_ON_MULTICAST) + printf(" multicast"); + if (events & IFWOL_WAKE_ON_BROADCAST) + printf(" broadcast"); + if (events & IFWOL_WAKE_ON_MAGIC) { + printf(" magic"); + if (events & IFWOL_ENABLE_SOPASSWD) + printf("[SecureOn password]"); + } +} + +/* + * Set wake on lan events. + */ +static void +setwol(const char *val, int d, int s, const struct afswtch *afp) +{ + struct ifreq ifr; + + memset(&ifr, 0, sizeof(ifr)); + strlcpy(ifr.ifr_name, name, IFNAMSIZ); + + if (ioctl(s, SIOCGIFWOLSUPP, &ifr) < 0) + err(EX_USAGE, "device does not support wake on lan"); + + parse_args(val, &ifr.ifr_wolopts); + if (ioctl(s, SIOCSIFWOLOPTS, &ifr) < 0) + err(EX_USAGE, "SIOCSIFWOLOPTS"); +} + +/*=20 + * Parse the argument string, which may contain one or more of the + * following: + * =20 + * unicast,multicast,broadcast,magic,sopasswd:xxxxxxxxxxxx, + * + * and fill the wolopts structure accordingly. + *=20 + */ +static void +parse_args(const char* args, struct if_wolopts *wolopts) +{ + uint32_t wol_events =3D 0; + char* opt; + + for (opt =3D strdup(args); (opt =3D strtok(opt, ",")) !=3D NULL; opt =3D = NULL) { + if (strcmp(opt, "unicast") =3D=3D 0) + wol_events |=3D IFWOL_WAKE_ON_UNICAST; + else if (strcmp(opt, "multicast") =3D=3D 0) + wol_events |=3D IFWOL_WAKE_ON_MULTICAST; + else if (strcmp(opt, "broadcast") =3D=3D 0) + wol_events |=3D IFWOL_WAKE_ON_BROADCAST; + else if (strcmp(opt, "magic") =3D=3D 0) + wol_events |=3D IFWOL_WAKE_ON_MAGIC; + else if (strcmp(opt, "sopasswd") =3D=3D 0) + errx(EX_USAGE, "no SecureOn password specfied."); + else if (strncmp(opt, "sopasswd:", strlen("sopasswd:")) =3D=3D 0) { + wol_events |=3D IFWOL_ENABLE_SOPASSWD; + parse_sopasswd(opt + strlen("sopasswd:"), wolopts->ifwol_sopasswd); + } else { + errx(EX_USAGE, "unknown wake event %s", opt); + } + } + free(opt); + wolopts->ifwol_events =3D wol_events; +} + +/* SecureOn passwords are not like plain text passwords. Instead, they con= sist + * of 6 bytes (ie unsigned char). Try to prevent users from giving anythin= g other + * than a string of six concatenated unsigned chars in hex as password. + */ +static void +parse_sopasswd(const char *pw, u_char *dest) { + char substr[3]; + int len, i, n; + + len =3D strlen(pw) / 2; + if (len !=3D 6) + errx(EX_USAGE, "Invalid SecureOn password."); + + for (i =3D 0; i < len; i++) { + (void)strncpy(substr, pw, 2); + substr[2] =3D '\0'; + if (sscanf(substr, "%x", &n) !=3D 1) + errx(EX_USAGE, "Invalid SecureOn password."); + if (n < 0x0 || n > 0xff) + /* Should never happen, but just in case... */ + errx(EX_USAGE, "Invalid SecureOn password."); + *dest++ =3D (u_char)n; + pw +=3D 2; + } +} + +/* + * Unset all wake on lan events. + */ +static void +unsetwol(const char *val, int d, int s, const struct afswtch *afp) +{ + struct ifreq ifr; + + memset(&ifr, 0, sizeof(ifr)); + strlcpy(ifr.ifr_name, name, IFNAMSIZ); + + if (ioctl(s, SIOCGIFWOLSUPP, &ifr) < 0) + err(EX_USAGE, "device does not support wake on lan"); + + ifr.ifr_wolopts.ifwol_events =3D IFWOL_DISABLE; + if (ioctl(s, SIOCSIFWOLOPTS, &ifr) < 0) + err(EX_USAGE, "SIOCSIFWOLOPTS"); +} + +static struct cmd wol_cmds[] =3D { + DEF_CMD_ARG("wakeon", setwol), + DEF_CMD("-wakeon", 0, unsetwol) +}; +static struct afswtch af_wol =3D { + .af_name =3D "af_wol", + .af_af =3D AF_UNSPEC, + .af_other_status =3D wol_status, +}; + +static __constructor void +ifwol_ctor(void) +{ +#define N(a) (sizeof(a) / sizeof(a[0])) + int i; + + for (i =3D 0; i < N(wol_cmds); i++) + cmd_register(&wol_cmds[i]); + af_register(&af_wol); +#undef N +} Index: sys/dev/nve/if_nve.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /usr/local/ncvs/src/sys/dev/nve/if_nve.c,v retrieving revision 1.7.2.11 diff -u -u -r1.7.2.11 if_nve.c --- sys/dev/nve/if_nve.c 13 Sep 2006 15:15:57 -0000 1.7.2.11 +++ sys/dev/nve/if_nve.c 13 Jan 2007 12:21:03 -0000 @@ -177,6 +177,10 @@ static NV_SINT32 nve_oslockrelease(PNV_VOID, NV_SINT32, PNV_VOID); static PNV_VOID nve_osreturnbufvirt(PNV_VOID, PNV_VOID); =20 +static void nve_enable_wol(struct nve_softc *); +static void nve_get_wolopts(struct nve_softc *, struct if_wolopts *); +static int nve_set_wolopts(struct nve_softc *, struct if_wolopts *); + static device_method_t nve_methods[] =3D { /* Device interface */ DEVMETHOD(device_probe, nve_probe), @@ -725,6 +729,10 @@ =20 sc =3D device_get_softc(dev); =20 + NVE_LOCK(sc); + nve_enable_wol(sc); + NVE_UNLOCK(sc); + /* Stop hardware activity */ NVE_LOCK(sc); nve_stop(sc); @@ -1036,6 +1044,21 @@ mii =3D device_get_softc(sc->miibus); error =3D ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); break; + case SIOCGIFWOLSUPP: + ifr->ifr_wolopts.ifwol_supported =3D NVE_SUPPORTED_WOL_EVENTS; + error =3D 0; + break; + case SIOCGIFWOLOPTS: + NVE_LOCK(sc); + nve_get_wolopts(sc, &ifr->ifr_wolopts); + NVE_UNLOCK(sc); + error =3D 0; + break; + case SIOCSIFWOLOPTS: + NVE_LOCK(sc); + error =3D nve_set_wolopts(sc, &ifr->ifr_wolopts); + NVE_UNLOCK(sc); + break; =20 default: /* Everything else we forward to generic ether ioctl */ @@ -1775,3 +1798,49 @@ } =20 /* --- End on NVOSAPI interface --- */ + +/* + * Enable Wake On Lan. + */ +static void +nve_enable_wol(struct nve_softc *sc) +{ + ADAPTER_POWERSTATE pstate =3D {0}; + + if (sc->wol_events =3D=3D 0) + return; +=09 + if (sc->wol_events & IFWOL_WAKE_ON_MAGIC) { + pstate.ulPowerFlags =3D POWER_STATE_D3; + pstate.ulMagicPacketWakeUpFlags =3D POWER_STATE_ALL; + pstate.ulLinkChangeWakeUpFlags =3D 0; + pstate.ulPatternWakeUpFlags =3D 0; + sc->hwapi->pfnSetPowerState(sc->hwapi->pADCX, &pstate); + } +} + +/* + * Write current wake on lan settings into an if_wolopts structure. + */ +static void +nve_get_wolopts(struct nve_softc *sc, struct if_wolopts *wolopts) +{ + wolopts->ifwol_events =3D sc->wol_events; +} + +/* + * Set wake on lan options. + */ +static int +nve_set_wolopts(struct nve_softc *sc, struct if_wolopts *wolopts) +{ + if (wolopts->ifwol_events =3D=3D IFWOL_DISABLE) + sc->wol_events =3D 0; + else { + if ((wolopts->ifwol_events & ~NVE_SUPPORTED_WOL_EVENTS) !=3D 0) + return EINVAL; + sc->wol_events =3D wolopts->ifwol_events; + } + + return 0; +} Index: sys/dev/nve/if_nvereg.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /usr/local/ncvs/src/sys/dev/nve/if_nvereg.h,v retrieving revision 1.3.2.2.2.1 diff -u -u -r1.3.2.2.2.1 if_nvereg.h --- sys/dev/nve/if_nvereg.h 7 Dec 2006 22:28:52 -0000 1.3.2.2.2.1 +++ sys/dev/nve/if_nvereg.h 13 Jan 2007 12:21:03 -0000 @@ -69,6 +69,8 @@ #define NVE_DEBUG_MII 0x0100 #define NVE_DEBUG_ALL 0xFFFF =20 +#define NVE_SUPPORTED_WOL_EVENTS IFWOL_WAKE_ON_MAGIC + #if NVE_DEBUG #define DEBUGOUT(level, fmt, args...) if (NVE_DEBUG & level) \ printf(fmt, ## args) @@ -143,6 +145,8 @@ =20 struct mtx mtx; =20 + uint32_t wol_events; + /* Stuff for dealing with the NVIDIA OS API */ struct callout ostimer; PTIMER_FUNC ostimer_func; Index: sys/net/if.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /usr/local/ncvs/src/sys/net/if.c,v retrieving revision 1.234.2.17 diff -u -u -r1.234.2.17 if.c --- sys/net/if.c 6 Oct 2006 20:26:05 -0000 1.234.2.17 +++ sys/net/if.c 13 Jan 2007 12:23:17 -0000 @@ -1461,6 +1461,7 @@ case SIOCSLIFPHYADDR: case SIOCSIFMEDIA: case SIOCSIFGENERIC: + case SIOCSIFWOLOPTS: error =3D suser(td); if (error) return (error); @@ -1482,6 +1483,8 @@ case SIOCGLIFPHYADDR: case SIOCGIFMEDIA: case SIOCGIFGENERIC: + case SIOCGIFWOLOPTS: + case SIOCGIFWOLSUPP: if (ifp->if_ioctl =3D=3D NULL) return (EOPNOTSUPP); IFF_LOCKGIANT(ifp); Index: sys/net/if.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /usr/local/ncvs/src/sys/net/if.h,v retrieving revision 1.96.2.4 diff -u -u -r1.96.2.4 if.h --- sys/net/if.h 15 Feb 2006 03:37:15 -0000 1.96.2.4 +++ sys/net/if.h 5 May 2006 23:05:57 -0000 @@ -254,6 +254,28 @@ #define IFAN_DEPARTURE 1 /* interface departure */ =20 /* + * Wake on Lan related options. + */ +struct if_wolopts { + uint32_t ifwol_supported;/* indicates wol capabilities */ + uint32_t ifwol_events; /* indicates desired wake events */ + + /* Supported wake on lan events. + * A given device may not support all of these, + * or even support wake events not listed here. + * If you add wake more events, make to sure to teach + * ifconfig about them too. */ +#define IFWOL_DISABLE 0x01 /* clears all other events */ +#define IFWOL_WAKE_ON_UNICAST 0x02 +#define IFWOL_WAKE_ON_MULTICAST 0x04 +#define IFWOL_WAKE_ON_BROADCAST 0x08 +#define IFWOL_WAKE_ON_MAGIC 0x10 /* wake on Magic Packet(tm) */ +#define IFWOL_ENABLE_SOPASSWD 0x20 /* whether to set SecureOn password */ + + u_char ifwol_sopasswd[6]; /* SecureOn password */ +}; + +/* * Interface request structure used for socket * ioctl's. All interface ioctl's must have parameter * definitions which begin with ifr_name. The @@ -265,6 +287,7 @@ struct sockaddr ifru_addr; struct sockaddr ifru_dstaddr; struct sockaddr ifru_broadaddr; + struct if_wolopts ifru_wolopts; short ifru_flags[2]; short ifru_index; int ifru_metric; @@ -277,6 +300,7 @@ #define ifr_addr ifr_ifru.ifru_addr /* address */ #define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-to-p link */ #define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */ +#define ifr_wolopts ifr_ifru.ifru_wolopts /* wake on lan related options */ #define ifr_flags ifr_ifru.ifru_flags[0] /* flags (low 16 bits) */ #define ifr_flagshigh ifr_ifru.ifru_flags[1] /* flags (high 16 bits) */ #define ifr_metric ifr_ifru.ifru_metric /* metric */ Index: sys/pci/if_sis.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /usr/local/ncvs/src/sys/pci/if_sis.c,v retrieving revision 1.132.2.7 diff -u -u -r1.132.2.7 if_sis.c --- sys/pci/if_sis.c 17 Mar 2006 21:30:57 -0000 1.132.2.7 +++ sys/pci/if_sis.c 5 May 2006 23:05:57 -0000 @@ -126,6 +126,10 @@ static void sis_startl(struct ifnet *); static void sis_stop(struct sis_softc *); static void sis_watchdog(struct ifnet *); +static void sis_get_wolopts(struct sis_softc *, struct if_wolopts *); +static int sis_set_wolopts(struct sis_softc *, struct if_wolopts *); +static void sis_enable_wol(struct sis_softc *); +static uint32_t sis_translate_wol_events(uint32_t); =20 #ifdef SIS_USEIOSPACE #define SIS_RES SYS_RES_IOPORT @@ -170,7 +174,7 @@ static void sis_dma_map_ring(void *arg, bus_dma_segment_t *segs, int nseg, int error) { - u_int32_t *p; + uint32_t *p; =20 p =3D arg; *p =3D segs->ds_addr; @@ -258,7 +262,7 @@ sis_eeprom_getword(struct sis_softc *sc, int addr, uint16_t *dest) { int i; - u_int16_t word =3D 0; + uint16_t word =3D 0; =20 /* Force EEPROM to idle state. */ sis_eeprom_idle(sc); @@ -301,11 +305,11 @@ sis_read_eeprom(struct sis_softc *sc, caddr_t dest, int off, int cnt, int = swap) { int i; - u_int16_t word =3D 0, *ptr; + uint16_t word =3D 0, *ptr; =20 for (i =3D 0; i < cnt; i++) { sis_eeprom_getword(sc, off + i, &word); - ptr =3D (u_int16_t *)(dest + (i * 2)); + ptr =3D (uint16_t *)(dest + (i * 2)); if (swap) *ptr =3D ntohs(word); else @@ -354,7 +358,7 @@ sis_read_cmos(struct sis_softc *sc, device_t dev, caddr_t dest, int off, i= nt cnt) { device_t bridge; - u_int8_t reg; + uint8_t reg; int i; bus_space_tag_t btag; =20 @@ -383,7 +387,7 @@ static void sis_read_mac(struct sis_softc *sc, device_t dev, caddr_t dest) { - u_int32_t filtsave, csrsave; + uint32_t filtsave, csrsave; =20 filtsave =3D CSR_READ_4(sc, SIS_RXFILT_CTL); csrsave =3D CSR_READ_4(sc, SIS_CSR); @@ -394,11 +398,11 @@ CSR_WRITE_4(sc, SIS_RXFILT_CTL, filtsave & ~SIS_RXFILTCTL_ENABLE); =20 CSR_WRITE_4(sc, SIS_RXFILT_CTL, SIS_FILTADDR_PAR0); - ((u_int16_t *)dest)[0] =3D CSR_READ_2(sc, SIS_RXFILT_DATA); + ((uint16_t *)dest)[0] =3D CSR_READ_2(sc, SIS_RXFILT_DATA); CSR_WRITE_4(sc, SIS_RXFILT_CTL,SIS_FILTADDR_PAR1); - ((u_int16_t *)dest)[1] =3D CSR_READ_2(sc, SIS_RXFILT_DATA); + ((uint16_t *)dest)[1] =3D CSR_READ_2(sc, SIS_RXFILT_DATA); CSR_WRITE_4(sc, SIS_RXFILT_CTL, SIS_FILTADDR_PAR2); - ((u_int16_t *)dest)[2] =3D CSR_READ_2(sc, SIS_RXFILT_DATA); + ((uint16_t *)dest)[2] =3D CSR_READ_2(sc, SIS_RXFILT_DATA); =20 CSR_WRITE_4(sc, SIS_RXFILT_CTL, filtsave); CSR_WRITE_4(sc, SIS_CSR, csrsave); @@ -731,7 +735,7 @@ { struct ifnet *ifp; struct ifmultiaddr *ifma; - u_int32_t h =3D 0, i, filtsave; + uint32_t h =3D 0, i, filtsave; int bit, index; =20 ifp =3D sc->sis_ifp; @@ -782,8 +786,8 @@ { struct ifnet *ifp; struct ifmultiaddr *ifma; - u_int32_t h, i, n, ctl; - u_int16_t hashes[16]; + uint32_t h, i, n, ctl; + uint16_t hashes[16]; =20 ifp =3D sc->sis_ifp; =20 @@ -984,7 +988,7 @@ * Why? Who the hell knows. */ { - u_int16_t tmp[4]; + uint16_t tmp[4]; =20 sis_read_eeprom(sc, (caddr_t)&tmp, NS_EE_NODEADDR, 4, 0); @@ -1406,7 +1410,7 @@ struct ifnet *ifp; struct sis_desc *cur_rx; int total_len =3D 0; - u_int32_t rxstat; + uint32_t rxstat; =20 SIS_LOCK_ASSERT(sc); =20 @@ -1501,7 +1505,7 @@ sis_txeof(struct sis_softc *sc) { struct ifnet *ifp; - u_int32_t idx; + uint32_t idx; =20 SIS_LOCK_ASSERT(sc); ifp =3D sc->sis_ifp; @@ -1605,7 +1609,7 @@ sis_startl(ifp); =20 if (sc->rxcycles > 0 || cmd =3D=3D POLL_AND_CHECK_STATUS) { - u_int32_t status; + uint32_t status; =20 /* Reading the ISR register clears all interrupts. */ status =3D CSR_READ_4(sc, SIS_ISR); @@ -1631,7 +1635,7 @@ { struct sis_softc *sc; struct ifnet *ifp; - u_int32_t status; + uint32_t status; =20 sc =3D arg; ifp =3D sc->sis_ifp; @@ -1785,7 +1789,7 @@ { struct sis_softc *sc; struct mbuf *m_head =3D NULL; - u_int32_t idx, queued =3D 0; + uint32_t idx, queued =3D 0; =20 sc =3D ifp->if_softc; =20 @@ -1872,23 +1876,23 @@ if (sc->sis_type =3D=3D SIS_TYPE_83815) { CSR_WRITE_4(sc, SIS_RXFILT_CTL, NS_FILTADDR_PAR0); CSR_WRITE_4(sc, SIS_RXFILT_DATA, - ((u_int16_t *)IFP2ENADDR(sc->sis_ifp))[0]); + ((uint16_t *)IFP2ENADDR(sc->sis_ifp))[0]); CSR_WRITE_4(sc, SIS_RXFILT_CTL, NS_FILTADDR_PAR1); CSR_WRITE_4(sc, SIS_RXFILT_DATA, - ((u_int16_t *)IFP2ENADDR(sc->sis_ifp))[1]); + ((uint16_t *)IFP2ENADDR(sc->sis_ifp))[1]); CSR_WRITE_4(sc, SIS_RXFILT_CTL, NS_FILTADDR_PAR2); CSR_WRITE_4(sc, SIS_RXFILT_DATA, - ((u_int16_t *)IFP2ENADDR(sc->sis_ifp))[2]); + ((uint16_t *)IFP2ENADDR(sc->sis_ifp))[2]); } else { CSR_WRITE_4(sc, SIS_RXFILT_CTL, SIS_FILTADDR_PAR0); CSR_WRITE_4(sc, SIS_RXFILT_DATA, - ((u_int16_t *)IFP2ENADDR(sc->sis_ifp))[0]); + ((uint16_t *)IFP2ENADDR(sc->sis_ifp))[0]); CSR_WRITE_4(sc, SIS_RXFILT_CTL, SIS_FILTADDR_PAR1); CSR_WRITE_4(sc, SIS_RXFILT_DATA, - ((u_int16_t *)IFP2ENADDR(sc->sis_ifp))[1]); + ((uint16_t *)IFP2ENADDR(sc->sis_ifp))[1]); CSR_WRITE_4(sc, SIS_RXFILT_CTL, SIS_FILTADDR_PAR2); CSR_WRITE_4(sc, SIS_RXFILT_DATA, - ((u_int16_t *)IFP2ENADDR(sc->sis_ifp))[2]); + ((uint16_t *)IFP2ENADDR(sc->sis_ifp))[2]); } =20 /* Init circular TX/RX lists. */ @@ -2162,6 +2166,21 @@ } #endif /* DEVICE_POLLING */ break; + case SIOCGIFWOLSUPP: + ifr->ifr_wolopts.ifwol_supported =3D NS_SUPPORTED_WOL_EVENTS; + error =3D 0; + break; + case SIOCGIFWOLOPTS: + SIS_LOCK(sc); + sis_get_wolopts(sc, &ifr->ifr_wolopts); + SIS_UNLOCK(sc); + error =3D 0; + break; + case SIOCSIFWOLOPTS: + SIS_LOCK(sc); + error =3D sis_set_wolopts(sc, &ifr->ifr_wolopts); + SIS_UNLOCK(sc); + break; default: error =3D ether_ioctl(ifp, command, data); break; @@ -2271,9 +2290,141 @@ SIS_LOCK(sc); sis_reset(sc); sis_stop(sc); + sis_enable_wol(sc); SIS_UNLOCK(sc); } =20 +/* + * Translate wake on lan events defined in if.h + * into flags the chip understands. + */ +static uint32_t +sis_translate_wol_events(uint32_t wol_events) +{ + uint32_t sis_wol_events =3D 0; +=09 + if (wol_events & IFWOL_WAKE_ON_UNICAST) + sis_wol_events |=3D NS_WCSR_WAKE_UCAST; + if (wol_events & IFWOL_WAKE_ON_MULTICAST) + sis_wol_events |=3D NS_WCSR_WAKE_MCAST; + if (wol_events & IFWOL_WAKE_ON_BROADCAST) + sis_wol_events |=3D NS_WCSR_WAKE_BCAST; + if (wol_events & IFWOL_WAKE_ON_MAGIC) + sis_wol_events |=3D NS_WCSR_WAKE_MAGIC; + + return sis_wol_events; +} + +/* + * Write current wake on lan settings into an if_wolopts structure. + * Note that the sopasswd field in the structure is cleared, because + * the password is confidential. + */ +static void +sis_get_wolopts(struct sis_softc *sc, struct if_wolopts *wolopts) +{ + int i; + + SIS_LOCK_ASSERT(sc); + + wolopts->ifwol_events =3D sc->ns_wol_events; +=09 + /* Do not disclose Secure On password. */ +#define N(a) (sizeof(a) / sizeof(a[0])) + for (i =3D 0; i < N(wolopts->ifwol_sopasswd); i++) + wolopts->ifwol_sopasswd[i] =3D '\0'; +#undef N +} +=09 +/* + * Set wake on lan options. + */ +static int +sis_set_wolopts(struct sis_softc *sc, struct if_wolopts *wolopts) +{ + SIS_LOCK_ASSERT(sc); + + /* FIXME: handle sopasswd */ + + if (wolopts->ifwol_events =3D=3D IFWOL_DISABLE) + sc->ns_wol_events =3D 0; + else { + if ((wolopts->ifwol_events & ~NS_SUPPORTED_WOL_EVENTS) !=3D 0) + return EINVAL; + sc->ns_wol_events =3D wolopts->ifwol_events; + } + + return 0; +} + +/*=20 + * Enable Wake On Lan on the DP83815, + * if any wake on lan options have been set. + */ +static void +sis_enable_wol(struct sis_softc *sc) +{ + SIS_LOCK_ASSERT(sc); +=09 + if (sc->sis_type !=3D SIS_TYPE_83815) + return; + + /* Check whether any wake on lan events have been set. */ + if (sc->ns_wol_events =3D=3D 0) + return; + + /* + * Configure the recieve filter to accept potential wake packets, + * configure wake events and enter low-power state. + */ + + /* Stop reciever. */ + SIS_SETBIT(sc, SIS_CSR, SIS_CSR_RX_DISABLE); +=09 + /* Reset recieve pointer */ + CSR_WRITE_4(sc, SIS_RX_LISTPTR, 0); + + /* Re-enable reciever (now in "silent recieve mode.") */ + SIS_SETBIT(sc, SIS_CSR, SIS_CSR_RX_ENABLE); + + /* Clear recieve filter register, so that the enable bit is unset. + * Other bits in this register can only be configured while the enable + * bit is zero. */ + CSR_WRITE_4(sc, SIS_RXFILT_CTL, 0); + + /*=20 + * Accept unicast packets. The datasheet seems to be inaccurate. + * It suggests simply setting the unicast bit in NS_RXFILTCTL, + * but this does not seem to work. Instead, we "perfect match" + * our own mac address, which makes the rx filter accept unicast + * packets. (section below copy pasted from sis_initl routine) + */ + CSR_WRITE_4(sc, SIS_RXFILT_CTL, NS_FILTADDR_PAR0); + CSR_WRITE_4(sc, SIS_RXFILT_DATA, + ((uint16_t *)IFP2ENADDR(sc->sis_ifp))[0]); + CSR_WRITE_4(sc, SIS_RXFILT_CTL, NS_FILTADDR_PAR1); + CSR_WRITE_4(sc, SIS_RXFILT_DATA, + ((uint16_t *)IFP2ENADDR(sc->sis_ifp))[1]); + CSR_WRITE_4(sc, SIS_RXFILT_CTL, NS_FILTADDR_PAR2); + CSR_WRITE_4(sc, SIS_RXFILT_DATA, + ((uint16_t *)IFP2ENADDR(sc->sis_ifp))[2]); + SIS_SETBIT(sc, SIS_RXFILT_CTL, NS_RXFILTCTL_PERFECT); + + /* Allow broadcast and multicast packets, too. */ + SIS_SETBIT(sc, SIS_RXFILT_CTL, SIS_RXFILTCTL_BROAD); + SIS_SETBIT(sc, SIS_RXFILT_CTL, SIS_RXFILTCTL_ALLMULTI); + + /* Re-enable RX filter. */ + SIS_SETBIT(sc, SIS_RXFILT_CTL, SIS_RXFILTCTL_ENABLE); + + /* Configure wake on lan events */ + CSR_WRITE_4(sc, NS_WCSR, sis_translate_wol_events(sc->ns_wol_events)); + + /* Set appropriate power state, so the card stays active + * after system shutdown. */ + CSR_WRITE_4(sc, NS_CLKRUN, NS_CLKRUN_PMESTS | NS_CLKRUN_PMEENB); +} + static device_method_t sis_methods[] =3D { /* Device interface */ DEVMETHOD(device_probe, sis_probe), Index: sys/pci/if_sisreg.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /usr/local/ncvs/src/sys/pci/if_sisreg.h,v retrieving revision 1.33.2.1 diff -u -u -r1.33.2.1 if_sisreg.h --- sys/pci/if_sisreg.h 29 Sep 2005 18:52:21 -0000 1.33.2.1 +++ sys/pci/if_sisreg.h 6 May 2006 10:59:50 -0000 @@ -77,6 +77,7 @@ /* NS DP83815/6 registers */ #define NS_IHR 0x1C #define NS_CLKRUN 0x3C +#define NS_WCSR 0x40 #define NS_SRR 0x58 #define NS_BMCR 0x80 #define NS_BMSR 0x84 @@ -463,6 +464,7 @@ #endif int in_tick; struct mtx sis_mtx; + uint32_t ns_wol_events; }; =20 #define SIS_LOCK(_sc) mtx_lock(&(_sc)->sis_mtx) @@ -523,3 +525,17 @@ #define SIS_PSTATE_D3 0x0003 #define SIS_PME_EN 0x0010 #define SIS_PME_STATUS 0x8000 + +/* DP83815 pci config space power management register */ +#define NS_PMCSR 0x44 + +/* DP83815 Wake On Lan Command/Status register */ +#define NS_WCSR_WAKE_UCAST 0x00000002 +#define NS_WCSR_WAKE_MCAST 0x00000004 +#define NS_WCSR_WAKE_BCAST 0x00000008 +#define NS_WCSR_WAKE_MAGIC 0x00000200 + +/* FIXME: handle sopasswd */ +#define NS_SUPPORTED_WOL_EVENTS (IFWOL_WAKE_ON_UNICAST | IFWOL_WAKE_ON_MUL= TICAST \ + | IFWOL_WAKE_ON_BROADCAST | IFWOL_WAKE_ON_MAGIC) + Index: sys/pci/if_vr.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /usr/local/ncvs/src/sys/pci/if_vr.c,v retrieving revision 1.104.2.6 diff -u -u -r1.104.2.6 if_vr.c --- sys/pci/if_vr.c 17 Mar 2006 21:30:57 -0000 1.104.2.6 +++ sys/pci/if_vr.c 13 Jun 2007 22:38:52 -0000 @@ -169,6 +169,10 @@ static int vr_list_rx_init(struct vr_softc *); static int vr_list_tx_init(struct vr_softc *); =20 +static int vr_set_wolopts(struct vr_softc *, struct if_wolopts *); +static void vr_get_wolopts(struct vr_softc *, struct if_wolopts *); +static void vr_enable_wol(struct vr_softc *); + #ifdef VR_USEIOSPACE #define VR_RES SYS_RES_IOPORT #define VR_RID VR_PCI_LOIO @@ -710,7 +714,7 @@ #endif =20 /* - * Windows may put the chip in suspend mode when it + * Windows or WOL may put the chip in suspend mode when it * shuts down. Be sure to kick it in the head to wake it * up again. */ @@ -761,6 +765,13 @@ =20 sc->suspended =3D 0; =20 + /* Check Wake on Lan support. */ + if (sc->vr_revid >=3D REV_ID_VT6102 ) { + sc->vr_wolsupport =3D 1; + if (sc->vr_revid >=3D REV_ID_VT6105_B0) + sc->vr_wol6patterns =3D 1; + } + /* Hook interrupt last to avoid having to lock softc */ error =3D bus_setup_intr(dev, sc->vr_irq, INTR_TYPE_NET | INTR_MPSAFE, vr_intr, sc, &sc->vr_intrhand); @@ -1618,6 +1629,21 @@ } #endif /* DEVICE_POLLING */ break; + case SIOCGIFWOLSUPP: + ifr->ifr_wolopts.ifwol_supported =3D VR_SUPPORTED_WOL_EVENTS; + error =3D 0; + break; + case SIOCGIFWOLOPTS: + VR_LOCK(sc); + vr_get_wolopts(sc, &ifr->ifr_wolopts); + VR_UNLOCK(sc); + error =3D 0; + break; + case SIOCSIFWOLOPTS: + VR_LOCK(sc); + error =3D vr_set_wolopts(sc, &ifr->ifr_wolopts); + VR_UNLOCK(sc); + break; default: error =3D ether_ioctl(ifp, command, data); break; @@ -1702,6 +1728,92 @@ static void vr_shutdown(device_t dev) { + struct vr_softc *sc; =20 + sc =3D device_get_softc(dev); + VR_LOCK(sc); + vr_enable_wol(sc); + VR_UNLOCK(sc); vr_detach(dev); } + +static void +vr_enable_wol(struct vr_softc *sc) +{ + VR_LOCK_ASSERT(sc); +=09 + /* Check whether wake on lan is available + * and whether events have been set. */ + if (!sc->vr_wolsupport || sc->vr_wolevents =3D=3D 0) + return; + + /* Set the chip to power state D0 */ + VR_CLRBIT(sc, VR_STICKHW, (VR_STICKHW_DS0|VR_STICKHW_DS1)); + + /* Clear WOL configuration */ + CSR_WRITE_1(sc, VR_WOLCRCLR, 0xFF); + if (sc->vr_wol6patterns) + CSR_WRITE_1(sc, VR_WOLCRCLR1, 0x03); + + /* Clear power-event status. */ + CSR_WRITE_1(sc, VR_PWRCSRCLR, 0xFF); + + /* Don't use extra patterns. */ + if (sc->vr_wol6patterns) + CSR_WRITE_1(sc, VR_WOLCGCLR, 0x04); +=09 + /* Set unicast wake event if applicable. */ + if (sc->vr_wolevents & IFWOL_WAKE_ON_UNICAST) + VR_SETBIT(sc, VR_WOLCRSET, VR_WAKE_UCAST); +=09 + /* Set magic wake event if applicable. */ + if (sc->vr_wolevents & IFWOL_WAKE_ON_MAGIC) { + VR_SETBIT(sc, VR_WOLCRSET, VR_WAKE_MAGIC); + /* enable EEPROM-controlled wake-up */ + VR_SETBIT(sc, VR_CONFIG, 0x03); + } +#if 0 + /* Set broadcast/multicast wake event if applicable. */ + /* Does not work for some reason :( */ + if (sc->vr_wolevents & IFWOL_WAKE_ON_BROADCAST || + sc->vr_wolevents & IFWOL_WAKE_ON_MULTICAST) + CSR_WRITE_1(sc, VR_WOLCGSET, VR_WAKE_BMCAST); +#endif + /* Enable Wake On Lan. */ + CSR_WRITE_1(sc, VR_PWCFGSET, 0x01); + VR_SETBIT(sc, VR_STICKHW, VR_STICKHW_WOL_ENB); + + /* Set power state to D3 */ + VR_SETBIT(sc, VR_STICKHW, (VR_STICKHW_DS0|VR_STICKHW_DS1)); +} + + +/* + * Write current wake on lan settings into an if_wolopts structure. + */ +static void +vr_get_wolopts(struct vr_softc *sc, struct if_wolopts *wolopts) +{ + VR_LOCK_ASSERT(sc); + wolopts->ifwol_events =3D sc->vr_wolevents; +} +=09 +/* + * Set wake on lan options. + */ +static int +vr_set_wolopts(struct vr_softc *sc, struct if_wolopts *wolopts) +{ + VR_LOCK_ASSERT(sc); + + if (wolopts->ifwol_events =3D=3D IFWOL_DISABLE) + sc->vr_wolevents =3D 0; + else { + if ((wolopts->ifwol_events & ~VR_SUPPORTED_WOL_EVENTS) !=3D 0) + return EINVAL; + sc->vr_wolevents =3D wolopts->ifwol_events; + } + + return 0; +} + Index: sys/pci/if_vrreg.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /usr/local/ncvs/src/sys/pci/if_vrreg.h,v retrieving revision 1.22.2.1 diff -u -u -r1.22.2.1 if_vrreg.h --- sys/pci/if_vrreg.h 8 Nov 2005 16:05:56 -0000 1.22.2.1 +++ sys/pci/if_vrreg.h 13 Jun 2007 22:38:19 -0000 @@ -283,6 +283,21 @@ #define VR_STICKHW_WOL_STS 0x08 #define VR_STICKHW_LEGWOL_ENB 0x80 =20 +/* Wake on Lan definitions (snooped from Linux driver) */ +#define VR_WOLCRSET 0xA0 +#define VR_PWCFGSET 0xA1 +#define VR_WOLCGSET 0xA3 +#define VR_WOLCRCLR 0xA4 +#define VR_WOLCRCLR1 0xA6 +#define VR_WOLCGCLR 0xA7 +#define VR_PWRCSRCLR 0xAC +#define VR_WAKE_UCAST 0x10 +#define VR_WAKE_MAGIC 0x20 +#define VR_WAKE_BMCAST 0x30 +#define VR_WAKE_LINKON 0x40 +#define VR_WAKE_LINKOFF 0x80 +#define VR_SUPPORTED_WOL_EVENTS (IFWOL_WAKE_ON_UNICAST | IFWOL_WAKE_ON_MAG= IC) + /* * BCR0 register bits. (At least for the VT6102 chip.) */ @@ -471,6 +486,10 @@ #ifdef DEVICE_POLLING int rxcycles; #endif + int vr_wolsupport; /* Chip supports WOL. */ + uint32_t vr_wolevents; /* Wake on Lan satus */ + /* some chips have 6 "patterns" for WOL instead of 4 */ + int vr_wol6patterns; }; =20 #define VR_F_RESTART 0x01 /* Restart unit on next tick */ @@ -545,10 +564,14 @@ #define REV_ID_VT3065_A 0x40 #define REV_ID_VT3065_B 0x41 #define REV_ID_VT3065_C 0x42 +#define REV_ID_VT6102 0x40 #define REV_ID_VT6102_APOLLO 0x74 #define REV_ID_VT3106 0x80 #define REV_ID_VT3106_J 0x80 /* 0x80-0x8F */ #define REV_ID_VT3106_S 0x90 /* 0x90-0xA0 */ +#define REV_ID_VT6105 0x80 +#define REV_ID_VT6105_B0 0x83 + =20 /* * PCI low memory base and low I/O base register, and Index: sys/pci/if_xl.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /usr/local/ncvs/src/sys/pci/if_xl.c,v retrieving revision 1.190.2.10 diff -u -u -r1.190.2.10 if_xl.c --- sys/pci/if_xl.c 17 Aug 2006 00:13:07 -0000 1.190.2.10 +++ sys/pci/if_xl.c 13 Jun 2007 23:00:35 -0000 @@ -249,6 +249,9 @@ static void xl_shutdown(device_t); static int xl_suspend(device_t); static int xl_resume(device_t); +static void xl_get_wolopts(struct xl_softc *, struct if_wolopts *); +static int xl_set_wolopts(struct xl_softc *, struct if_wolopts *); +static void xl_enable_wol(device_t dev); =20 #ifdef DEVICE_POLLING static void xl_poll(struct ifnet *ifp, enum poll_cmd cmd, int count); @@ -3218,6 +3221,25 @@ ifp->if_hwassist =3D 0; XL_UNLOCK(sc); break; + case SIOCGIFWOLSUPP: + if (sc->xl_type =3D=3D XL_TYPE_905B) + ifr->ifr_wolopts.ifwol_supported =3D + XL_SUPPORTED_WOL_EVENTS; + else + ifr->ifr_wolopts.ifwol_supported =3D 0; + error =3D 0; + break; + case SIOCGIFWOLOPTS: + XL_LOCK(sc); + xl_get_wolopts(sc, &ifr->ifr_wolopts); + XL_UNLOCK(sc); + error =3D 0; + break; + case SIOCSIFWOLOPTS: + XL_LOCK(sc); + error =3D xl_set_wolopts(sc, &ifr->ifr_wolopts); + XL_UNLOCK(sc); + break; default: error =3D ether_ioctl(ifp, command, data); break; @@ -3348,6 +3370,7 @@ XL_LOCK(sc); xl_reset(sc); xl_stop(sc); + xl_enable_wol(dev); XL_UNLOCK(sc); } =20 @@ -3384,3 +3407,80 @@ =20 return (0); } + +/* + * Write current wake on lan settings into an if_wolopts structure. + */ +static void +xl_get_wolopts(struct xl_softc *sc, struct if_wolopts *wolopts) +{ + XL_LOCK_ASSERT(sc); +=09 + if (sc->xl_type =3D=3D XL_TYPE_905B) + wolopts->ifwol_events =3D sc->xl_wol_events; + else + wolopts->ifwol_events =3D 0; +} + +/* + * Set wake on lan options. + */ +static int +xl_set_wolopts(struct xl_softc *sc, struct if_wolopts *wolopts) +{ + XL_LOCK_ASSERT(sc); + + if (sc->xl_type !=3D XL_TYPE_905B) + return ENOTSUP; + + if (wolopts->ifwol_events =3D=3D IFWOL_DISABLE) + sc->xl_wol_events =3D 0; + else { + if ((wolopts->ifwol_events & ~XL_SUPPORTED_WOL_EVENTS) !=3D 0) + return EINVAL; + sc->xl_wol_events =3D wolopts->ifwol_events; + } + + return 0; +} + +/*=20 + * Enable Wake On Lan if any wake on lan options have been set. + */ +static void +xl_enable_wol(device_t dev) +{ + u_int8_t rxfilt; + struct xl_softc *sc; + + sc =3D device_get_softc(dev); + + XL_LOCK_ASSERT(sc); + + if (sc->xl_type !=3D XL_TYPE_905B) + return; +=09 + /* Check whether any wake on lan events have been set. */ + if (sc->xl_wol_events =3D=3D 0) + return; + + /* Configure wake on lan events. */ + XL_SEL_WIN(7); + if (sc->xl_wol_events & IFWOL_WAKE_ON_MAGIC) + CSR_WRITE_2(sc, XL_W7_BM_WOL, XL_WAKE_ON_MAGIC); +=09 + /* Configure the recieve filter to accept WOL packets. + * We want to recieve everything. */ + XL_SEL_WIN(5); + rxfilt =3D CSR_READ_1(sc, XL_W5_RX_FILTER); + CSR_WRITE_1(sc, XL_W5_RX_FILTER, + rxfilt | XL_RXFILTER_INDIVIDUAL | XL_RXFILTER_ALLMULTI + | XL_RXFILTER_BROADCAST | XL_RXFILTER_ALLFRAMES); + + /* Make sure reciever is enabled. */ + CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_ENABLE); + + /* Set appropriate power state, so the card stays active + * after system shutdown. */ + pci_set_powerstate(dev, PCI_POWERSTATE_D3); +} Index: sys/pci/if_xlreg.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /usr/local/ncvs/src/sys/pci/if_xlreg.h,v retrieving revision 1.55.2.1 diff -u -u -r1.55.2.1 if_xlreg.h --- sys/pci/if_xlreg.h 26 Aug 2005 14:46:22 -0000 1.55.2.1 +++ sys/pci/if_xlreg.h 13 Jun 2007 23:12:49 -0000 @@ -408,6 +408,7 @@ #define XL_W7_BM_LEN 0x06 #define XL_W7_BM_STATUS 0x0B #define XL_W7_BM_TIMEr 0x0A +#define XL_W7_BM_WOL 0x0C =20 /* * bus master control registers @@ -611,6 +612,7 @@ #ifdef DEVICE_POLLING int rxcycles; #endif + uint32_t xl_wol_events; }; =20 #define XL_LOCK(_sc) mtx_lock(&(_sc)->xl_mtx) @@ -739,3 +741,7 @@ #ifndef IFM_10_FL #define IFM_10_FL 13 /* 10baseFL - Fiber */ #endif + +#define XL_WAKE_ON_MAGIC 0x0002 +#define XL_SUPPORTED_WOL_EVENTS IFWOL_WAKE_ON_MAGIC + Index: sys/sys/sockio.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /usr/local/ncvs/src/sys/sys/sockio.h,v retrieving revision 1.28.2.1 diff -u -u -r1.28.2.1 sockio.h --- sys/sys/sockio.h 15 Feb 2006 03:37:15 -0000 1.28.2.1 +++ sys/sys/sockio.h 5 May 2006 23:05:58 -0000 @@ -117,4 +117,11 @@ #define SIOCIFDESTROY _IOW('i', 121, struct ifreq) /* destroy clone if */ #define SIOCIFGCLONERS _IOWR('i', 120, struct if_clonereq) /* get cloners = */ =20 +#define SIOCGIFWOLOPTS _IOWR('i', 124, struct ifreq) /* get wake on lan + options */ +#define SIOCSIFWOLOPTS _IOW('i', 125, struct ifreq) /* set wake on lan + options */ +#define SIOCGIFWOLSUPP _IOWR('i', 126, struct ifreq) /* get wake on lan + modes supported by + device */ #endif /* !_SYS_SOCKIO_H_ */ --X1bOJ3K7DJ5YkBrT-- --s2ZSL+KKDSLx8OML Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.7 (FreeBSD) iD8DBQFGcHvf5dMCc/WdJfARAoD+AJ9EajUB3DOIafOuikyJt/7EJjAnDACg2NCC 4gZNYvE16OdgmRwfcrzM9BQ= =9bxq -----END PGP SIGNATURE----- --s2ZSL+KKDSLx8OML--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20070613232103.GA53373>