From stsp@stsp.in-berlin.de  Wed Jul 20 19:47:27 2005
Return-Path: <stsp@stsp.in-berlin.de>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id 9B6AD16A41F
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 20 Jul 2005 19:47:27 +0000 (GMT)
	(envelope-from stsp@stsp.in-berlin.de)
Received: from einhorn.in-berlin.de (einhorn.in-berlin.de [192.109.42.8])
	by mx1.FreeBSD.org (Postfix) with ESMTP id 0737A43D45
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 20 Jul 2005 19:47:26 +0000 (GMT)
	(envelope-from stsp@stsp.in-berlin.de)
Received: from dice.seeling33.de (e178161146.adsl.alicedsl.de [85.178.161.146])
	(authenticated bits=0)
	by einhorn.in-berlin.de (8.12.10/8.12.10/Debian-4) with ESMTP id j6KJlN53030830
	(version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NOT)
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 20 Jul 2005 21:47:23 +0200
Received: by dice.seeling33.de (Postfix, from userid 1001)
	id F0F4E33C26; Wed, 20 Jul 2005 21:47:22 +0200 (CEST)
Message-Id: <20050720194722.F0F4E33C26@dice.seeling33.de>
Date: Wed, 20 Jul 2005 21:47:22 +0200 (CEST)
From: Stefan Sperling <stsp@stsp.in-berlin.de>
Reply-To: Stefan Sperling <stsp@stsp.in-berlin.de>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: [patch] Wake On Lan support for FreeBSD
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         83807
>Category:       kern
>Synopsis:       [sis] [patch] if_sis: Wake On Lan support for FreeBSD
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    yongari
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Wed Jul 20 19:50:15 GMT 2005
>Closed-Date:    Mon Oct 11 20:04:47 UTC 2010
>Last-Modified:  Mon Oct 11 20:04:47 UTC 2010
>Originator:     Stefan Sperling
>Release:        FreeBSD 7.0-CURRENT i386
>Organization:
>Environment:
System: FreeBSD dice.seeling33.de 7.0-CURRENT FreeBSD 7.0-CURRENT #0: Wed Jul 20 11:35:03 CEST 2005 stsp@dice.seeling33.de:/usr/obj/home/FreeBSD/FreeBSD-wol/src/sys/DICE i386


	
>Description:
	This patch teaches the if_sis driver to enable Wake On Lan (WOL) functionality
	on the NatSemi DP8381[56] chip. This did not work previously because the driver
	has to enable WOL functionality explicitely on system shutdown.

	It also defines new ioctls that allow configuring WOL functionality from user space.
	These ioctls could also be used by other network drivers implementing WOL features
	as well (none yet known to me).

	The ifconfig command has been extended to accept a 'wakeon' command used to configure
	network packet types that shall trigger wake events. 
	For example:
		
		# ifconfig sis0 wakeon magic
	
	configures the card to wake upon recieving a MagicPacket(tm).

		# ifconfig sis0 wakeon broadcast

	configures the card to wake upon recieving a broadcast packet.
	Multiple events may be specified, seperated by commas.

	The WOL capabilities of a network card, if present, are printed by ifconfig:

	stsp@dice$ ifconfig sis0
	sis0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
		options=48<VLAN_MTU,POLLING>
		inet6 fe80::209:5bff:fe8a:d538%sis0 prefixlen 64 scopeid 0x1
		inet 192.168.0.1 netmask 0xffffff00 broadcast 192.168.0.255
		ether 00:09:5b:8a:d5:38
		media: Ethernet autoselect (100baseTX <full-duplex>)
		status: active
		supported wake on lan events: unicast multicast broadcast magic

	If wake up events have been defined (e.g. MagicPacket(tm)),
	ifconfig also shows the following line:

		will wake on: magic

	The patch also updates the ifconfig(8) man page accordingly.

	Oh, and it also does some s/u_int32_t/uint32_t/

>How-To-Repeat:
	
>Fix:

	


>Release-Note:
>Audit-Trail:

