kern/83807: [sis] [patch] if_sis: Wake On Lan support for FreeBSD

Stefan Sperling stsp at stsp.name
Thu Aug 30 04:10:07 PDT 2007


The following reply was made to PR kern/83807; it has been noted by GNATS.

From: Stefan Sperling <stsp at stsp.name>
To: bug-followup at FreeBSD.org
Cc:  
Subject: Re: kern/83807: [sis] [patch] if_sis: Wake On Lan support for
	FreeBSD
Date: Thu, 30 Aug 2007 12:58:23 +0200

 --U+BazGySraz5kW0T
 Content-Type: multipart/mixed; boundary="/9DWx/yDrRhgMJTb"
 Content-Disposition: inline
 
 
 --/9DWx/yDrRhgMJTb
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 Content-Transfer-Encoding: quoted-printable
 
 Updated patch for 7-current as of 29th of August 2007.
 This is just a port of the 6.2 patch, no driver fixes or additions.
 I have reports that neither if_xl support nor if_nve support work :(
 
 --=20
 stefan
 http://stsp.name                                         PGP Key: 0xF59D25F0
 
 --/9DWx/yDrRhgMJTb
 Content-Type: text/x-diff; charset=us-ascii
 Content-Disposition: attachment; filename="FreeBSD-7-wol-2007-08-29.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/ncvs/src/sbin/ifconfig/Makefile,v
 retrieving revision 1.33
 diff -u -r1.33 Makefile
 --- sbin/ifconfig/Makefile	17 Apr 2007 00:35:09 -0000	1.33
 +++ sbin/ifconfig/Makefile	28 Aug 2007 11:25:34 -0000
 @@ -32,6 +32,8 @@
  SRCS+=3D	ifbridge.c		# bridge support
  SRCS+=3D	iflagg.c		# lagg support
 =20
 +SRCS+=3D	ifwol.c			# wake on lan support
 +
  .if ${MK_IPX_SUPPORT} !=3D "no" && !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/ncvs/src/sbin/ifconfig/ifconfig.8,v
 retrieving revision 1.142
 diff -u -r1.142 ifconfig.8
 --- sbin/ifconfig/ifconfig.8	1 Aug 2007 00:33:52 -0000	1.142
 +++ sbin/ifconfig/ifconfig.8	28 Aug 2007 11:22:33 -0000
 @@ -1240,6 +1240,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.
 @@ -1247,7 +1268,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	29 Aug 2007 21:34:42 -0000
 @@ -0,0 +1,228 @@
 +/* $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)
 +			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/ncvs/src/sys/dev/nve/if_nve.c,v
 retrieving revision 1.28
 diff -u -r1.28 if_nve.c
 --- sys/dev/nve/if_nve.c	12 Jun 2007 02:21:02 -0000	1.28
 +++ sys/dev/nve/if_nve.c	28 Aug 2007 11:22:33 -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),
 @@ -726,6 +730,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);
 @@ -1037,6 +1045,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 */
 @@ -1776,3 +1799,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/ncvs/src/sys/dev/nve/if_nvereg.h,v
 retrieving revision 1.8
 diff -u -r1.8 if_nvereg.h
 --- sys/dev/nve/if_nvereg.h	5 Dec 2006 15:31:05 -0000	1.8
 +++ sys/dev/nve/if_nvereg.h	28 Aug 2007 11:22:33 -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/ncvs/src/sys/net/if.c,v
 retrieving revision 1.273
 diff -u -r1.273 if.c
 --- sys/net/if.c	27 Jul 2007 11:59:57 -0000	1.273
 +++ sys/net/if.c	28 Aug 2007 11:26:37 -0000
 @@ -1760,6 +1760,7 @@
  	case SIOCSLIFPHYADDR:
  	case SIOCSIFMEDIA:
  	case SIOCSIFGENERIC:
 + 	case SIOCSIFWOLOPTS:
  		error =3D priv_check(td, PRIV_NET_HWIOCTL);
  		if (error)
  			return (error);
 @@ -1781,6 +1782,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/ncvs/src/sys/net/if.h,v
 retrieving revision 1.108
 diff -u -r1.108 if.h
 --- sys/net/if.h	11 Jun 2007 20:08:11 -0000	1.108
 +++ sys/net/if.h	28 Aug 2007 11:22:33 -0000
 @@ -273,6 +273,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
 @@ -284,6 +306,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;
 @@ -296,6 +319,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/ncvs/src/sys/pci/if_sis.c,v
 retrieving revision 1.150
 diff -u -r1.150 if_sis.c
 --- sys/pci/if_sis.c	24 Feb 2007 14:27:36 -0000	1.150
 +++ sys/pci/if_sis.c	29 Aug 2007 23:35:02 -0000
 @@ -138,6 +138,10 @@
  static void sis_startl(struct ifnet *);
  static void sis_stop(struct sis_softc *);
  static void sis_watchdog(struct sis_softc *);
 +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
 =20
  static struct resource_spec sis_res_spec[] =3D {
 @@ -2157,6 +2161,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;
 @@ -2264,9 +2283,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,
 +	    ((u_int16_t *)IF_LLADDR(sc->sis_ifp))[0]);
 +	CSR_WRITE_4(sc, SIS_RXFILT_CTL, NS_FILTADDR_PAR1);
 +	CSR_WRITE_4(sc, SIS_RXFILT_DATA,
 +	    ((u_int16_t *)IF_LLADDR(sc->sis_ifp))[1]);
 +	CSR_WRITE_4(sc, SIS_RXFILT_CTL, NS_FILTADDR_PAR2);
 +	CSR_WRITE_4(sc, SIS_RXFILT_DATA,
 +	    ((u_int16_t *)IF_LLADDR(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/ncvs/src/sys/pci/if_sisreg.h,v
 retrieving revision 1.38
 diff -u -r1.38 if_sisreg.h
 --- sys/pci/if_sisreg.h	24 Feb 2007 14:27:36 -0000	1.38
 +++ sys/pci/if_sisreg.h	28 Aug 2007 11:22:33 -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
 @@ -461,6 +462,7 @@
  #endif
  	int			in_tick;
  	struct mtx		sis_mtx;
 +	uint32_t		ns_wol_events;
  };
 =20
  #define SIS_TIMEOUT		1000
 @@ -505,3 +507,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/ncvs/src/sys/pci/if_vr.c,v
 retrieving revision 1.126
 diff -u -r1.126 if_vr.c
 --- sys/pci/if_vr.c	23 Apr 2007 12:19:02 -0000	1.126
 +++ sys/pci/if_vr.c	28 Aug 2007 11:29:49 -0000
 @@ -165,6 +165,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
  static int vr_probe(device_t);
 @@ -201,6 +205,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
 @@ -587,7 +595,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.
  	 */
 @@ -638,6 +646,13 @@
 =20
  	sc->vr_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,
  	    NULL, vr_intr, sc, &sc->vr_intrhand);
 @@ -1517,6 +1532,21 @@
  		else
  			ifp->if_hwassist =3D 0;
  		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;
 @@ -1595,6 +1625,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/ncvs/src/sys/pci/if_vrreg.h,v
 retrieving revision 1.34
 diff -u -r1.34 if_vrreg.h
 --- sys/pci/if_vrreg.h	23 Apr 2007 12:19:02 -0000	1.34
 +++ sys/pci/if_vrreg.h	28 Aug 2007 11:22:33 -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.)
   */
 @@ -474,10 +489,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/ncvs/src/sys/pci/if_xl.c,v
 retrieving revision 1.210
 diff -u -r1.210 if_xl.c
 --- sys/pci/if_xl.c	6 Aug 2007 14:26:03 -0000	1.210
 +++ sys/pci/if_xl.c	28 Aug 2007 11:22:33 -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);
 @@ -3223,6 +3226,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;
 @@ -3354,6 +3376,7 @@
  	XL_LOCK(sc);
  	xl_reset(sc);
  	xl_stop(sc);
 +	xl_enable_wol(dev);
  	XL_UNLOCK(sc);
  }
 =20
 @@ -3390,3 +3413,85 @@
 =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;
 +	u_int32_t	config;
 +	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);
 +
 +	/* Make sure power management is enabled. */
 +	config =3D pci_read_config(dev, XL_PCI_PWRMGMTCTRL, 2);
 +	pci_write_config(dev, XL_PCI_PWRMGMTCTRL, config | XL_PME_EN, 2);
 +
 +	/* Set appropriate power state, so the card stays active
 +	 * after system shutdown. */
 +	(void)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/ncvs/src/sys/pci/if_xlreg.h,v
 retrieving revision 1.59
 diff -u -r1.59 if_xlreg.h
 --- sys/pci/if_xlreg.h	6 Dec 2006 02:18:41 -0000	1.59
 +++ sys/pci/if_xlreg.h	28 Aug 2007 11:22:33 -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
 @@ -613,6 +614,7 @@
  #ifdef DEVICE_POLLING
  	int			rxcycles;
  #endif
 +	uint32_t		xl_wol_events;
  };
 =20
  #define XL_LOCK(_sc)		mtx_lock(&(_sc)->xl_mtx)
 @@ -741,3 +743,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/ncvs/src/sys/sys/sockio.h,v
 retrieving revision 1.31
 diff -u -r1.31 sockio.h
 --- sys/sys/sockio.h	9 Jul 2006 06:04:00 -0000	1.31
 +++ sys/sys/sockio.h	29 Aug 2007 16:48:16 -0000
 @@ -118,6 +118,13 @@
  #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', 125, struct ifreq)	/* get wake on lan
 +							   	options */
 +#define	SIOCSIFWOLOPTS	 _IOW('i', 126, struct ifreq)	/* set wake on lan
 +							   	options */
 +#define	SIOCGIFWOLSUPP	_IOWR('i', 127, struct ifreq)	/* get wake on lan
 +							   modes supported by
 +							   device */
  #define	SIOCAIFGROUP	 _IOW('i', 135, struct ifgroupreq) /* add an ifgroup =
 */
  #define	SIOCGIFGROUP	_IOWR('i', 136, struct ifgroupreq) /* get ifgroups */
  #define	SIOCDIFGROUP	 _IOW('i', 137, struct ifgroupreq) /* delete ifgroup =
 */
 
 --/9DWx/yDrRhgMJTb--
 
 --U+BazGySraz5kW0T
 Content-Type: application/pgp-signature
 Content-Disposition: inline
 
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.7 (FreeBSD)
 
 iD8DBQFG1qLP5dMCc/WdJfARArYBAJ4ning6e8WF4WIc/tOGFHtbp72dHQCg7X+3
 +13lwRCloS3NqFbaWcpLbmY=
 =Tx8N
 -----END PGP SIGNATURE-----
 
 --U+BazGySraz5kW0T--


More information about the freebsd-bugs mailing list