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_ */