From: Stefan Sperling <stsp@stsp.in-berlin.de>
To: FreeBSD-gnats-submit@freebsd.org
Cc:  
Subject: Re: kern/83807: [patch] Wake On Lan support for FreeBSD
Date: Thu, 21 Jul 2005 00:25:10 +0200 (CEST)

 >Submitter-Id:	current-users
 >Originator:	Stefan Sperling
 >Organization:	
 >Confidential:	no 
 >Synopsis:	Re: kern/83807: [patch] Wake On Lan support for FreeBSD
 >Severity:	non-critical
 >Priority:	low
 >Category:	kern
 >Class:		change-request
 >Release:	FreeBSD 7.0-CURRENT i386
 >Environment:
 System: FreeBSD dice.seeling33.de 7.0-CURRENT FreeBSD 7.0-CURRENT #0: Wed Jul 20 11:35:03 CEST 2005 stsp@dice.seeling33.de:/usr/obj/home/FreeBSD/FreeBSD-wol/src/sys/DICE i386
 
 
 	
 >Description:
 	Somehow the patch got lost the last time.	
 	
 >How-To-Repeat:
 	
 >Fix:
 
 	
 
 --- FreeBSD-wol-05-07-20.diff begins here ---
 Index: sbin/ifconfig/Makefile
 ===================================================================
 RCS file: /home/ncvs/src/sbin/ifconfig/Makefile,v
 retrieving revision 1.29
 diff -u -r1.29 Makefile
 --- sbin/ifconfig/Makefile	5 Jun 2005 03:32:51 -0000	1.29
 +++ sbin/ifconfig/Makefile	20 Jul 2005 09:24:53 -0000
 @@ -28,6 +28,8 @@
  
  SRCS+=	ifbridge.c		# bridge support
  
 +SRCS+=	ifwol.c			# wake on lan support
 +
  .if !defined(RELEASE_CRUNCH)
  SRCS+=	af_ipx.c		# IPX support
  DPADD=	${LIBIPX}
 Index: sbin/ifconfig/ifconfig.8
 ===================================================================
 RCS file: /home/ncvs/src/sbin/ifconfig/ifconfig.8,v
 retrieving revision 1.98
 diff -u -r1.98 ifconfig.8
 --- sbin/ifconfig/ifconfig.8	14 Jul 2005 18:33:21 -0000	1.98
 +++ sbin/ifconfig/ifconfig.8	20 Jul 2005 12:52:57 -0000
 @@ -852,6 +852,26 @@
  efficient communication of realtime and multimedia data.
  To disable WME support, use
  .Fl wme .
 +.It Cm wakeon Ar events
 +Enable Wake On Lan support, if available. The 
 +.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> 
 +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.
  .El
  .Pp
  The following parameters are support for compatibility with other systems:
 Index: sbin/ifconfig/ifwol.c
 ===================================================================
 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 Jul 2005 12:47:44 -0000
 @@ -0,0 +1,232 @@
 +/* $FreeBSD$ */
 +
 +/*
 + * 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 WARRANTIES
 + * 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(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));
 +	strncpy(ifr.ifr_name, name, IFNAMSIZ);
 +
 +	if (ioctl(s, SIOCGIFWOLCAP, &ifr) < 0)
 +		/* Device does not support wake on lan */
 +		return;
 +
 +	printf("\tsupported wake on lan events:");
 +	print_wol_events(ifr.ifr_wolopts.ifwol_caps);
 +	printf("\n");
 +
 +	if (ioctl(s, SIOCGIFWOLOPTS, &ifr) < 0)
 +		err(EX_USAGE, "SIOCGIFWOLOPTS");
 +
 +	if (ifr.ifr_wolopts.ifwol_events == 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)
 +{
 +	char *args;
 +	struct ifreq ifr;
 +
 +	memset(&ifr, 0, sizeof(ifr));
 +	strncpy(ifr.ifr_name, name, IFNAMSIZ);
 +
 +	if (ioctl(s, SIOCGIFWOLCAP, &ifr) < 0)
 +		err(EX_USAGE, "device does not support wake on lan");
 +
 +	args = strdup(val);
 +	parse_args(args, &ifr.ifr_wolopts);
 +	free(args);
 +	if (ioctl(s, SIOCSIFWOLOPTS, &ifr) < 0)
 +		err(EX_USAGE, "SIOCSIFWOLOPTS");
 +}
 +
 +/* 
 + * Parse the argument string, which may contain one or more of the
 + * following:
 + *    
 + *     unicast,multicast,broadcast,magic,sopasswd:xxxxxxxxxxxx,
 + *
 + * and fill the wolopts structure accordingly.
 + * 
 + */
 +static void
 +parse_args(const char* args, struct if_wolopts *wolopts)
 +{
 +	uint32_t wol_events = 0;
 +	char* opt;
 +
 +	for (opt = strdup(args); (opt = strtok(opt, ",")) != NULL; opt = NULL) {
 +		if (strcmp(opt, "unicast") == 0)
 +			wol_events |= IFWOL_WAKE_ON_UNICAST;
 +		else if (strcmp(opt, "multicast") == 0)
 +			wol_events |= IFWOL_WAKE_ON_MULTICAST;
 +		else if (strcmp(opt, "broadcast") == 0)
 +			wol_events |= IFWOL_WAKE_ON_BROADCAST;
 +		else if (strcmp(opt, "magic") == 0)
 +			wol_events |= IFWOL_WAKE_ON_MAGIC;
 +		else if (strcmp(opt, "sopasswd") == 0)
 +			errx(EX_USAGE, "no SecureOn password specfied.");
 +		else if (strncmp(opt, "sopasswd:", strlen("sopasswd:")) == 0) {
 +			wol_events |= 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 = wol_events;
 +}
 +
 +/* SecureOn passwords are not like plain text passwords. Instead, they consist
 + * of 6 bytes (ie unsigned char). Try to prevent users from giving anything other
 + * than a string of six concatenated unsigned chars in hex as password.
 + */
 +static void
 +parse_sopasswd(char *pw, u_char *dest) {
 +	char substr[3];
 +	int len, i, n;
 +
 +	len = strlen(pw) / 2;
 +	if (len != 6)
 +		errx(EX_USAGE, "Invalid SecureOn password.");
 +
 +	for (i = 0; i < len; i++) {
 +		(void)strncpy(substr, pw, 2);
 +		substr[2] = '\0';
 +		if (sscanf(substr, "%x", &n) != 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++ = (u_char)n;
 +		pw += 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));
 +	strncpy(ifr.ifr_name, name, IFNAMSIZ);
 +
 +	if (ioctl(s, SIOCGIFWOLCAP, &ifr) < 0)
 +		err(EX_USAGE, "device does not support wake on lan");
 +
 +	ifr.ifr_wolopts.ifwol_events = IFWOL_DISABLE;
 +	if (ioctl(s, SIOCSIFWOLOPTS, &ifr) < 0)
 +		err(EX_USAGE, "SIOCSIFWOLOPTS");
 +}
 +
 +static struct cmd wol_cmds[] = {
 +	DEF_CMD_ARG("wakeon",	setwol),
 +	DEF_CMD("-wakeon", 0, unsetwol)
 +};
 +static struct afswtch af_wol = {
 +	.af_name	= "af_wol",
 +	.af_af		= AF_UNSPEC,
 +	.af_other_status = wol_status,
 +};
 +
 +static __constructor void
 +ifwol_ctor(void)
 +{
 +#define	N(a)	(sizeof(a) / sizeof(a[0]))
 +	int i;
 +
 +	for (i = 0; i < N(wol_cmds);  i++)
 +		cmd_register(&wol_cmds[i]);
 +	af_register(&af_wol);
 +#undef N
 +}
 Index: sys/net/if.c
 ===================================================================
 RCS file: /home/ncvs/src/sys/net/if.c,v
 retrieving revision 1.238
 diff -u -r1.238 if.c
 --- sys/net/if.c	19 Jul 2005 10:12:58 -0000	1.238
 +++ sys/net/if.c	20 Jul 2005 09:24:53 -0000
 @@ -1452,6 +1452,7 @@
  	case SIOCSLIFPHYADDR:
  	case SIOCSIFMEDIA:
  	case SIOCSIFGENERIC:
 +	case SIOCSIFWOLOPTS:
  		error = suser(td);
  		if (error)
  			return (error);
 @@ -1473,6 +1474,8 @@
  	case SIOCGLIFPHYADDR:
  	case SIOCGIFMEDIA:
  	case SIOCGIFGENERIC:
 +	case SIOCGIFWOLOPTS:
 +	case SIOCGIFWOLCAP:
  		if (ifp->if_ioctl == NULL)
  			return (EOPNOTSUPP);
  		IFF_LOCKGIANT(ifp);
 Index: sys/net/if.h
 ===================================================================
 RCS file: /home/ncvs/src/sys/net/if.h,v
 retrieving revision 1.96
 diff -u -r1.96 if.h
 --- sys/net/if.h	5 Jun 2005 03:13:11 -0000	1.96
 +++ sys/net/if.h	20 Jul 2005 09:24:53 -0000
 @@ -224,6 +224,28 @@
  #define	IFAN_DEPARTURE	1	/* interface departure */
  
  /*
 + * Wake on Lan related options.
 + */
 +struct if_wolopts {
 +	uint32_t	ifwol_caps;	/* 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
 @@ -235,6 +257,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;
 @@ -247,6 +270,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
 ===================================================================
 RCS file: /home/ncvs/src/sys/pci/if_sis.c,v
 retrieving revision 1.132
 diff -u -r1.132 if_sis.c
 --- sys/pci/if_sis.c	10 Jun 2005 16:49:22 -0000	1.132
 +++ sys/pci/if_sis.c	20 Jul 2005 09:24:53 -0000
 @@ -122,6 +122,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);
  
  #ifdef SIS_USEIOSPACE
  #define SIS_RES			SYS_RES_IOPORT
 @@ -166,7 +170,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;
  
  	p = arg;
  	*p = segs->ds_addr;
 @@ -254,7 +258,7 @@
  sis_eeprom_getword(struct sis_softc *sc, int addr, uint16_t *dest)
  {
  	int		i;
 -	u_int16_t		word = 0;
 +	uint16_t		word = 0;
  
  	/* Force EEPROM to idle state. */
  	sis_eeprom_idle(sc);
 @@ -297,11 +301,11 @@
  sis_read_eeprom(struct sis_softc *sc, caddr_t dest, int off, int cnt, int swap)
  {
  	int			i;
 -	u_int16_t		word = 0, *ptr;
 +	uint16_t		word = 0, *ptr;
  
  	for (i = 0; i < cnt; i++) {
  		sis_eeprom_getword(sc, off + i, &word);
 -		ptr = (u_int16_t *)(dest + (i * 2));
 +		ptr = (uint16_t *)(dest + (i * 2));
  		if (swap)
  			*ptr = ntohs(word);
  		else
 @@ -350,7 +354,7 @@
  sis_read_cmos(struct sis_softc *sc, device_t dev, caddr_t dest, int off, int cnt)
  {
  	device_t		bridge;
 -	u_int8_t		reg;
 +	uint8_t			reg;
  	int			i;
  	bus_space_tag_t		btag;
  
 @@ -379,7 +383,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;
  
  	filtsave = CSR_READ_4(sc, SIS_RXFILT_CTL);
  	csrsave = CSR_READ_4(sc, SIS_CSR);
 @@ -390,11 +394,11 @@
  	CSR_WRITE_4(sc, SIS_RXFILT_CTL, filtsave & ~SIS_RXFILTCTL_ENABLE);
  
  	CSR_WRITE_4(sc, SIS_RXFILT_CTL, SIS_FILTADDR_PAR0);
 -	((u_int16_t *)dest)[0] = CSR_READ_2(sc, SIS_RXFILT_DATA);
 +	((uint16_t *)dest)[0] = CSR_READ_2(sc, SIS_RXFILT_DATA);
  	CSR_WRITE_4(sc, SIS_RXFILT_CTL,SIS_FILTADDR_PAR1);
 -	((u_int16_t *)dest)[1] = CSR_READ_2(sc, SIS_RXFILT_DATA);
 +	((uint16_t *)dest)[1] = CSR_READ_2(sc, SIS_RXFILT_DATA);
  	CSR_WRITE_4(sc, SIS_RXFILT_CTL, SIS_FILTADDR_PAR2);
 -	((u_int16_t *)dest)[2] = CSR_READ_2(sc, SIS_RXFILT_DATA);
 +	((uint16_t *)dest)[2] = CSR_READ_2(sc, SIS_RXFILT_DATA);
  
  	CSR_WRITE_4(sc, SIS_RXFILT_CTL, filtsave);
  	CSR_WRITE_4(sc, SIS_CSR, csrsave);
 @@ -737,7 +741,7 @@
  {
  	struct ifnet		*ifp;
  	struct ifmultiaddr	*ifma;
 -	u_int32_t		h = 0, i, filtsave;
 +	uint32_t		h = 0, i, filtsave;
  	int			bit, index;
  
  	ifp = sc->sis_ifp;
 @@ -786,8 +790,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];
  
  	ifp = sc->sis_ifp;
  
 @@ -986,7 +990,7 @@
  		 * Why? Who the hell knows.
  		 */
  		{
 -			u_int16_t		tmp[4];
 +			uint16_t		tmp[4];
  
  			sis_read_eeprom(sc, (caddr_t)&tmp,
  			    NS_EE_NODEADDR, 4, 0);
 @@ -1410,7 +1414,7 @@
          struct ifnet		*ifp;
  	struct sis_desc		*cur_rx;
  	int			total_len = 0;
 -	u_int32_t		rxstat;
 +	uint32_t		rxstat;
  
  	SIS_LOCK_ASSERT(sc);
  
 @@ -1505,7 +1509,7 @@
  sis_txeof(struct sis_softc *sc)
  {
  	struct ifnet		*ifp;
 -	u_int32_t		idx;
 +	uint32_t		idx;
  
  	SIS_LOCK_ASSERT(sc);
  	ifp = sc->sis_ifp;
 @@ -1614,7 +1618,7 @@
  		sis_startl(ifp);
  
  	if (sc->rxcycles > 0 || cmd == POLL_AND_CHECK_STATUS) {
 -		u_int32_t	status;
 +		uint32_t	status;
  
  		/* Reading the ISR register clears all interrupts. */
  		status = CSR_READ_4(sc, SIS_ISR);
 @@ -1640,7 +1644,7 @@
  {
  	struct sis_softc	*sc;
  	struct ifnet		*ifp;
 -	u_int32_t		status;
 +	uint32_t		status;
  
  	sc = arg;
  	ifp = sc->sis_ifp;
 @@ -1800,7 +1804,7 @@
  {
  	struct sis_softc	*sc;
  	struct mbuf		*m_head = NULL;
 -	u_int32_t		idx, queued = 0;
 +	uint32_t		idx, queued = 0;
  
  	sc = ifp->if_softc;
  
 @@ -1887,23 +1891,23 @@
  	if (sc->sis_type == 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]);
  	}
  
  	/* Init circular TX/RX lists. */
 @@ -2150,6 +2154,22 @@
  	case SIOCSIFCAP:
  		ifp->if_capenable &= ~IFCAP_POLLING;
  		ifp->if_capenable |= ifr->ifr_reqcap & IFCAP_POLLING;
 +		error = 0;
 +		break;
 +	case SIOCGIFWOLCAP:
 +		ifr->ifr_wolopts.ifwol_caps = NS_SUPPORTED_WOL_EVENTS;
 +		error = 0;
 +		break;
 +	case SIOCGIFWOLOPTS:
 +		SIS_LOCK(sc);
 +		sis_get_wolopts(sc, &ifr->ifr_wolopts);
 +		SIS_UNLOCK(sc);
 +		error = 0;
 +		break;
 +	case SIOCSIFWOLOPTS:
 +		SIS_LOCK(sc);
 +		error = sis_set_wolopts(sc, &ifr->ifr_wolopts);
 +		SIS_UNLOCK(sc);
  		break;
  	default:
  		error = ether_ioctl(ifp, command, data);
 @@ -2263,9 +2283,141 @@
  	SIS_LOCK(sc);
  	sis_reset(sc);
  	sis_stop(sc);
 +	sis_enable_wol(sc);
  	SIS_UNLOCK(sc);
  }
  
 +/*
 + * 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 = 0;
 +	
 +	if (wol_events & IFWOL_WAKE_ON_UNICAST)
 +		sis_wol_events |= NS_WCSR_WAKE_UCAST;
 +	if (wol_events & IFWOL_WAKE_ON_MULTICAST)
 +		sis_wol_events |= NS_WCSR_WAKE_MCAST;
 +	if (wol_events & IFWOL_WAKE_ON_BROADCAST)
 +		sis_wol_events |= NS_WCSR_WAKE_BCAST;
 +	if (wol_events & IFWOL_WAKE_ON_MAGIC)
 +		sis_wol_events |= 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 = sc->ns_wol_events;
 +	
 +	/* Do not disclose Secure On password. */
 +#define	N(a)	(sizeof(a) / sizeof(a[0]))
 +	for (i = 0; i < N(wolopts->ifwol_sopasswd); i++)
 +		wolopts->ifwol_sopasswd[i] = '\0';
 +#undef N
 +}
 +	
 +/*
 + * 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 == IFWOL_DISABLE)
 +		sc->ns_wol_events = 0;
 +	else {
 +		if ((wolopts->ifwol_events & ~NS_SUPPORTED_WOL_EVENTS) != 0)
 +			return EINVAL;
 +		sc->ns_wol_events = wolopts->ifwol_events;
 +	}
 +
 +	return 0;
 +}
 +
 +/* 
 + * 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);
 +	
 +	if (sc->sis_type != SIS_TYPE_83815)
 +		return;
 +
 +	/* Check whether any wake on lan events have been set. */
 +	if (sc->ns_wol_events == 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);
 +	
 +	/* 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);
 +
 +	/* 
 +	 * 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[] = {
  	/* Device interface */
  	DEVMETHOD(device_probe,		sis_probe),
 Index: sys/pci/if_sisreg.h
 ===================================================================
 RCS file: /home/ncvs/src/sys/pci/if_sisreg.h,v
 retrieving revision 1.33
 diff -u -r1.33 if_sisreg.h
 --- sys/pci/if_sisreg.h	10 Jun 2005 16:49:22 -0000	1.33
 +++ sys/pci/if_sisreg.h	20 Jul 2005 09:24:53 -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
 @@ -464,6 +465,7 @@
  #endif
  	int			in_tick;
  	struct mtx		sis_mtx;
 +	uint32_t		ns_wol_events;
  };
  
  #define	SIS_LOCK(_sc)		mtx_lock(&(_sc)->sis_mtx)
 @@ -524,3 +526,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_MULTICAST \
 +				    | IFWOL_WAKE_ON_BROADCAST | IFWOL_WAKE_ON_MAGIC)
 +
 Index: sys/sys/sockio.h
 ===================================================================
 RCS file: /home/ncvs/src/sys/sys/sockio.h,v
 retrieving revision 1.28
 diff -u -r1.28 sockio.h
 --- sys/sys/sockio.h	5 Jun 2005 03:13:13 -0000	1.28
 +++ sys/sys/sockio.h	20 Jul 2005 09:24:53 -0000
 @@ -114,4 +114,11 @@
  #define	SIOCIFDESTROY	 _IOW('i', 121, struct ifreq)	/* destroy clone if */
  #define	SIOCIFGCLONERS	_IOWR('i', 120, struct if_clonereq) /* get cloners */
  
 +#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	SIOCGIFWOLCAP	_IOWR('i', 126, struct ifreq)	/* get wake on lan
 +							   modes supported by
 +							   device */
  #endif /* !_SYS_SOCKIO_H_ */
 --- FreeBSD-wol-05-07-20.diff ends here ---
 
 

From: Stefan Sperling <freebsd-gnats@stsp.in-berlin.de>
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/83807: [sis] [patch] if_sis: Wake On Lan support for FreeBSD
Date: Fri, 20 Oct 2006 11:58:50 +0200

 --5mCyUwZo2JvN/JJP
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 
 This is just a followup containing an updated version of this patch,
 which I've been using for several months now.
 
 It works very reliably with my NatSemi card, stability of my system is
 not affected in any way.
 
 This version contains support for more chipsets:
 
     * NatSemi DP83815
     * Via Rhine (VT6102 and up)
     * Nvidia nForce (nve driver, needs testing, I don't have this hardware)
 
 I can add support for more chipsets on request, but I may not have
 the hardware available to do testing.
 
 Also, "secure-on" passwords are still not supported, as I found
 myself not wanting to use this "security feature" anyway.
 
 As I don't run -current anymore, the patch is against RELENG_6.
 If it does not apply to -current anymore, I can fix this on request.
 
 Just in case the attached patch gets mangled, you can find a
 copy of it here: http://www.stsp.in-berlin.de/wol/
 
 -- 
 stefan
 http://stsp.in-berlin.de                                 PGP Key: 0xF59D25F0
 
 --5mCyUwZo2JvN/JJP
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: attachment; filename="FreeBSD-6.0-wol-2006-05-06.diff"
 
 Index: sbin/ifconfig/Makefile
 ===================================================================
 RCS file: /usr/mylocal/ncvs/src/sbin/ifconfig/Makefile,v
 retrieving revision 1.29
 diff -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 @@
  
  SRCS+=	ifbridge.c		# bridge support
  
 +SRCS+=	ifwol.c			# wake on lan support
 +
  .if !defined(RELEASE_CRUNCH)
  SRCS+=	af_ipx.c		# IPX support
  DPADD=	${LIBIPX}
 Index: sbin/ifconfig/ifconfig.8
 ===================================================================
 RCS file: /usr/mylocal/ncvs/src/sbin/ifconfig/ifconfig.8,v
 retrieving revision 1.95.2.14
 diff -u -r1.95.2.14 ifconfig.8
 --- sbin/ifconfig/ifconfig.8	10 Mar 2006 22:05:53 -0000	1.95.2.14
 +++ sbin/ifconfig/ifconfig.8	6 May 2006 10:49:48 -0000
 @@ -896,6 +896,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 
 +.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> 
 +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.
 @@ -903,7 +924,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
 ===================================================================
 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	6 May 2006 11:14:15 -0000
 @@ -0,0 +1,232 @@
 +/* $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 WARRANTIES
 + * 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(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));
 +	strncpy(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 == 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)
 +{
 +	char *args;
 +	struct ifreq ifr;
 +
 +	memset(&ifr, 0, sizeof(ifr));
 +	strncpy(ifr.ifr_name, name, IFNAMSIZ);
 +
 +	if (ioctl(s, SIOCGIFWOLSUPP, &ifr) < 0)
 +		err(EX_USAGE, "device does not support wake on lan");
 +
 +	args = strdup(val);
 +	parse_args(args, &ifr.ifr_wolopts);
 +	free(args);
 +	if (ioctl(s, SIOCSIFWOLOPTS, &ifr) < 0)
 +		err(EX_USAGE, "SIOCSIFWOLOPTS");
 +}
 +
 +/* 
 + * Parse the argument string, which may contain one or more of the
 + * following:
 + *    
 + *     unicast,multicast,broadcast,magic,sopasswd:xxxxxxxxxxxx,
 + *
 + * and fill the wolopts structure accordingly.
 + * 
 + */
 +static void
 +parse_args(const char* args, struct if_wolopts *wolopts)
 +{
 +	uint32_t wol_events = 0;
 +	char* opt;
 +
 +	for (opt = strdup(args); (opt = strtok(opt, ",")) != NULL; opt = NULL) {
 +		if (strcmp(opt, "unicast") == 0)
 +			wol_events |= IFWOL_WAKE_ON_UNICAST;
 +		else if (strcmp(opt, "multicast") == 0)
 +			wol_events |= IFWOL_WAKE_ON_MULTICAST;
 +		else if (strcmp(opt, "broadcast") == 0)
 +			wol_events |= IFWOL_WAKE_ON_BROADCAST;
 +		else if (strcmp(opt, "magic") == 0)
 +			wol_events |= IFWOL_WAKE_ON_MAGIC;
 +		else if (strcmp(opt, "sopasswd") == 0)
 +			errx(EX_USAGE, "no SecureOn password specfied.");
 +		else if (strncmp(opt, "sopasswd:", strlen("sopasswd:")) == 0) {
 +			wol_events |= 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 = wol_events;
 +}
 +
 +/* SecureOn passwords are not like plain text passwords. Instead, they consist
 + * of 6 bytes (ie unsigned char). Try to prevent users from giving anything other
 + * than a string of six concatenated unsigned chars in hex as password.
 + */
 +static void
 +parse_sopasswd(char *pw, u_char *dest) {
 +	char substr[3];
 +	int len, i, n;
 +
 +	len = strlen(pw) / 2;
 +	if (len != 6)
 +		errx(EX_USAGE, "Invalid SecureOn password.");
 +
 +	for (i = 0; i < len; i++) {
 +		(void)strncpy(substr, pw, 2);
 +		substr[2] = '\0';
 +		if (sscanf(substr, "%x", &n) != 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++ = (u_char)n;
 +		pw += 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));
 +	strncpy(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 = IFWOL_DISABLE;
 +	if (ioctl(s, SIOCSIFWOLOPTS, &ifr) < 0)
 +		err(EX_USAGE, "SIOCSIFWOLOPTS");
 +}
 +
 +static struct cmd wol_cmds[] = {
 +	DEF_CMD_ARG("wakeon",	setwol),
 +	DEF_CMD("-wakeon", 0, unsetwol)
 +};
 +static struct afswtch af_wol = {
 +	.af_name	= "af_wol",
 +	.af_af		= AF_UNSPEC,
 +	.af_other_status = wol_status,
 +};
 +
 +static __constructor void
 +ifwol_ctor(void)
 +{
 +#define	N(a)	(sizeof(a) / sizeof(a[0]))
 +	int i;
 +
 +	for (i = 0; i < N(wol_cmds);  i++)
 +		cmd_register(&wol_cmds[i]);
 +	af_register(&af_wol);
 +#undef N
 +}
 Index: sys/dev/nve/if_nve.c
 ===================================================================
 RCS file: /usr/mylocal/ncvs/src/sys/dev/nve/if_nve.c,v
 retrieving revision 1.7.2.8
 diff -u -r1.7.2.8 if_nve.c
 --- sys/dev/nve/if_nve.c	25 Dec 2005 21:57:03 -0000	1.7.2.8
 +++ sys/dev/nve/if_nve.c	5 May 2006 23:05:57 -0000
 @@ -179,6 +179,10 @@
  static NV_SINT32 nve_oslockrelease(PNV_VOID, NV_SINT32, PNV_VOID);
  static PNV_VOID  nve_osreturnbufvirt(PNV_VOID, PNV_VOID);
  
 +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[] = {
  	/* Device interface */
  	DEVMETHOD(device_probe, nve_probe),
 @@ -718,6 +722,10 @@
  
  	sc = device_get_softc(dev);
  
 +	NVE_LOCK(sc);
 +	nve_enable_wol(sc);
 +	NVE_UNLOCK(sc);
 +
  	/* Stop hardware activity */
  	NVE_LOCK(sc);
  	nve_stop(sc);
 @@ -1018,6 +1026,21 @@
  		mii = device_get_softc(sc->miibus);
  		error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
  		break;
 + 	case SIOCGIFWOLSUPP:
 + 		ifr->ifr_wolopts.ifwol_supported = NVE_SUPPORTED_WOL_EVENTS;
 + 		error = 0;
 + 		break;
 + 	case SIOCGIFWOLOPTS:
 + 		NVE_LOCK(sc);
 + 		nve_get_wolopts(sc, &ifr->ifr_wolopts);
 + 		NVE_UNLOCK(sc);
 + 		error = 0;
 + 		break;
 + 	case SIOCSIFWOLOPTS:
 + 		NVE_LOCK(sc);
 + 		error = nve_set_wolopts(sc, &ifr->ifr_wolopts);
 + 		NVE_UNLOCK(sc);
 +  		break;
  
  	default:
  		/* Everything else we forward to generic ether ioctl */
 @@ -1736,3 +1759,49 @@
  }
  
  /* --- End on NVOSAPI interface --- */
 +
 +/*
 + * Enable Wake On Lan.
 + */
 +static void
 +nve_enable_wol(struct nve_softc *sc)
 +{
 +	ADAPTER_POWERSTATE pstate = {0};
 +
 +	if (sc->wol_events == 0)
 +		return;
 +	
 +	if (sc->wol_events & IFWOL_WAKE_ON_MAGIC) {
 +		pstate.ulPowerFlags = POWER_STATE_D3;
 +		pstate.ulMagicPacketWakeUpFlags = POWER_STATE_ALL;
 +		pstate.ulLinkChangeWakeUpFlags = 0;
 +		pstate.ulPatternWakeUpFlags = 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 = 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 == IFWOL_DISABLE)
 +		sc->wol_events = 0;
 +	else {
 +		if ((wolopts->ifwol_events & ~NVE_SUPPORTED_WOL_EVENTS) != 0)
 +			return EINVAL;
 +		sc->wol_events = wolopts->ifwol_events;
 +	}
 +
 +	return 0;
 +}
 Index: sys/dev/nve/if_nvereg.h
 ===================================================================
 RCS file: /usr/mylocal/ncvs/src/sys/dev/nve/if_nvereg.h,v
 retrieving revision 1.3.2.1
 diff -u -r1.3.2.1 if_nvereg.h
 --- sys/dev/nve/if_nvereg.h	12 Dec 2005 19:40:04 -0000	1.3.2.1
 +++ sys/dev/nve/if_nvereg.h	5 May 2006 23:05:57 -0000
 @@ -67,6 +67,8 @@
  #define	NVE_DEBUG_MII		0x0100
  #define	NVE_DEBUG_ALL		0xFFFF
  
 +#define NVE_SUPPORTED_WOL_EVENTS	IFWOL_WAKE_ON_MAGIC
 +
  #if NVE_DEBUG
  #define	DEBUGOUT(level, fmt, args...) if (NVE_DEBUG & level) \
      printf(fmt, ## args)
 @@ -141,6 +143,8 @@
  
  	struct mtx mtx;
  
 +	uint32_t wol_events;
 +
  	/* Stuff for dealing with the NVIDIA OS API */
  	struct callout ostimer;
  	PTIMER_FUNC ostimer_func;
 Index: sys/net/if.c
 ===================================================================
 RCS file: /usr/mylocal/ncvs/src/sys/net/if.c,v
 retrieving revision 1.234.2.13
 diff -u -r1.234.2.13 if.c
 --- sys/net/if.c	15 Feb 2006 03:37:15 -0000	1.234.2.13
 +++ sys/net/if.c	5 May 2006 23:05:57 -0000
 @@ -1436,6 +1436,7 @@
  	case SIOCSLIFPHYADDR:
  	case SIOCSIFMEDIA:
  	case SIOCSIFGENERIC:
 +	case SIOCSIFWOLOPTS:
  		error = suser(td);
  		if (error)
  			return (error);
 @@ -1457,6 +1458,8 @@
  	case SIOCGLIFPHYADDR:
  	case SIOCGIFMEDIA:
  	case SIOCGIFGENERIC:
 +	case SIOCGIFWOLOPTS:
 +	case SIOCGIFWOLSUPP:
  		if (ifp->if_ioctl == NULL)
  			return (EOPNOTSUPP);
  		IFF_LOCKGIANT(ifp);
 Index: sys/net/if.h
 ===================================================================
 RCS file: /usr/mylocal/ncvs/src/sys/net/if.h,v
 retrieving revision 1.96.2.4
 diff -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 */
  
  /*
 + * 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
 ===================================================================
 RCS file: /usr/mylocal/ncvs/src/sys/pci/if_sis.c,v
 retrieving revision 1.132.2.7
 diff -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);
  
  #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;
  
  	p = arg;
  	*p = 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 = 0;
 +	uint16_t		word = 0;
  
  	/* 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 = 0, *ptr;
 +	uint16_t		word = 0, *ptr;
  
  	for (i = 0; i < cnt; i++) {
  		sis_eeprom_getword(sc, off + i, &word);
 -		ptr = (u_int16_t *)(dest + (i * 2));
 +		ptr = (uint16_t *)(dest + (i * 2));
  		if (swap)
  			*ptr = ntohs(word);
  		else
 @@ -354,7 +358,7 @@
  sis_read_cmos(struct sis_softc *sc, device_t dev, caddr_t dest, int off, int cnt)
  {
  	device_t		bridge;
 -	u_int8_t		reg;
 +	uint8_t			reg;
  	int			i;
  	bus_space_tag_t		btag;
  
 @@ -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;
  
  	filtsave = CSR_READ_4(sc, SIS_RXFILT_CTL);
  	csrsave = CSR_READ_4(sc, SIS_CSR);
 @@ -394,11 +398,11 @@
  	CSR_WRITE_4(sc, SIS_RXFILT_CTL, filtsave & ~SIS_RXFILTCTL_ENABLE);
  
  	CSR_WRITE_4(sc, SIS_RXFILT_CTL, SIS_FILTADDR_PAR0);
 -	((u_int16_t *)dest)[0] = CSR_READ_2(sc, SIS_RXFILT_DATA);
 +	((uint16_t *)dest)[0] = CSR_READ_2(sc, SIS_RXFILT_DATA);
  	CSR_WRITE_4(sc, SIS_RXFILT_CTL,SIS_FILTADDR_PAR1);
 -	((u_int16_t *)dest)[1] = CSR_READ_2(sc, SIS_RXFILT_DATA);
 +	((uint16_t *)dest)[1] = CSR_READ_2(sc, SIS_RXFILT_DATA);
  	CSR_WRITE_4(sc, SIS_RXFILT_CTL, SIS_FILTADDR_PAR2);
 -	((u_int16_t *)dest)[2] = CSR_READ_2(sc, SIS_RXFILT_DATA);
 +	((uint16_t *)dest)[2] = CSR_READ_2(sc, SIS_RXFILT_DATA);
  
  	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 = 0, i, filtsave;
 +	uint32_t		h = 0, i, filtsave;
  	int			bit, index;
  
  	ifp = 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];
  
  	ifp = sc->sis_ifp;
  
 @@ -984,7 +988,7 @@
  		 * Why? Who the hell knows.
  		 */
  		{
 -			u_int16_t		tmp[4];
 +			uint16_t		tmp[4];
  
  			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 = 0;
 -	u_int32_t		rxstat;
 +	uint32_t		rxstat;
  
  	SIS_LOCK_ASSERT(sc);
  
 @@ -1501,7 +1505,7 @@
  sis_txeof(struct sis_softc *sc)
  {
  	struct ifnet		*ifp;
 -	u_int32_t		idx;
 +	uint32_t		idx;
  
  	SIS_LOCK_ASSERT(sc);
  	ifp = sc->sis_ifp;
 @@ -1605,7 +1609,7 @@
  		sis_startl(ifp);
  
  	if (sc->rxcycles > 0 || cmd == POLL_AND_CHECK_STATUS) {
 -		u_int32_t	status;
 +		uint32_t	status;
  
  		/* Reading the ISR register clears all interrupts. */
  		status = CSR_READ_4(sc, SIS_ISR);
 @@ -1631,7 +1635,7 @@
  {
  	struct sis_softc	*sc;
  	struct ifnet		*ifp;
 -	u_int32_t		status;
 +	uint32_t		status;
  
  	sc = arg;
  	ifp = sc->sis_ifp;
 @@ -1785,7 +1789,7 @@
  {
  	struct sis_softc	*sc;
  	struct mbuf		*m_head = NULL;
 -	u_int32_t		idx, queued = 0;
 +	uint32_t		idx, queued = 0;
  
  	sc = ifp->if_softc;
  
 @@ -1872,23 +1876,23 @@
  	if (sc->sis_type == 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]);
  	}
  
  	/* Init circular TX/RX lists. */
 @@ -2162,6 +2166,21 @@
  		}
  #endif /* DEVICE_POLLING */
  		break;
 + 	case SIOCGIFWOLSUPP:
 + 		ifr->ifr_wolopts.ifwol_supported = NS_SUPPORTED_WOL_EVENTS;
 + 		error = 0;
 + 		break;
 + 	case SIOCGIFWOLOPTS:
 + 		SIS_LOCK(sc);
 + 		sis_get_wolopts(sc, &ifr->ifr_wolopts);
 + 		SIS_UNLOCK(sc);
 + 		error = 0;
 + 		break;
 + 	case SIOCSIFWOLOPTS:
 + 		SIS_LOCK(sc);
 + 		error = sis_set_wolopts(sc, &ifr->ifr_wolopts);
 + 		SIS_UNLOCK(sc);
 +  		break;
  	default:
  		error = 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);
  }
  
 +/*
 + * 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 = 0;
 +	
 +	if (wol_events & IFWOL_WAKE_ON_UNICAST)
 +		sis_wol_events |= NS_WCSR_WAKE_UCAST;
 +	if (wol_events & IFWOL_WAKE_ON_MULTICAST)
 +		sis_wol_events |= NS_WCSR_WAKE_MCAST;
 +	if (wol_events & IFWOL_WAKE_ON_BROADCAST)
 +		sis_wol_events |= NS_WCSR_WAKE_BCAST;
 +	if (wol_events & IFWOL_WAKE_ON_MAGIC)
 +		sis_wol_events |= 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 = sc->ns_wol_events;
 +	
 +	/* Do not disclose Secure On password. */
 +#define	N(a)	(sizeof(a) / sizeof(a[0]))
 +	for (i = 0; i < N(wolopts->ifwol_sopasswd); i++)
 +		wolopts->ifwol_sopasswd[i] = '\0';
 +#undef N
 +}
 +	
 +/*
 + * 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 == IFWOL_DISABLE)
 +		sc->ns_wol_events = 0;
 +	else {
 +		if ((wolopts->ifwol_events & ~NS_SUPPORTED_WOL_EVENTS) != 0)
 +			return EINVAL;
 +		sc->ns_wol_events = wolopts->ifwol_events;
 +	}
 +
 +	return 0;
 +}
 +
 +/* 
 + * 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);
 +	
 +	if (sc->sis_type != SIS_TYPE_83815)
 +		return;
 +
 +	/* Check whether any wake on lan events have been set. */
 +	if (sc->ns_wol_events == 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);
 +	
 +	/* 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);
 +
 +	/* 
 +	 * 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[] = {
  	/* Device interface */
  	DEVMETHOD(device_probe,		sis_probe),
 Index: sys/pci/if_sisreg.h
 ===================================================================
 RCS file: /usr/mylocal/ncvs/src/sys/pci/if_sisreg.h,v
 retrieving revision 1.33.2.1
 diff -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;
  };
  
  #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_MULTICAST \
 +				    | IFWOL_WAKE_ON_BROADCAST | IFWOL_WAKE_ON_MAGIC)
 +
 Index: sys/pci/if_vr.c
 ===================================================================
 RCS file: /usr/mylocal/ncvs/src/sys/pci/if_vr.c,v
 retrieving revision 1.104.2.6
 diff -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	5 May 2006 23:05:57 -0000
 @@ -169,6 +169,10 @@
  static int vr_list_rx_init(struct vr_softc *);
  static int vr_list_tx_init(struct vr_softc *);
  
 +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
  
  	/*
 -	 * 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 @@
  
  	sc->suspended = 0;
  
 +	/* Check Wake on Lan support. */
 +	if (sc->vr_revid >= REV_ID_VT6102 ) {
 +		sc->wol_support = 1;
 +		if (sc->vr_revid >= REV_ID_VT6105_B0)
 +			sc->wol_6patterns = 1;
 +	}
 +
  	/* Hook interrupt last to avoid having to lock softc */
  	error = 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 = VR_SUPPORTED_WOL_EVENTS;
 + 		error = 0;
 + 		break;
 + 	case SIOCGIFWOLOPTS:
 + 		VR_LOCK(sc);
 + 		vr_get_wolopts(sc, &ifr->ifr_wolopts);
 + 		VR_UNLOCK(sc);
 + 		error = 0;
 + 		break;
 + 	case SIOCSIFWOLOPTS:
 + 		VR_LOCK(sc);
 + 		error = vr_set_wolopts(sc, &ifr->ifr_wolopts);
 + 		VR_UNLOCK(sc);
 +  		break;
  	default:
  		error = ether_ioctl(ifp, command, data);
  		break;
 @@ -1702,6 +1728,92 @@
  static void
  vr_shutdown(device_t dev)
  {
 +	struct vr_softc *sc;
  
 +	sc = 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);
 +	
 +	/* Check whether wake on lan is available
 +	 * and whether events have been set. */
 +	if (!sc->wol_support || sc->wol_events == 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->wol_6patterns)
 +		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->wol_6patterns)
 +		CSR_WRITE_1(sc, VR_WOLCGCLR, 0x04);
 +	
 +	/* Set unicast wake event if applicable. */
 +	if (sc->wol_events & IFWOL_WAKE_ON_UNICAST)
 +		VR_SETBIT(sc, VR_WOLCRSET, VR_WAKE_UCAST);
 +	
 +	/* Set magic wake event if applicable. */
 +	if (sc->wol_events & 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->wol_events & IFWOL_WAKE_ON_BROADCAST ||
 +	    sc->wol_events & 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 = sc->wol_events;
 +}
 +	
 +/*
 + * 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 == IFWOL_DISABLE)
 +		sc->wol_events = 0;
 +	else {
 +		if ((wolopts->ifwol_events & ~VR_SUPPORTED_WOL_EVENTS) != 0)
 +			return EINVAL;
 +		sc->wol_events = wolopts->ifwol_events;
 +	}
 +
 +	return 0;
 +}
 +
 Index: sys/pci/if_vrreg.h
 ===================================================================
 RCS file: /usr/mylocal/ncvs/src/sys/pci/if_vrreg.h,v
 retrieving revision 1.22.2.1
 diff -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	5 May 2006 23:05:58 -0000
 @@ -283,6 +283,21 @@
  #define VR_STICKHW_WOL_STS	0x08
  #define VR_STICKHW_LEGWOL_ENB	0x80
  
 +/* 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_MAGIC)
 +
  /*
   * BCR0 register bits. (At least for the VT6102 chip.)
   */
 @@ -471,6 +486,10 @@
  #ifdef DEVICE_POLLING
  	int			rxcycles;
  #endif
 +	int			wol_support;	/* Chip supports WOL. */
 +	uint32_t		wol_events;	/* Wake on Lan satus */
 +	int			wol_6patterns;	/* some chips have 6 patterns
 +						   for WOL instead of 4 */
  };
  
  #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
 +
  
  /*
   * PCI low memory base and low I/O base register, and
 Index: sys/sys/sockio.h
 ===================================================================
 RCS file: /usr/mylocal/ncvs/src/sys/sys/sockio.h,v
 retrieving revision 1.28.2.1
 diff -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 */
  
 +#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_ */
 
 --5mCyUwZo2JvN/JJP--

From: Stefan Sperling <stsp@stsp.in-berlin.de>
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/83807: [sis] [patch] if_sis: Wake On Lan support for FreeBSD
Date: Fri, 20 Oct 2006 12:44:55 +0200

 --AhhlLboLdkugWU4S
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 
 This is another revision which cleans out some minor issues in the part
 of the patch affecting /sbin/ifconfig:
 
 	* Fix several instances of misuse of strncpy that could
 	  theoretically lead to buffer overflow.
 	* Remove unnecessary strdup() invocation.
 	  One copy operation is enough :)
 
 -- 
 stefan
 http://stsp.in-berlin.de                                 PGP Key: 0xF59D25F0
 
 --AhhlLboLdkugWU4S
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: attachment; filename="FreeBSD-6.1-wol-2006-10-20.diff"
 
 Index: sbin/ifconfig/Makefile
 ===================================================================
 RCS file: /usr/local/ncvs/src/sbin/ifconfig/Makefile,v
 retrieving revision 1.29
 diff -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 @@
  
  SRCS+=	ifbridge.c		# bridge support
  
 +SRCS+=	ifwol.c			# wake on lan support
 +
  .if !defined(RELEASE_CRUNCH)
  SRCS+=	af_ipx.c		# IPX support
  DPADD=	${LIBIPX}
 Index: sbin/ifconfig/ifconfig.8
 ===================================================================
 RCS file: /usr/local/ncvs/src/sbin/ifconfig/ifconfig.8,v
 retrieving revision 1.95.2.14
 diff -u -r1.95.2.14 ifconfig.8
 --- sbin/ifconfig/ifconfig.8	10 Mar 2006 22:05:53 -0000	1.95.2.14
 +++ sbin/ifconfig/ifconfig.8	6 May 2006 10:49:48 -0000
 @@ -896,6 +896,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 
 +.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> 
 +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.
 @@ -903,7 +924,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
 ===================================================================
 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 WARRANTIES
 + * 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 == 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");
 +}
 +
 +/* 
 + * Parse the argument string, which may contain one or more of the
 + * following:
 + *    
 + *     unicast,multicast,broadcast,magic,sopasswd:xxxxxxxxxxxx,
 + *
 + * and fill the wolopts structure accordingly.
 + * 
 + */
 +static void
 +parse_args(const char* args, struct if_wolopts *wolopts)
 +{
 +	uint32_t wol_events = 0;
 +	char* opt;
 +
 +	for (opt = strdup(args); (opt = strtok(opt, ",")) != NULL; opt = NULL) {
 +		if (strcmp(opt, "unicast") == 0)
 +			wol_events |= IFWOL_WAKE_ON_UNICAST;
 +		else if (strcmp(opt, "multicast") == 0)
 +			wol_events |= IFWOL_WAKE_ON_MULTICAST;
 +		else if (strcmp(opt, "broadcast") == 0)
 +			wol_events |= IFWOL_WAKE_ON_BROADCAST;
 +		else if (strcmp(opt, "magic") == 0)
 +			wol_events |= IFWOL_WAKE_ON_MAGIC;
 +		else if (strcmp(opt, "sopasswd") == 0)
 +			errx(EX_USAGE, "no SecureOn password specfied.");
 +		else if (strncmp(opt, "sopasswd:", strlen("sopasswd:")) == 0) {
 +			wol_events |= 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 = wol_events;
 +}
 +
 +/* SecureOn passwords are not like plain text passwords. Instead, they consist
 + * of 6 bytes (ie unsigned char). Try to prevent users from giving anything 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 = strlen(pw) / 2;
 +	if (len != 6)
 +		errx(EX_USAGE, "Invalid SecureOn password.");
 +
 +	for (i = 0; i < len; i++) {
 +		(void)strncpy(substr, pw, 2);
 +		substr[2] = '\0';
 +		if (sscanf(substr, "%x", &n) != 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++ = (u_char)n;
 +		pw += 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 = IFWOL_DISABLE;
 +	if (ioctl(s, SIOCSIFWOLOPTS, &ifr) < 0)
 +		err(EX_USAGE, "SIOCSIFWOLOPTS");
 +}
 +
 +static struct cmd wol_cmds[] = {
 +	DEF_CMD_ARG("wakeon",	setwol),
 +	DEF_CMD("-wakeon", 0, unsetwol)
 +};
 +static struct afswtch af_wol = {
 +	.af_name	= "af_wol",
 +	.af_af		= AF_UNSPEC,
 +	.af_other_status = wol_status,
 +};
 +
 +static __constructor void
 +ifwol_ctor(void)
 +{
 +#define	N(a)	(sizeof(a) / sizeof(a[0]))
 +	int i;
 +
 +	for (i = 0; i < N(wol_cmds);  i++)
 +		cmd_register(&wol_cmds[i]);
 +	af_register(&af_wol);
 +#undef N
 +}
 Index: sys/dev/nve/if_nve.c
 ===================================================================
 RCS file: /usr/local/ncvs/src/sys/dev/nve/if_nve.c,v
 retrieving revision 1.7.2.8
 diff -u -r1.7.2.8 if_nve.c
 --- sys/dev/nve/if_nve.c	25 Dec 2005 21:57:03 -0000	1.7.2.8
 +++ sys/dev/nve/if_nve.c	5 May 2006 23:05:57 -0000
 @@ -179,6 +179,10 @@
  static NV_SINT32 nve_oslockrelease(PNV_VOID, NV_SINT32, PNV_VOID);
  static PNV_VOID  nve_osreturnbufvirt(PNV_VOID, PNV_VOID);
  
 +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[] = {
  	/* Device interface */
  	DEVMETHOD(device_probe, nve_probe),
 @@ -718,6 +722,10 @@
  
  	sc = device_get_softc(dev);
  
 +	NVE_LOCK(sc);
 +	nve_enable_wol(sc);
 +	NVE_UNLOCK(sc);
 +
  	/* Stop hardware activity */
  	NVE_LOCK(sc);
  	nve_stop(sc);
 @@ -1018,6 +1026,21 @@
  		mii = device_get_softc(sc->miibus);
  		error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
  		break;
 + 	case SIOCGIFWOLSUPP:
 + 		ifr->ifr_wolopts.ifwol_supported = NVE_SUPPORTED_WOL_EVENTS;
 + 		error = 0;
 + 		break;
 + 	case SIOCGIFWOLOPTS:
 + 		NVE_LOCK(sc);
 + 		nve_get_wolopts(sc, &ifr->ifr_wolopts);
 + 		NVE_UNLOCK(sc);
 + 		error = 0;
 + 		break;
 + 	case SIOCSIFWOLOPTS:
 + 		NVE_LOCK(sc);
 + 		error = nve_set_wolopts(sc, &ifr->ifr_wolopts);
 + 		NVE_UNLOCK(sc);
 +  		break;
  
  	default:
  		/* Everything else we forward to generic ether ioctl */
 @@ -1736,3 +1759,49 @@
  }
  
  /* --- End on NVOSAPI interface --- */
 +
 +/*
 + * Enable Wake On Lan.
 + */
 +static void
 +nve_enable_wol(struct nve_softc *sc)
 +{
 +	ADAPTER_POWERSTATE pstate = {0};
 +
 +	if (sc->wol_events == 0)
 +		return;
 +	
 +	if (sc->wol_events & IFWOL_WAKE_ON_MAGIC) {
 +		pstate.ulPowerFlags = POWER_STATE_D3;
 +		pstate.ulMagicPacketWakeUpFlags = POWER_STATE_ALL;
 +		pstate.ulLinkChangeWakeUpFlags = 0;
 +		pstate.ulPatternWakeUpFlags = 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 = 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 == IFWOL_DISABLE)
 +		sc->wol_events = 0;
 +	else {
 +		if ((wolopts->ifwol_events & ~NVE_SUPPORTED_WOL_EVENTS) != 0)
 +			return EINVAL;
 +		sc->wol_events = wolopts->ifwol_events;
 +	}
 +
 +	return 0;
 +}
 Index: sys/dev/nve/if_nvereg.h
 ===================================================================
 RCS file: /usr/local/ncvs/src/sys/dev/nve/if_nvereg.h,v
 retrieving revision 1.3.2.1
 diff -u -r1.3.2.1 if_nvereg.h
 --- sys/dev/nve/if_nvereg.h	12 Dec 2005 19:40:04 -0000	1.3.2.1
 +++ sys/dev/nve/if_nvereg.h	5 May 2006 23:05:57 -0000
 @@ -67,6 +67,8 @@
  #define	NVE_DEBUG_MII		0x0100
  #define	NVE_DEBUG_ALL		0xFFFF
  
 +#define NVE_SUPPORTED_WOL_EVENTS	IFWOL_WAKE_ON_MAGIC
 +
  #if NVE_DEBUG
  #define	DEBUGOUT(level, fmt, args...) if (NVE_DEBUG & level) \
      printf(fmt, ## args)
 @@ -141,6 +143,8 @@
  
  	struct mtx mtx;
  
 +	uint32_t wol_events;
 +
  	/* Stuff for dealing with the NVIDIA OS API */
  	struct callout ostimer;
  	PTIMER_FUNC ostimer_func;
 Index: sys/net/if.c
 ===================================================================
 RCS file: /usr/local/ncvs/src/sys/net/if.c,v
 retrieving revision 1.234.2.13
 diff -u -r1.234.2.13 if.c
 --- sys/net/if.c	15 Feb 2006 03:37:15 -0000	1.234.2.13
 +++ sys/net/if.c	5 May 2006 23:05:57 -0000
 @@ -1436,6 +1436,7 @@
  	case SIOCSLIFPHYADDR:
  	case SIOCSIFMEDIA:
  	case SIOCSIFGENERIC:
 +	case SIOCSIFWOLOPTS:
  		error = suser(td);
  		if (error)
  			return (error);
 @@ -1457,6 +1458,8 @@
  	case SIOCGLIFPHYADDR:
  	case SIOCGIFMEDIA:
  	case SIOCGIFGENERIC:
 +	case SIOCGIFWOLOPTS:
 +	case SIOCGIFWOLSUPP:
  		if (ifp->if_ioctl == NULL)
  			return (EOPNOTSUPP);
  		IFF_LOCKGIANT(ifp);
 Index: sys/net/if.h
 ===================================================================
 RCS file: /usr/local/ncvs/src/sys/net/if.h,v
 retrieving revision 1.96.2.4
 diff -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 */
  
  /*
 + * 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
 ===================================================================
 RCS file: /usr/local/ncvs/src/sys/pci/if_sis.c,v
 retrieving revision 1.132.2.7
 diff -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);
  
  #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;
  
  	p = arg;
  	*p = 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 = 0;
 +	uint16_t		word = 0;
  
  	/* 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 = 0, *ptr;
 +	uint16_t		word = 0, *ptr;
  
  	for (i = 0; i < cnt; i++) {
  		sis_eeprom_getword(sc, off + i, &word);
 -		ptr = (u_int16_t *)(dest + (i * 2));
 +		ptr = (uint16_t *)(dest + (i * 2));
  		if (swap)
  			*ptr = ntohs(word);
  		else
 @@ -354,7 +358,7 @@
  sis_read_cmos(struct sis_softc *sc, device_t dev, caddr_t dest, int off, int cnt)
  {
  	device_t		bridge;
 -	u_int8_t		reg;
 +	uint8_t			reg;
  	int			i;
  	bus_space_tag_t		btag;
  
 @@ -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;
  
  	filtsave = CSR_READ_4(sc, SIS_RXFILT_CTL);
  	csrsave = CSR_READ_4(sc, SIS_CSR);
 @@ -394,11 +398,11 @@
  	CSR_WRITE_4(sc, SIS_RXFILT_CTL, filtsave & ~SIS_RXFILTCTL_ENABLE);
  
  	CSR_WRITE_4(sc, SIS_RXFILT_CTL, SIS_FILTADDR_PAR0);
 -	((u_int16_t *)dest)[0] = CSR_READ_2(sc, SIS_RXFILT_DATA);
 +	((uint16_t *)dest)[0] = CSR_READ_2(sc, SIS_RXFILT_DATA);
  	CSR_WRITE_4(sc, SIS_RXFILT_CTL,SIS_FILTADDR_PAR1);
 -	((u_int16_t *)dest)[1] = CSR_READ_2(sc, SIS_RXFILT_DATA);
 +	((uint16_t *)dest)[1] = CSR_READ_2(sc, SIS_RXFILT_DATA);
  	CSR_WRITE_4(sc, SIS_RXFILT_CTL, SIS_FILTADDR_PAR2);
 -	((u_int16_t *)dest)[2] = CSR_READ_2(sc, SIS_RXFILT_DATA);
 +	((uint16_t *)dest)[2] = CSR_READ_2(sc, SIS_RXFILT_DATA);
  
  	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 = 0, i, filtsave;
 +	uint32_t		h = 0, i, filtsave;
  	int			bit, index;
  
  	ifp = 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];
  
  	ifp = sc->sis_ifp;
  
 @@ -984,7 +988,7 @@
  		 * Why? Who the hell knows.
  		 */
  		{
 -			u_int16_t		tmp[4];
 +			uint16_t		tmp[4];
  
  			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 = 0;
 -	u_int32_t		rxstat;
 +	uint32_t		rxstat;
  
  	SIS_LOCK_ASSERT(sc);
  
 @@ -1501,7 +1505,7 @@
  sis_txeof(struct sis_softc *sc)
  {
  	struct ifnet		*ifp;
 -	u_int32_t		idx;
 +	uint32_t		idx;
  
  	SIS_LOCK_ASSERT(sc);
  	ifp = sc->sis_ifp;
 @@ -1605,7 +1609,7 @@
  		sis_startl(ifp);
  
  	if (sc->rxcycles > 0 || cmd == POLL_AND_CHECK_STATUS) {
 -		u_int32_t	status;
 +		uint32_t	status;
  
  		/* Reading the ISR register clears all interrupts. */
  		status = CSR_READ_4(sc, SIS_ISR);
 @@ -1631,7 +1635,7 @@
  {
  	struct sis_softc	*sc;
  	struct ifnet		*ifp;
 -	u_int32_t		status;
 +	uint32_t		status;
  
  	sc = arg;
  	ifp = sc->sis_ifp;
 @@ -1785,7 +1789,7 @@
  {
  	struct sis_softc	*sc;
  	struct mbuf		*m_head = NULL;
 -	u_int32_t		idx, queued = 0;
 +	uint32_t		idx, queued = 0;
  
  	sc = ifp->if_softc;
  
 @@ -1872,23 +1876,23 @@
  	if (sc->sis_type == 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]);
  	}
  
  	/* Init circular TX/RX lists. */
 @@ -2162,6 +2166,21 @@
  		}
  #endif /* DEVICE_POLLING */
  		break;
 + 	case SIOCGIFWOLSUPP:
 + 		ifr->ifr_wolopts.ifwol_supported = NS_SUPPORTED_WOL_EVENTS;
 + 		error = 0;
 + 		break;
 + 	case SIOCGIFWOLOPTS:
 + 		SIS_LOCK(sc);
 + 		sis_get_wolopts(sc, &ifr->ifr_wolopts);
 + 		SIS_UNLOCK(sc);
 + 		error = 0;
 + 		break;
 + 	case SIOCSIFWOLOPTS:
 + 		SIS_LOCK(sc);
 + 		error = sis_set_wolopts(sc, &ifr->ifr_wolopts);
 + 		SIS_UNLOCK(sc);
 +  		break;
  	default:
  		error = 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);
  }
  
 +/*
 + * 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 = 0;
 +	
 +	if (wol_events & IFWOL_WAKE_ON_UNICAST)
 +		sis_wol_events |= NS_WCSR_WAKE_UCAST;
 +	if (wol_events & IFWOL_WAKE_ON_MULTICAST)
 +		sis_wol_events |= NS_WCSR_WAKE_MCAST;
 +	if (wol_events & IFWOL_WAKE_ON_BROADCAST)
 +		sis_wol_events |= NS_WCSR_WAKE_BCAST;
 +	if (wol_events & IFWOL_WAKE_ON_MAGIC)
 +		sis_wol_events |= 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 = sc->ns_wol_events;
 +	
 +	/* Do not disclose Secure On password. */
 +#define	N(a)	(sizeof(a) / sizeof(a[0]))
 +	for (i = 0; i < N(wolopts->ifwol_sopasswd); i++)
 +		wolopts->ifwol_sopasswd[i] = '\0';
 +#undef N
 +}
 +	
 +/*
 + * 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 == IFWOL_DISABLE)
 +		sc->ns_wol_events = 0;
 +	else {
 +		if ((wolopts->ifwol_events & ~NS_SUPPORTED_WOL_EVENTS) != 0)
 +			return EINVAL;
 +		sc->ns_wol_events = wolopts->ifwol_events;
 +	}
 +
 +	return 0;
 +}
 +
 +/* 
 + * 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);
 +	
 +	if (sc->sis_type != SIS_TYPE_83815)
 +		return;
 +
 +	/* Check whether any wake on lan events have been set. */
 +	if (sc->ns_wol_events == 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);
 +	
 +	/* 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);
 +
 +	/* 
 +	 * 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[] = {
  	/* Device interface */
  	DEVMETHOD(device_probe,		sis_probe),
 Index: sys/pci/if_sisreg.h
 ===================================================================
 RCS file: /usr/local/ncvs/src/sys/pci/if_sisreg.h,v
 retrieving revision 1.33.2.1
 diff -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;
  };
  
  #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_MULTICAST \
 +				    | IFWOL_WAKE_ON_BROADCAST | IFWOL_WAKE_ON_MAGIC)
 +
 Index: sys/pci/if_vr.c
 ===================================================================
 RCS file: /usr/local/ncvs/src/sys/pci/if_vr.c,v
 retrieving revision 1.104.2.6
 diff -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	5 May 2006 23:05:57 -0000
 @@ -169,6 +169,10 @@
  static int vr_list_rx_init(struct vr_softc *);
  static int vr_list_tx_init(struct vr_softc *);
  
 +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
  
  	/*
 -	 * 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 @@
  
  	sc->suspended = 0;
  
 +	/* Check Wake on Lan support. */
 +	if (sc->vr_revid >= REV_ID_VT6102 ) {
 +		sc->wol_support = 1;
 +		if (sc->vr_revid >= REV_ID_VT6105_B0)
 +			sc->wol_6patterns = 1;
 +	}
 +
  	/* Hook interrupt last to avoid having to lock softc */
  	error = 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 = VR_SUPPORTED_WOL_EVENTS;
 + 		error = 0;
 + 		break;
 + 	case SIOCGIFWOLOPTS:
 + 		VR_LOCK(sc);
 + 		vr_get_wolopts(sc, &ifr->ifr_wolopts);
 + 		VR_UNLOCK(sc);
 + 		error = 0;
 + 		break;
 + 	case SIOCSIFWOLOPTS:
 + 		VR_LOCK(sc);
 + 		error = vr_set_wolopts(sc, &ifr->ifr_wolopts);
 + 		VR_UNLOCK(sc);
 +  		break;
  	default:
  		error = ether_ioctl(ifp, command, data);
  		break;
 @@ -1702,6 +1728,92 @@
  static void
  vr_shutdown(device_t dev)
  {
 +	struct vr_softc *sc;
  
 +	sc = 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);
 +	
 +	/* Check whether wake on lan is available
 +	 * and whether events have been set. */
 +	if (!sc->wol_support || sc->wol_events == 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->wol_6patterns)
 +		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->wol_6patterns)
 +		CSR_WRITE_1(sc, VR_WOLCGCLR, 0x04);
 +	
 +	/* Set unicast wake event if applicable. */
 +	if (sc->wol_events & IFWOL_WAKE_ON_UNICAST)
 +		VR_SETBIT(sc, VR_WOLCRSET, VR_WAKE_UCAST);
 +	
 +	/* Set magic wake event if applicable. */
 +	if (sc->wol_events & 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->wol_events & IFWOL_WAKE_ON_BROADCAST ||
 +	    sc->wol_events & 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 = sc->wol_events;
 +}
 +	
 +/*
 + * 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 == IFWOL_DISABLE)
 +		sc->wol_events = 0;
 +	else {
 +		if ((wolopts->ifwol_events & ~VR_SUPPORTED_WOL_EVENTS) != 0)
 +			return EINVAL;
 +		sc->wol_events = wolopts->ifwol_events;
 +	}
 +
 +	return 0;
 +}
 +
 Index: sys/pci/if_vrreg.h
 ===================================================================
 RCS file: /usr/local/ncvs/src/sys/pci/if_vrreg.h,v
 retrieving revision 1.22.2.1
 diff -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	5 May 2006 23:05:58 -0000
 @@ -283,6 +283,21 @@
  #define VR_STICKHW_WOL_STS	0x08
  #define VR_STICKHW_LEGWOL_ENB	0x80
  
 +/* 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_MAGIC)
 +
  /*
   * BCR0 register bits. (At least for the VT6102 chip.)
   */
 @@ -471,6 +486,10 @@
  #ifdef DEVICE_POLLING
  	int			rxcycles;
  #endif
 +	int			wol_support;	/* Chip supports WOL. */
 +	uint32_t		wol_events;	/* Wake on Lan satus */
 +	int			wol_6patterns;	/* some chips have 6 patterns
 +						   for WOL instead of 4 */
  };
  
  #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
 +
  
  /*
   * PCI low memory base and low I/O base register, and
 Index: sys/sys/sockio.h
 ===================================================================
 RCS file: /usr/local/ncvs/src/sys/sys/sockio.h,v
 retrieving revision 1.28.2.1
 diff -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 */
  
 +#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_ */
 
 --AhhlLboLdkugWU4S--

From: Edwin Mons <freebsd@edwinm.ik.nu>
To: bug-followup@FreeBSD.org,  stsp@stsp.in-berlin.de
Cc:  
Subject: Re: kern/83807: [sis] [patch] if_sis: Wake On Lan support for FreeBSD
Date: Sat, 09 Jun 2007 11:08:01 +0200

 Will this feature ever be incorporated in mainstream FreeBSD?  I'm 
 eagerly waiting for it to land in -CURRENT...
  
 Kind regards,
 Edwin Mons
 

From: Stefan Sperling <stsp@stsp.name>
To: bug-followup@FreeBSD.org
Cc: Edwin Mons <freebsd@edwinm.ik.nu>, freebsd-hackers@FreeBSD.org
Subject: Re: kern/83807: [sis] [patch] if_sis: Wake On Lan support for
	FreeBSD
Date: Sat, 9 Jun 2007 12:38:48 +0200

 --NzB8fVQJ5HfG6fxh
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 Content-Transfer-Encoding: quoted-printable
 
 On Sat, Jun 09, 2007 at 11:08:01AM +0200, Edwin Mons wrote:
 >  Will this feature ever be incorporated in mainstream FreeBSD?  I'm eager=
 ly=20
 >  waiting for it to land in -CURRENT...
 
 I have no idea.
 
 I haven't got much feedback on this patch, apart from one
 or two people who sent me a quick thank you note :)
 
 So I have no idea how many people are actually using the patch.
 
 I know that:
 
 	* if_sis and if_vr wake on lan support is very stable for me.
 	  I've been using this code for nearly 2 years now.
 
 	* if_nve support has afaik never been tested (plus
 	  it's a binary blob driver and will apparently be
 	  replaced with OpenBSD's nfe driver soon.)
 
 I run a single 6.2 box here that I maintain the patch for.
 I'd be happy to setup a -current box to port the patch to -CURRENT.
 
 But I need to know whether it's worth doing the work.
 
 I'd like to get feedback on my patch by someone who is willing
 and able to help me get it into the tree. I need to know what needs
 to be done and/or changed to make the patch ready for mainline.
 
 There are some small bits in the patch that are incomplete,
 e.g. "secure on password" support. I've been thinking about simply
 dropping this feature because I consider it useless but ymmv.
 
 I'd also be happy to add WOL support for more chipsets.
 Adding support is relatively easy as long as another open source
 OS (e.g. Linux) supports wake on lan for a chipset and even easier
 if a good datasheet is available (as in case of if_sis).
 
 If anyone has a card that does wake on lan after shutdown from Linux
 but not after shutdown from FreeBSD with my patch applied let me know.
 You may need to use the ethtool utility to enable WOL on Linux.
 
 Cc'ing hackers@ in case someone there is interested in helping out.
 
 >  Kind regards,
 >  Edwin Mons
 
 --=20
 stefan
 http://stsp.name                                         PGP Key: 0xF59D25F0
 
 --NzB8fVQJ5HfG6fxh
 Content-Type: application/pgp-signature
 Content-Disposition: inline
 
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.7 (FreeBSD)
 
 iD8DBQFGaoM45dMCc/WdJfARAkCVAJ4sGsoZllkxTMLZCcdrnllYrmVE5ACfbRhm
 e0VRmi3y+uMcksCsP6QX9IQ=
 =j6TM
 -----END PGP SIGNATURE-----
 
 --NzB8fVQJ5HfG6fxh--

From: Edwin Mons <freebsd@edwinm.ik.nu>
To: bug-followup@FreeBSD.org, Edwin Mons <freebsd@edwinm.ik.nu>, 
 freebsd-hackers@freebsd.org
Cc:  
Subject: Re: kern/83807: [sis] [patch] if_sis: Wake On Lan support for	FreeBSD
Date: Sat, 09 Jun 2007 17:07:39 +0200

 Stefan Sperling wrote:
 > On Sat, Jun 09, 2007 at 11:08:01AM +0200, Edwin Mons wrote:
 >   
 >>  Will this feature ever be incorporated in mainstream FreeBSD?  I'm eagerly 
 >>  waiting for it to land in -CURRENT...
 >>     
 >
 > I have no idea.
 >
 > I haven't got much feedback on this patch, apart from one
 > or two people who sent me a quick thank you note :)
 >
 > So I have no idea how many people are actually using the patch.
 >
 > I know that:
 >
 > 	* if_sis and if_vr wake on lan support is very stable for me.
 > 	  I've been using this code for nearly 2 years now.
 >
 > 	* if_nve support has afaik never been tested (plus
 > 	  it's a binary blob driver and will apparently be
 > 	  replaced with OpenBSD's nfe driver soon.)
 >
 > I run a single 6.2 box here that I maintain the patch for.
 > I'd be happy to setup a -current box to port the patch to -CURRENT.
 >   
 
 I currently have one -CURRENT machine, and several 6.2-STABLE machines.  
 For at least two of them (the -CURRENT and an x86 -STABLE machine) I'd 
 really like to have WoL support, as these are my workstation and a home 
 server, both of them really do not need to be on all the time, but I 
 want to be able to reach them when I need a file from them when I'm 
 elsewhere.
 > I'd also be happy to add WOL support for more chipsets.
 > Adding support is relatively easy as long as another open source
 > OS (e.g. Linux) supports wake on lan for a chipset and even easier
 > if a good datasheet is available (as in case of if_sis).
 >   
 
 I usually use either if_em or if_xl chipsets, so I hoped landing this 
 code in at least -CURRENT (should go there first, I guess) would result 
 in more chipsets supported ;)
 
 > If anyone has a card that does wake on lan after shutdown from Linux
 > but not after shutdown from FreeBSD with my patch applied let me know.
 > You may need to use the ethtool utility to enable WOL on Linux.
 >   
 
 I don't run Linux on either machine.  Perhaps I could do some tests on 
 my workstation with a CD-based linux distribution.
 
 Edwin
 

From: Stefan Sperling <stsp@stsp.name>
To: Edwin Mons <freebsd@edwinm.ik.nu>, bug-followup@FreeBSD.org,
        freebsd-hackers@FreeBSD.org
Cc:  
Subject: Re: kern/83807: [sis] [patch] if_sis: Wake On Lan support for
	FreeBSD
Date: Sun, 10 Jun 2007 16:45:04 +0200

 --dDRMvlgZJXvWKvBx
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 Content-Transfer-Encoding: quoted-printable
 
 On Sat, Jun 09, 2007 at 05:07:39PM +0200, Edwin Mons wrote:
 >  I currently have one -CURRENT machine, and several 6.2-STABLE machines. =
  For=20
 >  at least two of them (the -CURRENT and an x86 -STABLE machine) I'd reall=
 y=20
 >  like to have WoL support, as these are my workstation and a home server,=
 =20
 >  both of them really do not need to be on all the time, but I want to be =
 able=20
 >  to reach them when I need a file from them when I'm elsewhere.
 
 Yes, wake on lan, if used properly, makes computers a bit more
 friendly to the environment :-)
 
 >  I usually use either if_em or if_xl chipsets, so I hoped landing this co=
 de=20
 >  in at least -CURRENT (should go there first, I guess) would result in mo=
 re=20
 >  chipsets supported ;)
 
 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.
 
 So I don't think adding support for these cards is a problem.
 Just need to find some time to do it...
 
 If anyone has data sheets for these cards I'd like a copy if possible.
 
 By the way if anyone has data sheets for if_vr I'd like a copy as
 well please because there is something the Linux driver does that
 I do not understand because the code is not obvious enough.
 Specifically I need to understand what the hell they mean exactly
 by "patterns for WOL".
 
 > > If anyone has a card that does wake on lan after shutdown from Linux
 > > but not after shutdown from FreeBSD with my patch applied let me know.
 > > You may need to use the ethtool utility to enable WOL on Linux.
 >=20
 >  I don't run Linux on either machine.  Perhaps I could do some tests on m=
 y=20
 >  workstation with a CD-based linux distribution.
 
 No need to test your cards with Linux since we know now there is code
 for this in Linux so it should work anyway.
 
 --=20
 stefan
 http://stsp.name                                         PGP Key: 0xF59D25F0
 
 --dDRMvlgZJXvWKvBx
 Content-Type: application/pgp-signature
 Content-Disposition: inline
 
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.7 (FreeBSD)
 
 iD8DBQFGbA5w5dMCc/WdJfARAsfRAKCAN99RWTQfOU94AG7q8DYcOkt40wCgxZmR
 gYO8dLu+kqvBDI3IQCpGg6E=
 =hPO/
 -----END PGP SIGNATURE-----
 
 --dDRMvlgZJXvWKvBx--

From: Stefan Sperling <stsp@stsp.name>
To: Edwin Mons <freebsd@edwinm.ik.nu>, bug-followup@FreeBSD.org,
        freebsd-hackers@FreeBSD.org
Cc:  
Subject: Re: kern/83807: [sis] [patch] if_sis: Wake On Lan support for
	FreeBSD
Date: Thu, 14 Jun 2007 01:21:03 +0200

 --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--

From: Stefan Sperling <stsp@stsp.name>
To: bug-followup@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--
Responsible-Changed-From-To: freebsd-bugs->kmacy 
Responsible-Changed-By: kmacy 
Responsible-Changed-When: Sun Nov 18 08:27:46 UTC 2007 
Responsible-Changed-Why:  

I don't have sis, so I'll have to pass that off to someone else, but WOL support is  
worth incorporating into FreeBSD. Don't give up yet Stefan :-). 

http://www.freebsd.org/cgi/query-pr.cgi?pr=83807 

From: Dan Lukes <dan@obluda.cz>
To: stst@stsp.name, stsp@stsp.in-berlin.de
Cc: bug-followup@FreeBSD.org
Subject: kern/83807: [sis] [patch] if_sis: Wake On Lan support for FreeBSD
Date: Thu, 31 Jan 2008 00:07:04 +0100

 This is a multi-part message in MIME format.
 --------------070807070101070604020706
 Content-Type: text/plain; charset=ISO-8859-2; format=flowed
 Content-Transfer-Encoding: 7bit
 
    	Possible WOL patch for if_re (based on 6.3-R) is attached.
 
 	I have no data sheet for Realtek NIC, so the algorithm is stolen from 
 Linux driver with some small modifications. I write new state to EEPROM 
 only when necessary (to save limited number of write cycles). I read the 
 actual mode from card on startup with no modification of it (Linux 
 driver sets NIC to compiled in default state on startup despite of NIC's 
 saved configuration).
 
 	Unfortunately, I can't test it fully. It didn't work form me. I wish 
 the true reason is that the rest of system doesn't know the driver will 
 WOL, so it remove power from the NIC when system ho to power-off state.
 
 	As I'm not familiar with power management handling in FreeBSD I have no 
 idea how to tell "you must not remove power from me nor from parents 
 devices" to the system. The system devices has the ACPI method called on 
 power state change which may claim that device's minimal power 
 requirements for it's current specific configuration, but I don't know 
 how to do it on OS driver level.
 
 	May be a system BIOS configuration may be workaround that can fix OS 
 support deficiency, but I didn't found a configuration that worked for 
 my MB. It may be related to specific BIOS version so it may work for 
 someone other.
 
 					Dan
 
 
 --------------070807070101070604020706
 Content-Type: text/plain;
  name="patch-re"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: inline;
  filename="patch-re"
 
 --- sys/pci/if_rlreg.h.ORIG	2008-01-06 15:13:57.000000000 +0100
 +++ sys/pci/if_rlreg.h	2008-01-06 20:57:24.000000000 +0100
 @@ -76,7 +76,11 @@
  #define RL_EECMD	0x0050		/* EEPROM command register */
  #define RL_CFG0		0x0051		/* config register #0 */
  #define RL_CFG1		0x0052		/* config register #1 */
 -                                        /* 0053-0057 reserved */   
 +#define RL_CFG2		0x0053		/* config register #2 */
 +#define RL_CFG3		0x0054		/* config register #3 */
 +#define RL_CFG4		0x0055		/* config register #4 */
 +#define RL_CFG5		0x0056		/* config register #5 */
 +                                        /* 0057 reserved */   
  #define RL_MEDIASTAT	0x0058		/* media status register (8139) */
  					/* 0059-005A reserved */
  #define RL_MII		0x005A		/* 8129 chip only */
 @@ -357,7 +361,7 @@
  /*
   * Config 1 register
   */
 -#define RL_CFG1_PWRDWN		0x01
 +#define RL_CFG1_PWRDWN		0x01	/* Power Management Enable */
  #define RL_CFG1_SLEEP		0x02
  #define RL_CFG1_IOMAP		0x04
  #define RL_CFG1_MEMMAP		0x08
 @@ -368,6 +372,22 @@
  #define RL_CFG1_LED1		0x80
  
  /*
 + * Config 3 register
 + */
 +#define RL_CFG3_WAKE_ON_MAGIC	0x20	/* Wake up when receives a Magic Packet */
 +#define RL_CFG3_WAKE_ON_LINK	0x10	/* Wake up when the cable connection is re-established */
 +
 +/*
 + * Config 5 register
 + */
 +#define RL_CFG5_WAKE_BCAST	0x40	/* Accept Broadcast wakeup frame */
 +#define RL_CFG5_WAKE_MCAST	0x20	/* Accept Multicast wakeup frame */
 +#define RL_CFG5_WAKE_UCAST	0x10	/* Accept Unicast wakeup frame */
 +#define RL_CFG5_WAKE_ANY	0x02	/* LanWake enable/disable */
 +#define RL_CFG5_PMESTATUS	0x01	/* PME status can be reset by PCI RST# */
 +
 +
 +/*
   * 8139C+ register definitions
   */
  
 @@ -741,6 +761,8 @@
  	struct mtx		rl_intlock;
  	int			rl_txstart;
  	int			rl_link;
 +	int			rl_wolsupport;  /* Chip supports WOL. */
 +	u_int32_t		rl_wolevents;   /* Wake on Lan status */
  };
  
  #define	RL_LOCK(_sc)		mtx_lock(&(_sc)->rl_mtx)
 @@ -989,3 +1011,5 @@
  #define RL_PSTATE_D3		0x0003
  #define RL_PME_EN		0x0010
  #define RL_PME_STATUS		0x8000
 +
 +#define ISSET(t, f)      ((t) & (f))
 --- sys/dev/re/if_re.c.orig	2008-01-24 10:14:48.000000000 +0100
 +++ sys/dev/re/if_re.c	2008-01-30 23:52:52.000000000 +0100
 @@ -162,6 +162,8 @@
  
  #define RE_CSUM_FEATURES    (CSUM_IP | CSUM_TCP | CSUM_UDP)
  
 +#define RE_SUPPORTED_WOL_EVENTS (IFWOL_WAKE_ON_UNICAST | IFWOL_WAKE_ON_MULTICAST | IFWOL_WAKE_ON_BROADCAST | IFWOL_WAKE_ON_MAGIC | IFWOL_WAKE_ON_LINK)
 +
  /*
   * Various supported device vendors/types and their names.
   */
 @@ -278,6 +280,10 @@
  static int re_diag		(struct rl_softc *);
  #endif
  
 +static int re_set_wolopts(struct rl_softc *, struct if_wolopts *);
 +static void re_get_wolopts(struct rl_softc *, struct if_wolopts *);
 +static void re_enable_wol(struct rl_softc *);
 +
  #ifdef RE_USEIOSPACE
  #define RL_RES			SYS_RES_IOPORT
  #define RL_RID			RL_PCI_LOIO
 @@ -2474,6 +2480,25 @@
  
  	CSR_WRITE_1(sc, RL_CFG1, CSR_READ_1(sc, RL_CFG1) | RL_CFG1_DRVLOAD);
  
 +	/* Read initial WOL settings */
 +	sc->rl_wolevents = 0;
 +	if (ISSET(CSR_READ_1(sc, RL_CFG1), RL_CFG1_PWRDWN)) {
 +		u_int32_t cfg;
 +		
 +		cfg = CSR_READ_1(sc, RL_CFG3);
 +		if (ISSET(cfg, RL_CFG3_WAKE_ON_LINK))
 +			sc->rl_wolevents |= IFWOL_WAKE_ON_LINK;
 +		if (ISSET(cfg, RL_CFG3_WAKE_ON_MAGIC))
 +			sc->rl_wolevents |= IFWOL_WAKE_ON_MAGIC;
 +		cfg = CSR_READ_1(sc, RL_CFG5);
 +		if (ISSET(cfg, RL_CFG5_WAKE_UCAST))
 +			sc->rl_wolevents |= IFWOL_WAKE_ON_UNICAST;
 +		if (ISSET(cfg, RL_CFG5_WAKE_MCAST))
 +			sc->rl_wolevents |= IFWOL_WAKE_ON_MULTICAST;
 +		if (ISSET(cfg, RL_CFG5_WAKE_BCAST))
 +			sc->rl_wolevents |= IFWOL_WAKE_ON_BROADCAST;
 +	}
 +
  	ifp->if_drv_flags |= IFF_DRV_RUNNING;
  	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
  
 @@ -2614,6 +2639,21 @@
  #endif
  	    }
  		break;
 + 	case SIOCGIFWOLSUPP:
 + 		ifr->ifr_wolopts.ifwol_supported = RE_SUPPORTED_WOL_EVENTS;
 + 		error = 0;
 + 		break;
 + 	case SIOCGIFWOLOPTS:
 + 		RL_LOCK(sc);
 + 		re_get_wolopts(sc, &ifr->ifr_wolopts);
 + 		RL_UNLOCK(sc);
 + 		error = 0;
 + 		break;
 + 	case SIOCSIFWOLOPTS:
 + 		RL_LOCK(sc);
 + 		error = re_set_wolopts(sc, &ifr->ifr_wolopts);
 + 		RL_UNLOCK(sc);
 +  		break;
  	default:
  		error = ether_ioctl(ifp, command, data);
  		break;
 @@ -2706,6 +2746,7 @@
  
  	RL_LOCK(sc);
  	re_stop(sc);
 +	re_enable_wol(sc);
  	sc->suspended = 1;
  	RL_UNLOCK(sc);
  
 @@ -2760,5 +2801,87 @@
  	 * cases.
  	 */
  	sc->rl_ifp->if_flags &= ~IFF_UP;
 +	re_enable_wol(sc);
  	RL_UNLOCK(sc);
  }
 +
 +static void
 +re_enable_wol(struct rl_softc *sc)
 +{
 +	u_int32_t ocfg1, ocfg3, ocfg5, cfg1, cfg3, cfg5;
 +
 +	RL_LOCK_ASSERT(sc);
 +	
 +	/* Check whether wake on lan is available
 +	 * and whether events have been set. */
 +	if (!sc->rl_wolsupport)
 +		return;
 +
 +	ocfg1 = cfg1 = CSR_READ_1(sc, RL_CFG1);
 +	ocfg3 = cfg3 = CSR_READ_1(sc, RL_CFG3);
 +	ocfg5 = cfg5 = CSR_READ_1(sc, RL_CFG5);
 +
 +	cfg1 &= (RL_CFG1_PWRDWN);
 +	cfg3 &= (RL_CFG3_WAKE_ON_LINK | RL_CFG3_WAKE_ON_MAGIC);
 +	cfg5 &= (RL_CFG5_WAKE_UCAST | RL_CFG5_WAKE_MCAST 
 +		| RL_CFG5_WAKE_BCAST | RL_CFG5_WAKE_ANY);
 +
 +	if (sc->rl_wolevents != 0) {
 +		if (ISSET(sc->rl_wolevents, IFWOL_WAKE_ON_UNICAST))
 +			cfg5 |= RL_CFG5_WAKE_UCAST;
 +		if (ISSET(sc->rl_wolevents, IFWOL_WAKE_ON_MULTICAST))
 +			cfg5 |= RL_CFG5_WAKE_BCAST;
 +		if (ISSET(sc->rl_wolevents, IFWOL_WAKE_ON_BROADCAST))
 +			cfg5 |= RL_CFG5_WAKE_BCAST;
 +		cfg5 |= RL_CFG5_WAKE_ANY;
 +		if (ISSET(sc->rl_wolevents, IFWOL_WAKE_ON_MAGIC))
 +			cfg3 |= RL_CFG3_WAKE_ON_MAGIC;
 +		if (ISSET(sc->rl_wolevents, IFWOL_WAKE_ON_LINK))
 +			cfg3 |= RL_CFG3_WAKE_ON_LINK;
 +		cfg1 |= RL_CFG1_PWRDWN;
 +	};
 +			
 +	/* Don't write to EEPROM unless necesary */
 +	if (ocfg3 != cfg3 || ocfg5 != cfg5 || ocfg1 != cfg1) {
 +		CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_WRITECFG);
 +		if (ocfg3 != cfg3)
 +			CSR_WRITE_1(sc, RL_CFG3, cfg3);
 +		if (ocfg5 != cfg5)
 +			CSR_WRITE_1(sc, RL_CFG5, cfg5);
 +		if (ocfg1 != cfg1)
 +			CSR_WRITE_1(sc, RL_CFG1, cfg1);
 +		CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_OFF);
 +	}
 +}
 +
 +/*
 + * Write current wake on lan settings into an if_wolopts structure.
 + */
 +static void
 +re_get_wolopts(struct rl_softc *sc, struct if_wolopts *wolopts)
 +{
 +	RL_LOCK_ASSERT(sc);
 +
 +	wolopts->ifwol_events = sc->rl_wolevents;
 +	return;
 +}
 +	
 +/*
 + * Set wake on lan options.
 + */
 +static int
 +re_set_wolopts(struct rl_softc *sc, struct if_wolopts *wolopts)
 +{
 +	RL_LOCK_ASSERT(sc);
 +
 +	if (wolopts->ifwol_events == IFWOL_DISABLE)
 +		sc->rl_wolevents = 0;
 +	else {
 +		if ((wolopts->ifwol_events & ~RE_SUPPORTED_WOL_EVENTS) != 0)
 +			return EINVAL;
 +		sc->rl_wolevents = wolopts->ifwol_events;
 +	}
 +
 +	return 0;
 +}
 +
 
 
 --------------070807070101070604020706--

From: Stefan Sperling <stsp@stsp.name>
To: Dan Lukes <dan@obluda.cz>
Cc: bug-followup@FreeBSD.org, sam@errno.com
Subject: Re: kern/83807: [sis] [patch] if_sis: Wake On Lan support for
	FreeBSD
Date: Thu, 31 Jan 2008 12:58:33 +0100

 --huq684BweRXVnRxX
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 Content-Transfer-Encoding: quoted-printable
 
 On Thu, Jan 31, 2008 at 12:07:04AM +0100, Dan Lukes wrote:
 >   	Possible WOL patch for if_re (based on 6.3-R) is attached.
 
 =20
 > @@ -2614,6 +2639,21 @@
 >  #endif
 >  	    }
 >  		break;
 > + 	case SIOCGIFWOLSUPP:
 > + 		ifr->ifr_wolopts.ifwol_supported =3D RE_SUPPORTED_WOL_EVENTS;
 > + 		error =3D 0;
 > + 		break;
 > + 	case SIOCGIFWOLOPTS:
 > + 		RL_LOCK(sc);
 > + 		re_get_wolopts(sc, &ifr->ifr_wolopts);
 > + 		RL_UNLOCK(sc);
 > + 		error =3D 0;
 > + 		break;
 > + 	case SIOCSIFWOLOPTS:
 > + 		RL_LOCK(sc);
 > + 		error =3D re_set_wolopts(sc, &ifr->ifr_wolopts);
 > + 		RL_UNLOCK(sc);
 > +  		break;
 >  	default:
 >  		error =3D ether_ioctl(ifp, command, data);
 >  		break;
 
 Note that the ioctl-based configuration has been made obsolete by
 a commit Sam Leffler made to -CURRENT, see r1.135 of ifconfig.c:
 http://www.freebsd.org/cgi/cvsweb.cgi/src/sbin/ifconfig/ifconfig.c
 (He attributed the patch that was comitted to me, but I didn't actually
 write it.)
 
 Drivers should use ifcaps now instead of ioctls. This reduces
 WOL-related code size tremendously in both ifconfig and drivers.
 You should rebase your changes on -CURRENT code and send the patch
 to Sam Leffler and a copy of it to this PR.
 
 See http://people.freebsd.org/~yongari/vr/if_vr.c for an example
 of a driver that does WOL configuration via ifcaps.
 
 --=20
 stefan
 http://stsp.name                                         PGP Key: 0xF59D25F0
 
 --huq684BweRXVnRxX
 Content-Type: application/pgp-signature
 Content-Disposition: inline
 
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.7 (OpenBSD)
 
 iD8DBQFHobfp5dMCc/WdJfARApPuAKCzPhrJMsCmDuEwQ3X3JgzelrfzCwCfdPqr
 ZBFrd8Yy34Q5fzuMKHNwSKU=
 =FBC2
 -----END PGP SIGNATURE-----
 
 --huq684BweRXVnRxX--
Responsible-Changed-From-To: kmacy->brucec  
Responsible-Changed-By: brucec 
Responsible-Changed-When: Fri Mar 5 20:43:58 UTC 2010 
Responsible-Changed-Why:  
Take. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=83807 
State-Changed-From-To: open->patched 
State-Changed-By: yongari 
State-Changed-When: Fri Sep 3 23:44:38 UTC 2010 
State-Changed-Why:  
WOL support was implemented in HEAD(r212167). 
Will MFC after a couple of weeks. 
Thanks! 


Responsible-Changed-From-To: brucec->yongari 
Responsible-Changed-By: yongari 
Responsible-Changed-When: Fri Sep 3 23:44:38 UTC 2010 
Responsible-Changed-Why:  
Track, I implemented WOL feature. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=83807 
State-Changed-From-To: patched->closed 
State-Changed-By: yongari 
State-Changed-When: Mon Oct 11 20:04:26 UTC 2010 
State-Changed-Why:  
Close, MFC WOL changes to both stable/8 stable/7 done. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=83807 
>Unformatted:
