diff -urN ../sys/alpha/conf/ALTQ ./alpha/conf/ALTQ
--- ../sys/alpha/conf/ALTQ	Thu Jan  1 09:00:00 1970
+++ ./alpha/conf/ALTQ	Tue Oct  2 22:21:10 2001
@@ -0,0 +1,211 @@
+#
+# GENERIC -- Generic kernel configuration file for FreeBSD/alpha
+#
+# For more information on this file, please read the handbook section on
+# Kernel Configuration Files:
+#
+#    http://www.FreeBSD.org/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../i386/conf/LINT configuration file. 
+# If you are in doubt as to the purpose or necessity of a line, check first 
+# in LINT. Please note that this is the i386 LINT, but it still contains
+# valuable info for alpha too
+#
+# For hardware specific information check HARDWARE.TXT
+#
+# $FreeBSD: src/sys/alpha/conf/GENERIC,v 1.71.2.15 2001/07/30 17:31:41 wpaul Exp $
+
+machine		alpha
+cpu		EV4
+cpu		EV5
+ident		ALTQ
+maxusers	32
+
+#makeoptions	DEBUG=-g		#Build kernel with gdb(1) debug symbols
+
+# Platforms supported
+options		API_UP1000		# UP1000 (Nautilus)
+options 	DEC_AXPPCI_33		# UDB, Multia, AXPpci33, Noname
+options 	DEC_EB164		# EB164, PC164, PC164LX, PC164SX
+options 	DEC_EB64PLUS		# EB64+, Aspen Alpine, etc
+options 	DEC_2100_A50		# AlphaStation 200, 250, 255, 400
+options 	DEC_2100_A500		# AlphaServer 2000, 2100, 2100A
+options 	DEC_KN20AA		# AlphaStation 500, 600
+options 	DEC_ST550		# Personal Workstation 433, 500, 600
+options 	DEC_ST6600		# xp1000, dp264, ds20, ds10, family
+options 	DEC_3000_300		# DEC3000/300* Pelic* family
+options 	DEC_3000_500		# DEC3000/[4-9]00 Flamingo/Sandpiper family
+options 	DEC_1000A		# AlphaServer 1000, 1000A, 800
+options 	DEC_KN8AE		# AlphaServer 8200/8400 (Turbolaser)
+options 	DEC_KN300		# AlphaServer 4100 (Rawhide), 1200 (Tincup)
+
+options 	INET			#InterNETworking
+options 	INET6			#IPv6 communications protocols
+options 	FFS			#Berkeley Fast Filesystem
+options 	FFS_ROOT		#FFS usable as root device [keep this!]
+options 	SOFTUPDATES		#Enable FFS soft updates support
+options 	MFS			#Memory Filesystem
+options 	MD_ROOT			#MD is a potential root device
+options 	NFS			#Network Filesystem
+options 	NFS_ROOT		#NFS usable as root device
+options 	MSDOSFS			#MSDOS Filesystem
+options 	CD9660			#ISO 9660 Filesystem
+options 	CD9660_ROOT		#CD-ROM usable as root device
+options 	PROCFS			#Process filesystem
+options 	COMPAT_43		#Compatible with BSD 4.3 [KEEP THIS!]
+options 	SCSI_DELAY=15000	#Delay (in ms) before probing SCSI 
+options 	UCONSOLE		#Allow users to grab the console
+options 	KTRACE			#ktrace(1) syscall trace support
+options 	SYSVSHM			#SYSV-style shared memory
+options 	SYSVMSG			#SYSV-style message queues
+options 	SYSVSEM			#SYSV-style semaphores
+options		P1003_1B		#Posix P1003_1B real-time extentions
+options 	_KPOSIX_PRIORITY_SCHEDULING
+options		ICMP_BANDLIM		#Rate limit bad replies
+
+# Standard busses
+device		isa
+device		pci
+
+# Floppy drives
+device		fdc0	at isa? port IO_FD1 irq 6 drq 2
+device		fd0	at fdc0 drive 0
+
+# ATA and ATAPI devices
+device		ata
+device		atadisk		# ATA disk drives
+device		atapicd		# ATAPI CDROM drives
+device		atapifd		# ATAPI floppy drives
+device		atapist		# ATAPI tape drives
+
+# SCSI Controllers
+device		ahc		# AHA2940 and onboard AIC7xxx devices
+#device		esp		# 53C94 & friends, not CAM-ified
+device		isp		# Qlogic family
+device		ncr		# NCR/Symbios Logic
+device		sym		# NCR/Symbios Logic (newer chipsets)
+
+# SCSI peripherals
+device		scbus		# SCSI bus (required)
+device		da		# Direct Access (disks)
+device		sa		# Sequential Access (tape etc)
+device		cd		# CD
+device		pass		# Passthrough device (direct SCSI access)
+
+# RAID controllers
+device		amr		# AMI MegaRAID
+device		mlx		# Mylex DAC960 family
+
+# atkbdc0 controls both the keyboard and the PS/2 mouse
+device		atkbdc0	at isa? port IO_KBD
+device		atkbd0	at atkbdc? irq 1
+device		psm0	at atkbdc? irq 12
+
+device		vga0	at isa?
+
+# splash screen/screen saver
+pseudo-device	splash
+
+# syscons is the default console driver, resembling an SCO console
+device		sc0	at isa?
+
+# real time clock
+device		mcclock0 at isa? port 0x70
+
+# Serial (COM) ports
+device		sio0	at isa? port IO_COM1 irq 4
+device		sio1	at isa? port IO_COM2 irq 3 flags 0x50
+
+# Parallel port
+device          ppc0    at isa? irq 7
+device          ppbus           # Parallel port bus (required)
+device          lpt             # Printer
+device          plip            # TCP/IP over parallel
+device          ppi             # Parallel port interface device
+#device         vpo             # Requires scbus and da
+ 
+# PCI Ethernet NICs.
+device		de		# DEC/Intel DC21x4x (``Tulip'')
+device		txp		# 3Com 3cR990 (``Typhoon'')
+device		le		# Lance
+
+# PCI Ethernet NICs that use the common MII bus controller code.
+device		miibus		# MII bus support
+device		dc		# DEC/Intel 21143 and workalikes
+device		fxp		# Intel EtherExpress PRO/100B (82557, 82558)
+device		pcn		# AMD Am79C97x PCI 10/100 NICs
+device		rl		# RealTek 8129/8139
+device		sf		# Adaptec AIC-6915 (``Starfire'')
+device		sis		# Silicon Integrated Systems SiS 900/SiS 7016
+device		ste		# Sundance ST201 (D-Link DFE-550TX)
+device		tl		# Texas Instruments ThunderLAN
+device		vr		# VIA Rhine, Rhine II
+device		wb		# Winbond W89C840F
+device		wx		# Intel Gigabit Ethernet Card (``Wiseman'')
+device		xl		# 3Com 3c90x (``Boomerang'', ``Cyclone'')
+
+# Pseudo devices - the number indicates how many units to allocated.
+pseudo-device	loop		# Network loopback
+pseudo-device	ether		# Ethernet support
+pseudo-device	sl	1	# Kernel SLIP
+pseudo-device	ppp	1	# Kernel PPP
+pseudo-device	tun		# Packet tunnel.
+pseudo-device	pty		# Pseudo-ttys (telnet etc)
+pseudo-device	md		# Memory "disks"
+pseudo-device	gif		# IPv6 and IPv4 tunneling
+pseudo-device	faith	1	# IPv6-to-IPv4 relaying/(translation)
+
+# The `bpf' pseudo-device enables the Berkeley Packet Filter.
+# Be aware of the administrative consequences of enabling this!
+pseudo-device	bpf		#Berkeley packet filter
+
+# USB support
+# (if you add any USB devices to this list, they must be added to the Alpha
+#  section of src/release/scripts/dokern.sh)
+device		uhci		# UHCI PCI->USB interface
+device		ohci		# OHCI PCI->USB interface
+device		usb		# USB Bus (required)
+device		ugen		# Generic
+device		uhid		# "Human Interface Devices"
+device		ukbd		# Keyboard
+device		ulpt		# Printer
+device		umass		# Disks/Mass storage - Requires scbus and da0
+device		ums		# Mouse
+# USB Ethernet
+device		aue		# ADMtek USB ethernet
+device		cue		# CATC USB ethernet
+device		kue		# Kawasaki LSI USB ethernet
+
+# ALTQ options
+options 	ALTQ		#alternate queueing
+#options 	ALTQ_CBQ	#class based queueing
+#options 	ALTQ_WFQ	#weighted fair queueing
+#options 	ALTQ_FIFOQ	#fifo queueing
+#options 	ALTQ_RED	#random early detection
+#options 	ALTQ_FLOWVALVE	#flowvalve for RED (needs RED)
+#options 	ALTQ_RIO	#triple	 red for diffserv (needs RED)
+#options 	ALTQ_LOCALQ	#local use
+#options 	ALTQ_HFSC	#hierarchical fair service curve
+#options 	ALTQ_ECN	#ecn extention to tcp (needs RED)
+#options 	ALTQ_IPSEC	#check ipsec in IPv4
+#options 	ALTQ_CDNR	#diffserv traffic conditioner
+#options 	ALTQ_BLUE	#blue by wu-chang feng
+#options 	ALTQ_PRIQ	#priority queue
+#options 	ALTQ_NOPCC	#don't use processor cycle counter
+#options 	ALTQ_DEBUG	#for debugging
+# you might want to set kernel timer to 1kHz if you use CBQ,
+# especially with 100baseT
+#options 	HZ=1000
+
+# options added for ALTQ
+options		NMBCLUSTERS=2048
+options		MROUTING		# Multicast routing
+pseudo-device	atm
+device		en
+#options	NATM			#native mode atm
diff -urN ../sys/conf/files ./conf/files
--- ../sys/conf/files	Sat Aug 11 09:54:14 2001
+++ ./conf/files	Tue Oct  2 22:06:19 2001
@@ -40,6 +40,20 @@
 	compile-with	"perl5 $S/kern/makeops.pl -h $S/kern/bus_if.m"	\
 	no-obj no-implicit-rule before-depend				\
 	clean		"bus_if.h"
+altq/altq_afmap.c	optional altq
+altq/altq_blue.c	optional altq
+altq/altq_cbq.c		optional altq
+altq/altq_cdnr.c	optional altq
+altq/altq_conf.c	optional altq
+altq/altq_fifoq.c	optional altq
+altq/altq_hfsc.c	optional altq
+altq/altq_localq.c	optional altq
+altq/altq_priq.c	optional altq
+altq/altq_red.c		optional altq
+altq/altq_rio.c		optional altq
+altq/altq_rmclass.c	optional altq
+altq/altq_subr.c	optional altq
+altq/altq_wfq.c		optional altq
 coda/coda_namecache.c	optional vcoda
 coda/coda_fbsd.c	optional vcoda
 coda/coda_psdev.c	optional vcoda
diff -urN ../sys/conf/options ./conf/options
--- ../sys/conf/options	Fri Aug  3 09:47:27 2001
+++ ./conf/options	Tue Oct  2 22:06:19 2001
@@ -225,6 +225,25 @@
 MAXSSIZ			opt_rlimit.h
 
 # Net stuff.
+# altq stuff
+ALTQ			opt_global.h
+ALTQ_ECN		opt_global.h
+ALTQ_CBQ		opt_altq.h
+ALTQ_WFQ		opt_altq.h
+ALTQ_AFMAP		opt_altq.h
+ALTQ_FIFOQ		opt_altq.h
+ALTQ_RED		opt_altq.h
+ALTQ_FLOWVALVE		opt_altq.h
+ALTQ_RIO		opt_altq.h
+ALTQ_IPSEC		opt_altq.h
+ALTQ_LOCALQ		opt_altq.h
+ALTQ_HFSC		opt_altq.h
+ALTQ_CDNR		opt_altq.h
+ALTQ_BLUE		opt_altq.h
+ALTQ_PRIQ		opt_altq.h
+ALTQ_NOPCC		opt_altq.h
+ALTQ_DEBUG		opt_altq.h
+ 
 ACCEPT_FILTER_DATA
 ACCEPT_FILTER_HTTP
 BOOTP			opt_bootp.h
diff -urN ../sys/dev/ed/if_ed.c ./dev/ed/if_ed.c
--- ../sys/dev/ed/if_ed.c	Thu Jul 26 03:06:00 2001
+++ ./dev/ed/if_ed.c	Tue Oct  2 22:06:19 2001
@@ -1604,9 +1604,10 @@
 		ifp->if_ioctl = ed_ioctl;
 		ifp->if_watchdog = ed_watchdog;
 		ifp->if_init = ed_init;
-		ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
+		IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
 		ifp->if_linkmib = &sc->mibdata;
 		ifp->if_linkmiblen = sizeof sc->mibdata;
+		IFQ_SET_READY(&ifp->if_snd);
 		/*
 		 * XXX - should do a better job.
 		 */
@@ -2009,7 +2010,7 @@
 		ifp->if_flags |= IFF_OACTIVE;
 		return;
 	}
-	IF_DEQUEUE(&ifp->if_snd, m);
+	IFQ_DEQUEUE(&ifp->if_snd, m);
 	if (m == 0) {
 
 		/*
diff -urN ../sys/dev/en/midway.c ./dev/en/midway.c
--- ../sys/dev/en/midway.c	Sat Jan 29 23:38:04 2000
+++ ./dev/en/midway.c	Tue Oct  2 22:06:19 2001
@@ -48,6 +48,26 @@
  *   I would also like to thank Werner for promptly answering email and being
  *   generally helpful.
  */
+/*
+ *  1997/12/02, major update on 1999/04/06 kjc
+ *    new features added:
+ *	- BPF support (link type is DLT_ATM_RFC1483)
+ *	  BPF understands only LLC/SNAP!! (because bpf can't
+ *	  handle variable link header length.)
+ *	  (bpfwrite should work if atm_pseudohdr and LLC/SNAP are prepended.)
+ *	- support vc shaping
+ *	- integrate IPv6 support.
+ *	- support pvc sub interface
+ *
+ *	  initial work on per-pvc-interface for ipv6 was done
+ *	  by Katsushi Kobayashi <ikob@cc.uec.ac.jp> of the WIDE Project.
+ * 	  some of the extensions for pvc subinterfaces are merged from
+ *	  the CAIRN project written by Suresh Bhogavilli (suresh@isi.edu).
+ *
+ *    code cleanup:
+ *	- remove WMAYBE related code.  ENI WMAYBE DMA doen't work.
+ *	- remove updating if_lastchange for every packet.
+ */
 
 #undef	EN_DEBUG
 #undef	EN_DEBUG_RANGE		/* check ranges on en_read/en_write's? */
@@ -108,7 +128,6 @@
 #endif /* EN_DEBUG */
 
 #ifdef __FreeBSD__
-#include "en.h"			/* XXX for midwayvar.h's NEN */
 #include "opt_inet.h"
 #include "opt_natm.h"
 #include "opt_ddb.h"
@@ -126,6 +145,7 @@
 #include <sys/device.h>
 #endif
 #include <sys/sockio.h>
+#include <sys/malloc.h>
 #include <sys/mbuf.h>
 #include <sys/socket.h>
 #include <sys/proc.h>
@@ -144,19 +164,15 @@
 #include <netnatm/natm.h>
 #endif
 
-#if !defined(sparc) && !defined(__FreeBSD__)
-#include <machine/bus.h>
-#endif
-
 #if defined(__NetBSD__) || defined(__OpenBSD__)
+#include <machine/bus.h>
 #include <dev/ic/midwayreg.h>
 #include <dev/ic/midwayvar.h>
-#if defined(__alpha__)
-/* XXX XXX NEED REAL DMA MAPPING SUPPORT XXX XXX */
-#undef vtophys
-#define	vtophys(va)	alpha_XXX_dmamap((vm_offset_t)(va))
-#endif
 #elif defined(__FreeBSD__)
+#include <sys/bus.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <machine/resource.h>
 #include <machine/clock.h>              /* for DELAY */
 #include <dev/en/midwayreg.h>
 #include <dev/en/midwayvar.h>
@@ -168,6 +184,22 @@
 
 #endif	/* __FreeBSD__ */
 
+#if defined(__alpha__)
+/* XXX XXX NEED REAL DMA MAPPING SUPPORT XXX XXX */
+#undef vtophys
+#define	vtophys(va)	alpha_XXX_dmamap((vm_offset_t)(va))
+#endif
+
+#ifdef ATM_PVCEXT
+# ifndef NATM
+   /* this is for __KAME__ */
+#  include <netinet/in.h>
+# endif
+# if defined(__KAME__) && defined(INET6)
+#  include <netinet6/in6_ifattach.h>
+# endif
+#endif /*ATM_PVCEXT*/
+
 #include "bpf.h"
 #if NBPF > 0
 #include <net/bpf.h>
@@ -204,6 +236,7 @@
 
 static int en_dma = EN_DMA;		/* use DMA (switch off for dbg) */
 
+#ifndef __FreeBSD__
 /*
  * autoconfig attachments
  */
@@ -211,6 +244,7 @@
 struct cfdriver en_cd = {
     0, "en", DV_IFNET,
 };
+#endif
 
 /*
  * local structures
@@ -295,6 +329,17 @@
 STATIC INLINE	void en_write __P((struct en_softc *, u_int32_t,
 		    u_int32_t)) __attribute__ ((unused));
 
+#ifdef ATM_PVCEXT
+static void rrp_add __P((struct en_softc *, struct ifnet *));
+static struct ifnet *en_pvcattach __P((struct ifnet *));
+static int en_txctl __P((struct en_softc *, int, int, int));
+static int en_pvctx __P((struct en_softc *, struct pvctxreq *));
+static int en_pvctxget __P((struct en_softc *, struct pvctxreq *));
+static int en_pcr2txspeed __P((int));
+static int en_txspeed2pcr __P((int));
+static struct ifnet *en_vci2ifp __P((struct en_softc *, int));
+#endif
+
 /*
  * macros/inline
  */
@@ -310,7 +355,7 @@
  * cooked read/write macros
  */
 
-#define EN_READ(SC,R) ntohl(en_read(SC,R))
+#define EN_READ(SC,R) (u_int32_t)ntohl(en_read(SC,R))
 #define EN_WRITE(SC,R,V) en_write(SC,R, htonl(V))
 
 #define EN_WRAPADD(START,STOP,CUR,VAL) { \
@@ -623,7 +668,7 @@
       if ((m->m_flags & M_EXT) == 0) {
 	m_free(m);
 	m_freem(top);
-	return(NULL);	  /* out of mbuf clusters */
+	return(NULL);	/* out of mbuf clusters */
       }
       m->m_len = MCLBYTES;
     }
@@ -700,7 +745,7 @@
 	(MID_IS_SABRE(reg)) ? "sabre controller, " : "",
 	(MID_IS_SUNI(reg)) ? "SUNI" : "Utopia",
 	(!MID_IS_SUNI(reg) && MID_IS_UPIPE(reg)) ? " (pipelined)" : "",
-	(long)(sc->en_obmemsz / 1024));
+	(long)sc->en_obmemsz / 1024);
 
   if (sc->is_adaptec) {
     if (sc->bestburstlen == 64 && sc->alburst == 0)
@@ -725,6 +770,7 @@
   ifp->if_ioctl = en_ioctl;
   ifp->if_output = atm_output;
   ifp->if_start = en_start;
+  IFQ_SET_READY(&ifp->if_snd);
 
   /*
    * init softc
@@ -751,6 +797,9 @@
     sz -= (EN_TXSZ * 1024);
     sc->txslot[lcv].stop = ptr;
     sc->txslot[lcv].nref = 0;
+#ifdef ATM_PVCEXT
+    sc->txrrp = NULL;
+#endif
     bzero(&sc->txslot[lcv].indma, sizeof(sc->txslot[lcv].indma));
     bzero(&sc->txslot[lcv].q, sizeof(sc->txslot[lcv].q));
 #ifdef EN_DEBUG
@@ -822,6 +871,9 @@
 #if NBPF > 0 
   BPFATTACH(ifp, DLT_ATM_RFC1483, sizeof(struct atmllc));
 #endif
+#ifdef ATM_PVCEXT
+  rrp_add(sc, ifp);
+#endif
 }
 
 
@@ -839,7 +891,7 @@
  * p166:   bestburstlen=64, alburst=0 
  */
 
-#if 1 /* __FreeBSD__ */
+#if defined(__FreeBSD__) && defined(__i386__)
 #define NBURSTS	3	/* number of bursts to use for dmaprobe */
 #define BOUNDARY 1024	/* test misaligned dma crossing the bounday.
 			   should be n * 64.  at least 64*(NBURSTS+1).
@@ -932,7 +984,7 @@
  * en_dmaprobe_doit: do actual testing
  */
 
-static int
+STATIC int
 en_dmaprobe_doit(sc, sp, dp, wmtry)
 
 struct en_softc *sc;
@@ -985,8 +1037,8 @@
   for (lcv = 8 ; lcv <= MIDDMA_MAXBURST ; lcv = lcv * 2) {
 
 #ifdef EN_DEBUG
-    printf("DMA test lcv=%d, sp=0x%x, dp=0x%x, wmtry=%d\n",
-	   lcv, sp, dp, wmtry);
+    printf("DMA test lcv=%d, sp=0x%lx, dp=0x%lx, wmtry=%d\n",
+	   lcv, (unsigned long)sp, (unsigned long)dp, wmtry);
 #endif
 
     /* zero SRAM and dest buffer */
@@ -1184,6 +1236,9 @@
 		break;
 #endif
 	case SIOCSIFADDR: 
+#if defined(INET6) && defined(SIOCSIFADDR_IN6)
+	case SIOCSIFADDR_IN6: 
+#endif
 		ifp->if_flags |= IFF_UP;
 #if defined(INET) || defined(INET6)
 		if (ifa->ifa_addr->sa_family == AF_INET
@@ -1204,7 +1259,18 @@
 		break;
 
 	case SIOCSIFFLAGS: 
+#ifdef ATM_PVCEXT
+	  	/* point-2-point pvc is allowed to change if_flags */
+		if (((ifp->if_flags & IFF_UP)
+		     && !(ifp->if_flags & IFF_RUNNING))
+		    || (!(ifp->if_flags & IFF_UP)
+			&& (ifp->if_flags & IFF_RUNNING))) {
+			en_reset(sc);
+			en_init(sc);
+		}
+#else
 		error = EINVAL;
+#endif
 		break;
 
 #if defined(SIOCSIFMTU)		/* ??? copied from if_de */
@@ -1228,6 +1294,110 @@
 	    break;
 #endif /* SIOCSIFMTU */
 
+#ifdef ATM_PVCEXT
+	case SIOCADDMULTI:
+	case SIOCDELMULTI:
+		if (ifp == &sc->enif || ifr == 0) {
+			error = EAFNOSUPPORT;	/* XXX */
+			break;
+		}
+		switch (ifr->ifr_addr.sa_family) {
+#ifdef INET
+		case AF_INET:
+			break;
+#endif
+#ifdef INET6
+		case AF_INET6:
+			break;
+#endif
+		default:
+			error = EAFNOSUPPORT;
+			break;
+		}
+		break;
+
+	case SIOCGPVCSIF:
+		if (ifp != &sc->enif) {
+#ifdef __NetBSD__
+		  strcpy(ifr->ifr_name, sc->enif.if_xname);
+#else
+		  sprintf(ifr->ifr_name, "%s%d",
+			  sc->enif.if_name, sc->enif.if_unit);
+#endif
+		}
+		else
+		  error = EINVAL;
+		break;
+
+	case SIOCSPVCSIF:
+		if (ifp == &sc->enif) {
+		  struct ifnet *sifp;
+		    
+#if (__FreeBSD_version >= 400000)
+		  if ((error = suser(curproc)) != 0)
+		    break;
+#else
+		  if (error = suser(curproc->p_ucred, &curproc->p_acflag))
+		    break;
+#endif
+
+		  if ((sifp = en_pvcattach(ifp)) != NULL) {
+#ifdef __NetBSD__
+		    strcpy(ifr->ifr_name, sifp->if_xname);
+#else
+		    sprintf(ifr->ifr_name, "%s%d",
+			    sifp->if_name, sifp->if_unit);
+#endif
+#if defined(__KAME__) && defined(INET6)
+		    /* get EUI64 for PVC, from ATM hardware interface */
+		    in6_ifattach(sifp, ifp);
+#endif
+		  }
+		  else
+		    error = ENOMEM;
+		}
+		else
+		  error = EINVAL;
+		break;
+
+	case SIOCGPVCTX:
+		error = en_pvctxget(sc, (struct pvctxreq *)data);
+		break;
+
+	case SIOCSPVCTX:
+#if (__FreeBSD_version >= 400000)
+		if ((error = suser(curproc)) == 0)
+			error = en_pvctx(sc, (struct pvctxreq *)data);
+#else
+		if ((error = suser(curproc->p_ucred, &curproc->p_acflag)) == 0)
+			error = en_pvctx(sc, (struct pvctxreq *)data);
+#endif
+		break;
+
+	case SIOCGPVCFWD:
+	{
+		struct pvcfwdreq *req = (struct pvcfwdreq *)data;
+		error = pvc_set_fwd(req->pvc_ifname, req->pvc_ifname2, 2);
+		break;
+	}	
+
+	case SIOCSPVCFWD:
+	{
+		struct pvcfwdreq *req = (struct pvcfwdreq *)data;
+#if (__FreeBSD_version >= 400000)
+		if ((error = suser(curproc)) == 0)
+			error = pvc_set_fwd(req->pvc_ifname, req->pvc_ifname2,
+					    req->pvc_op);
+#else
+		if ((error = suser(curproc->p_ucred, &curproc->p_acflag)) == 0)
+			error = pvc_set_fwd(req->pvc_ifname, req->pvc_ifname2,
+					    req->pvc_op);
+#endif
+		break;
+	}
+
+#endif /* ATM_PVCEXT */
+
 	default: 
 	    error = EINVAL;
 	    break;
@@ -1369,12 +1539,14 @@
       if (m == NULL) 
 	break;		/* >>> exit 'while(1)' here <<< */
       m_freem(m);
+      IF_DROP(&sc->enif.if_snd);
     }
     while (1) {
       IF_DEQUEUE(&sc->rxslot[slot].q, m);
       if (m == NULL) 
 	break;		/* >>> exit 'while(1)' here <<< */
       m_freem(m);
+      IF_DROP(&sc->enif.if_snd);
     }
     sc->rxslot[slot].oth_flags &= ~ENOTHER_SWSL;
     if (sc->rxslot[slot].oth_flags & ENOTHER_DRAIN) {
@@ -1403,7 +1575,6 @@
 	break;		/* >>> exit 'while(1)' here <<< */
       m_freem(m);
     }
-
     sc->txslot[lcv].mbsize = 0;
   }
 
@@ -1422,8 +1593,23 @@
 {
   int vc, slot;
   u_int32_t loc;
+#ifdef ATM_PVCEXT
+    struct pvcsif *pvcsif;
+#endif
 
   if ((sc->enif.if_flags & IFF_UP) == 0) {
+#ifdef ATM_PVCEXT
+    LIST_FOREACH(pvcsif, &sc->sif_list, sif_links) {
+      if (pvcsif->sif_if.if_flags & IFF_UP) {
+	/*
+	 * down the device only when there is no active pvc subinterface.
+	 * if there is, we have to go through the init sequence to reflect
+	 * the software states to the device.
+	 */
+	goto up;
+      }
+    }
+#endif
 #ifdef EN_DEBUG
     printf("%s: going down\n", sc->sc_dev.dv_xname);
 #endif
@@ -1432,10 +1618,18 @@
     return;
   }
 
+#ifdef ATM_PVCEXT
+ up:
+#endif
 #ifdef EN_DEBUG
   printf("%s: going up\n", sc->sc_dev.dv_xname);
 #endif
   sc->enif.if_flags |= IFF_RUNNING;	/* enable */
+#ifdef ATM_PVCEXT
+  LIST_FOREACH(pvcsif, &sc->sif_list, sif_links) {
+    pvcsif->sif_if.if_flags |= IFF_RUNNING;
+  }
+#endif
 
   if (sc->en_busreset)
     sc->en_busreset(sc);
@@ -1492,7 +1686,7 @@
     EN_WRITE(sc, MIDX_PLACE(slot), MIDX_MKPLACE(en_k2sz(EN_TXSZ), loc));
 #ifdef EN_DEBUG
     printf("%s: tx%d: place 0x%x\n", sc->sc_dev.dv_xname,  slot,
-	EN_READ(sc, MIDX_PLACE(slot)));
+	(u_int)EN_READ(sc, MIDX_PLACE(slot)));
 #endif
   }
 
@@ -1552,7 +1746,6 @@
 
 {
     struct en_softc *sc = (struct en_softc *) ifp->if_softc;
-    struct ifqueue *ifq = &ifp->if_snd; /* if INPUT QUEUE */
     struct mbuf *m, *lastm, *prev;
     struct atm_pseudohdr *ap, *new_ap;
     int txchan, mlen, got, need, toadd, cellcnt, first;
@@ -1569,7 +1762,7 @@
 
     while (1) {
 
-      IF_DEQUEUE(ifq, m);
+      IFQ_DEQUEUE(&ifp->if_snd, m);
       if (m == NULL)
 	return;		/* EMPTY: >>> exit here <<< */
     
@@ -1595,6 +1788,7 @@
 	    if (en_mfix(sc, &lastm, prev) == 0) {	/* failed? */
 	      m_freem(m);
 	      m = NULL;
+	      sc->enif.if_oerrors++;
               break;
             }
 	    if (first)
@@ -1628,6 +1822,7 @@
 	printf("%s: output vpi=%d, vci=%d out of card range, dropping...\n", 
 		sc->sc_dev.dv_xname, atm_vpi, atm_vci);
 	m_freem(m);
+	sc->enif.if_oerrors++;
 	continue;
       }
 
@@ -1644,7 +1839,7 @@
        *	[including AAL5 PDU, if AAL5]
        */
 
-      got = mlen - sizeof(struct atm_pseudohdr *);
+      got = mlen - sizeof(struct atm_pseudohdr);
       toadd = (aal == MID_TBD_AAL5) ? MID_PDU_SIZE : 0;	/* PDU */
       cellcnt = (got + toadd + (MID_ATMDATASZ - 1)) / MID_ATMDATASZ;
       need = cellcnt * MID_ATMDATASZ;
@@ -1654,7 +1849,7 @@
       printf("%s: txvci%d: mlen=%d, got=%d, need=%d, toadd=%d, cell#=%d\n",
 	sc->sc_dev.dv_xname, atm_vci, mlen, got, need, toadd, cellcnt);
       printf("     leading_space=%d, trailing_space=%d\n", 
-	M_LEADINGSPACE(m), M_TRAILINGSPACE(lastm));
+	(int)M_LEADINGSPACE(m), (int)M_TRAILINGSPACE(lastm));
 #endif
 
 #ifdef EN_MBUF_OPT
@@ -1707,6 +1902,7 @@
       if (sc->txslot[txchan].mbsize > EN_TXHIWAT) {
 	EN_COUNT(sc->txmbovr);
 	m_freem(m);
+	IF_DROP(&ifp->if_snd);
 #ifdef EN_DEBUG
 	printf("%s: tx%d: buffer space shortage\n", sc->sc_dev.dv_xname,
 		txchan);
@@ -1759,7 +1955,7 @@
 #endif
 
   d = mtod(m, u_char *);
-  off = ((unsigned long) d) % sizeof(u_int32_t);
+  off = ((uintptr_t) (void *) d) % sizeof(u_int32_t);
 
   if (off) {
     if ((m->m_flags & M_EXT) == 0) {
@@ -1886,12 +2082,12 @@
 
   EN_COUNT(sc->mfix);			/* count # of calls */
 #ifdef EN_DEBUG
-  printf("%s: mfix mbuf m_data=0x%x, m_len=%d\n", sc->sc_dev.dv_xname,
+  printf("%s: mfix mbuf m_data=%p, m_len=%d\n", sc->sc_dev.dv_xname,
 	m->m_data, m->m_len);
 #endif
 
   d = mtod(m, u_char *);
-  off = ((uintptr_t) (void *) d) % sizeof(u_int32_t);
+  off = ((unsigned long) d) % sizeof(u_int32_t);
 
   if (off) {
     if ((m->m_flags & M_EXT) == 0) {
@@ -2103,7 +2299,12 @@
    */
 
   EN_COUNT(sc->launch);
+#ifdef ATM_PVCEXT
+  /* if there's a subinterface for this vci, override ifp. */
+  ifp = en_vci2ifp(sc, launch.atm_vci);
+#else
   ifp = &sc->enif;
+#endif
   ifp->if_opackets++;
   
   if ((launch.atm_flags & EN_OBHDR) == 0) {
@@ -2160,6 +2361,7 @@
   if (launch.t != tmp)
     panic("en dequeue drop");
   m_freem(launch.t);
+  IF_DROP(&sc->enif.if_snd);
   sc->txslot[chan].mbsize -= launch.mlen;
   goto again;
 }
@@ -2217,8 +2419,9 @@
 	sc->sc_dev.dv_xname, chan, l->t, cur, (cur-start)/4, need, addtail);
   count = EN_READ(sc, MIDX_PLACE(chan));
   printf("     HW: base_address=0x%x, size=%d, read=%d, descstart=%d\n",
-	MIDX_BASE(count), MIDX_SZ(count), EN_READ(sc, MIDX_READPTR(chan)), 
-	EN_READ(sc, MIDX_DESCSTART(chan)));
+	 (u_int)MIDX_BASE(count), MIDX_SZ(count),
+	 (int)EN_READ(sc, MIDX_READPTR(chan)),
+	 (int)EN_READ(sc, MIDX_DESCSTART(chan)));
 #endif
 
  /*
@@ -2492,7 +2695,7 @@
       pad -= 2;
 #ifdef EN_DEBUG
       printf("%s: tx%d: padding %d bytes (cur now 0x%x)\n", 
-		sc->sc_dev.dv_xname, chan, pad * sizeof(u_int32_t), cur);
+	     sc->sc_dev.dv_xname, chan, (int)(pad * sizeof(u_int32_t)), cur);
 #endif
     while (pad--) {
       EN_WRITEDAT(sc, cur, 0);	/* no byte order issues with zero */
@@ -2705,8 +2908,15 @@
 		EN_DQ_LEN(drq), sc->rxslot[slot].rxhand);
 #endif
 
+#ifdef ATM_PVCEXT
+	  /* if there's a subinterface for this vci, override ifp. */
+	  ifp = en_vci2ifp(sc, sc->rxslot[slot].atm_vci);
+	  ifp->if_ipackets++;
+	  m->m_pkthdr.rcvif = ifp;	/* XXX */
+#else
 	  ifp = &sc->enif;
 	  ifp->if_ipackets++;
+#endif
 
 #if NBPF > 0
 	  if (ifp->if_bpf)
@@ -2796,6 +3006,28 @@
   sc->vtrash += MID_VTRASH(reg);
 #endif
 
+#ifdef ATM_PVCEXT
+  /*
+   * when the tx buffer is full, packets are left in the interface queue.
+   * (en dequeues all packets even when the tx buffer is full.)
+   * call en_start for each pvc interface using round-robin scheduling
+   * to avoid starvation.
+   */
+  if (kick) {
+    struct rrp *rrp_start;
+
+    if ((rrp_start = sc->txrrp) != NULL) {
+      while (1) {
+	en_start(sc->txrrp->ifp);
+	if (sc->txrrp->next == rrp_start)
+	  break;
+	else
+	  sc->txrrp = sc->txrrp->next;
+      }
+    }
+  }
+#endif
+
   EN_INTR_RET(1); /* for us */
 }
 
@@ -2941,7 +3173,11 @@
 	}
 	fill = tlen;
 
+#ifdef ATM_PVCEXT
+	ifp = en_vci2ifp(sc, vci);
+#else
 	ifp = &sc->enif;
+#endif
 	ifp->if_ierrors++;
 
       }
@@ -3257,9 +3493,22 @@
   struct en_softc *sc;
   int lcv, cnt, slot;
   u_int32_t ptr, reg;
+#ifdef __FreeBSD__
+  devclass_t dc;
+  int maxunit;
 
+  dc = devclass_find("en");
+  if (dc == NULL) {
+    printf("en_dump: can't find devclass!\n");
+    return 0;
+  }
+  maxunit = devclass_get_maxunit(dc);
+  for (lcv = 0 ; lcv < maxunit ; lcv++) {
+    sc = devclass_get_softc(dc, lcv);
+#else
   for (lcv = 0 ; lcv < en_cd.cd_ndevs ; lcv++) {
     sc = (struct en_softc *) en_cd.cd_devs[lcv];
+#endif
     if (sc == NULL) continue;
     if (unit != -1 && unit != lcv)
       continue;
@@ -3308,24 +3557,21 @@
 
     if (level & END_MREGS) {
       printf("mregs:\n");
-      printf("resid = 0x%lx\n", (u_long)EN_READ(sc, MID_RESID));
+      printf("resid = 0x%x\n", EN_READ(sc, MID_RESID));
       printf("interrupt status = 0x%b\n", 
-				(int)EN_READ(sc, MID_INTSTAT), MID_INTBITS);
+	     (int)EN_READ(sc, MID_INTSTAT), MID_INTBITS);
       printf("interrupt enable = 0x%b\n", 
-				(int)EN_READ(sc, MID_INTENA), MID_INTBITS);
+	     (int)EN_READ(sc, MID_INTENA), MID_INTBITS);
       printf("mcsr = 0x%b\n", (int)EN_READ(sc, MID_MAST_CSR), MID_MCSRBITS);
-      printf("serv_write = [chip=%ld] [us=%d]\n",
-			(long)EN_READ(sc, MID_SERV_WRITE),
-			MID_SL_A2REG(sc->hwslistp));
-      printf("dma addr = 0x%lx\n", (u_long)EN_READ(sc, MID_DMA_ADDR));
-      printf("DRQ: chip[rd=0x%lx,wr=0x%lx], sc[chip=0x%x,us=0x%x]\n",
-	(u_long)MID_DRQ_REG2A(EN_READ(sc, MID_DMA_RDRX)), 
-	(u_long)MID_DRQ_REG2A(EN_READ(sc, MID_DMA_WRRX)),
-	sc->drq_chip, sc->drq_us);
-      printf("DTQ: chip[rd=0x%lx,wr=0x%lx], sc[chip=0x%x,us=0x%x]\n",
-	(u_long)MID_DTQ_REG2A(EN_READ(sc, MID_DMA_RDTX)), 
-	(u_long)MID_DTQ_REG2A(EN_READ(sc, MID_DMA_WRTX)),
-	sc->dtq_chip, sc->dtq_us);
+      printf("serv_write = [chip=%u] [us=%u]\n", EN_READ(sc, MID_SERV_WRITE),
+	     MID_SL_A2REG(sc->hwslistp));
+      printf("dma addr = 0x%x\n", EN_READ(sc, MID_DMA_ADDR));
+      printf("DRQ: chip[rd=0x%x,wr=0x%x], sc[chip=0x%x,us=0x%x]\n",
+	MID_DRQ_REG2A(EN_READ(sc, MID_DMA_RDRX)), 
+	MID_DRQ_REG2A(EN_READ(sc, MID_DMA_WRRX)), sc->drq_chip, sc->drq_us);
+      printf("DTQ: chip[rd=0x%x,wr=0x%x], sc[chip=0x%x,us=0x%x]\n",
+	MID_DTQ_REG2A(EN_READ(sc, MID_DMA_RDTX)), 
+	MID_DTQ_REG2A(EN_READ(sc, MID_DMA_WRTX)), sc->dtq_chip, sc->dtq_us);
 
       printf("  unusal txspeeds: ");
       for (cnt = 0 ; cnt < MID_N_VC ; cnt++)
@@ -3349,11 +3595,10 @@
 		(sc->txslot[slot].cur - sc->txslot[slot].start)/4);
 	printf("mbsize=%d, bfree=%d\n", sc->txslot[slot].mbsize,
 		sc->txslot[slot].bfree);
-        printf("txhw: base_address=0x%lx, size=%ld, read=%ld, descstart=%ld\n",
-	  (u_long)MIDX_BASE(EN_READ(sc, MIDX_PLACE(slot))), 
-	  (u_long)MIDX_SZ(EN_READ(sc, MIDX_PLACE(slot))),
-	  (long)EN_READ(sc, MIDX_READPTR(slot)),
-	  (long)EN_READ(sc, MIDX_DESCSTART(slot)));
+        printf("txhw: base_address=0x%x, size=%u, read=%u, descstart=%u\n",
+	  (u_int)MIDX_BASE(EN_READ(sc, MIDX_PLACE(slot))), 
+	  MIDX_SZ(EN_READ(sc, MIDX_PLACE(slot))),
+	  EN_READ(sc, MIDX_READPTR(slot)), EN_READ(sc, MIDX_DESCSTART(slot)));
       }
     }
 
@@ -3366,10 +3611,10 @@
 	printf("mode=0x%x, atm_flags=0x%x, oth_flags=0x%x\n", 
 	sc->rxslot[slot].mode, sc->rxslot[slot].atm_flags, 
 		sc->rxslot[slot].oth_flags);
-        printf("RXHW: mode=0x%lx, DST_RP=0x%lx, WP_ST_CNT=0x%lx\n",
-	  (u_long)EN_READ(sc, MID_VC(sc->rxslot[slot].atm_vci)),
-	  (u_long)EN_READ(sc, MID_DST_RP(sc->rxslot[slot].atm_vci)),
-	  (u_long)EN_READ(sc, MID_WP_ST_CNT(sc->rxslot[slot].atm_vci)));
+        printf("RXHW: mode=0x%x, DST_RP=0x%x, WP_ST_CNT=0x%x\n",
+	  EN_READ(sc, MID_VC(sc->rxslot[slot].atm_vci)),
+	  EN_READ(sc, MID_DST_RP(sc->rxslot[slot].atm_vci)),
+	  EN_READ(sc, MID_WP_ST_CNT(sc->rxslot[slot].atm_vci)));
       }
     }
 
@@ -3379,10 +3624,9 @@
       ptr = sc->dtq_chip;
       while (ptr != sc->dtq_us) {
         reg = EN_READ(sc, ptr);
-        printf("\t0x%x=[cnt=%d, chan=%d, end=%d, type=%d @ 0x%lx]\n", 
+        printf("\t0x%x=[cnt=%d, chan=%d, end=%d, type=%d @ 0x%x]\n", 
 	    sc->dtq[MID_DTQ_A2REG(ptr)], MID_DMA_CNT(reg), MID_DMA_TXCHAN(reg),
-	    (reg & MID_DMA_END) != 0, MID_DMA_TYPE(reg),
-	    (u_long)EN_READ(sc, ptr+4));
+	    (reg & MID_DMA_END) != 0, MID_DMA_TYPE(reg), EN_READ(sc, ptr+4));
         EN_WRAPADD(MID_DTQOFF, MID_DTQEND, ptr, 8);
       }
     }
@@ -3393,10 +3637,9 @@
       ptr = sc->drq_chip;
       while (ptr != sc->drq_us) {
         reg = EN_READ(sc, ptr);
-	printf("\t0x%x=[cnt=%d, chan=%d, end=%d, type=%d @ 0x%lx]\n", 
+	printf("\t0x%x=[cnt=%d, chan=%d, end=%d, type=%d @ 0x%x]\n", 
 	  sc->drq[MID_DRQ_A2REG(ptr)], MID_DMA_CNT(reg), MID_DMA_RXVCI(reg),
-	  (reg & MID_DMA_END) != 0, MID_DMA_TYPE(reg),
-	  (u_long)EN_READ(sc, ptr+4));
+	  (reg & MID_DMA_END) != 0, MID_DMA_TYPE(reg), EN_READ(sc, ptr+4));
 	EN_WRAPADD(MID_DRQOFF, MID_DRQEND, ptr, 8);
       }
     }
@@ -3424,12 +3667,23 @@
 {
   struct en_softc *sc;
   u_int32_t reg;
+#ifdef __FreeBSD__
+  devclass_t dc;
 
+  dc = devclass_find("en");
+  if (dc == NULL) {
+    printf("en_dumpmem: can't find devclass!\n");
+    return 0;
+  }
+  sc = devclass_get_softc(dc, unit);
+#else
   if (unit < 0 || unit > en_cd.cd_ndevs ||
 	(sc = (struct en_softc *) en_cd.cd_devs[unit]) == NULL) {
     printf("invalid unit number: %d\n", unit);
     return(0);
   }
+#endif
+
   addr = addr & ~3;
   if (addr < MID_RAMOFF || addr + len*4 > MID_MAXOFF || len <= 0) {
     printf("invalid addr/len number: %d, %d\n", addr, len);
@@ -3444,3 +3698,422 @@
   return(0);
 }
 #endif
+
+#ifdef ATM_PVCEXT
+/*
+ * ATM PVC extention: shaper control and pvc subinterfaces
+ */
+
+/*
+ * the list of the interfaces sharing the physical device.
+ * in order to avoid starvation, the interfaces are scheduled in
+ * a round-robin fashion when en_start is called from tx complete
+ * interrupts.
+ */
+static void rrp_add(sc, ifp)
+	struct en_softc *sc;
+	struct ifnet *ifp;
+{
+	struct rrp *head, *p, *new;
+
+	head = sc->txrrp;
+	if ((p = head) != NULL) {
+		while (1) {
+			if (p->ifp == ifp) {
+				/* an entry for this ifp already exits */
+				p->nref++;
+				return;
+			}
+			if (p->next == head)
+				break;
+			p = p->next;
+		}
+	}
+	
+	/* create a new entry */
+	MALLOC(new, struct rrp *, sizeof(struct rrp), M_DEVBUF, M_WAITOK);
+	if (new == NULL) {
+		printf("en_rrp_add: malloc failed!\n");
+		return;
+	}
+
+	new->ifp = ifp;
+	new->nref = 1;
+
+	if (p == NULL) {
+		/* this is the only one in the list */
+		new->next = new;
+		sc->txrrp = new;
+	}
+	else {
+		/* add the new entry at the tail of the list */
+		new->next = p->next;
+		p->next = new;
+	}
+}
+
+#if 0 /* not used */
+static void rrp_delete(sc, ifp)
+	struct en_softc *sc;
+	struct ifnet *ifp;
+{
+	struct rrp *head, *p, *prev;
+
+	head = sc->txrrp;
+
+	prev = head;
+	if (prev == NULL) {
+		printf("rrp_delete: no list!\n");
+		return;
+	}
+	p = prev->next;
+
+	while (1) {
+		if (p->ifp == ifp) {
+			p->nref--;
+			if (p->nref > 0)
+				return;
+			/* remove this entry */
+			if (p == prev) {
+				/* this is the only entry in the list */
+				sc->txrrp = NULL;
+			}
+			else {
+				prev->next = p->next;
+				if (head == p)
+					sc->txrrp = p->next;
+			}
+			FREE(p, M_DEVBUF);
+		}
+		prev = p;
+		p = prev->next;
+		if (prev == head) {
+			printf("rrp_delete: no matching entry!\n");
+			return;
+		}
+	}
+}
+#endif /* 0 */
+
+static struct ifnet *
+en_vci2ifp(sc, vci)
+	struct en_softc *sc;
+	int vci;
+{
+	struct pvcsif *pvcsif;
+
+	LIST_FOREACH(pvcsif, &sc->sif_list, sif_links) {
+		if (vci == pvcsif->sif_vci)
+			return (&pvcsif->sif_if);
+	}
+	return (&sc->enif);
+}
+
+/*
+ * create and attach per pvc subinterface
+ * (currently detach is not supported)
+ */
+static struct ifnet *
+en_pvcattach(ifp)
+	struct ifnet *ifp;
+{
+	struct en_softc *sc = (struct en_softc *) ifp->if_softc;
+	struct ifnet *pvc_ifp;
+	int s;
+
+	if ((pvc_ifp = pvcsif_alloc()) == NULL)
+		return (NULL);
+
+	pvc_ifp->if_softc = sc;
+	pvc_ifp->if_ioctl = en_ioctl;
+	pvc_ifp->if_start = en_start;
+	pvc_ifp->if_flags = (IFF_POINTOPOINT|IFF_MULTICAST) |
+		(ifp->if_flags & (IFF_RUNNING|IFF_SIMPLEX|IFF_NOTRAILERS));
+	IFQ_SET_READY(&pvc_ifp->if_snd);
+
+	s = splimp();
+	LIST_INSERT_HEAD(&sc->sif_list, (struct pvcsif *)pvc_ifp, sif_links);
+	if_attach(pvc_ifp);
+	atm_ifattach(pvc_ifp); 
+
+#if NBPF > 0 
+	BPFATTACH(pvc_ifp, DLT_ATM_RFC1483, sizeof(struct atmllc));
+#endif
+#ifdef ATM_PVCEXT
+	rrp_add(sc, pvc_ifp);
+#endif
+	splx(s);
+
+	return (pvc_ifp);
+}
+
+
+/* txspeed conversion derived from linux drivers/atm/eni.c
+   by Werner Almesberger, EPFL LRC */
+static const int pre_div[] = { 4,16,128,2048 };
+
+static int en_pcr2txspeed(pcr)
+	int pcr;
+{
+	int pre, res, div;
+
+	if (pcr == 0 || pcr > 347222)
+		pre = res = 0;	/* max rate */
+	else {
+		for (pre = 0; pre < 3; pre++)
+			if (25000000/pre_div[pre]/64 <= pcr)
+				break;
+		div = pre_div[pre]*(pcr);
+#if 1
+		/*
+		 * the shaper value should be rounded down,
+		 * instead of rounded up.
+		 * (which means "res" should be rounded up.)
+		 */
+		res = (25000000 + div -1)/div - 1;
+#else
+		res = 25000000/div-1;
+#endif
+		if (res < 0)
+			res = 0;
+		if (res > 63)
+			res = 63;
+	}
+	return ((pre << 6) + res);
+}
+
+static int en_txspeed2pcr(txspeed)
+	int txspeed;
+{
+	int pre, res, pcr;
+
+	pre = (txspeed >> 6) & 0x3;
+	res = txspeed & 0x3f;
+	pcr = 25000000 / pre_div[pre] / (res+1);
+	return (pcr);
+}
+
+/*
+ * en_txctl selects a hardware transmit channel and sets the shaper value.
+ * en_txctl should be called after enabling the vc by en_rxctl
+ * since it assumes a transmit channel is already assigned by en_rxctl
+ * to the vc.
+ */
+static int en_txctl(sc, vci, joint_vci, pcr)
+	struct en_softc *sc;
+	int vci;
+	int joint_vci;
+	int pcr;
+{
+	int txspeed, txchan, s;
+
+	if (pcr)
+		txspeed = en_pcr2txspeed(pcr);
+	else
+		txspeed = 0;
+
+	s = splimp();
+	txchan = sc->txvc2slot[vci];
+	sc->txslot[txchan].nref--;
+    
+	/* select a slot */
+	if (joint_vci != 0)
+		/* use the same channel */
+		txchan = sc->txvc2slot[joint_vci];
+	else if (pcr == 0)
+		txchan = 0;
+	else {
+		for (txchan = 1; txchan < EN_NTX; txchan++) {
+			if (sc->txslot[txchan].nref == 0)
+				break;
+		}
+	}
+	if (txchan == EN_NTX) {
+#if 1
+		/* no free slot! */
+		splx(s);
+		return (ENOSPC);
+#else
+		/*
+		 * to allow multiple vc's to share a slot,
+		 * use a slot with the smallest reference count
+		 */
+		int slot = 1;
+		txchan = 1;
+		for (slot = 2; slot < EN_NTX; slot++)
+			if (sc->txslot[slot].nref < sc->txslot[txchan].nref)
+				txchan = slot;
+#endif
+	}
+
+	sc->txvc2slot[vci] = txchan;
+	sc->txslot[txchan].nref++;
+
+	/* set the shaper parameter */
+	sc->txspeed[vci] = (u_int8_t)txspeed;
+
+	splx(s);
+#ifdef EN_DEBUG
+	printf("VCI:%d PCR set to %d, tx channel %d\n", vci, pcr, txchan);
+	if (joint_vci != 0)
+		printf("  slot shared with VCI:%d\n", joint_vci);
+#endif
+	return (0);
+}
+
+static int en_pvctx(sc, pvcreq)
+	struct en_softc *sc;
+	struct pvctxreq *pvcreq;
+{
+	struct ifnet *ifp;
+	struct atm_pseudoioctl api;
+	struct atm_pseudohdr *pvc_aph, *pvc_joint;
+	int vci, joint_vci, pcr;
+	int error = 0;
+
+	/* check vpi:vci values */
+	pvc_aph = &pvcreq->pvc_aph;
+	pvc_joint = &pvcreq->pvc_joint;
+
+	vci = ATM_PH_VCI(pvc_aph);
+	joint_vci = ATM_PH_VCI(pvc_joint);
+	pcr = pvcreq->pvc_pcr;
+
+	if (ATM_PH_VPI(pvc_aph) != 0 || vci >= MID_N_VC ||
+	    ATM_PH_VPI(pvc_joint) != 0 || joint_vci >= MID_N_VC)
+		return (EADDRNOTAVAIL);
+
+	if ((ifp = ifunit(pvcreq->pvc_ifname)) == NULL)
+		return (ENXIO);
+
+	if (pcr < 0) {
+		/* negative pcr means disable the vc. */
+		if (sc->rxvc2slot[vci] == RX_NONE)
+			/* already disabled */
+			return 0;
+
+		ATM_PH_FLAGS(&api.aph) = 0;
+		ATM_PH_VPI(&api.aph) = 0;
+		ATM_PH_SETVCI(&api.aph, vci);
+		api.rxhand = NULL;
+
+		error = en_rxctl(sc, &api, 0);
+		
+		if (error == 0 && &sc->enif != ifp) {
+			/* clear vc info of this subinterface */
+			struct pvcsif *pvcsif = (struct pvcsif *)ifp;
+
+			ATM_PH_SETVCI(&api.aph, 0);
+			pvcsif->sif_aph = api.aph;
+			pvcsif->sif_vci = 0;
+		}
+		return (error);
+	}
+
+	if (&sc->enif == ifp) {
+		/* called for an en interface */
+		if (sc->rxvc2slot[vci] == RX_NONE) {
+			/* vc is not active */
+#ifdef __NetBSD__
+			printf("%s: en_pvctx: rx not active! vci=%d\n",
+			       ifp->if_xname, vci);
+#else
+			printf("%s%d: en_pvctx: rx not active! vci=%d\n",
+			       ifp->if_name, ifp->if_unit, vci);
+#endif
+			return (EINVAL);
+		}
+	}
+	else {
+		/* called for a pvc subinterface */
+		struct pvcsif *pvcsif = (struct pvcsif *)ifp;
+
+#ifdef __NetBSD__
+    		strcpy(pvcreq->pvc_ifname, sc->enif.if_xname);
+#else
+    		sprintf(pvcreq->pvc_ifname, "%s%d",
+			sc->enif.if_name, sc->enif.if_unit);
+#endif
+		ATM_PH_FLAGS(&api.aph) =
+			(ATM_PH_FLAGS(pvc_aph) & (ATM_PH_AAL5|ATM_PH_LLCSNAP));
+		ATM_PH_VPI(&api.aph) = 0;
+		ATM_PH_SETVCI(&api.aph, vci);
+		api.rxhand = NULL;
+		pvcsif->sif_aph = api.aph;
+		pvcsif->sif_vci = ATM_PH_VCI(&api.aph);
+
+		if (sc->rxvc2slot[vci] == RX_NONE) {
+			/* vc is not active, enable rx */
+			error = en_rxctl(sc, &api, 1);
+			if (error)
+				return error;
+		}
+		else {
+			/* vc is already active, update aph in softc */
+			sc->rxslot[sc->rxvc2slot[vci]].atm_flags =
+				ATM_PH_FLAGS(&api.aph);
+		}
+	}
+
+	error = en_txctl(sc, vci, joint_vci, pcr);
+
+	if (error == 0) {
+		if (sc->txspeed[vci] != 0)
+			pvcreq->pvc_pcr = en_txspeed2pcr(sc->txspeed[vci]);
+		else
+			pvcreq->pvc_pcr = 0;
+	}
+
+	return error;
+}
+
+static int en_pvctxget(sc, pvcreq)
+	struct en_softc *sc;
+	struct pvctxreq *pvcreq;
+{
+	struct pvcsif *pvcsif;
+	struct ifnet *ifp;
+	int vci, slot;
+
+	if ((ifp = ifunit(pvcreq->pvc_ifname)) == NULL)
+		return (ENXIO);
+
+	if (ifp == &sc->enif) {
+		/* physical interface: assume vci is specified */
+		struct atm_pseudohdr *pvc_aph;
+
+		pvc_aph = &pvcreq->pvc_aph;
+		vci = ATM_PH_VCI(pvc_aph);
+		if ((slot = sc->rxvc2slot[vci]) == RX_NONE)
+			ATM_PH_FLAGS(pvc_aph) = 0;
+		else
+			ATM_PH_FLAGS(pvc_aph) = sc->rxslot[slot].atm_flags;
+		ATM_PH_VPI(pvc_aph) = 0;
+	}
+	else {
+		/* pvc subinterface */
+#ifdef __NetBSD__
+		strcpy(pvcreq->pvc_ifname, sc->enif.if_xname);
+#else
+		sprintf(pvcreq->pvc_ifname, "%s%d",
+			sc->enif.if_name, sc->enif.if_unit);
+#endif
+		pvcsif = (struct pvcsif *)ifp;
+		pvcreq->pvc_aph = pvcsif->sif_aph;
+		vci = pvcsif->sif_vci;
+	}
+
+	if ((slot = sc->rxvc2slot[vci]) == RX_NONE) {
+		/* vc is not active */
+		ATM_PH_FLAGS(&pvcreq->pvc_aph) = 0;
+		pvcreq->pvc_pcr = -1;
+	}
+	else if (sc->txspeed[vci])
+		pvcreq->pvc_pcr = en_txspeed2pcr(sc->txspeed[vci]);
+	else
+		pvcreq->pvc_pcr = 0;
+
+	return (0);
+}
+
+#endif /* ATM_PVCEXT */
diff -urN ../sys/dev/en/midwayreg.h ./dev/en/midwayreg.h
--- ../sys/dev/en/midwayreg.h	Wed Jul 29 14:34:12 1998
+++ ./dev/en/midwayreg.h	Tue Oct  2 22:06:19 2001
@@ -8,26 +8,6 @@
  *
  */
 
-#if defined(sparc) || defined(__FreeBSD__)
-/* XXX: gross.   netbsd/sparc doesn't have machine/bus.h yet. */
-typedef void * bus_space_tag_t;
-typedef u_int32_t pci_chipset_tag_t;
-typedef caddr_t bus_space_handle_t;
-typedef u_int32_t bus_size_t;
-typedef caddr_t bus_addr_t;
-
-#define bus_space_read_4(t, h, o) ((void) t,                            \
-    (*(volatile u_int32_t *)((h) + (o))))
-#define bus_space_write_4(t, h, o, v)                                   \
-    ((void) t, ((void)(*(volatile u_int32_t *)((h) + (o)) = (v))))
-
-#if defined(sparc)
-#define vtophys(x) ((u_int32_t)(x))	/* sun4c dvma */
-#endif
-
-#endif
-
-
 #define MID_SZTOB(X) 	((X) * 256 * 4) /* size to bytes */
 #define MID_BTOSZ(X)	((X) / 256 / 4)	/* bytes to "size" */
 
diff -urN ../sys/dev/en/midwayvar.h ./dev/en/midwayvar.h
--- ../sys/dev/en/midwayvar.h	Wed Jul 29 14:34:13 1998
+++ ./dev/en/midwayvar.h	Tue Oct  2 22:06:19 2001
@@ -80,14 +80,17 @@
 
 #define DV_IFNET 1
 
-struct cfdriver {
-  int zero;
-  char *name;
-  int one;
-  int cd_ndevs;
-  void *cd_devs[NEN];
-};
+#endif
 
+#if 1 /* for ATM_PVCEXT */
+#include <sys/queue.h>
+
+/* round-robin scheduler */
+struct rrp {
+	struct rrp *next;
+	struct ifnet *ifp;
+	int	nref;
+};
 #endif
 
 /*
@@ -143,6 +146,10 @@
   u_int8_t txspeed[MID_N_VC];	/* speed of tx on a VC */
   u_int8_t txvc2slot[MID_N_VC]; /* map VC to slot */
 
+#if 1 /* for ATM_PVCEXT */
+  struct rrp *txrrp;		/* round-robin pointer to ifnet */
+#endif
+
   /* recv vc ctrl. (per vc).   maps VC number to recv slot */
   u_int16_t rxvc2slot[MID_N_VC];
   int en_nrx;			/* # of active rx slots */
@@ -195,6 +202,10 @@
   u_int8_t bestburstmask;	/* bits to check if not multiple of burst */
   u_int8_t alburst;		/* align dma bursts? */
   u_int8_t is_adaptec;		/* adaptec version of midway? */
+
+#if 1 /* for ATM_PVCEXT */
+  LIST_HEAD(sif_list, pvcsif) sif_list;	/* pvc subinterface list */
+#endif
 };
 
 /*
diff -urN ../sys/dev/ep/if_ep.c ./dev/ep/if_ep.c
--- ../sys/dev/ep/if_ep.c	Tue Jul 18 06:24:26 2000
+++ ./dev/ep/if_ep.c	Tue Oct  2 22:06:19 2001
@@ -297,7 +297,8 @@
 	ifp->if_ioctl = ep_if_ioctl;
 	ifp->if_watchdog = ep_if_watchdog;
 	ifp->if_init = ep_if_init;
-	ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
+	IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
+	IFQ_SET_READY(&ifp->if_snd);
 
 	if (!sc->epb.mii_trans) {
 		ifmedia_init(&sc->ifmedia, 0, ep_ifmedia_upd, ep_ifmedia_sts);
@@ -452,7 +453,7 @@
 
 startagain:
     /* Sneak a peek at the next packet */
-    m = ifp->if_snd.ifq_head;
+    IFQ_POLL(&ifp->if_snd, m);
     if (m == 0) {
 	return;
     }
@@ -469,7 +470,7 @@
     if (len + pad > ETHER_MAX_LEN) {
 	/* packet is obviously too large: toss it */
 	++ifp->if_oerrors;
-	IF_DEQUEUE(&ifp->if_snd, m);
+	IFQ_DEQUEUE(&ifp->if_snd, m);
 	m_freem(m);
 	goto readcheck;
     }
@@ -485,7 +486,7 @@
 	outw(BASE + EP_COMMAND, SET_TX_AVAIL_THRESH | EP_THRESH_DISABLE);
     }
 
-    IF_DEQUEUE(&ifp->if_snd, m);
+    IFQ_DEQUEUE(&ifp->if_snd, m);
 
     s = splhigh();
 
@@ -533,7 +534,7 @@
 	 * we check if we have packets left, in that case we prepare to come
 	 * back later
 	 */
-	if (ifp->if_snd.ifq_head) {
+	if (!IFQ_IS_EMPTY(&ifp->if_snd)) {
 	    outw(BASE + EP_COMMAND, SET_TX_AVAIL_THRESH | 8);
 	}
 	return;
@@ -631,7 +632,7 @@
 		     * To have a tx_avail_int but giving the chance to the
 		     * Reception
 		     */
-		    if (ifp->if_snd.ifq_head) {
+		    if (!IFQ_IS_EMPTY(&ifp->if_snd)) {
 			outw(BASE + EP_COMMAND, SET_TX_AVAIL_THRESH | 8);
 		    }
 		}
diff -urN ../sys/dev/ex/if_ex.c ./dev/ex/if_ex.c
--- ../sys/dev/ex/if_ex.c	Mon Mar  5 14:33:20 2001
+++ ./dev/ex/if_ex.c	Tue Oct  2 22:06:19 2001
@@ -241,7 +241,8 @@
 	ifp->if_ioctl = ex_ioctl;
 	ifp->if_watchdog = ex_watchdog;
 	ifp->if_init = ex_init;
-	ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
+	IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
+	IFQ_SET_READY(&ifp->if_snd);
 
 	ifmedia_init(&sc->ifmedia, 0, ex_ifmedia_upd, ex_ifmedia_sts);
 
@@ -381,8 +382,10 @@
 	 * Main loop: send outgoing packets to network card until there are no
 	 * more packets left, or the card cannot accept any more yet.
 	 */
-	while (((opkt = ifp->if_snd.ifq_head) != NULL) &&
-	       !(ifp->if_flags & IFF_OACTIVE)) {
+	while (!(ifp->if_flags & IFF_OACTIVE)) {
+		IFQ_POLL(&ifp->if_snd, opkt);
+		if (opkt == NULL)
+			break;
 
 		/*
 		 * Ensure there is enough free transmit buffer space for
@@ -415,7 +418,7 @@
 		DODEBUG(Sent_Pkts, printf("i=%d, avail=%d\n", i, avail););
 
 		if (avail >= len + XMT_HEADER_LEN) {
-			IF_DEQUEUE(&ifp->if_snd, opkt);
+			IFQ_DEQUEUE(&ifp->if_snd, opkt);
 
 #ifdef EX_PSA_INTR      
 			/*
@@ -605,7 +608,7 @@
 	 * be sent, attempt to send more packets to the network card.
 	 */
 
-	if (send_pkts && (ifp->if_snd.ifq_head != NULL)) {
+	if (send_pkts && !IFQ_IS_EMPTY(&ifp->if_snd)) {
 		ex_start(ifp);
 	}
 
diff -urN ../sys/dev/fxp/if_fxp.c ./dev/fxp/if_fxp.c
--- ../sys/dev/fxp/if_fxp.c	Fri Aug 31 11:17:02 2001
+++ ./dev/fxp/if_fxp.c	Tue Oct  2 22:16:13 2001
@@ -614,6 +614,8 @@
 	ifp->if_ioctl = fxp_ioctl;
 	ifp->if_start = fxp_start;
 	ifp->if_watchdog = fxp_watchdog;
+	IFQ_SET_READY(&ifp->if_snd);
+	IFQ_SET_READY(&ifp->if_snd);
 
 	/*
 	 * Attach the interface.
@@ -631,7 +633,7 @@
 	 * Let the system queue as many packets as we have available
 	 * TX descriptors.
 	 */
-	ifp->if_snd.ifq_maxlen = FXP_NTXCB - 1;
+	IFQ_SET_MAXLEN(&ifp->if_snd, FXP_NTXCB - 1);
 
 	splx(s);
 	return (0);
@@ -1000,14 +1002,16 @@
 	 * NOTE: One TxCB is reserved to guarantee that fxp_mc_setup() can add
 	 *       a NOP command when needed.
 	 */
-	while (ifp->if_snd.ifq_head != NULL && sc->tx_queued < FXP_NTXCB - 1) {
+	while (!IFQ_IS_EMPTY(&ifp->if_snd) && sc->tx_queued < FXP_NTXCB - 1) {
 		struct mbuf *m, *mb_head;
 		int segment;
 
 		/*
 		 * Grab a packet to transmit.
 		 */
-		IF_DEQUEUE(&ifp->if_snd, mb_head);
+		IFQ_DEQUEUE(&ifp->if_snd, mb_head);
+		if (mb_head == NULL)
+			break;
 
 		/*
 		 * Get pointer to next available tx desc.
@@ -1118,6 +1122,11 @@
 	 * going again if suspended.
 	 */
 	if (txp != NULL) {
+#ifdef ALTQ
+		/* if tb regulator is used, we need tx complete interrupt */
+		if (TBR_IS_ENABLED(&ifp->if_snd))
+			txp->cb_command |= FXP_CB_COMMAND_I;
+#endif
 		fxp_scb_wait(sc);
 		fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_RESUME);
 	}
@@ -1186,7 +1195,7 @@
 			/*
 			 * Try to start more packets transmitting.
 			 */
-			if (ifp->if_snd.ifq_head != NULL)
+			if (!IFQ_IS_EMPTY(&ifp->if_snd))
 				fxp_start(ifp);
 		}
 		/*
diff -urN ../sys/dev/vx/if_vx.c ./dev/vx/if_vx.c
--- ../sys/dev/vx/if_vx.c	Mon Jul 30 07:48:37 2001
+++ ./dev/vx/if_vx.c	Tue Oct  2 22:06:19 2001
@@ -201,7 +201,7 @@
     ifp->if_unit = sc->unit;
     ifp->if_name = "vx";
     ifp->if_mtu = ETHERMTU;
-    ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
+    IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
     ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
     ifp->if_output = ether_output;
     ifp->if_start = vxstart;
@@ -209,6 +209,7 @@
     ifp->if_init = vxinit;
     ifp->if_watchdog = vxwatchdog;
     ifp->if_softc = sc;
+    IFQ_SET_READY(&ifp->if_snd);
 
     ether_ifattach(ifp, ETHER_BPF_SUPPORTED);
 
@@ -445,7 +446,7 @@
 
 startagain:
     /* Sneak a peek at the next packet */
-    m0 = ifp->if_snd.ifq_head;
+    IFQ_POLL(&ifp->if_snd, m0);
     if (m0 == 0) {
 	return;
     }
@@ -464,7 +465,7 @@
     if (len + pad > ETHER_MAX_LEN) {
 	/* packet is obviously too large: toss it */
 	++ifp->if_oerrors;
-	IF_DEQUEUE(&ifp->if_snd, m0);
+	IFQ_DEQUEUE(&ifp->if_snd, m0);
 	m_freem(m0);
 	goto readcheck;
     }
@@ -479,7 +480,7 @@
 	}
     }
     outw(BASE + VX_COMMAND, SET_TX_AVAIL_THRESH | (8188 >> 2));
-    IF_DEQUEUE(&ifp->if_snd, m0);
+    IFQ_DEQUEUE(&ifp->if_snd, m0);
     if (m0 == 0) {		/* not really needed */
 	return;
     }
diff -urN ../sys/i386/conf/ALTQ ./i386/conf/ALTQ
--- ../sys/i386/conf/ALTQ	Thu Jan  1 09:00:00 1970
+++ ./i386/conf/ALTQ	Tue Oct  2 22:20:13 2001
@@ -0,0 +1,277 @@
+#
+# GENERIC -- Generic kernel configuration file for FreeBSD/i386
+#
+# For more information on this file, please read the handbook section on
+# Kernel Configuration Files:
+#
+#    http://www.FreeBSD.org/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ./LINT configuration file. If you are
+# in doubt as to the purpose or necessity of a line, check first in LINT.
+#
+# $FreeBSD: src/sys/i386/conf/GENERIC,v 1.246.2.34 2001/08/12 13:13:46 joerg Exp $
+
+machine		i386
+cpu		I386_CPU
+cpu		I486_CPU
+cpu		I586_CPU
+cpu		I686_CPU
+ident		ALTQ
+maxusers	32
+
+#makeoptions	DEBUG=-g		#Build kernel with gdb(1) debug symbols
+
+options 	MATH_EMULATE		#Support for x87 emulation
+options 	INET			#InterNETworking
+options 	INET6			#IPv6 communications protocols
+options 	FFS			#Berkeley Fast Filesystem
+options 	FFS_ROOT		#FFS usable as root device [keep this!]
+options 	SOFTUPDATES		#Enable FFS soft updates support
+options 	MFS			#Memory Filesystem
+options 	MD_ROOT			#MD is a potential root device
+options 	NFS			#Network Filesystem
+options 	NFS_ROOT		#NFS usable as root device, NFS required
+options 	MSDOSFS			#MSDOS Filesystem
+options 	CD9660			#ISO 9660 Filesystem
+options 	CD9660_ROOT		#CD-ROM usable as root, CD9660 required
+options 	PROCFS			#Process filesystem
+options 	COMPAT_43		#Compatible with BSD 4.3 [KEEP THIS!]
+options 	SCSI_DELAY=15000	#Delay (in ms) before probing SCSI
+options 	UCONSOLE		#Allow users to grab the console
+options 	USERCONFIG		#boot -c editor
+options 	VISUAL_USERCONFIG	#visual boot -c editor
+options 	KTRACE			#ktrace(1) support
+options 	SYSVSHM			#SYSV-style shared memory
+options 	SYSVMSG			#SYSV-style message queues
+options 	SYSVSEM			#SYSV-style semaphores
+options 	P1003_1B		#Posix P1003_1B real-time extensions
+options 	_KPOSIX_PRIORITY_SCHEDULING
+options		ICMP_BANDLIM		#Rate limit bad replies
+options 	KBD_INSTALL_CDEV	# install a CDEV entry in /dev
+
+# To make an SMP kernel, the next two are needed
+#options 	SMP			# Symmetric MultiProcessor Kernel
+#options 	APIC_IO			# Symmetric (APIC) I/O
+
+device		isa
+device		eisa
+device		pci
+
+# Floppy drives
+device		fdc0	at isa? port IO_FD1 irq 6 drq 2
+device		fd0	at fdc0 drive 0
+device		fd1	at fdc0 drive 1
+#
+# If you have a Toshiba Libretto with its Y-E Data PCMCIA floppy,
+# don't use the above line for fdc0 but the following one:
+#device		fdc0
+
+# ATA and ATAPI devices
+device		ata0	at isa? port IO_WD1 irq 14
+device		ata1	at isa? port IO_WD2 irq 15
+device		ata
+device		atadisk			# ATA disk drives
+device		atapicd			# ATAPI CDROM drives
+device		atapifd			# ATAPI floppy drives
+device		atapist			# ATAPI tape drives
+options 	ATA_STATIC_ID		#Static device numbering
+
+# SCSI Controllers
+device		ahb		# EISA AHA1742 family
+device		ahc		# AHA2940 and onboard AIC7xxx devices
+device		amd		# AMD 53C974 (Tekram DC-390(T))
+device		isp		# Qlogic family
+device		ncr		# NCR/Symbios Logic
+device		sym		# NCR/Symbios Logic (newer chipsets)
+options		SYM_SETUP_LP_PROBE_MAP=0x40
+				# Allow ncr to attach legacy NCR devices when 
+				# both sym and ncr are configured
+
+device		adv0	at isa?
+device		adw
+device		bt0	at isa?
+device		aha0	at isa?
+device		aic0	at isa?
+
+device		ncv		# NCR 53C500
+device		nsp		# Workbit Ninja SCSI-3
+device		stg		# TMC 18C30/18C50
+
+# SCSI peripherals
+device		scbus		# SCSI bus (required)
+device		da		# Direct Access (disks)
+device		sa		# Sequential Access (tape etc)
+device		cd		# CD
+device		pass		# Passthrough device (direct SCSI access)
+
+# RAID controllers interfaced to the SCSI subsystem
+device		asr		# DPT SmartRAID V, VI and Adaptec SCSI RAID
+device		dpt		# DPT Smartcache - See LINT for options!
+device		mly		# Mylex AcceleRAID/eXtremeRAID
+
+# RAID controllers
+device		aac		# Adaptec FSA RAID, Dell PERC2/PERC3
+device		ida		# Compaq Smart RAID
+device		amr		# AMI MegaRAID
+device		mlx		# Mylex DAC960 family
+device		twe		# 3ware Escalade
+
+# atkbdc0 controls both the keyboard and the PS/2 mouse
+device		atkbdc0	at isa? port IO_KBD
+device		atkbd0	at atkbdc? irq 1 flags 0x1
+device		psm0	at atkbdc? irq 12
+
+device		vga0	at isa?
+
+# splash screen/screen saver
+pseudo-device	splash
+
+# syscons is the default console driver, resembling an SCO console
+device		sc0	at isa? flags 0x100
+
+# Enable this and PCVT_FREEBSD for pcvt vt220 compatible console driver
+#device		vt0	at isa?
+#options 	XSERVER			# support for X server on a vt console
+#options 	FAT_CURSOR		# start with block cursor
+# If you have a ThinkPAD, uncomment this along with the rest of the PCVT lines
+#options 	PCVT_SCANSET=2		# IBM keyboards are non-std
+
+# Floating point support - do not disable.
+device		npx0	at nexus? port IO_NPX irq 13
+
+# Power management support (see LINT for more options)
+device		apm0    at nexus? disable flags 0x20 # Advanced Power Management
+
+# PCCARD (PCMCIA) support
+device		card
+device		pcic0	at isa? irq 0 port 0x3e0 iomem 0xd0000
+device		pcic1	at isa? irq 0 port 0x3e2 iomem 0xd4000 disable
+
+# Serial (COM) ports
+device		sio0	at isa? port IO_COM1 flags 0x10 irq 4
+device		sio1	at isa? port IO_COM2 irq 3
+device		sio2	at isa? disable port IO_COM3 irq 5
+device		sio3	at isa? disable port IO_COM4 irq 9
+
+# Parallel port
+device		ppc0	at isa? irq 7
+device		ppbus		# Parallel port bus (required)
+device		lpt		# Printer
+device		plip		# TCP/IP over parallel
+device		ppi		# Parallel port interface device
+#device		vpo		# Requires scbus and da
+
+
+# PCI Ethernet NICs.
+device		de		# DEC/Intel DC21x4x (``Tulip'')
+device		txp		# 3Com 3cR990 (``Typhoon'')
+device		vx		# 3Com 3c590, 3c595 (``Vortex'')
+
+# PCI Ethernet NICs that use the common MII bus controller code.
+# NOTE: Be sure to keep the 'device miibus' line in order to use these NICs!
+device		miibus		# MII bus support
+device		dc		# DEC/Intel 21143 and various workalikes
+device		fxp		# Intel EtherExpress PRO/100B (82557, 82558)
+device		pcn		# AMD Am79C97x PCI 10/100 NICs
+device		rl		# RealTek 8129/8139
+device		sf		# Adaptec AIC-6915 (``Starfire'')
+device		sis		# Silicon Integrated Systems SiS 900/SiS 7016
+device		ste		# Sundance ST201 (D-Link DFE-550TX)
+device		tl		# Texas Instruments ThunderLAN
+device		tx		# SMC EtherPower II (83c170 ``EPIC'')
+device		vr		# VIA Rhine, Rhine II
+device		wb		# Winbond W89C840F
+device		wx		# Intel Gigabit Ethernet Card (``Wiseman'')
+device		xl		# 3Com 3c90x (``Boomerang'', ``Cyclone'')
+
+# ISA Ethernet NICs.
+# 'device ed' requires 'device miibus'
+device		ed0	at isa? port 0x280 irq 10 iomem 0xd8000
+device		ex
+device		ep
+device		fe0	at isa? port 0x300
+# Xircom Ethernet
+device		xe
+# PRISM I IEEE 802.11b wireless NIC.
+device		awi
+# WaveLAN/IEEE 802.11 wireless NICs. Note: the WaveLAN/IEEE really
+# exists only as a PCMCIA device, so there is no ISA attachment needed
+# and resources will always be dynamically assigned by the pccard code.
+device		wi
+# Aironet 4500/4800 802.11 wireless NICs. Note: the declaration below will
+# work for PCMCIA and PCI cards, as well as ISA cards set to ISA PnP
+# mode (the factory default). If you set the switches on your ISA
+# card for a manually chosen I/O address and IRQ, you must specify
+# those parameters here.
+device		an
+# The probe order of these is presently determined by i386/isa/isa_compat.c.
+device		ie0	at isa? port 0x300 irq 10 iomem 0xd0000
+#device		le0	at isa? port 0x300 irq 5 iomem 0xd0000
+device		lnc0	at isa? port 0x280 irq 10 drq 0
+device		cs0	at isa? port 0x300
+device		sn0	at isa? port 0x300 irq 10
+
+# Pseudo devices - the number indicates how many units to allocate.
+pseudo-device	loop		# Network loopback
+pseudo-device	ether		# Ethernet support
+pseudo-device	sl	1	# Kernel SLIP
+pseudo-device	ppp	1	# Kernel PPP
+pseudo-device	tun		# Packet tunnel.
+pseudo-device	pty		# Pseudo-ttys (telnet etc)
+pseudo-device	md		# Memory "disks"
+pseudo-device	gif		# IPv6 and IPv4 tunneling
+pseudo-device	faith	1	# IPv6-to-IPv4 relaying (translation)
+
+# The `bpf' pseudo-device enables the Berkeley Packet Filter.
+# Be aware of the administrative consequences of enabling this!
+pseudo-device	bpf		#Berkeley packet filter
+
+# USB support
+device		uhci		# UHCI PCI->USB interface
+device		ohci		# OHCI PCI->USB interface
+device		usb		# USB Bus (required)
+device		ugen		# Generic
+device		uhid		# "Human Interface Devices"
+device		ukbd		# Keyboard
+device		ulpt		# Printer
+device		umass		# Disks/Mass storage - Requires scbus and da
+device		ums		# Mouse
+device		uscanner	# Scanners
+# USB Ethernet, requires mii
+device		aue		# ADMtek USB ethernet
+device		cue		# CATC USB ethernet
+device		kue		# Kawasaki LSI USB ethernet
+
+# ALTQ options
+options 	ALTQ		#alternate queueing
+#options 	ALTQ_CBQ	#class based queueing
+#options 	ALTQ_WFQ	#weighted fair queueing
+#options 	ALTQ_FIFOQ	#fifo queueing
+#options 	ALTQ_RED	#random early detection
+#options 	ALTQ_FLOWVALVE	#flowvalve for RED (needs RED)
+#options 	ALTQ_RIO	#triple	 red for diffserv (needs RED)
+#options 	ALTQ_LOCALQ	#local use
+#options 	ALTQ_HFSC	#hierarchical fair service curve
+#options 	ALTQ_ECN	#ecn extention to tcp (needs RED)
+#options 	ALTQ_IPSEC	#check ipsec in IPv4
+#options 	ALTQ_CDNR	#diffserv traffic conditioner
+#options 	ALTQ_BLUE	#blue by wu-chang feng
+#options 	ALTQ_PRIQ	#priority queue
+#options 	ALTQ_NOPCC	#don't use processor cycle counter
+#options 	ALTQ_DEBUG	#for debugging
+# you might want to set kernel timer to 1kHz if you use CBQ,
+# especially with 100baseT
+#options 	HZ=1000
+
+# options added for ALTQ
+options		NMBCLUSTERS=2048
+options		MROUTING		# Multicast routing
+pseudo-device	atm
+device		en
+#options	NATM			#native mode atm
diff -urN ../sys/i386/conf/LINT ./i386/conf/LINT
--- ../sys/i386/conf/LINT	Thu Aug 30 21:29:56 2001
+++ ./i386/conf/LINT	Tue Oct  2 22:06:19 2001
@@ -2526,3 +2526,21 @@
 options 	VM_KMEM_SIZE_MAX
 options 	VM_KMEM_SIZE_SCALE
 options		XBONEHACK
+
+# ALTQ options
+options 	ALTQ		#alternate queueing
+options 	ALTQ_CBQ	#class based queueing
+options 	ALTQ_WFQ	#weighted fair queueing
+options 	ALTQ_FIFOQ	#fifo queueing
+options 	ALTQ_RED	#random early detection
+options 	ALTQ_FLOWVALVE	#flowvalve for RED (needs RED)
+options 	ALTQ_RIO	#triple	 red for diffserv (needs RED)
+options 	ALTQ_LOCALQ	#local use
+options 	ALTQ_HFSC	#hierarchical fair service curve
+options 	ALTQ_ECN	#ecn extention to tcp (needs RED)
+options 	ALTQ_IPSEC	#check ipsec in IPv4
+options 	ALTQ_CDNR	#diffserv traffic conditioner
+options 	ALTQ_BLUE	#blue by wu-chang feng
+options 	ALTQ_PRIQ	#priority queue
+options 	ALTQ_NOPCC	#don't use processor cycle counter
+options 	ALTQ_DEBUG	#for debugging
diff -urN ../sys/i386/isa/if_ar.c ./i386/isa/if_ar.c
--- ../sys/i386/isa/if_ar.c	Fri Jan 21 10:39:39 2000
+++ ./i386/isa/if_ar.c	Tue Oct  2 22:06:19 2001
@@ -472,6 +472,7 @@
 		ifp->if_ioctl = arioctl;
 		ifp->if_start = arstart;
 		ifp->if_watchdog = arwatchdog;
+		IFQ_SET_READY(&ifp->if_snd);
 
 		sc->ifsppp.pp_flags = PP_KEEPALIVE;
 
diff -urN ../sys/i386/isa/if_cx.c ./i386/isa/if_cx.c
--- ../sys/i386/isa/if_cx.c	Thu Nov 18 17:36:42 1999
+++ ./i386/isa/if_cx.c	Tue Oct  2 22:06:19 2001
@@ -273,6 +273,7 @@
 			c->ifp->if_ioctl = cxsioctl;
 			c->ifp->if_start = (start_func_t) cxstart;
 			c->ifp->if_watchdog = (watchdog_func_t) cxwatchdog;
+			IFQ_SET_READY(&c->ifp->if_snd);
 			/* Init routine is never called by upper level? */
 			sppp_attach (c->ifp);
 			if_attach (c->ifp);
diff -urN ../sys/i386/isa/if_lnc.c ./i386/isa/if_lnc.c
--- ../sys/i386/isa/if_lnc.c	Tue Jan  9 00:37:59 2001
+++ ./i386/isa/if_lnc.c	Tue Oct  2 22:06:19 2001
@@ -356,6 +356,7 @@
 
 	head = desc->buff.mbuf;
 	head->m_flags |= M_PKTHDR;
+	bzero(&head->m_pkthdr, sizeof(head->m_pkthdr));
 
 	m = head;
 	do {
@@ -1240,7 +1241,8 @@
 	sc->arpcom.ac_if.if_type = IFT_ETHER;
 	sc->arpcom.ac_if.if_addrlen = ETHER_ADDR_LEN;
 	sc->arpcom.ac_if.if_hdrlen = ETHER_HDR_LEN;
-	sc->arpcom.ac_if.if_snd.ifq_maxlen = IFQ_MAXLEN;
+	IFQ_SET_MAXLEN(&sc->arpcom.ac_if.if_snd, IFQ_MAXLEN);
+	IFQ_SET_READY(&sc->arpcom.ac_if.if_snd);
 
 	ether_ifattach(&sc->arpcom.ac_if, ETHER_BPF_SUPPORTED);
 
@@ -1649,7 +1651,7 @@
 
 	do {
 
-		IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, head);
+		IFQ_DEQUEUE(&sc->arpcom.ac_if.if_snd, head);
 		if (!head)
 			return;
 
diff -urN ../sys/i386/isa/if_sr.c ./i386/isa/if_sr.c
--- ../sys/i386/isa/if_sr.c	Thu Mar  1 04:08:56 2001
+++ ./i386/isa/if_sr.c	Tue Oct  2 22:06:19 2001
@@ -913,6 +913,7 @@
 		ifp->if_ioctl = srioctl;
 		ifp->if_start = srstart;
 		ifp->if_watchdog = srwatchdog;
+		IFQ_SET_READY(&ifp->if_snd);
 
 		sc->ifsppp.pp_flags = PP_KEEPALIVE;
 		sppp_attach((struct ifnet *)&sc->ifsppp);
diff -urN ../sys/i386/isa/if_wi.c ./i386/isa/if_wi.c
--- ../sys/i386/isa/if_wi.c	Tue Aug 28 15:21:14 2001
+++ ./i386/isa/if_wi.c	Tue Oct  2 22:08:51 2001
@@ -483,7 +483,8 @@
 	ifp->if_watchdog = wi_watchdog;
 	ifp->if_init = wi_init;
 	ifp->if_baudrate = 10000000;
-	ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
+	IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
+	IFQ_SET_READY(&ifp->if_snd);
 
 	bzero(sc->wi_node_name, sizeof(sc->wi_node_name));
 	bcopy(WI_DEFAULT_NODENAME, sc->wi_node_name,
@@ -815,7 +816,7 @@
 	/* Re-enable interrupts. */
 	CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
 
-	if (ifp->if_snd.ifq_head != NULL) {
+	if (!IFQ_IS_EMPTY(&ifp->if_snd)) {
 		wi_start(ifp);
 	}
 
@@ -1782,7 +1783,7 @@
 		return;
 	}
 
-	IF_DEQUEUE(&ifp->if_snd, m0);
+	IFQ_DEQUEUE(&ifp->if_snd, m0);
 	if (m0 == NULL) {
 		return;
 	}
diff -urN ../sys/i386/isa/if_wl.c ./i386/isa/if_wl.c
--- ../sys/i386/isa/if_wl.c	Tue Jul 18 06:24:32 2000
+++ ./i386/isa/if_wl.c	Tue Oct  2 22:06:19 2001
@@ -505,6 +505,7 @@
        ifp->if_done
        ifp->if_reset
        */
+    IFQ_SET_READY(&ifp->if_snd);
     ether_ifattach(ifp, ETHER_BPF_SUPPORTED);
 
     bcopy(&sc->wl_addr[0], sc->wl_ac.ac_enaddr, WAVELAN_ADDR_SIZE);
@@ -886,7 +887,7 @@
 
     /* get ourselves some data */
     ifp = &(sc->wl_if);
-    IF_DEQUEUE(&ifp->if_snd, m);
+    IFQ_DEQUEUE(&ifp->if_snd, m);
     if (m != (struct mbuf *)0) {
 	/* let BPF see it before we commit it */
 	if (ifp->if_bpf) {
diff -urN ../sys/modules/Makefile ./modules/Makefile
--- ../sys/modules/Makefile	Sat Aug 11 09:54:14 2001
+++ ./modules/Makefile	Tue Oct  2 22:06:20 2001
@@ -100,6 +100,8 @@
 	wi
 .endif
 
+SUBDIR+=altq
+
 .if ${MACHINE} == "pc98"
 SUBDIR+=snc
 .endif
diff -urN ../sys/modules/altq/Makefile ./modules/altq/Makefile
--- ../sys/modules/altq/Makefile	Thu Jan  1 09:00:00 1970
+++ ./modules/altq/Makefile	Tue Oct  2 22:06:20 2001
@@ -0,0 +1,4 @@
+
+SUBDIR=	altq_blue altq_cbq altq_cdnr altq_fifoq altq_hfsc altq_localq altq_priq altq_red altq_rio altq_wfq
+
+.include <bsd.subdir.mk>
diff -urN ../sys/modules/altq/Makefile.inc ./modules/altq/Makefile.inc
--- ../sys/modules/altq/Makefile.inc	Thu Jan  1 09:00:00 1970
+++ ./modules/altq/Makefile.inc	Tue Oct  2 22:06:20 2001
@@ -0,0 +1,3 @@
+# $Id: Makefile.inc,v 1.1 2000/04/17 11:32:21 kjc Exp $
+
+KLDMOD=	true
diff -urN ../sys/modules/altq/altq_blue/Makefile ./modules/altq/altq_blue/Makefile
--- ../sys/modules/altq/altq_blue/Makefile	Thu Jan  1 09:00:00 1970
+++ ./modules/altq/altq_blue/Makefile	Tue Oct  2 22:06:20 2001
@@ -0,0 +1,28 @@
+
+.PATH:	${.CURDIR}/../../../altq
+KMOD=	altq_blue
+SRCS=	altq_blue.c opt_altq.h opt_inet.h opt_inet6.h
+
+CFLAGS+= -DALTQ
+CLEANFILES+= opt_altq.h opt_inet.h opt_inet6.h
+
+ALTQMOD_INET?=	1
+ALTQMOD_INET6?=	1
+
+opt_altq.h:
+	echo "#define ALTQ_BLUE 1" > opt_altq.h
+
+opt_inet.h:
+	touch opt_inet.h
+.if ${ALTQMOD_INET} > 0
+	echo "#define INET 1" > opt_inet.h
+.endif
+
+opt_inet6.h:
+	touch opt_inet6.h
+.if ${ALTQMOD_INET6} > 0
+	echo "#define INET6 1" > opt_inet6.h
+.endif
+
+.include <bsd.kmod.mk>
+
diff -urN ../sys/modules/altq/altq_cbq/Makefile ./modules/altq/altq_cbq/Makefile
--- ../sys/modules/altq/altq_cbq/Makefile	Thu Jan  1 09:00:00 1970
+++ ./modules/altq/altq_cbq/Makefile	Tue Oct  2 22:06:20 2001
@@ -0,0 +1,41 @@
+
+.PATH:	${.CURDIR}/../../../altq
+KMOD=	altq_cbq
+SRCS=	altq_cbq.c altq_rmclass.c opt_altq.h opt_inet.h opt_inet6.h
+KMODDEPS=	altq_red altq_rio
+
+CFLAGS+= -DALTQ
+CLEANFILES+= opt_altq.h opt_inet.h opt_inet6.h
+
+ALTQMOD_ALTQ_RED?=	1
+ALTQMOD_ALTQ_RIO?=	1
+ALTQMOD_ALTQ_FLOWVALVE?=	1
+ALTQMOD_INET?=	1
+ALTQMOD_INET6?=	1
+
+opt_altq.h:
+	echo "#define ALTQ_CBQ 1" > opt_altq.h
+.if ${ALTQMOD_ALTQ_RED} > 0
+	echo "#define ALTQ_RED 1" >> opt_altq.h
+.endif
+.if ${ALTQMOD_ALTQ_RIO} > 0
+	echo "#define ALTQ_RIO 1" >> opt_altq.h
+.endif
+.if ${ALTQMOD_ALTQ_FLOWVALVE} > 0
+	echo "#define ALTQ_FLOWVALVE 1" >> opt_altq.h
+.endif
+
+opt_inet.h:
+	touch opt_inet.h
+.if ${ALTQMOD_INET} > 0
+	echo "#define INET 1" > opt_inet.h
+.endif
+
+opt_inet6.h:
+	touch opt_inet6.h
+.if ${ALTQMOD_INET6} > 0
+	echo "#define INET6 1" > opt_inet6.h
+.endif
+
+.include <bsd.kmod.mk>
+
diff -urN ../sys/modules/altq/altq_cdnr/Makefile ./modules/altq/altq_cdnr/Makefile
--- ../sys/modules/altq/altq_cdnr/Makefile	Thu Jan  1 09:00:00 1970
+++ ./modules/altq/altq_cdnr/Makefile	Tue Oct  2 22:06:20 2001
@@ -0,0 +1,28 @@
+
+.PATH:	${.CURDIR}/../../../altq
+KMOD=	altq_cdnr
+SRCS=	altq_cdnr.c opt_altq.h opt_inet.h opt_inet6.h
+
+CFLAGS+= -DALTQ
+CLEANFILES+= opt_altq.h opt_inet.h opt_inet6.h
+
+ALTQMOD_INET?=	1
+ALTQMOD_INET6?=	1
+
+opt_altq.h:
+	echo "#define ALTQ_CDNR 1" > opt_altq.h
+
+opt_inet.h:
+	touch opt_inet.h
+.if ${ALTQMOD_INET} > 0
+	echo "#define INET 1" > opt_inet.h
+.endif
+
+opt_inet6.h:
+	touch opt_inet6.h
+.if ${ALTQMOD_INET6} > 0
+	echo "#define INET6 1" > opt_inet6.h
+.endif
+
+.include <bsd.kmod.mk>
+
diff -urN ../sys/modules/altq/altq_fifoq/Makefile ./modules/altq/altq_fifoq/Makefile
--- ../sys/modules/altq/altq_fifoq/Makefile	Thu Jan  1 09:00:00 1970
+++ ./modules/altq/altq_fifoq/Makefile	Tue Oct  2 22:06:20 2001
@@ -0,0 +1,13 @@
+
+.PATH:	${.CURDIR}/../../../altq
+KMOD=	altq_fifoq
+SRCS=	altq_fifoq.c opt_altq.h
+
+CFLAGS+= -DALTQ
+CLEANFILES+= opt_altq.h
+
+opt_altq.h:
+	echo "#define ALTQ_FIFOQ 1" > opt_altq.h
+
+.include <bsd.kmod.mk>
+
diff -urN ../sys/modules/altq/altq_hfsc/Makefile ./modules/altq/altq_hfsc/Makefile
--- ../sys/modules/altq/altq_hfsc/Makefile	Thu Jan  1 09:00:00 1970
+++ ./modules/altq/altq_hfsc/Makefile	Tue Oct  2 22:06:20 2001
@@ -0,0 +1,40 @@
+
+.PATH:	${.CURDIR}/../../../altq
+KMOD=	altq_hfsc
+SRCS=	altq_hfsc.c opt_altq.h opt_inet.h opt_inet6.h
+KMODDEPS=	altq_red altq_rio
+
+CFLAGS+= -DALTQ
+CLEANFILES+= opt_altq.h opt_inet.h opt_inet6.h
+
+ALTQMOD_ALTQ_RED?=	1
+ALTQMOD_ALTQ_RIO?=	1
+ALTQMOD_ALTQ_FLOWVALVE?=	1
+ALTQMOD_INET?=	1
+ALTQMOD_INET6?=	1
+
+opt_altq.h:
+	echo "#define ALTQ_HFSC 1" > opt_altq.h
+.if ${ALTQMOD_ALTQ_RED} > 0
+	echo "#define ALTQ_RED 1" >> opt_altq.h
+.endif
+.if ${ALTQMOD_ALTQ_RIO} > 0
+	echo "#define ALTQ_RIO 1" >> opt_altq.h
+.endif
+.if ${ALTQMOD_ALTQ_FLOWVALVE} > 0
+	echo "#define ALTQ_FLOWVALVE 1" >> opt_altq.h
+.endif
+
+opt_inet.h:
+	touch opt_inet.h
+.if ${ALTQMOD_INET} > 0
+	echo "#define INET 1" > opt_inet.h
+.endif
+
+opt_inet6.h:
+	touch opt_inet6.h
+.if ${ALTQMOD_INET6} > 0
+	echo "#define INET6 1" > opt_inet6.h
+.endif
+
+.include <bsd.kmod.mk>
diff -urN ../sys/modules/altq/altq_localq/Makefile ./modules/altq/altq_localq/Makefile
--- ../sys/modules/altq/altq_localq/Makefile	Thu Jan  1 09:00:00 1970
+++ ./modules/altq/altq_localq/Makefile	Tue Oct  2 22:06:20 2001
@@ -0,0 +1,12 @@
+
+.PATH:	${.CURDIR}/../../../altq
+KMOD=	altq_localq
+SRCS=	altq_localq.c opt_altq.h
+
+CFLAGS+= -DALTQ
+CLEANFILES+= opt_altq.h
+
+opt_altq.h:
+	echo "#define ALTQ_LOCALQ 1" > opt_altq.h
+
+.include <bsd.kmod.mk>
diff -urN ../sys/modules/altq/altq_priq/Makefile ./modules/altq/altq_priq/Makefile
--- ../sys/modules/altq/altq_priq/Makefile	Thu Jan  1 09:00:00 1970
+++ ./modules/altq/altq_priq/Makefile	Tue Oct  2 22:06:20 2001
@@ -0,0 +1,40 @@
+
+.PATH:	${.CURDIR}/../../../altq
+KMOD=	altq_priq
+SRCS=	altq_priq.c opt_altq.h opt_inet.h opt_inet6.h
+KMODDEPS=	altq_red altq_rio
+
+CFLAGS+= -DALTQ
+CLEANFILES+= opt_altq.h opt_inet.h opt_inet6.h
+
+ALTQMOD_ALTQ_RED?=	1
+ALTQMOD_ALTQ_RIO?=	1
+ALTQMOD_ALTQ_FLOWVALVE?=	1
+ALTQMOD_INET?=	1
+ALTQMOD_INET6?=	1
+
+opt_altq.h:
+	echo "#define ALTQ_PRIQ 1" > opt_altq.h
+.if ${ALTQMOD_ALTQ_RED} > 0
+	echo "#define ALTQ_RED 1" >> opt_altq.h
+.endif
+.if ${ALTQMOD_ALTQ_RIO} > 0
+	echo "#define ALTQ_RIO 1" >> opt_altq.h
+.endif
+.if ${ALTQMOD_ALTQ_FLOWVALVE} > 0
+	echo "#define ALTQ_FLOWVALVE 1" >> opt_altq.h
+.endif
+
+opt_inet.h:
+	touch opt_inet.h
+.if ${ALTQMOD_INET} > 0
+	echo "#define INET 1" > opt_inet.h
+.endif
+
+opt_inet6.h:
+	touch opt_inet6.h
+.if ${ALTQMOD_INET6} > 0
+	echo "#define INET6 1" > opt_inet6.h
+.endif
+
+.include <bsd.kmod.mk>
diff -urN ../sys/modules/altq/altq_red/Makefile ./modules/altq/altq_red/Makefile
--- ../sys/modules/altq/altq_red/Makefile	Thu Jan  1 09:00:00 1970
+++ ./modules/altq/altq_red/Makefile	Tue Oct  2 22:06:20 2001
@@ -0,0 +1,32 @@
+
+.PATH:	${.CURDIR}/../../../altq
+KMOD=	altq_red
+SRCS=	altq_red.c opt_altq.h opt_inet.h opt_inet6.h
+
+CFLAGS+= -DALTQ
+CLEANFILES+= opt_altq.h opt_inet.h opt_inet6.h
+
+ALTQMOD_ALTQ_FLOWVALVE?=	1
+ALTQMOD_INET?=	1
+ALTQMOD_INET6?=	1
+
+opt_altq.h:
+	echo "#define ALTQ_RED 1" > opt_altq.h
+.if ${ALTQMOD_ALTQ_FLOWVALVE} > 0
+	echo "#define ALTQ_FLOWVALVE 1" >> opt_altq.h
+.endif
+
+opt_inet.h:
+	touch opt_inet.h
+.if ${ALTQMOD_INET} > 0
+	echo "#define INET 1" > opt_inet.h
+.endif
+
+opt_inet6.h:
+	touch opt_inet6.h
+.if ${ALTQMOD_INET6} > 0
+	echo "#define INET6 1" > opt_inet6.h
+.endif
+
+.include <bsd.kmod.mk>
+
diff -urN ../sys/modules/altq/altq_rio/Makefile ./modules/altq/altq_rio/Makefile
--- ../sys/modules/altq/altq_rio/Makefile	Thu Jan  1 09:00:00 1970
+++ ./modules/altq/altq_rio/Makefile	Tue Oct  2 22:06:21 2001
@@ -0,0 +1,28 @@
+
+.PATH:	${.CURDIR}/../../../altq
+KMOD=	altq_rio
+SRCS=	altq_rio.c opt_altq.h opt_inet.h opt_inet6.h
+
+CFLAGS+= -DALTQ
+CLEANFILES+= opt_altq.h opt_inet.h opt_inet6.h
+
+ALTQMOD_INET?=	1
+ALTQMOD_INET6?=	1
+
+opt_altq.h:
+	echo "#define ALTQ_RIO 1" > opt_altq.h
+
+opt_inet.h:
+	touch opt_inet.h
+.if ${ALTQMOD_INET} > 0
+	echo "#define INET 1" > opt_inet.h
+.endif
+
+opt_inet6.h:
+	touch opt_inet6.h
+.if ${ALTQMOD_INET6} > 0
+	echo "#define INET6 1" > opt_inet6.h
+.endif
+
+.include <bsd.kmod.mk>
+
diff -urN ../sys/modules/altq/altq_wfq/Makefile ./modules/altq/altq_wfq/Makefile
--- ../sys/modules/altq/altq_wfq/Makefile	Thu Jan  1 09:00:00 1970
+++ ./modules/altq/altq_wfq/Makefile	Tue Oct  2 22:06:21 2001
@@ -0,0 +1,26 @@
+
+.PATH:	${.CURDIR}/../../../altq
+KMOD=	altq_wfq
+SRCS=	altq_wfq.c opt_altq.h opt_inet.h opt_inet6.h
+
+CFLAGS+= -DALTQ
+CLEANFILES+= opt_altq.h opt_inet.h opt_inet6.h
+
+ALTQMOD_INET?=	1
+ALTQMOD_INET6?=	1
+
+opt_altq.h:
+	echo "#define ALTQ_WFQ 1" > opt_altq.h
+
+opt_inet.h:
+	touch opt_inet.h
+.if ${ALTQMOD_INET} > 0
+	echo "#define INET 1" > opt_inet.h
+.endif
+
+opt_inet6.h:
+	touch opt_inet6.h
+.if ${ALTQMOD_INET6} > 0
+	echo "#define INET6 1" > opt_inet6.h
+.endif
+.include <bsd.kmod.mk>
diff -urN ../sys/net/bridge.c ./net/bridge.c
--- ../sys/net/bridge.c	Sat Feb 10 08:13:41 2001
+++ ./net/bridge.c	Tue Oct  2 22:06:21 2001
@@ -79,6 +79,9 @@
 
 #include <net/if.h>
 #include <net/if_types.h>
+#ifdef ALTQ
+#include <net/if_llc.h>
+#endif
 
 #include <netinet/in.h> /* for struct arpcom */
 #include <netinet/in_systm.h>
@@ -607,7 +610,7 @@
 {
     struct ifnet *src = m0->m_pkthdr.rcvif; /* could be NULL in output */
     struct ifnet *ifp, *last = NULL ;
-    int s ;
+    int error = 0, s ;
     int shared = bdg_copy ; /* someone else is using the mbuf */
     int once = 0;      /* loop only once */
     struct ifnet *real_dst = dst ; /* real dst from ether_output */
@@ -780,6 +783,13 @@
     for (;;) {
 	if (last) { /* need to forward packet leftover from previous loop */
 	    struct mbuf *m ;
+	    short mflags;
+	    int len;
+#ifdef ALTQ
+	    struct altq_pktattr pktattr;
+	    int af;
+#endif
+
 	    if (shared == 0 && once ) { /* no need to copy */
 		m = m0 ;
 		m0 = NULL ; /* original is gone */
@@ -790,6 +800,26 @@
 		    return m0 ; /* the original is still there... */
 		}
 	    }
+#ifdef ALTQ
+	    if (ALTQ_IS_ENABLED(&last->if_snd)) {
+		    u_short	ether_type;
+
+		    /*
+		     * if the queueing discipline needs packet classification,
+		     * do it before prepending link headers.
+		     */
+		    ether_type = ntohs(eh->ether_type);
+		    if (ether_type == ETHERTYPE_IP)
+			    af = AF_INET;
+#ifdef INET6
+		    else if (ether_type == ETHERTYPE_IPV6)
+			    af = AF_INET6;
+#endif
+		    else
+			    af = AF_UNSPEC;
+		    IFQ_CLASSIFY(&last->if_snd, m, af, &pktattr);
+	    }
+#endif /* ALTQ */
 	    /*
 	     * Add header (optimized for the common case of eh pointing
 	     * already into the mbuf) and execute last part of ether_output:
@@ -807,26 +837,26 @@
 		    return m0;
 		bcopy(&save_eh, mtod(m, struct ether_header *), ETHER_HDR_LEN);
 	    }
+	    mflags = m->m_flags;
+	    len = m->m_pkthdr.len;
 	    s = splimp();
-	    if (IF_QFULL(&last->if_snd)) {
-		IF_DROP(&last->if_snd);
-#if 0
-		BDG_MUTE(last); /* should I also mute ? */
+#ifdef ALTQ
+	    IFQ_ENQUEUE(&last->if_snd, m, &pktattr, error);
+#else
+	    IFQ_ENQUEUE(&last->if_snd, m, error);
 #endif
-		splx(s);
-		m_freem(m); /* consume the pkt anyways */
-	    } else {
-		last->if_obytes += m->m_pkthdr.len ;
-		if (m->m_flags & M_MCAST)
+	    if (error == 0) {
+		last->if_obytes += len;
+		if (mflags & M_MCAST)
 		    last->if_omcasts++;
 		if (m->m_pkthdr.len != m->m_len) /* this pkt is on >1 bufs */
 		    bdg_split_pkts++;
 
-		IF_ENQUEUE(&last->if_snd, m);
 		if ((last->if_flags & IFF_OACTIVE) == 0)
 		    (*last->if_start)(last);
-		splx(s);
 	    }
+	    splx(s);
+
 	    BDG_STAT(last, BDG_OUT);
 	    last = NULL ;
 	    if (once)
@@ -839,7 +869,10 @@
 	 * up and running, is not the source interface, and belongs to
 	 * the same cluster as the 'real_dst', then send here.
 	 */
-	if ( BDG_USED(ifp) && !BDG_MUTED(ifp) && !IF_QFULL(&ifp->if_snd)  &&
+	if ( BDG_USED(ifp) && !BDG_MUTED(ifp) &&
+#ifndef ALTQ
+	     !IF_QFULL(&ifp->if_snd)  &&
+#endif
 	     (ifp->if_flags & (IFF_UP|IFF_RUNNING)) == (IFF_UP|IFF_RUNNING) &&
 	     ifp != src && BDG_SAMECLUSTER(ifp, real_dst) )
 	    last = ifp ;
diff -urN ../sys/net/if.c ./net/if.c
--- ../sys/net/if.c	Wed Jul 25 04:10:17 2001
+++ ./net/if.c	Tue Oct  2 22:06:21 2001
@@ -76,7 +76,11 @@
 
 static int ifconf __P((u_long, caddr_t));
 static void ifinit __P((void *));
+#ifdef ALTQ
+static void if_qflush __P((struct ifaltq *));
+#else
 static void if_qflush __P((struct ifqueue *));
+#endif
 static void if_slowtimo __P((void *));
 static void link_rtrequest __P((int, struct rtentry *, struct sockaddr *));
 static int  if_rtdel __P((struct radix_node *, void *));
@@ -224,6 +228,13 @@
 			sdl->sdl_data[--namelen] = 0xff;
 		TAILQ_INSERT_HEAD(&ifp->if_addrhead, ifa, ifa_link);
 	}
+#ifdef ALTQ
+	ifp->if_snd.altq_type = 0;
+	ifp->if_snd.altq_disc = NULL;
+	ifp->if_snd.altq_flags &= ALTQF_CANTCHANGE;
+	ifp->if_snd.altq_tbr  = NULL;
+	ifp->if_snd.altq_ifp  = ifp;
+#endif
 }
 
 /*
@@ -244,6 +255,12 @@
 	 */
 	s = splnet();
 	if_down(ifp);
+#ifdef ALTQ
+	if (ALTQ_IS_ENABLED(&ifp->if_snd))
+		altq_disable(&ifp->if_snd);
+	if (ALTQ_IS_ATTACHED(&ifp->if_snd))
+		altq_detach(&ifp->if_snd);
+#endif
 
 	/*
 	 * Remove address from ifnet_addrs[] and maybe decrement if_index.
@@ -823,10 +840,18 @@
  */
 static void
 if_qflush(ifq)
+#ifdef ALTQ
+	struct ifaltq *ifq;
+#else
 	register struct ifqueue *ifq;
+#endif
 {
 	register struct mbuf *m, *n;
 
+#ifdef ALTQ
+	if (ALTQ_IS_ENABLED(ifq))
+		ALTQ_PURGE(ifq);
+#endif
 	n = ifq->ifq_head;
 	while ((m = n) != 0) {
 		n = m->m_act;
diff -urN ../sys/net/if_atm.h ./net/if_atm.h
--- ../sys/net/if_atm.h	Wed Dec 29 13:38:34 1999
+++ ./net/if_atm.h	Tue Oct  2 22:06:21 2001
@@ -37,6 +37,14 @@
  * net/if_atm.h
  */
 
+#ifndef NO_ATM_PVCEXT
+/*
+ * ATM_PVCEXT enables PVC extention: VP/VC shaping
+ * and PVC shadow interfaces.
+ */
+#define ATM_PVCEXT	/* enable pvc extention */
+#endif
+
 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__)
 #define RTALLOC1(A,B)		rtalloc1((A),(B))
 #elif defined(__FreeBSD__)
@@ -61,6 +69,9 @@
 #define ATM_PH_AAL5    0x01	/* use AAL5? (0 == aal0) */
 #define ATM_PH_LLCSNAP 0x02	/* use the LLC SNAP encoding (iff aal5) */
 
+#ifdef ATM_PVCEXT
+#define ATM_PH_INERNAL  0x20	/* reserve for kernel internal use */
+#endif
 #define ATM_PH_DRIVER7  0x40	/* reserve for driver's use */
 #define ATM_PH_DRIVER8  0x80	/* reserve for driver's use */
 
@@ -79,6 +90,35 @@
 #define SIOCATMENA	_IOWR('a', 123, struct atm_pseudoioctl) /* enable */
 #define SIOCATMDIS	_IOWR('a', 124, struct atm_pseudoioctl) /* disable */
 
+#ifdef ATM_PVCEXT
+
+/* structure to control PVC transmitter */
+struct pvctxreq {
+    /* first entry must be compatible with struct ifreq */
+    char pvc_ifname[IFNAMSIZ];		/* if name, e.g. "en0" */
+    struct atm_pseudohdr pvc_aph;	/* (flags) + vpi:vci */
+    struct atm_pseudohdr pvc_joint;	/* for vp shaping: another vc
+					   to share the shaper */
+    int pvc_pcr;			/* peak cell rate (shaper value) */
+};
+
+/* structure to control PVC bridging */
+struct pvcfwdreq {
+    /* first entry must be compatible with struct ifreq */
+    char pvc_ifname[IFNAMSIZ];		/* if name, e.g. "en0" */
+    char pvc_ifname2[IFNAMSIZ];		/* if name to be bridged to/from */
+    int	 pvc_op;			/* 1:add 0:delete */
+};
+
+/* use ifioctl for now */
+#define SIOCSPVCFWD	_IOW('i', 93, struct pvcfwdreq)
+#define SIOCGPVCFWD	_IOWR('i', 94, struct pvcfwdreq)
+#define SIOCSPVCTX	_IOWR('i', 95, struct pvctxreq)
+#define SIOCGPVCTX	_IOWR('i', 96, struct pvctxreq)
+#define SIOCSPVCSIF	_IOWR('i', 97, struct ifreq)
+#define SIOCGPVCSIF	_IOWR('i', 98, struct ifreq)
+
+#endif /* ATM_PVCEXT */
 
 /*
  * XXX forget all the garbage in if_llc.h and do it the easy way
@@ -105,3 +145,28 @@
 		struct rtentry *));
 #endif
 
+#ifdef ATM_PVCEXT
+#ifdef _KERNEL
+#include <sys/queue.h>
+/*
+ * ATM PVC subinterface: a trick to assign a subinterface
+ * to a PVC.
+ * with a pvc subinterface, each PVC looks like an individual
+ * Point-to-Point interface.
+ * as opposed to the NBMA model, a pvc subinterface is inherently
+ * multicast capable (no LANE/MARS required).
+ */
+struct pvcsif {
+	/*
+	 * The ifnet struct _must_ be at the head of this structure.
+	 */
+	struct ifnet sif_if;		/* ifnet structure per pvc */
+	struct atm_pseudohdr sif_aph;	/* flags + vpi:vci */
+	int	sif_vci;		/* vci no */
+	struct ifnet *sif_fwdifp;	/* bridging ifp */
+	LIST_ENTRY(pvcsif) sif_links;
+};
+struct ifnet *pvcsif_alloc __P((void));
+int pvc_set_fwd __P((char *, char *, int));
+#endif
+#endif /* ATM_PVCEXT */
diff -urN ../sys/net/if_atmsubr.c ./net/if_atmsubr.c
--- ../sys/net/if_atmsubr.c	Tue Mar  6 09:29:26 2001
+++ ./net/if_atmsubr.c	Tue Oct  2 22:06:21 2001
@@ -47,6 +47,7 @@
 #include <sys/mbuf.h>
 #include <sys/socket.h>
 #include <sys/sockio.h>
+#include <sys/malloc.h>
 #include <sys/errno.h>
 
 #include <net/if.h>
@@ -95,17 +96,28 @@
 	struct rtentry *rt0;
 {
 	u_int16_t etype = 0;			/* if using LLC/SNAP */
-	int s, error = 0, sz;
+	int s, error = 0, sz, len;
 	struct atm_pseudohdr atmdst, *ad;
 	struct mbuf *m = m0;
 	struct rtentry *rt;
 	struct atmllc *atmllc;
 	struct atmllc *llc_hdr = NULL;
 	u_int32_t atm_flags;
+#ifdef ALTQ
+	struct altq_pktattr pktattr;
+#endif
 
 	if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
 		senderr(ENETDOWN);
 
+#ifdef ALTQ
+	/*
+	 * if the queueing discipline needs packet classification,
+	 * do it before prepending link headers.
+	 */
+	IFQ_CLASSIFY(&ifp->if_snd, m,
+		     (dst != NULL ? dst->sa_family : AF_UNSPEC), &pktattr);
+#endif
 	/*
 	 * check route
 	 */
@@ -139,12 +151,24 @@
 	if (dst) {
 		switch (dst->sa_family) {
 #if defined(INET) || defined(INET6)
+#ifdef INET
 		case AF_INET:
+#endif
+#ifdef INET6
 		case AF_INET6:
+#endif
 			if (dst->sa_family == AF_INET6)
 			        etype = htons(ETHERTYPE_IPV6);
 			else
 			        etype = htons(ETHERTYPE_IP);
+#ifdef ATM_PVCEXT
+			if (ifp->if_flags & IFF_POINTOPOINT) {
+				/* pvc subinterface */
+				struct pvcsif *pvcsif = (struct pvcsif *)ifp;
+				atmdst = pvcsif->sif_aph;
+				break;
+			}
+#endif
 			if (!atmresolve(rt, m, dst, &atmdst)) {
 				m = NULL; 
 				/* XXX: atmresolve already free'd it */
@@ -203,14 +227,18 @@
 	 * Queue message on interface, and start output if interface
 	 * not yet active.
 	 */
+	len = m->m_pkthdr.len;
 	s = splimp();
-	if (IF_QFULL(&ifp->if_snd)) {
-		IF_DROP(&ifp->if_snd);
+#ifdef ALTQ
+	IFQ_ENQUEUE(&ifp->if_snd, m, &pktattr, error);
+#else
+	IFQ_ENQUEUE(&ifp->if_snd, m, error);
+#endif
+	if (error) {
 		splx(s);
-		senderr(ENOBUFS);
+		return (error);
 	}
-	ifp->if_obytes += m->m_pkthdr.len;
-	IF_ENQUEUE(&ifp->if_snd, m);
+	ifp->if_obytes += len;
 	if ((ifp->if_flags & IFF_OACTIVE) == 0)
 		(*ifp->if_start)(ifp);
 	splx(s);
@@ -282,6 +310,33 @@
 			m_adj(m, sizeof(*alc));
 		}
 
+#ifdef ATM_PVCEXT
+		/* atm bridging support */
+		if ((ifp->if_flags & (IFF_POINTOPOINT|IFF_LINK2)) ==
+		    (IFF_POINTOPOINT|IFF_LINK2)) {
+			struct pvcsif *pvcsif = (struct pvcsif *)ifp;
+
+			if (pvcsif->sif_fwdifp != NULL) {
+				struct sockaddr dst;
+
+				/* set address family to dummy dst addr */
+				switch (etype) {
+				case ETHERTYPE_IP:
+					dst.sa_family = AF_INET;
+					break;
+				case ETHERTYPE_IPV6:
+					dst.sa_family = AF_INET6;
+					break;
+				default:
+					m_freem(m);
+					return;
+				}
+				atm_output(pvcsif->sif_fwdifp, m, &dst, NULL);
+				return;
+			}
+		}
+#endif /* ATM_PVCEXT */
+
 		switch (etype) {
 #ifdef INET
 		case ETHERTYPE_IP:
@@ -325,7 +380,7 @@
 	ifp->if_hdrlen = 0;
 	ifp->if_mtu = ATMMTU;
 	ifp->if_output = atm_output;
-	ifp->if_snd.ifq_maxlen = 50;	/* dummy */
+	IFQ_SET_MAXLEN(&ifp->if_snd, 50);	/* dummy */
 
 #if defined(__NetBSD__) || defined(__OpenBSD__)
 	for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != 0;
@@ -347,3 +402,86 @@
 		}
 
 }
+
+#ifdef ATM_PVCEXT
+
+static int pvc_max_number = 16;	/* max number of PVCs */
+static int pvc_number = 0;	/* pvc unit number */
+
+struct ifnet *
+pvcsif_alloc()
+{
+	struct pvcsif *pvcsif;
+
+	if (pvc_number >= pvc_max_number)
+		return (NULL);
+	MALLOC(pvcsif, struct pvcsif *, sizeof(struct pvcsif),
+	       M_DEVBUF, M_WAITOK);
+	if (pvcsif == NULL)
+		return (NULL);
+	bzero(pvcsif, sizeof(struct pvcsif));
+
+#ifdef __NetBSD__
+	sprintf(pvcsif->sif_if.if_xname, "pvc%d", pvc_number++);
+#else
+	pvcsif->sif_if.if_name = "pvc";
+	pvcsif->sif_if.if_unit = pvc_number++;
+#endif
+	return (&pvcsif->sif_if);
+}
+
+/*
+ * pvc bridging support:
+ * add or delete brigding between 2 pvc interfaces.
+ */
+int
+pvc_set_fwd(if_name, if_name2, op)
+	char *if_name, *if_name2;
+	int op;		/* 0:delete 1:add 2:get */
+{
+	struct ifnet *ifp, *ifp2;
+	struct pvcsif *pvcsif, *pvcsif2;
+
+	if (strncmp(if_name, "pvc", 3) != 0
+	    || (ifp = ifunit(if_name)) == NULL)
+		return (EINVAL);
+	pvcsif = (struct pvcsif *)ifp;
+
+	if (op == 2) {
+		/* get bridging info */
+		if ((ifp2 = pvcsif->sif_fwdifp) == NULL)
+			*if_name2 = '\0';
+		else
+#ifdef __NetBSD__
+			sprintf(if_name2, "%s", ifp2->if_xname);
+#else
+			sprintf(if_name2, "%s%d",
+				ifp2->if_name, ifp2->if_unit);
+#endif
+		return (0);
+	}
+
+	if (strncmp(if_name2, "pvc", 3) != 0
+	    || (ifp2 = ifunit(if_name2)) == NULL)
+		return (EINVAL);
+	pvcsif2 = (struct pvcsif *)ifp2;
+
+	if (op) {
+		/* set up bridging */
+		pvcsif->sif_fwdifp = ifp2;
+		pvcsif2->sif_fwdifp = ifp;
+		ifp->if_flags |= IFF_LINK2;	/* use IFF_LINK2 to show */
+		ifp2->if_flags |= IFF_LINK2;	/* bridging is enabled   */
+	}
+	else {
+		/* delete bridging */
+		if (pvcsif->sif_fwdifp != ifp2 || pvcsif2->sif_fwdifp != ifp)
+			return (EINVAL);
+		pvcsif->sif_fwdifp = NULL;
+		pvcsif2->sif_fwdifp = NULL;
+		ifp->if_flags &= ~IFF_LINK2;
+		ifp2->if_flags &= ~IFF_LINK2;
+	}
+	return (0);
+}
+#endif /* ATM_PVCEXT */
diff -urN ../sys/net/if_ethersubr.c ./net/if_ethersubr.c
--- ../sys/net/if_ethersubr.c	Wed Aug  1 09:47:49 2001
+++ ./net/if_ethersubr.c	Tue Oct  2 22:06:21 2001
@@ -364,7 +364,11 @@
 	struct ifnet *ifp;
 	struct mbuf *m;
 {
-	int s, error = 0;
+	int s, len, error = 0;
+	short mflags;
+#ifdef ALTQ
+	struct altq_pktattr pktattr;
+#endif
 
 #ifdef BRIDGE
 	if (do_bridge && BDG_USED(ifp) ) {
@@ -379,22 +383,30 @@
 		return (0);
 	}
 #endif
-
+#ifdef ALTQ
+	if (ALTQ_IS_ENABLED(&ifp->if_snd))
+		altq_etherclassify(&ifp->if_snd, m, &pktattr);
+#endif
+	mflags = m->m_flags;
+	len = m->m_pkthdr.len;
 	s = splimp();
 	/*
 	 * Queue message on interface, and start output if interface
 	 * not yet active.
 	 */
-	if (IF_QFULL(&ifp->if_snd)) {
-		IF_DROP(&ifp->if_snd);
+#ifdef ALTQ
+	IFQ_ENQUEUE(&ifp->if_snd, m, &pktattr, error);
+#else
+	IFQ_ENQUEUE(&ifp->if_snd, m, error);
+#endif
+	if (error) {
+		/* mbuf is already freed */
 		splx(s);
-		m_freem(m);
-		return (ENOBUFS);
+		return (error);
 	}
-	ifp->if_obytes += m->m_pkthdr.len;
-	if (m->m_flags & M_MCAST)
+	ifp->if_obytes += len;
+	if (mflags & M_MCAST)
 		ifp->if_omcasts++;
-	IF_ENQUEUE(&ifp->if_snd, m);
 	if ((ifp->if_flags & IFF_OACTIVE) == 0)
 		(*ifp->if_start)(ifp);
 	splx(s);
@@ -899,3 +911,79 @@
 	}
 }
 
+#ifdef ALTQ
+/*
+ * find the size of ethernet header, and call classifier
+ */
+int
+altq_etherclassify(ifq, m, pktattr)
+	struct ifaltq *ifq;
+	struct mbuf *m;
+	struct altq_pktattr *pktattr;
+{
+	struct ether_header *eh;
+	u_short	ether_type;
+	int	hlen, af, hdrsize;
+	caddr_t hdr;
+
+	hlen = sizeof(struct ether_header);
+	eh = mtod(m, struct ether_header *);
+
+	ether_type = ntohs(eh->ether_type);
+	if (ether_type < ETHERMTU) {
+		/* ick! LLC/SNAP */
+		struct llc *llc = (struct llc *)(eh + 1);
+		hlen += 8;
+
+		if (m->m_len < hlen ||
+		    llc->llc_dsap != LLC_SNAP_LSAP ||
+		    llc->llc_ssap != LLC_SNAP_LSAP ||
+		    llc->llc_control != LLC_UI)
+			goto bad;  /* not snap! */
+
+		ether_type = ntohs(llc->llc_un.type_snap.ether_type);
+	}
+
+	if (ether_type == ETHERTYPE_IP) {
+		af = AF_INET;
+		hdrsize = 20;  /* sizeof(struct ip) */
+#ifdef INET6
+	} else if (ether_type == ETHERTYPE_IPV6) {
+		af = AF_INET6;
+		hdrsize = 40;  /* sizeof(struct ip6_hdr) */
+#endif
+	} else
+		goto bad;
+
+	while (m->m_len <= hlen) {
+		hlen -= m->m_len;
+		m = m->m_next;
+	}
+	hdr = m->m_data + hlen;
+	if (m->m_len < hlen + hdrsize) {
+		/*
+		 * ip header is not in a single mbuf.  this should not
+		 * happen in the current code.
+		 * (todo: use m_pulldown in the future)
+		 */
+		goto bad;
+	}
+	m->m_data += hlen;
+	m->m_len -= hlen;
+	if (ALTQ_NEEDS_CLASSIFY(ifq))
+		pktattr->pattr_class =
+		    (*ifq->altq_classify)(ifq->altq_clfier, m, af);
+	m->m_data -= hlen;
+	m->m_len += hlen;
+
+	pktattr->pattr_af = af;
+	pktattr->pattr_hdr = hdr;
+	return (1);
+
+bad:
+	pktattr->pattr_class = NULL;
+	pktattr->pattr_hdr = NULL;
+	pktattr->pattr_af = AF_UNSPEC;
+	return (0);
+}
+#endif /* ALTQ */
diff -urN ../sys/net/if_loop.c ./net/if_loop.c
--- ../sys/net/if_loop.c	Tue Jul  3 20:01:41 2001
+++ ./net/if_loop.c	Tue Oct  2 22:06:21 2001
@@ -90,6 +90,9 @@
 static void lortrequest __P((int, struct rtentry *, struct sockaddr *));
 
 static void loopattach __P((void *));
+#ifdef ALTQ
+static void lo_altqstart __P((struct ifnet *));
+#endif
 PSEUDO_SET(loopattach, if_loop);
 
 int looutput __P((struct ifnet *ifp,
@@ -121,7 +124,11 @@
 	    ifp->if_ioctl = loioctl;
 	    ifp->if_output = looutput;
 	    ifp->if_type = IFT_LOOP;
-	    ifp->if_snd.ifq_maxlen = ifqmaxlen;
+	    IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+	    IFQ_SET_READY(&ifp->if_snd);
+#ifdef ALTQ
+	    ifp->if_start = lo_altqstart;
+#endif
 	    if_attach(ifp);
 	    bpfattach(ifp, DLT_NULL, sizeof(u_int));
 	}
@@ -262,6 +269,38 @@
 #endif
 	}
 
+#ifdef ALTQ
+	/*
+	 * altq for loop is just for debugging.
+	 * only used when called for loop interface (not for
+	 * a simplex interface).
+	 */
+	if ((ALTQ_IS_ENABLED(&ifp->if_snd) || TBR_IS_ENABLED(&ifp->if_snd))
+	    && ifp->if_start == lo_altqstart) {
+		struct altq_pktattr pktattr;
+		int32_t *afp;
+	        int error;
+
+		/*
+		 * if the queueing discipline needs packet classification,
+		 * do it before prepending link headers.
+		 */
+		IFQ_CLASSIFY(&ifp->if_snd, m, af, &pktattr);
+
+		M_PREPEND(m, sizeof(int32_t), M_DONTWAIT);
+		if (m == 0)
+			return(ENOBUFS);
+		afp = mtod(m, int32_t *);
+		*afp = (int32_t)af;
+
+	        s = splimp();
+		IFQ_ENQUEUE(&ifp->if_snd, m, &pktattr, error);
+		(*ifp->if_start)(ifp);
+		splx(s);
+		return (error);
+	}
+#endif /* ALTQ */
+
 	/* Deliver to upper layer protocol */
 	switch (af) {
 #ifdef INET
@@ -314,6 +353,87 @@
 	splx(s);
 	return (0);
 }
+
+#ifdef ALTQ
+static void
+lo_altqstart(ifp)
+	struct ifnet *ifp;
+{
+	struct ifqueue *ifq;
+	struct mbuf *m;
+	int32_t af, *afp;
+	int s, isr;
+	
+	while (1) {
+		s = splimp();
+		IFQ_DEQUEUE(&ifp->if_snd, m);
+		splx(s);
+		if (m == NULL)
+			return;
+
+		afp = mtod(m, int32_t *);
+		af = *afp;
+		m_adj(m, sizeof(int32_t));
+
+		switch (af) {
+#ifdef INET
+		case AF_INET:
+			ifq = &ipintrq;
+			isr = NETISR_IP;
+			break;
+#endif
+#ifdef INET6
+		case AF_INET6:
+			m->m_flags |= M_LOOP;
+			ifq = &ip6intrq;
+			isr = NETISR_IPV6;
+			break;
+#endif
+#ifdef IPX
+		case AF_IPX:
+			ifq = &ipxintrq;
+			isr = NETISR_IPX;
+			break;
+#endif
+#ifdef NS
+		case AF_NS:
+			ifq = &nsintrq;
+			isr = NETISR_NS;
+			break;
+#endif
+#ifdef ISO
+		case AF_ISO:
+			ifq = &clnlintrq;
+			isr = NETISR_ISO;
+			break;
+#endif
+#ifdef NETATALK
+		case AF_APPLETALK:
+			ifq = &atintrq2;
+			isr = NETISR_ATALK;
+			break;
+#endif NETATALK
+		default:
+			printf("lo_altqstart: can't handle af%d\n", af);
+			m_freem(m);
+			return;
+		}
+
+		s = splimp();
+		if (IF_QFULL(ifq)) {
+			IF_DROP(ifq);
+			m_freem(m);
+			splx(s);
+			return;
+		}
+		IF_ENQUEUE(ifq, m);
+		schednetisr(isr);
+		ifp->if_ipackets++;
+		ifp->if_ibytes += m->m_pkthdr.len;
+		splx(s);
+	}
+}
+#endif /* ALTQ */
 
 /* ARGSUSED */
 static void
diff -urN ../sys/net/if_ppp.c ./net/if_ppp.c
--- ../sys/net/if_ppp.c	Tue Sep 11 18:49:54 2001
+++ ./net/if_ppp.c	Tue Oct  2 22:06:21 2001
@@ -207,10 +207,11 @@
 	sc->sc_if.if_hdrlen = PPP_HDRLEN;
 	sc->sc_if.if_ioctl = pppsioctl;
 	sc->sc_if.if_output = pppoutput;
-	sc->sc_if.if_snd.ifq_maxlen = IFQ_MAXLEN;
+	IFQ_SET_MAXLEN(&sc->sc_if.if_snd, IFQ_MAXLEN);
 	sc->sc_inq.ifq_maxlen = IFQ_MAXLEN;
 	sc->sc_fastq.ifq_maxlen = IFQ_MAXLEN;
 	sc->sc_rawq.ifq_maxlen = IFQ_MAXLEN;
+	IFQ_SET_READY(&sc->sc_if.if_snd);
 	if_attach(&sc->sc_if);
 	bpfattach(&sc->sc_if, DLT_PPP, PPP_HDRLEN);
     }
@@ -693,6 +694,9 @@
     enum NPmode mode;
     int len;
     struct mbuf *m;
+#ifdef ALTQ
+    struct altq_pktattr pktattr;
+#endif
 
     if (sc->sc_devp == NULL || (ifp->if_flags & IFF_RUNNING) == 0
 	|| ((ifp->if_flags & IFF_UP) == 0 && dst->sa_family != AF_UNSPEC)) {
@@ -700,6 +704,9 @@
 	goto bad;
     }
 
+#ifdef ALTQ
+    IFQ_CLASSIFY(&ifp->if_snd, m0, dst->sa_family, &pktattr);
+#endif
     /*
      * Compute PPP header.
      */
@@ -835,16 +842,34 @@
 	sc->sc_npqtail = &m0->m_nextpkt;
     } else {
 	/* fastq and if_snd are emptied at spl[soft]net now */
-	ifq = (m0->m_flags & M_HIGHPRI)? &sc->sc_fastq: &ifp->if_snd;
-	if (IF_QFULL(ifq) && dst->sa_family != AF_UNSPEC) {
-	    IF_DROP(ifq);
+	if ((m0->m_flags & M_HIGHPRI)
+#ifdef ALTQ
+	    && !ALTQ_IS_ENABLED(&sc->sc_if.if_snd)
+#endif
+	    ) {
+	    ifq = &sc->sc_fastq;
+	    if (IF_QFULL(ifq) && dst->sa_family != AF_UNSPEC) {
+		IF_DROP(ifq);
+		m_freem(m0);
+		error = ENOBUFS;
+	    }
+	    else {
+		IF_ENQUEUE(ifq, m0);
+		error = 0;
+	    }
+	} else {
+#ifdef ALTQ
+	    IFQ_ENQUEUE(&sc->sc_if.if_snd, m0, &pktattr, error);
+#else
+	    IFQ_ENQUEUE(&sc->sc_if.if_snd, m0, error);
+#endif
+	}
+	if (error) {
 	    splx(s);
 	    sc->sc_if.if_oerrors++;
 	    sc->sc_stats.ppp_oerrors++;
-	    error = ENOBUFS;
-	    goto bad;
+	    return (error);
 	}
-	IF_ENQUEUE(ifq, m0);
 	(*sc->sc_start)(sc);
     }
     getmicrotime(&ifp->if_lastchange);
@@ -871,6 +896,7 @@
     struct mbuf *m, **mpp;
     struct ifqueue *ifq;
     enum NPmode mode;
+    int error;
 
     for (mpp = &sc->sc_npqueue; (m = *mpp) != NULL; ) {
 	switch (PPP_PROTOCOL(mtod(m, u_char *))) {
@@ -888,13 +914,32 @@
 	     */
 	    *mpp = m->m_nextpkt;
 	    m->m_nextpkt = NULL;
-	    ifq = (m->m_flags & M_HIGHPRI)? &sc->sc_fastq: &sc->sc_if.if_snd;
-	    if (IF_QFULL(ifq)) {
-		IF_DROP(ifq);
+	    if ((m->m_flags & M_HIGHPRI)
+#ifdef ALTQ
+		&& !ALTQ_IS_ENABLED(&sc->sc_if.if_snd)
+#endif
+		) {
+		ifq = &sc->sc_fastq;
+		if (IF_QFULL(ifq)) {
+		    IF_DROP(ifq);
+		    m_freem(m);
+		    error = ENOBUFS;
+		}
+		else {
+		    IF_ENQUEUE(ifq, m);
+		    error = 0;
+		}
+	    } else {
+#ifdef ALTQ
+		IFQ_ENQUEUE(&sc->sc_if.if_snd, m, NULL, error);
+#else
+		IFQ_ENQUEUE(&sc->sc_if.if_snd, m, error);
+#endif
+	    }
+	    if (error) {
 		sc->sc_if.if_oerrors++;
 		sc->sc_stats.ppp_oerrors++;
-	    } else
-		IF_ENQUEUE(ifq, m);
+	    }
 	    break;
 
 	case NPMODE_DROP:
@@ -947,7 +992,7 @@
      */
     IF_DEQUEUE(&sc->sc_fastq, m);
     if (m == NULL)
-	IF_DEQUEUE(&sc->sc_if.if_snd, m);
+	IFQ_DEQUEUE(&sc->sc_if.if_snd, m);
     if (m == NULL)
 	return NULL;
 
@@ -1072,7 +1117,7 @@
     for (i = 0; i < NPPP; ++i, ++sc) {
 	s = splimp();
 	if (!(sc->sc_flags & SC_TBUSY)
-	    && (sc->sc_if.if_snd.ifq_head || sc->sc_fastq.ifq_head)) {
+	    && (!IFQ_IS_EMPTY(&sc->sc_if.if_snd) || sc->sc_fastq.ifq_head)) {
 	    sc->sc_flags |= SC_TBUSY;
 	    splx(s);
 	    (*sc->sc_start)(sc);
diff -urN ../sys/net/if_sl.c ./net/if_sl.c
--- ../sys/net/if_sl.c	Tue Dec 26 11:22:57 2000
+++ ./net/if_sl.c	Tue Oct  2 22:06:21 2001
@@ -223,10 +223,11 @@
 		sc->sc_if.if_type = IFT_SLIP;
 		sc->sc_if.if_ioctl = slioctl;
 		sc->sc_if.if_output = sloutput;
-		sc->sc_if.if_snd.ifq_maxlen = 50;
+		IFQ_SET_MAXLEN(&sc->sc_if.if_snd, 50);
 		sc->sc_fastq.ifq_maxlen = 32;
 		sc->sc_if.if_linkmib = sc;
 		sc->sc_if.if_linkmiblen = sizeof *sc;
+		IFQ_SET_READY(&sc->sc_if.if_snd);
 		if_attach(&sc->sc_if);
 		bpfattach(&sc->sc_if, DLT_SLIP, SLIP_HDRLEN);
 	}
@@ -489,8 +490,14 @@
 	register struct sl_softc *sc = &sl_softc[ifp->if_unit];
 	register struct ip *ip;
 	register struct ifqueue *ifq;
-	int s;
+	int s, error;
+#ifdef ALTQ
+	struct altq_pktattr pktattr;
+#endif
 
+#ifdef ALTQ
+	IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr);
+#endif
 	/*
 	 * `Cannot happen' (see slioctl).  Someday we will extend
 	 * the line protocol to support other address families.
@@ -511,23 +518,38 @@
 		m_freem(m);
 		return (EHOSTUNREACH);
 	}
-	ifq = &sc->sc_if.if_snd;
 	ip = mtod(m, struct ip *);
 	if (sc->sc_if.if_flags & SC_NOICMP && ip->ip_p == IPPROTO_ICMP) {
 		m_freem(m);
 		return (ENETRESET);		/* XXX ? */
 	}
-	if (ip->ip_tos & IPTOS_LOWDELAY)
-		ifq = &sc->sc_fastq;
 	s = splimp();
-	if (IF_QFULL(ifq)) {
-		IF_DROP(ifq);
-		m_freem(m);
+	if ((ip->ip_tos & IPTOS_LOWDELAY)
+#ifdef ALTQ
+	    && !ALTQ_IS_ENABLED(&sc->sc_if.if_snd)
+#endif
+		) {
+		ifq = &sc->sc_fastq;
+		if (IF_QFULL(ifq)) {
+			IF_DROP(ifq);
+			m_freem(m);
+			error = ENOBUFS;
+		} else {
+			IF_ENQUEUE(ifq, m);
+			error = 0;
+		}
+	} else {
+#ifdef ALTQ
+		IFQ_ENQUEUE(&sc->sc_if.if_snd, m, &pktattr, error);
+#else
+		IFQ_ENQUEUE(&sc->sc_if.if_snd, m, error);
+#endif
+	}
+	if (error) {
 		splx(s);
 		sc->sc_if.if_oerrors++;
-		return (ENOBUFS);
+		return (error);
 	}
-	IF_ENQUEUE(ifq, m);
 	if (sc->sc_ttyp->t_outq.c_cc == 0)
 		slstart(sc->sc_ttyp);
 	splx(s);
@@ -581,7 +603,7 @@
 		if (m)
 			sc->sc_if.if_omcasts++;		/* XXX */
 		else
-			IF_DEQUEUE(&sc->sc_if.if_snd, m);
+			IFQ_DEQUEUE(&sc->sc_if.if_snd, m);
 		splx(s);
 		if (m == NULL)
 			return 0;
diff -urN ../sys/net/if_spppsubr.c ./net/if_spppsubr.c
--- ../sys/net/if_spppsubr.c	Wed Aug  1 04:43:55 2001
+++ ./net/if_spppsubr.c	Tue Oct  2 22:13:12 2001
@@ -697,7 +697,7 @@
 	struct sppp *sp = (struct sppp*) ifp;
 	struct ppp_header *h;
 	struct ifqueue *ifq = NULL;
-	int s, rv = 0;
+	int s, len, rv = 0;
 	int debug = ifp->if_flags & IFF_DEBUG;
 
 	s = splimp();
@@ -720,7 +720,13 @@
 		s = splimp();
 	}
 
-	ifq = &ifp->if_snd;
+#ifdef ALTQ
+	/*
+	 * if the queueing discipline needs packet classification,
+	 * do it before prepending link headers.
+	 */
+	IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr);
+#endif
 #ifdef INET
 	if (dst->sa_family == AF_INET) {
 		/* XXX Check mbuf length here? */
@@ -773,6 +779,12 @@
 	}
 #endif
 
+#ifdef INET6
+        if (dst->sa_family == AF_INET6) {
+                /* XXX do something tricky here? */
+        }
+#endif
+
 	/*
 	 * Prepend general data packet PPP header. For now, IP only.
 	 */
@@ -863,14 +875,33 @@
 	 * Queue message on interface, and start output if interface
 	 * not yet active.
 	 */
-	if (IF_QFULL (ifq)) {
-		IF_DROP (&ifp->if_snd);
-		m_freem (m);
+	len = m->m_pkthdr.len;
+	if (ifq != NULL
+#ifdef ALTQ
+	    && !ALTQ_IS_ENABLED(&ifp->if_snd)
+#endif
+		) {
+		if (IF_QFULL (ifq)) {
+			IF_DROP (&ifp->if_snd);
+			m_freem (m);
+			if (rv == 0)
+				rv = ENOBUFS;
+		}
+		IF_ENQUEUE (ifq, m);
+	}
+	else {
+#ifdef ALTQ
+		IFQ_ENQUEUE(&ifp->if_snd, m, &pktattr, rv);
+#else
+		IFQ_ENQUEUE(&ifp->if_snd, m, rv);
+#endif
+	}
+	if (rv != 0) {
 		++ifp->if_oerrors;
 		splx (s);
-		return (rv? rv: ENOBUFS);
+		return (rv);
 	}
-	IF_ENQUEUE (ifq, m);
+
 	if (! (ifp->if_flags & IFF_OACTIVE))
 		(*ifp->if_start) (ifp);
 
@@ -879,7 +910,7 @@
 	 * The packet length includes header, FCS and 1 flag,
 	 * according to RFC 1333.
 	 */
-	ifp->if_obytes += m->m_pkthdr.len + 3;
+	ifp->if_obytes += len + 3;
 	splx (s);
 	return (0);
 }
@@ -952,7 +983,7 @@
 {
 	struct sppp *sp = (struct sppp*) ifp;
 
-	sppp_qflush (&sp->pp_if.if_snd);
+	IFQ_PURGE(&sp->pp_if.if_snd);
 	sppp_qflush (&sp->pp_fastq);
 	sppp_qflush (&sp->pp_cpq);
 }
@@ -968,7 +999,7 @@
 
 	s = splimp();
 	empty = !sp->pp_fastq.ifq_head && !sp->pp_cpq.ifq_head &&
-		!sp->pp_if.if_snd.ifq_head;
+		IFQ_IS_EMPTY(&sp->pp_if.if_snd);
 	splx(s);
 	return (empty);
 }
@@ -995,7 +1026,7 @@
 	    (sppp_ncp_check(sp) || sp->pp_mode == IFF_CISCO)) {
 		IF_DEQUEUE(&sp->pp_fastq, m);
 		if (m == NULL)
-			IF_DEQUEUE (&sp->pp_if.if_snd, m);
+			IFQ_DEQUEUE (&sp->pp_if.if_snd, m);
 	}
 	splx(s);
 	return m;
@@ -1017,7 +1048,7 @@
 	if (m == NULL &&
 	    (sp->pp_phase == PHASE_NETWORK || sp->pp_mode == IFF_CISCO))
 		if ((m = sp->pp_fastq.ifq_head) == NULL)
-			m = sp->pp_if.if_snd.ifq_head;
+			IFQ_POLL(&sp->pp_if.if_snd, m);
 	splx (s);
 	return (m);
 }
diff -urN ../sys/net/if_tun.c ./net/if_tun.c
--- ../sys/net/if_tun.c	Wed Aug  8 22:07:00 2001
+++ ./net/if_tun.c	Tue Oct  2 22:06:21 2001
@@ -65,6 +65,9 @@
 	    struct rtentry *rt));
 static int tunifioctl __P((struct ifnet *, u_long, caddr_t));
 static int tuninit __P((struct ifnet *));
+#ifdef ALTQ
+static void tunstart __P((struct ifnet *));
+#endif
 
 static	d_open_t	tunopen;
 static	d_close_t	tunclose;
@@ -119,9 +122,13 @@
 	ifp->if_mtu = TUNMTU;
 	ifp->if_ioctl = tunifioctl;
 	ifp->if_output = tunoutput;
+#ifdef ALTQ
+	ifp->if_start = tunstart;
+#endif
 	ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
 	ifp->if_type = IFT_PPP;
-	ifp->if_snd.ifq_maxlen = ifqmaxlen;
+	IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+	IFQ_SET_READY(&ifp->if_snd);
 	ifp->if_softc = sc;
 	if_attach(ifp);
 	bpfattach(ifp, DLT_NULL, sizeof(u_int));
@@ -174,7 +181,6 @@
 	register int	s;
 	struct tun_softc *tp;
 	struct ifnet	*ifp;
-	struct mbuf	*m;
 
 	tp = dev->si_drv1;
 	ifp = &tp->tun_if;
@@ -185,13 +191,9 @@
 	/*
 	 * junk all pending output
 	 */
-	do {
-		s = splimp();
-		IF_DEQUEUE(&ifp->if_snd, m);
-		splx(s);
-		if (m)
-			m_freem(m);
-	} while (m);
+	s = splimp();
+	IFQ_PURGE(&ifp->if_snd);
+	splx(s);
 
 	if (ifp->if_flags & IFF_UP) {
 		s = splimp();
@@ -315,7 +317,10 @@
 	struct rtentry *rt;
 {
 	struct tun_softc *tp = ifp->if_softc;
-	int		s;
+	int		s, error, len;
+#ifdef ALTQ
+	struct altq_pktattr pktattr;
+#endif
 
 	TUNDEBUG ("%s%d: tunoutput\n", ifp->if_name, ifp->if_unit);
 
@@ -326,6 +331,13 @@
 		return EHOSTDOWN;
 	}
 
+#ifdef ALTQ
+	/*
+	 * if the queueing discipline needs packet classification,
+	 * do it before prepending link headers.
+	 */
+	IFQ_CLASSIFY(&ifp->if_snd, m0, dst->sa_family, &pktattr);
+#endif
 	/* BPF write needs to be handled specially */
 	if (dst->sa_family == AF_UNSPEC) {
 		dst->sa_family = *(mtod(m0, int *));
@@ -392,16 +404,19 @@
 		}
 	}
 
+	len = m0->m_pkthdr.len;
 	s = splimp();
-	if (IF_QFULL(&ifp->if_snd)) {
-		IF_DROP(&ifp->if_snd);
-		m_freem(m0);
+#ifdef ALTQ
+	IFQ_ENQUEUE(&ifp->if_snd, m0, &pktattr, error);
+#else
+	IFQ_ENQUEUE(&ifp->if_snd, m0, error);
+#endif
+	if (error) {
 		splx(s);
 		ifp->if_collisions++;
-		return ENOBUFS;
+		return (error);
 	}
-	ifp->if_obytes += m0->m_pkthdr.len;
-	IF_ENQUEUE(&ifp->if_snd, m0);
+	ifp->if_obytes += len;
 	splx(s);
 	ifp->if_opackets++;
 
@@ -499,8 +514,10 @@
 		break;
 	case FIONREAD:
 		s = splimp();
-		if (tp->tun_if.if_snd.ifq_head) {
-			struct mbuf *mb = tp->tun_if.if_snd.ifq_head;
+		if (!IFQ_IS_EMPTY(&tp->tun_if.if_snd)) {
+			struct mbuf *mb;
+
+			IFQ_POLL(&tp->tun_if.if_snd, mb);
 			for( *(int *)data = 0; mb != 0; mb = mb->m_next) 
 				*(int *)data += mb->m_len;
 		} else
@@ -555,7 +572,7 @@
 
 	s = splimp();
 	do {
-		IF_DEQUEUE(&ifp->if_snd, m0);
+		IFQ_DEQUEUE(&ifp->if_snd, m0);
 		if (m0 == 0) {
 			if (flag & IO_NDELAY) {
 				splx(s);
@@ -713,7 +730,7 @@
 	TUNDEBUG("%s%d: tunpoll\n", ifp->if_name, ifp->if_unit);
 
 	if (events & (POLLIN | POLLRDNORM)) {
-		if (ifp->if_snd.ifq_len > 0) {
+		if (!IFQ_IS_EMPTY(&ifp->if_snd)) {
 			TUNDEBUG("%s%d: tunpoll q=%d\n", ifp->if_name,
 			    ifp->if_unit, ifp->if_snd.ifq_len);
 			revents |= events & (POLLIN | POLLRDNORM);
@@ -729,3 +746,33 @@
 	splx(s);
 	return (revents);
 }
+
+#ifdef ALTQ
+/*
+ * Start packet transmission on the interface.
+ * when the interface queue is rate-limited by ALTQ or TBR,
+ * if_start is needed to drain packets from the queue in order
+ * to notify readers when outgoing packets become ready.
+ */
+static void
+tunstart(ifp)
+	struct ifnet *ifp;
+{
+	struct tun_softc *tp = ifp->if_softc;
+	struct mbuf *m;
+
+	if (!ALTQ_IS_ENABLED(&ifp->if_snd) && !TBR_IS_ENABLED(&ifp->if_snd))
+		return;
+
+	IFQ_POLL(&ifp->if_snd, m);
+	if (m != NULL) {
+		if (tp->tun_flags & TUN_RWAIT) {
+			tp->tun_flags &= ~TUN_RWAIT;
+			wakeup((caddr_t)tp);
+		}
+		if (tp->tun_flags & TUN_ASYNC && tp->tun_sigio)
+			pgsigio(tp->tun_sigio, SIGIO, 0);
+		selwakeup(&tp->tun_rsel);
+	}
+}
+#endif
diff -urN ../sys/net/if_var.h ./net/if_var.h
--- ../sys/net/if_var.h	Wed Jul 25 04:10:18 2001
+++ ./net/if_var.h	Tue Oct  2 22:06:21 2001
@@ -74,6 +74,9 @@
 #endif
 
 #include <sys/queue.h>		/* get TAILQ macros */
+#if 1 /* ALTQ */
+#include <altq/if_altq.h>
+#endif
 
 TAILQ_HEAD(ifnethead, ifnet);	/* we use TAILQs so that the order of */
 TAILQ_HEAD(ifaddrhead, ifaddr);	/* instantiation is preserved in the list */
@@ -137,7 +140,11 @@
 		__P((void *));
 	int	(*if_resolvemulti)	/* validate/resolve multicast */
 		__P((struct ifnet *, struct sockaddr **, struct sockaddr *));
+#if 1 /* ALTQ */
+	struct	ifaltq if_snd;		/* output queue (includes altq) */
+#else
 	struct	ifqueue if_snd;		/* output queue */
+#endif
 	struct	ifqueue *if_poll_slowq;	/* input queue for slow devices */
 	struct	ifprefixhead if_prefixhead; /* list of prefixes per if */
 };
@@ -210,6 +217,17 @@
 		(ifq)->ifq_len--; \
 	} \
 }
+#define	IF_POLL(ifq, m)		((m) = (ifq)->ifq_head)
+#define	IF_PURGE(ifq)							\
+while (1) {								\
+	struct mbuf *m0;						\
+	IF_DEQUEUE((ifq), m0);						\
+	if (m0 == NULL)							\
+		break;							\
+	else								\
+		m_freem(m0);						\
+}
+#define	IF_IS_EMPTY(ifq)	((ifq)->ifq_len == 0)
 
 #ifdef _KERNEL
 #define	IF_ENQ_DROP(ifq, m)	if_enq_drop(ifq, m)
@@ -248,6 +266,110 @@
 
 #endif /* _KERNEL */
 
+#ifdef _KERNEL
+#ifdef ALTQ
+
+#define	IFQ_ENQUEUE(ifq, m, pattr, err)					\
+do {									\
+	if (ALTQ_IS_ENABLED((ifq)))					\
+		ALTQ_ENQUEUE((ifq), (m), (pattr), (err));		\
+	else {								\
+		if (IF_QFULL((ifq))) {					\
+			m_freem((m));					\
+			(err) = ENOBUFS;				\
+		} else {						\
+			IF_ENQUEUE((ifq), (m));				\
+			(err) = 0;					\
+		}							\
+	}								\
+	if ((err))							\
+		(ifq)->ifq_drops++;					\
+} while (0)
+
+#define	IFQ_DEQUEUE(ifq, m)						\
+do {									\
+	if (TBR_IS_ENABLED((ifq)))					\
+		(m) = tbr_dequeue((ifq), ALTDQ_REMOVE);			\
+	else if (ALTQ_IS_ENABLED((ifq)))				\
+		ALTQ_DEQUEUE((ifq), (m));				\
+	else								\
+		IF_DEQUEUE((ifq), (m));					\
+} while (0)
+
+#define	IFQ_POLL(ifq, m)						\
+do {									\
+	if (TBR_IS_ENABLED((ifq)))					\
+		(m) = tbr_dequeue((ifq), ALTDQ_POLL);			\
+	else if (ALTQ_IS_ENABLED((ifq)))				\
+		ALTQ_POLL((ifq), (m));					\
+	else								\
+		IF_POLL((ifq), (m));					\
+} while (0)
+
+#define	IFQ_PURGE(ifq)							\
+do {									\
+	if (ALTQ_IS_ENABLED((ifq)))					\
+		ALTQ_PURGE((ifq));					\
+	else								\
+		IF_PURGE((ifq));					\
+} while (0)
+
+#define	IFQ_SET_READY(ifq)						\
+	do { ((ifq)->altq_flags |= ALTQF_READY); } while (0)
+
+#define	IFQ_CLASSIFY(ifq, m, af, pa)					\
+do {									\
+	if (ALTQ_IS_ENABLED((ifq))) {					\
+		if (ALTQ_NEEDS_CLASSIFY((ifq)))				\
+			(pa)->pattr_class = (*(ifq)->altq_classify)	\
+				((ifq)->altq_clfier, (m), (af));	\
+		(pa)->pattr_af = (af);					\
+		(pa)->pattr_hdr = mtod((m), caddr_t);			\
+	}								\
+} while (0)
+
+#else /* !ALTQ */
+
+#define	IFQ_ENQUEUE(ifq, m, err)					\
+do {									\
+	if (IF_QFULL((ifq))) {						\
+		m_freem((m));						\
+		(err) = ENOBUFS;					\
+	} else {							\
+		IF_ENQUEUE((ifq), (m));					\
+		(err) = 0;						\
+	}								\
+	if ((err))							\
+		(ifq)->ifq_drops++;					\
+} while (0)
+
+#define	IFQ_DEQUEUE(ifq, m)	IF_DEQUEUE((ifq), (m))
+
+#define	IFQ_POLL(ifq, m)	IF_POLL((ifq), (m))
+
+#define	IFQ_PURGE(ifq)							\
+while (1) {								\
+	struct mbuf *m0;						\
+	IF_DEQUEUE((ifq), m0);						\
+	if (m0 == NULL)							\
+		break;							\
+	else								\
+		m_freem(m0);						\
+}
+
+#define	IFQ_SET_READY(ifq)		((void)0)
+#define	IFQ_CLASSIFY(ifq, m, af, pa)	((void)0)
+
+#endif /* !ALTQ */
+
+#define	IFQ_IS_EMPTY(ifq)		((ifq)->ifq_len == 0)
+#define	IFQ_INC_LEN(ifq)		((ifq)->ifq_len++)
+#define	IFQ_DEC_LEN(ifq)		(--(ifq)->ifq_len)
+#define	IFQ_INC_DROPS(ifq)		((ifq)->ifq_drops++)
+#define	IFQ_SET_MAXLEN(ifq, len)	((ifq)->ifq_maxlen = (len))
+
+#endif /* _KERNEL */
+
 /*
  * The ifaddr structure contains information about one address
  * of an interface.  They are maintained by the different address families,
@@ -332,6 +454,10 @@
 	   struct mbuf *, struct sockaddr *, struct rtentry *));
 int	ether_output_frame __P((struct ifnet *, struct mbuf *));
 int	ether_ioctl __P((struct ifnet *, int, caddr_t));
+#ifdef ALTQ
+int	altq_etherclassify __P((struct ifaltq *, struct mbuf *,
+				struct altq_pktattr *));
+#endif
 
 int	if_addmulti __P((struct ifnet *, struct sockaddr *,
 			 struct ifmultiaddr **));
diff -urN ../sys/netinet/if_atm.c ./netinet/if_atm.c
--- ../sys/netinet/if_atm.c	Wed Dec  8 02:39:06 1999
+++ ./netinet/if_atm.c	Tue Oct  2 22:06:21 2001
@@ -95,7 +95,9 @@
 	switch (req) {
 
 	case RTM_RESOLVE: /* resolve: only happens when cloning */
+#ifdef DIAGNOSTIC
 		printf("atm_rtrequest: RTM_RESOLVE request detected?\n");
+#endif
 		break;
 
 	case RTM_ADD:
@@ -116,12 +118,16 @@
 		}
 
 		if ((rt->rt_flags & RTF_CLONING) != 0) {
+#ifdef DIAGNOSTIC
 			printf("atm_rtrequest: cloning route detected?\n");
+#endif
 			break;
 		}
 		if (gate->sa_family != AF_LINK ||
 		    gate->sa_len < sizeof(null_sdl)) {
+#ifdef DIAGNOSTIC
 			log(LOG_DEBUG, "atm_rtrequest: bad gateway value");
+#endif
 			break;
 		}
 
diff -urN ../sys/netinet/ip_input.c ./netinet/ip_input.c
--- ../sys/netinet/ip_input.c	Thu Aug 30 06:41:37 2001
+++ ./netinet/ip_input.c	Tue Oct  2 22:06:21 2001
@@ -369,6 +369,11 @@
 		goto bad;
 	}
 
+#ifdef ALTQ
+	if (altq_input != NULL && (*altq_input)(m, AF_INET) == 0)
+		/* packet is dropped by traffic conditioner */
+		return;
+#endif
 	/*
 	 * Convert fields to host representation.
 	 */
@@ -1791,9 +1796,19 @@
 		break;
 
 	case ENOBUFS:
+#ifdef ALTQ
+		/*
+		 * don't generate ICMP_SOURCEQUENCH
+		 * (RFC1812 Requirements for IP Version 4 Routers)
+		 */
+		if (mcopy)
+			m_freem(mcopy);
+		return;
+#else
 		type = ICMP_SOURCEQUENCH;
 		code = 0;
 		break;
+#endif
 
 	case EACCES:			/* ipfw denied packet */
 		m_freem(mcopy);
diff -urN ../sys/netinet/ip_mroute.c ./netinet/ip_mroute.c
--- ../sys/netinet/ip_mroute.c	Thu Jul 19 15:37:26 2001
+++ ./netinet/ip_mroute.c	Tue Oct  2 22:06:21 2001
@@ -30,6 +30,7 @@
 #include <net/route.h>
 #include <netinet/in.h>
 #include <netinet/in_systm.h>
+#include <netinet/in_pcb.h>
 #include <netinet/ip.h>
 #include <netinet/ip_var.h>
 #include <netinet/in_var.h>
@@ -2136,6 +2137,12 @@
     static struct sockaddr_in rsvp_src = { sizeof rsvp_src, AF_INET };
     register int s;
     struct ifnet *ifp;
+#ifdef ALTQ
+    /* support IP_RECVIF used by rsvpd rel4.2a1 */
+    struct inpcb *inp;
+    struct socket *so;
+    struct mbuf *opts;
+#endif
 
     if (rsvpdebug)
 	printf("rsvp_input: rsvp_on %d\n",rsvp_on);
@@ -2165,7 +2172,11 @@
 	if (viftable[vifi].v_ifp == ifp)
 	    break;
 
+#ifdef ALTQ
+    if (vifi == numvifs || (so = viftable[vifi].v_rsvpd) == NULL) {
+#else
     if (vifi == numvifs || viftable[vifi].v_rsvpd == NULL) {
+#endif
 	/*
 	 * If the old-style non-vif-associated socket is set,
 	 * then use it.  Otherwise, drop packet since there
@@ -2191,6 +2202,26 @@
 	printf("rsvp_input: m->m_len = %d, sbspace() = %ld\n",
 	       m->m_len,sbspace(&(viftable[vifi].v_rsvpd->so_rcv)));
 
+#ifdef ALTQ
+    opts = NULL;
+    inp = (struct inpcb *)so->so_pcb;
+    if (inp->inp_flags & INP_CONTROLOPTS ||
+	inp->inp_socket->so_options & SO_TIMESTAMP)
+	ip_savecontrol(inp, &opts, ip, m);
+    if (sbappendaddr(&so->so_rcv,
+		     (struct sockaddr *)&rsvp_src,m, opts) == 0) {
+	m_freem(m);
+	if (opts)
+	    m_freem(opts);
+	if (rsvpdebug)
+	    printf("rsvp_input: Failed to append to socket\n");
+    }
+    else {
+	sorwakeup(so);
+	if (rsvpdebug)
+	    printf("rsvp_input: send packet up\n");
+    }
+#else /* !ALTQ */
     if (socket_send(viftable[vifi].v_rsvpd, m, &rsvp_src) < 0) {
 	if (rsvpdebug)
 	    printf("rsvp_input: Failed to append to socket\n");
@@ -2198,6 +2229,7 @@
 	if (rsvpdebug)
 	    printf("rsvp_input: send packet up\n");
     }
+#endif /* !ALTQ */
 
     splx(s);
 }
diff -urN ../sys/netinet/ip_output.c ./netinet/ip_output.c
--- ../sys/netinet/ip_output.c	Thu Jul 19 15:37:26 2001
+++ ./netinet/ip_output.c	Tue Oct  2 22:06:21 2001
@@ -396,6 +396,12 @@
 #endif /* IPFIREWALL_FORWARD */
 	}
 #endif /* notdef */
+#ifdef ALTQ
+	/*
+	 * disable packet drop hack.
+	 * packetdrop should be done by queueing.
+	 */
+#else /* !ALTQ */
 	/*
 	 * Verify that we have any chance at all of being able to queue
 	 *      the packet or packet fragments
@@ -405,6 +411,7 @@
 			error = ENOBUFS;
 			goto bad;
 	}
+#endif /* !ALTQ */
 
 	/*
 	 * Look for broadcast address and
diff -urN ../sys/netinet6/ip6_input.c ./netinet6/ip6_input.c
--- ../sys/netinet6/ip6_input.c	Wed Jul 25 04:10:18 2001
+++ ./netinet6/ip6_input.c	Tue Oct  2 22:06:21 2001
@@ -350,6 +350,12 @@
 
 	ip6stat.ip6s_nxthist[ip6->ip6_nxt]++;
 
+#ifdef ALTQ
+	if (altq_input != NULL && (*altq_input)(m, AF_INET6) == 0) {
+		/* packet is dropped by traffic conditioner */
+		return;
+	}
+#endif
 	/*
 	 * Check with the firewall...
 	 */
diff -urN ../sys/pci/if_dc.c ./pci/if_dc.c
--- ../sys/pci/if_dc.c	Fri Jul 20 11:01:26 2001
+++ ./pci/if_dc.c	Tue Oct  2 22:06:21 2001
@@ -1912,7 +1912,8 @@
 	ifp->if_watchdog = dc_watchdog;
 	ifp->if_init = dc_init;
 	ifp->if_baudrate = 10000000;
-	ifp->if_snd.ifq_maxlen = DC_TX_LIST_CNT - 1;
+	IFQ_SET_MAXLEN(&ifp->if_snd, DC_TX_LIST_CNT - 1);
+	IFQ_SET_READY(&ifp->if_snd);
 
 	/*
 	 * Do MII setup. If this is a 21143, check for a PHY on the
@@ -2540,7 +2541,7 @@
 		if (mii->mii_media_status & IFM_ACTIVE &&
 		    IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
 			sc->dc_link++;
-			if (ifp->if_snd.ifq_head != NULL)
+			if (!IFQ_IS_EMPTY(&ifp->if_snd))
 				dc_start(ifp);
 		}
 	}
@@ -2678,7 +2679,7 @@
 	/* Re-enable interrupts. */
 	CSR_WRITE_4(sc, DC_IMR, DC_INTRS);
 
-	if (ifp->if_snd.ifq_head != NULL)
+	if (!IFQ_IS_EMPTY(&ifp->if_snd))
 		dc_start(ifp);
 
 	return;
@@ -2742,6 +2743,11 @@
 		sc->dc_ldata->dc_tx_list[cur].dc_ctl |= DC_TXCTL_FINT;
 	if (sc->dc_flags & DC_TX_USE_TX_INTR && sc->dc_cdata.dc_tx_cnt > 64)
 		sc->dc_ldata->dc_tx_list[cur].dc_ctl |= DC_TXCTL_FINT;
+#ifdef ALTQ
+	else if ((sc->dc_flags & DC_TX_USE_TX_INTR) &&
+		 TBR_IS_ENABLED(&sc->arpcom.ac_if.if_snd))
+		sc->dc_ldata->dc_tx_list[cur].dc_ctl |= DC_TXCTL_FINT;
+#endif
 	sc->dc_ldata->dc_tx_list[*txidx].dc_status = DC_TXSTAT_OWN;
 	*txidx = frag;
 
@@ -2806,24 +2812,34 @@
 	idx = sc->dc_cdata.dc_tx_prod;
 
 	while(sc->dc_cdata.dc_tx_chain[idx] == NULL) {
-		IF_DEQUEUE(&ifp->if_snd, m_head);
+		IFQ_POLL(&ifp->if_snd, m_head);
 		if (m_head == NULL)
 			break;
 
 		if (sc->dc_flags & DC_TX_COALESCE) {
+#ifdef ALTQ
+			/* note: dc_coal breaks the poll-and-dequeue rule.
+			 * if dc_coal fails, we lose the packet.
+			 */
+#endif
+			IFQ_DEQUEUE(&ifp->if_snd, m_head);
 			if (dc_coal(sc, &m_head)) {
-				IF_PREPEND(&ifp->if_snd, m_head);
 				ifp->if_flags |= IFF_OACTIVE;
 				break;
 			}
 		}
 
 		if (dc_encap(sc, m_head, &idx)) {
-			IF_PREPEND(&ifp->if_snd, m_head);
 			ifp->if_flags |= IFF_OACTIVE;
 			break;
 		}
 
+		/* now we are committed to transmit the packet */
+		if (sc->dc_flags & DC_TX_COALESCE) {
+			/* if mbuf is coalesced, it is already dequeued */
+		} else
+			IFQ_DEQUEUE(&ifp->if_snd, m_head);
+
 		/*
 		 * If there's a BPF listener, bounce a copy of this frame
 		 * to him.
@@ -2836,6 +2852,8 @@
 			break;
 		}
 	}
+	if (idx == sc->dc_cdata.dc_tx_prod)
+		return;
 
 	/* Transmit */
 	sc->dc_cdata.dc_tx_prod = idx;
@@ -3142,7 +3160,7 @@
 	dc_reset(sc);
 	dc_init(sc);
 
-	if (ifp->if_snd.ifq_head != NULL)
+	if (!IFQ_IS_EMPTY(&ifp->if_snd))
 		dc_start(ifp);
 
 	return;
diff -urN ../sys/pci/if_de.c ./pci/if_de.c
--- ../sys/pci/if_de.c	Sat Aug  5 08:25:09 2000
+++ ./pci/if_de.c	Tue Oct  2 22:06:21 2001
@@ -4135,6 +4135,11 @@
 #else
     struct mbuf *m0;
 #endif
+#if 1 /* ALTQ */
+    struct ifnet *ifp = &sc->tulip_if;
+    struct mbuf *ombuf = m;
+    int compressed = 0;
+#endif
 
 #if defined(TULIP_DEBUG)
     if ((sc->tulip_cmdmode & TULIP_CMD_TXRUN) == 0) {
@@ -4285,6 +4290,26 @@
 		 * entries that we can use for one packet, so we have
 		 * recopy it into one mbuf and then try again.
 		 */
+#if 1 /* ALTQ */
+		struct mbuf *tmp;
+		/*
+		 * tulip_mbuf_compress() frees the original mbuf.
+		 * thus, we have to remove the mbuf from the queue
+		 * before calling it.
+		 * we don't have to worry about space shortage
+		 * after compressing the mbuf since the compressed
+		 * mbuf will take only two segs.
+		 */
+		if (compressed) {
+		    /* should not happen */
+		    printf("tulip_txput: compress called twice!\n");
+		    goto finish;
+		}
+		IFQ_DEQUEUE(&ifp->if_snd, tmp);
+		if (tmp != ombuf)
+		    panic("tulip_txput: different mbuf dequeued!");
+		compressed = 1;
+#endif
 		m = tulip_mbuf_compress(m);
 		if (m == NULL)
 		    goto finish;
@@ -4346,6 +4371,16 @@
      * The descriptors have been filled in.  Now get ready
      * to transmit.
      */
+#if 1 /* ALTQ */
+    if (!compressed && (sc->tulip_flags & TULIP_TXPROBE_ACTIVE) == 0) {
+	/* remove the mbuf from the queue */
+	struct mbuf *tmp;
+	IFQ_DEQUEUE(&ifp->if_snd, tmp);
+	if (tmp != ombuf)
+	    panic("tulip_txput: different mbuf dequeued!");
+    }
+#endif
+
     IF_ENQUEUE(&sc->tulip_txq, m);
     m = NULL;
 
@@ -4693,6 +4728,14 @@
     return error;
 }
 
+#if 1 /* ALTQ */
+/*
+ * the original dequeueing policy is dequeue-and-prepend if something
+ * goes wrong.  when altq is used, it is changed to peek-and-dequeue.
+ * the modification becomes a bit complicated since tulip_txput() might
+ * copy and modify the mbuf passed.
+ */
+#endif
 /*
  * These routines gets called at device spl (from ether_output).  This might
  * pose a problem for TULIP_USE_SOFTINTR if ether_output is called at
@@ -4711,15 +4754,23 @@
 	if ((sc->tulip_flags & (TULIP_WANTSETUP|TULIP_TXPROBE_ACTIVE)) == TULIP_WANTSETUP)
 	    tulip_txput_setup(sc);
 
-	while (sc->tulip_if.if_snd.ifq_head != NULL) {
-	    struct mbuf *m;
-	    IF_DEQUEUE(&sc->tulip_if.if_snd, m);
-	    if ((m = tulip_txput(sc, m)) != NULL) {
-		IF_PREPEND(&sc->tulip_if.if_snd, m);
+	while (!IFQ_IS_EMPTY(&sc->tulip_if.if_snd)) {
+	    struct mbuf *m, *m0;
+	    IFQ_POLL(&sc->tulip_if.if_snd, m);
+	    if (m == NULL)
+		break;
+	    if ((m0 = tulip_txput(sc, m)) != NULL) {
+		if (m0 != m)
+		    /* should not happen */
+		    printf("tulip_if_start: txput failed!\n");
 		break;
 	    }
 	}
-	if (sc->tulip_if.if_snd.ifq_head == NULL)
+#ifdef ALTQ
+	if (0) /* don't switch to the one packet mode */
+#else
+	if (IFQ_IS_EMPTY(&sc->tulip_if.if_snd))
+#endif
 	    sc->tulip_if.if_start = tulip_ifstart_one;
     }
 
@@ -4734,11 +4785,13 @@
     tulip_softc_t * const sc = (tulip_softc_t *)ifp->if_softc;
 
     if ((sc->tulip_if.if_flags & IFF_RUNNING)
-	    && sc->tulip_if.if_snd.ifq_head != NULL) {
-	struct mbuf *m;
-	IF_DEQUEUE(&sc->tulip_if.if_snd, m);
-	if ((m = tulip_txput(sc, m)) != NULL)
-	    IF_PREPEND(&sc->tulip_if.if_snd, m);
+	    && !IFQ_IS_EMPTY(&sc->tulip_if.if_snd)) {
+	struct mbuf *m, *m0;
+	IFQ_POLL(&sc->tulip_if.if_snd, m);
+	if (m != NULL && (m0 = tulip_txput(sc, m)) != NULL)
+	    if (m0 != m)
+		/* should not happen */
+		printf("tulip_if_start_one: txput failed!\n");
     }
     TULIP_PERFEND(ifstart_one);
 }
@@ -4844,7 +4897,8 @@
     ifp->if_watchdog = tulip_ifwatchdog;
     ifp->if_timer = 1;
     ifp->if_output = ether_output;
-  
+    IFQ_SET_READY(&ifp->if_snd);
+
     printf("%s%d: %s%s pass %d.%d%s\n",
 	   sc->tulip_name, sc->tulip_unit,
 	   sc->tulip_boardid,
@@ -4874,8 +4928,8 @@
 
     tulip_reset(sc);
 
+    IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
     ether_ifattach(&(sc)->tulip_if, ETHER_BPF_SUPPORTED);
-    ifp->if_snd.ifq_maxlen = ifqmaxlen;
 }
 
 #if defined(TULIP_BUS_DMA)
diff -urN ../sys/pci/if_en_pci.c ./pci/if_en_pci.c
--- ../sys/pci/if_en_pci.c	Sun Aug 22 07:10:49 1999
+++ ./pci/if_en_pci.c	Tue Oct  2 22:06:22 2001
@@ -45,19 +45,17 @@
  * thanks to Matt Thomas for figuring out FreeBSD vs NetBSD vs etc.. diffs.
  */
 
-#include "en.h"
-
 #include <sys/param.h>
 #include <sys/kernel.h>
 #include <sys/systm.h>
-#if defined(__FreeBSD__)
-#include <sys/eventhandler.h>
-#endif
 #include <sys/malloc.h>
 #include <sys/socket.h>
 
+#include <sys/bus.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <machine/resource.h>
 #include <machine/clock.h>		/* for DELAY */
-
 #include <net/if.h>
 
 #include <pci/pcivar.h>
@@ -71,9 +69,10 @@
  * prototypes
  */
 
-static	void en_pci_attach __P((pcici_t, int));
-static	const char *en_pci_probe __P((pcici_t, pcidi_t));
-static void en_pci_shutdown __P((void *, int));
+static	int en_pci_probe __P((device_t));
+static	int en_pci_attach __P((device_t));
+static	int en_pci_detach __P((device_t));
+static	int en_pci_shutdown __P((device_t));
 
 /*
  * local structures
@@ -83,43 +82,20 @@
   /* bus independent stuff */
   struct en_softc esc;		/* includes "device" structure */
 
-  /* PCI bus glue */
-  void *sc_ih;			/* interrupt handle */
-  pci_chipset_tag_t en_pc;	/* for PCI calls */
-  pcici_t en_confid;		/* config id */
+  /* freebsd newbus glue */
+  struct resource *res;		/* resource descriptor for registers */
+  struct resource *irq;		/* resource descriptor for interrupt */
+  void *ih;			/* interrupt handle */
 };
 
 #if !defined(MIDWAY_ENIONLY)
-static  void eni_get_macaddr __P((struct en_pci_softc *));
+static  void eni_get_macaddr __P((device_t, struct en_pci_softc *));
 #endif
 #if !defined(MIDWAY_ADPONLY)
 static  void adp_get_macaddr __P((struct en_pci_softc *));
 #endif
 
 /*
- * pointers to softcs (we alloc)
- */
-
-static struct en_pci_softc *enpcis[NEN] = {0};
-extern struct cfdriver en_cd;
-
-/*
- * autoconfig structures
- */
-
-static u_long en_pci_count;
-
-static struct pci_device endevice = {
-	"en",
-	en_pci_probe,
-	en_pci_attach,
-	&en_pci_count,
-	NULL,
-};  
-
-COMPAT_PCI_DRIVER (en, endevice);
-
-/*
  * local defines (PCI specific stuff)
  */
 
@@ -194,94 +170,104 @@
  * autoconfig stuff
  */
 
-static const char *en_pci_probe(config_id, device_id)
-
-pcici_t config_id;
-pcidi_t device_id;
-
+static int
+en_pci_probe(device_t dev)
 {
+  switch (pci_get_vendor(dev)) {
 #if !defined(MIDWAY_ADPONLY)
-  if (PCI_VENDOR(device_id) == PCI_VENDOR_EFFICIENTNETS && 
-      (PCI_CHIPID(device_id) == PCI_PRODUCT_EFFICIENTNETS_ENI155PF ||
-       PCI_CHIPID(device_id) == PCI_PRODUCT_EFFICIENTNETS_ENI155PA))
-    return "Efficient Networks ENI-155p";
+  case PCI_VENDOR_EFFICIENTNETS:
+    switch (pci_get_device(dev)) {
+    case PCI_PRODUCT_EFFICIENTNETS_ENI155PF:
+    case PCI_PRODUCT_EFFICIENTNETS_ENI155PA:
+      device_set_desc(dev, "Efficient Networks ENI-155p");
+      return 0;
+    }
+    break;
 #endif
-
 #if !defined(MIDWAY_ENIONLY)
-  if (PCI_VENDOR(device_id) == PCI_VENDOR_ADP && 
-      (PCI_CHIPID(device_id) == PCI_PRODUCT_ADP_AIC5900 ||
-       PCI_CHIPID(device_id) == PCI_PRODUCT_ADP_AIC5905))
-    return "Adaptec 155 ATM";
+  case PCI_VENDOR_ADP:
+    switch (pci_get_device(dev)) {
+    case PCI_PRODUCT_ADP_AIC5900:
+    case PCI_PRODUCT_ADP_AIC5905:
+      device_set_desc(dev, "Adaptec 155 ATM");
+      return 0;
+    }
+    break;
 #endif
-
-  return 0;
+  }
+  return ENXIO;
 }
 
-static void en_pci_attach(config_id, unit)
-
-pcici_t config_id;
-int unit;
-
+static int
+en_pci_attach(device_t dev)
 {
   struct en_softc *sc;
   struct en_pci_softc *scp;
-  pcidi_t device_id;
-  int retval;
-  vm_offset_t pa;
-
-  if (unit >= NEN) {
-    printf("en%d: not configured; kernel is built for only %d device%s.\n",
-	unit, NEN, NEN == 1 ? "" : "s");
-    return;
-  }
+  u_long val;
+  int rid, s, unit, error = 0;
 
-  scp = (struct en_pci_softc *) malloc(sizeof(*scp), M_DEVBUF, M_NOWAIT);
-  if (scp == NULL)
-    return;
+  sc = device_get_softc(dev);
+  scp = (struct en_pci_softc *)sc;
   bzero(scp, sizeof(*scp));		/* zero */
-  sc = &scp->esc;
 
-  retval = pci_map_mem(config_id, PCI_CBMA, (vm_offset_t *) &sc->en_base, &pa);
+  s = splimp();
 
-  if (!retval) {
-    free((caddr_t) scp, M_DEVBUF);
-    return;
-  }
-  enpcis[unit] = scp;			/* lock it in */
-  en_cd.cd_devs[unit] = sc;		/* fake a cfdriver structure */
-  en_cd.cd_ndevs = NEN;
-  snprintf(sc->sc_dev.dv_xname, sizeof(sc->sc_dev.dv_xname), "en%d", unit);
-  sc->enif.if_unit = unit;
-  sc->enif.if_name = "en";
-  scp->en_confid = config_id;
+  /*
+   * Enable bus mastering.
+   */
+  val = pci_read_config(dev, PCIR_COMMAND, 2);
+  val |= (PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
+  pci_write_config(dev, PCIR_COMMAND, val, 2);
 
   /*
-   * figure out if we are an adaptec card or not.
-   * XXX: why do we have to re-read PC_ID_REG when en_pci_probe already
-   * had that info?
+   * Map control/status registers.
    */
+  rid = PCI_CBMA;
+  scp->res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
+				0, ~0, 1, RF_ACTIVE);
+  if (!scp->res) {
+    device_printf(dev, "could not map memory\n");
+    error = ENXIO;
+    goto fail;
+  }
 
-  device_id = pci_conf_read(config_id, PCI_ID_REG);
-  sc->is_adaptec = (PCI_VENDOR(device_id) == PCI_VENDOR_ADP) ? 1 : 0;
+  sc->en_memt = rman_get_bustag(scp->res);
+  sc->en_base = rman_get_bushandle(scp->res);
   
   /*
-   * Add shutdown hook so that DMA is disabled prior to reboot. Not
-   * doing so could allow DMA to corrupt kernel memory during the
-   * reboot before the driver initializes.
+   * Allocate our interrupt.
    */
-  EVENTHANDLER_REGISTER(shutdown_post_sync, en_pci_shutdown, scp,
-			SHUTDOWN_PRI_DEFAULT);
+  rid = 0;
+  scp->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
+				RF_SHAREABLE | RF_ACTIVE);
+  if (scp->irq == NULL) {
+    device_printf(dev, "could not map interrupt\n");
+    bus_release_resource(dev, SYS_RES_MEMORY, PCI_CBMA, scp->res);
+    error = ENXIO;
+    goto fail;
+  }
 
-  if (!pci_map_int(config_id, en_intr, (void *) sc, &net_imask)) {
-    printf("%s: couldn't establish interrupt\n", sc->sc_dev.dv_xname);
-    return;
+  error = bus_setup_intr(dev, scp->irq, INTR_TYPE_NET,
+			 en_intr, sc, &scp->ih);
+  if (error) {
+    device_printf(dev, "could not setup irq\n");
+    bus_release_resource(dev, SYS_RES_IRQ, 0, scp->irq);
+    bus_release_resource(dev, SYS_RES_MEMORY, PCI_CBMA, scp->res);
+    goto fail;
   }
-  sc->ipl = 1; /* XXX */
+  sc->ipl = 1; /* XXX (required to enable interrupt on midway) */
+
+  unit = device_get_unit(dev);
+  snprintf(sc->sc_dev.dv_xname, sizeof(sc->sc_dev.dv_xname), "en%d", unit);
+  sc->enif.if_unit = unit;
+  sc->enif.if_name = "en";
 
+  /* figure out if we are an adaptec card or not */
+  sc->is_adaptec = (pci_get_vendor(dev) == PCI_VENDOR_ADP) ? 1 : 0;
+  
   /*
    * set up pci bridge
    */
-
 #if !defined(MIDWAY_ENIONLY)
   if (sc->is_adaptec) {
     adp_get_macaddr(scp);
@@ -292,9 +278,9 @@
 
 #if !defined(MIDWAY_ADPONLY)
   if (!sc->is_adaptec) {
-    eni_get_macaddr(scp);
+    eni_get_macaddr(dev, scp);
     sc->en_busreset = NULL;
-    pci_conf_write(config_id, EN_TONGA, (TONGA_SWAP_DMA|TONGA_SWAP_WORD));
+    pci_write_config(dev, EN_TONGA, (TONGA_SWAP_DMA|TONGA_SWAP_WORD), 4);
   }
 #endif
 
@@ -304,26 +290,64 @@
 
   en_attach(sc);
 
+  splx(s);
+
+  return 0;
+
+ fail:
+  splx(s);
+  return error;
+}
+
+static int
+en_pci_detach(device_t dev)
+{
+	struct en_softc *sc = device_get_softc(dev);
+	struct en_pci_softc *scp = (struct en_pci_softc *)sc;
+	int s;
+
+	s = splimp();
+
+	/*
+	 * Close down routes etc.
+	 */
+	if_detach(&sc->enif);
+
+	/*
+	 * Stop DMA and drop transmit queue.
+	 */
+	en_reset(sc);
+
+	/*
+	 * Deallocate resources.
+	 */
+	bus_teardown_intr(dev, scp->irq, scp->ih);
+	bus_release_resource(dev, SYS_RES_IRQ, 0, scp->irq);
+	bus_release_resource(dev, SYS_RES_MEMORY, PCI_CBMA, scp->res);
+
+#ifdef notyet
+	/*
+	 * Free all the driver internal resources
+	 */
+#endif
+
+	splx(s);
+
+	return 0;
 }
 
-static void
-en_pci_shutdown(
-	void *sc,
-	int howto)
+static int
+en_pci_shutdown(device_t dev)
 {
-    struct en_pci_softc *psc = (struct en_pci_softc *)sc;
+    struct en_pci_softc *psc = (struct en_pci_softc *)device_get_softc(dev);
     
     en_reset(&psc->esc);
-    DELAY(10);
+    DELAY(10);	/* is this necessary? -kjc */
+    return (0);
 }
 
 #if !defined(MIDWAY_ENIONLY)
 
-#if defined(sparc) || defined(__FreeBSD__)
-#define bus_space_read_1(t, h, o) \
-  		((void)t, (*(volatile u_int8_t *)((h) + (o))))
-#endif
-
 static void 
 adp_get_macaddr(scp)
      struct en_pci_softc *scp;
@@ -332,8 +356,8 @@
   int lcv;
 
   for (lcv = 0; lcv < sizeof(sc->macaddr); lcv++)
-    sc->macaddr[lcv] = bus_space_read_1(sc->en_memt, sc->en_base,
-					MID_ADPMACOFF + lcv);
+	  sc->macaddr[lcv] = bus_space_read_1(sc->en_memt, sc->en_base,
+					      MID_ADPMACOFF + lcv);
 }
 
 #endif /* MIDWAY_ENIONLY */
@@ -350,90 +374,109 @@
 #define EN_ESI         64
 
 static void 
-eni_get_macaddr(scp)
-     struct en_pci_softc *scp;
+eni_get_macaddr(device_t dev, struct en_pci_softc *scp)
 {
   struct en_softc * sc = (struct en_softc *)scp;
-  pcici_t id = scp->en_confid;
   int i, j, address, status;
   u_int32_t data, t_data;
   u_int8_t tmp;
   
-  t_data = pci_conf_read(id, EN_TONGA) & 0xffffff00;
+  t_data = pci_read_config(dev, EN_TONGA, 4) & 0xffffff00;
 
   data =  EN_PROM_MAGIC | EN_PROM_DATA | EN_PROM_CLK;
-  pci_conf_write(id, EN_TONGA, data);
+  pci_write_config(dev, EN_TONGA, data, 4);
 
   for (i = 0; i < sizeof(sc->macaddr); i ++){
     /* start operation */
     data |= EN_PROM_DATA ;
-    pci_conf_write(id, EN_TONGA, data);
+    pci_write_config(dev, EN_TONGA, data, 4);
     data |= EN_PROM_CLK ;
-    pci_conf_write(id, EN_TONGA, data);
+    pci_write_config(dev, EN_TONGA, data, 4);
     data &= ~EN_PROM_DATA ;
-    pci_conf_write(id, EN_TONGA, data);
+    pci_write_config(dev, EN_TONGA, data, 4);
     data &= ~EN_PROM_CLK ;
-    pci_conf_write(id, EN_TONGA, data);
+    pci_write_config(dev, EN_TONGA, data, 4);
     /* send address with serial line */
     address = ((i + EN_ESI) << 1) + 1;
     for ( j = 7 ; j >= 0 ; j --){
       data = (address >> j) & 1 ? data | EN_PROM_DATA :
       data & ~EN_PROM_DATA;
-      pci_conf_write(id, EN_TONGA, data);
+      pci_write_config(dev, EN_TONGA, data, 4);
       data |= EN_PROM_CLK ;
-      pci_conf_write(id, EN_TONGA, data);
+      pci_write_config(dev, EN_TONGA, data, 4);
       data &= ~EN_PROM_CLK ;
-      pci_conf_write(id, EN_TONGA, data);
+      pci_write_config(dev, EN_TONGA, data, 4);
     }
     /* get ack */
     data |= EN_PROM_DATA ;
-    pci_conf_write(id, EN_TONGA, data);
+    pci_write_config(dev, EN_TONGA, data, 4);
     data |= EN_PROM_CLK ;
-    pci_conf_write(id, EN_TONGA, data);
-    data = pci_conf_read(id, EN_TONGA);
+    pci_write_config(dev, EN_TONGA, data, 4);
+    data = pci_read_config(dev, EN_TONGA, 4);
     status = data & EN_PROM_DATA;
     data &= ~EN_PROM_CLK ;
-    pci_conf_write(id, EN_TONGA, data);
+    pci_write_config(dev, EN_TONGA, data, 4);
     data |= EN_PROM_DATA ;
-    pci_conf_write(id, EN_TONGA, data);
+    pci_write_config(dev, EN_TONGA, data, 4);
 
     tmp = 0;
 
     for ( j = 7 ; j >= 0 ; j --){
       tmp <<= 1;
       data |= EN_PROM_DATA ;
-      pci_conf_write(id, EN_TONGA, data);
+      pci_write_config(dev, EN_TONGA, data, 4);
       data |= EN_PROM_CLK ;
-      pci_conf_write(id, EN_TONGA, data);
-      data = pci_conf_read(id, EN_TONGA);
+      pci_write_config(dev, EN_TONGA, data, 4);
+      data = pci_read_config(dev, EN_TONGA, 4);
       if(data & EN_PROM_DATA) tmp |= 1;
       data &= ~EN_PROM_CLK ;
-      pci_conf_write(id, EN_TONGA, data);
+      pci_write_config(dev, EN_TONGA, data, 4);
       data |= EN_PROM_DATA ;
-      pci_conf_write(id, EN_TONGA, data);
+      pci_write_config(dev, EN_TONGA, data, 4);
     }
     /* get ack */
     data |= EN_PROM_DATA ;
-    pci_conf_write(id, EN_TONGA, data);
+    pci_write_config(dev, EN_TONGA, data, 4);
     data |= EN_PROM_CLK ;
-    pci_conf_write(id, EN_TONGA, data);
-    data = pci_conf_read(id, EN_TONGA);
+    pci_write_config(dev, EN_TONGA, data, 4);
+    data = pci_read_config(dev, EN_TONGA, 4);
     status = data & EN_PROM_DATA;
     data &= ~EN_PROM_CLK ;
-    pci_conf_write(id, EN_TONGA, data);
+    pci_write_config(dev, EN_TONGA, data, 4);
     data |= EN_PROM_DATA ;
-    pci_conf_write(id, EN_TONGA, data);
+    pci_write_config(dev, EN_TONGA, data, 4);
 
     sc->macaddr[i] = tmp;
   }
   /* stop operation */
   data &=  ~EN_PROM_DATA;
-  pci_conf_write(id, EN_TONGA, data);
+  pci_write_config(dev, EN_TONGA, data, 4);
   data |=  EN_PROM_CLK;
-  pci_conf_write(id, EN_TONGA, data);
+  pci_write_config(dev, EN_TONGA, data, 4);
   data |=  EN_PROM_DATA;
-  pci_conf_write(id, EN_TONGA, data);
-  pci_conf_write(id, EN_TONGA, t_data);
+  pci_write_config(dev, EN_TONGA, data, 4);
+  pci_write_config(dev, EN_TONGA, t_data, 4);
 }
 
 #endif /* !MIDWAY_ADPONLY */
+
+static device_method_t en_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		en_pci_probe),
+	DEVMETHOD(device_attach,	en_pci_attach),
+	DEVMETHOD(device_detach,	en_pci_detach),
+	DEVMETHOD(device_shutdown,	en_pci_shutdown),
+
+	{ 0, 0 }
+};
+
+static driver_t en_driver = {
+	"en",
+	en_methods,
+	sizeof(struct en_pci_softc),
+};
+
+static devclass_t en_devclass;
+
+DRIVER_MODULE(if_en, pci, en_driver, en_devclass, 0, 0);
+
diff -urN ../sys/pci/if_fxp.c ./pci/if_fxp.c
--- ../sys/pci/if_fxp.c	Wed Oct 25 06:47:36 2000
+++ ./pci/if_fxp.c	Tue Oct  2 22:06:22 2001
@@ -421,6 +421,7 @@
 	ifp->if_ioctl = fxp_ioctl;
 	ifp->if_start = fxp_start;
 	ifp->if_watchdog = fxp_watchdog;
+	IFQ_SET_READY(&ifp->if_snd);
 
 	/*
 	 * Attach the interface.
@@ -430,7 +431,7 @@
 	 * Let the system queue as many packets as we have available
 	 * TX descriptors.
 	 */
-	ifp->if_snd.ifq_maxlen = FXP_NTXCB - 1;
+	IFQ_SET_MAXLEN(&ifp->if_snd, FXP_NTXCB - 1);
 	ether_ifattach(ifp, enaddr);
 	bpfattach(&sc->sc_ethercom.ec_if.if_bpf, ifp, DLT_EN10MB,
 	    sizeof(struct ether_header));
@@ -614,6 +615,7 @@
 	ifp->if_ioctl = fxp_ioctl;
 	ifp->if_start = fxp_start;
 	ifp->if_watchdog = fxp_watchdog;
+	IFQ_SET_READY(&ifp->if_snd);
 
 	/*
 	 * Attach the interface.
@@ -623,7 +625,7 @@
 	 * Let the system queue as many packets as we have available
 	 * TX descriptors.
 	 */
-	ifp->if_snd.ifq_maxlen = FXP_NTXCB - 1;
+	IFQ_SET_MAXLEN(&ifp->if_snd, FXP_NTXCB - 1);
 
 	splx(s);
 	return 0;
@@ -1068,14 +1070,16 @@
 	 * NOTE: One TxCB is reserved to guarantee that fxp_mc_setup() can add
 	 *       a NOP command when needed.
 	 */
-	while (ifp->if_snd.ifq_head != NULL && sc->tx_queued < FXP_NTXCB - 1) {
+	while (!IFQ_IS_EMPTY(&ifp->if_snd) && sc->tx_queued < FXP_NTXCB - 1) {
 		struct mbuf *m, *mb_head;
 		int segment;
 
 		/*
 		 * Grab a packet to transmit.
 		 */
-		IF_DEQUEUE(&ifp->if_snd, mb_head);
+		IFQ_DEQUEUE(&ifp->if_snd, mb_head);
+		if (mb_head == NULL)
+			break;
 
 		/*
 		 * Get pointer to next available tx desc.
@@ -1183,6 +1187,11 @@
 	 * going again if suspended.
 	 */
 	if (txp != NULL) {
+#ifdef ALTQ
+		/* if tb regulator is used, we need tx complete interrupt */
+		if (TBR_IS_ENABLED(&ifp->if_snd))
+			txp->cb_command |= FXP_CB_COMMAND_I;
+#endif
 		fxp_scb_wait(sc);
 		CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_RESUME);
 	}
@@ -1239,7 +1248,7 @@
 			/*
 			 * Try to start more packets transmitting.
 			 */
-			if (ifp->if_snd.ifq_head != NULL)
+			if (!IFQ_IS_EMPTY(&ifp->if_snd))
 				fxp_start(ifp);
 		}
 		/*
diff -urN ../sys/pci/if_rl.c ./pci/if_rl.c
--- ../sys/pci/if_rl.c	Fri Jul 20 03:33:07 2001
+++ ./pci/if_rl.c	Tue Oct  2 22:06:22 2001
@@ -954,7 +954,8 @@
 	ifp->if_watchdog = rl_watchdog;
 	ifp->if_init = rl_init;
 	ifp->if_baudrate = 10000000;
-	ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
+	IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
+	IFQ_SET_READY(&ifp->if_snd);
 
 	/*
 	 * Call MI attach routine.
@@ -1289,7 +1290,7 @@
 	/* Re-enable interrupts. */
 	CSR_WRITE_2(sc, RL_IMR, RL_INTRS);
 
-	if (ifp->if_snd.ifq_head != NULL)
+	if (!IFQ_IS_EMPTY(&ifp->if_snd))
 		rl_start(ifp);
 
 	return;
@@ -1359,20 +1360,24 @@
 {
 	struct rl_softc		*sc;
 	struct mbuf		*m_head = NULL;
+	int			pkts = 0;
 
 	sc = ifp->if_softc;
 
 	while(RL_CUR_TXMBUF(sc) == NULL) {
-		IF_DEQUEUE(&ifp->if_snd, m_head);
+		IFQ_POLL(&ifp->if_snd, m_head);
 		if (m_head == NULL)
 			break;
 
 		if (rl_encap(sc, m_head)) {
-			IF_PREPEND(&ifp->if_snd, m_head);
 			ifp->if_flags |= IFF_OACTIVE;
 			break;
 		}
 
+		/* now we are committed to transmit the packet */
+		IFQ_DEQUEUE(&ifp->if_snd, m_head);
+		pkts++;
+
 		/*
 		 * If there's a BPF listener, bounce a copy of this frame
 		 * to him.
@@ -1391,6 +1396,8 @@
 
 		RL_INC(sc->rl_cdata.cur_tx);
 	}
+	if (pkts == 0)
+		return;
 
 	/*
 	 * We broke out of the loop because all our TX slots are
diff -urN ../sys/pci/if_sf.c ./pci/if_sf.c
--- ../sys/pci/if_sf.c	Fri Aug 17 05:35:04 2001
+++ ./pci/if_sf.c	Tue Oct  2 22:06:22 2001
@@ -825,7 +825,8 @@
 	ifp->if_watchdog = sf_watchdog;
 	ifp->if_init = sf_init;
 	ifp->if_baudrate = 10000000;
-	ifp->if_snd.ifq_maxlen = SF_TX_DLIST_CNT - 1;
+	IFQ_SET_MAXLEN(&ifp->if_snd, SF_TX_DLIST_CNT - 1);
+	IFQ_SET_READY(&ifp->if_snd);
 
 	/*
 	 * Call MI attach routine.
@@ -1152,7 +1153,7 @@
 	/* Re-enable interrupts. */
 	csr_write_4(sc, SF_IMR, SF_INTRS);
 
-	if (ifp->if_snd.ifq_head != NULL)
+	if (!IFQ_IS_EMPTY(&ifp->if_snd))
 		sf_start(ifp);
 
 	return;
@@ -1368,18 +1369,19 @@
 			cur_tx = NULL;
 			break;
 		}
-		IF_DEQUEUE(&ifp->if_snd, m_head);
+		IFQ_POLL(&ifp->if_snd, m_head);
 		if (m_head == NULL)
 			break;
 
 		cur_tx = &sc->sf_ldata->sf_tx_dlist[i];
 		if (sf_encap(sc, cur_tx, m_head)) {
-			IF_PREPEND(&ifp->if_snd, m_head);
 			ifp->if_flags |= IFF_OACTIVE;
 			cur_tx = NULL;
 			break;
 		}
 
+		/* now we are committed to transmit the packet */
+		IFQ_DEQUEUE(&ifp->if_snd, m_head);
 
 		/*
 		 * If there's a BPF listener, bounce a copy of this frame
@@ -1493,7 +1495,7 @@
 		if (mii->mii_media_status & IFM_ACTIVE &&
 		    IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE)
 			sc->sf_link++;
-			if (ifp->if_snd.ifq_head != NULL)
+			if (!IFQ_IS_EMPTY(&ifp->if_snd))
 				sf_start(ifp);
 	}
 
@@ -1518,7 +1520,7 @@
 	sf_reset(sc);
 	sf_init(sc);
 
-	if (ifp->if_snd.ifq_head != NULL)
+	if (!IFQ_IS_EMPTY(&ifp->if_snd))
 		sf_start(ifp);
 
 	return;
diff -urN ../sys/pci/if_sis.c ./pci/if_sis.c
--- ../sys/pci/if_sis.c	Thu Feb 22 07:17:51 2001
+++ ./pci/if_sis.c	Tue Oct  2 22:06:22 2001
@@ -922,7 +922,8 @@
 	ifp->if_watchdog = sis_watchdog;
 	ifp->if_init = sis_init;
 	ifp->if_baudrate = 10000000;
-	ifp->if_snd.ifq_maxlen = SIS_TX_LIST_CNT - 1;
+	IFQ_SET_MAXLEN(&ifp->if_snd, SIS_TX_LIST_CNT - 1);
+	IFQ_SET_READY(&ifp->if_snd);
 
 	/*
 	 * Do MII setup.
@@ -1249,7 +1250,7 @@
 		if (mii->mii_media_status & IFM_ACTIVE &&
 		    IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE)
 			sc->sis_link++;
-			if (ifp->if_snd.ifq_head != NULL)
+			if (!IFQ_IS_EMPTY(&ifp->if_snd))
 				sis_start(ifp);
 	}
 
@@ -1310,7 +1311,7 @@
 	/* Re-enable interrupts. */
 	CSR_WRITE_4(sc, SIS_IER, 1);
 
-	if (ifp->if_snd.ifq_head != NULL)
+	if (!IFQ_IS_EMPTY(&ifp->if_snd))
 		sis_start(ifp);
 
 	return;
@@ -1390,16 +1391,18 @@
 		return;
 
 	while(sc->sis_ldata->sis_tx_list[idx].sis_mbuf == NULL) {
-		IF_DEQUEUE(&ifp->if_snd, m_head);
+		IFQ_POLL(&ifp->if_snd, m_head);
 		if (m_head == NULL)
 			break;
 
 		if (sis_encap(sc, m_head, &idx)) {
-			IF_PREPEND(&ifp->if_snd, m_head);
 			ifp->if_flags |= IFF_OACTIVE;
 			break;
 		}
 
+		/* now we are committed to transmit the packet */
+		IFQ_DEQUEUE(&ifp->if_snd, m_head);
+
 		/*
 		 * If there's a BPF listener, bounce a copy of this frame
 		 * to him.
@@ -1408,6 +1411,8 @@
 			bpf_mtap(ifp, m_head);
 
 	}
+	if (idx == sc->sis_cdata.sis_tx_prod)
+		return;
 
 	/* Transmit */
 	sc->sis_cdata.sis_tx_prod = idx;
@@ -1689,7 +1694,7 @@
 	sis_reset(sc);
 	sis_init(sc);
 
-	if (ifp->if_snd.ifq_head != NULL)
+	if (!IFQ_IS_EMPTY(&ifp->if_snd))
 		sis_start(ifp);
 
 	return;
diff -urN ../sys/pci/if_ti.c ./pci/if_ti.c
--- ../sys/pci/if_ti.c	Wed Aug  1 10:08:25 2001
+++ ./pci/if_ti.c	Tue Oct  2 22:06:22 2001
@@ -1739,7 +1739,8 @@
 	ifp->if_watchdog = ti_watchdog;
 	ifp->if_init = ti_init;
 	ifp->if_mtu = ETHERMTU;
-	ifp->if_snd.ifq_maxlen = TI_TX_RING_CNT - 1;
+	IFQ_SET_MAXLEN(&ifp->if_snd, TI_TX_RING_CNT - 1);
+	IFQ_SET_READY(&ifp->if_snd);
 
 	/* Set up ifmedia support. */
 	ifmedia_init(&sc->ifmedia, IFM_IMASK, ti_ifmedia_upd, ti_ifmedia_sts);
@@ -2017,7 +2018,7 @@
 	/* Re-enable interrupts. */
 	CSR_WRITE_4(sc, TI_MB_HOSTINTR, 0);
 
-	if (ifp->if_flags & IFF_RUNNING && ifp->if_snd.ifq_head != NULL)
+	if (ifp->if_flags & IFF_RUNNING && !IFQ_IS_EMPTY(&ifp->if_snd))
 		ti_start(ifp);
 
 	return;
@@ -2152,13 +2153,14 @@
 	struct ti_softc		*sc;
 	struct mbuf		*m_head = NULL;
 	u_int32_t		prodidx = 0;
+	int			pkts = 0;
 
 	sc = ifp->if_softc;
 
 	prodidx = CSR_READ_4(sc, TI_MB_SENDPROD_IDX);
 
 	while(sc->ti_cdata.ti_tx_chain[prodidx] == NULL) {
-		IF_DEQUEUE(&ifp->if_snd, m_head);
+		IFQ_POLL(&ifp->if_snd, m_head);
 		if (m_head == NULL)
 			break;
 
@@ -2174,7 +2176,6 @@
 		    m_head->m_pkthdr.csum_flags & (CSUM_DELAY_DATA)) {
 			if ((TI_TX_RING_CNT - sc->ti_txcnt) <
 			    m_head->m_pkthdr.csum_data + 16) {
-				IF_PREPEND(&ifp->if_snd, m_head);
 				ifp->if_flags |= IFF_OACTIVE;
 				break;
 			}
@@ -2186,11 +2187,14 @@
 		 * for the NIC to drain the ring.
 		 */
 		if (ti_encap(sc, m_head, &prodidx)) {
-			IF_PREPEND(&ifp->if_snd, m_head);
 			ifp->if_flags |= IFF_OACTIVE;
 			break;
 		}
 
+		/* now we are committed to transmit the packet */
+		IFQ_DEQUEUE(&ifp->if_snd, m_head);
+		pkts++;
+
 		/*
 		 * If there's a BPF listener, bounce a copy of this frame
 		 * to him.
@@ -2198,6 +2202,8 @@
 		if (ifp->if_bpf)
 			bpf_mtap(ifp, m_head);
 	}
+	if (pkts == 0)
+		return;
 
 	/* Transmit */
 	CSR_WRITE_4(sc, TI_MB_SENDPROD_IDX, prodidx);
diff -urN ../sys/pci/if_tl.c ./pci/if_tl.c
--- ../sys/pci/if_tl.c	Thu Nov  2 09:04:28 2000
+++ ./pci/if_tl.c	Tue Oct  2 22:06:22 2001
@@ -1302,7 +1302,8 @@
 	ifp->if_watchdog = tl_watchdog;
 	ifp->if_init = tl_init;
 	ifp->if_mtu = ETHERMTU;
-	ifp->if_snd.ifq_maxlen = TL_TX_LIST_CNT - 1;
+	IFQ_SET_MAXLEN(&ifp->if_snd, TL_TX_LIST_CNT - 1);
+	IFQ_SET_READY(&ifp->if_snd);
 	callout_handle_init(&sc->tl_stat_ch);
 
 	/* Reset the adapter again. */
@@ -1775,7 +1776,7 @@
 		CMD_PUT(sc, TL_CMD_ACK | r | type);
 	}
 
-	if (ifp->if_snd.ifq_head != NULL)
+	if (!IFQ_IS_EMPTY(&ifp->if_snd))
 		tl_start(ifp);
 
 	return;
@@ -1964,7 +1965,7 @@
 	start_tx = sc->tl_cdata.tl_tx_free;
 
 	while(sc->tl_cdata.tl_tx_free != NULL) {
-		IF_DEQUEUE(&ifp->if_snd, m_head);
+		IFQ_DEQUEUE(&ifp->if_snd, m_head);
 		if (m_head == NULL)
 			break;
 
diff -urN ../sys/pci/if_tx.c ./pci/if_tx.c
--- ../sys/pci/if_tx.c	Sat Sep  1 16:21:56 2001
+++ ./pci/if_tx.c	Tue Oct  2 22:06:22 2001
@@ -460,7 +460,8 @@
 	ifp->if_init = (if_init_f_t*)epic_init;
 	ifp->if_timer = 0;
 	ifp->if_baudrate = 10000000;
-	ifp->if_snd.ifq_maxlen = TX_RING_SIZE - 1;
+	IFQ_SET_MAXLEN(&ifp->if_snd, TX_RING_SIZE - 1);
+	IFQ_SET_READY(&ifp->if_snd);
 
 	/* Enable ports, memory and busmastering */
 	command = pci_read_config(dev, PCIR_COMMAND, 4);
@@ -850,7 +851,7 @@
 		flist = sc->tx_flist + sc->cur_tx;
 
 		/* Get next packet to send */
-		IF_DEQUEUE( &ifp->if_snd, m0 );
+		IFQ_DEQUEUE( &ifp->if_snd, m0 );
 
 		/* If nothing to send, return */
 		if( NULL == m0 ) return;
@@ -1066,7 +1067,7 @@
         if( status & (INTSTAT_TXC|INTSTAT_TCC|INTSTAT_TQE) ) {
             epic_tx_done( sc );
 	    if(!(sc->sc_if.if_flags & IFF_OACTIVE) &&
-		sc->sc_if.if_snd.ifq_head )
+		!IFQ_IS_EMPTY( &sc->sc_if.if_snd ))
 		    epic_ifstart( &sc->sc_if );
 	}
 
@@ -1156,7 +1157,7 @@
 		printf("seems we can continue normaly\n");
 
 	/* Start output */
-	if( ifp->if_snd.ifq_head ) epic_ifstart( ifp );
+	if( !IFQ_IS_EMPTY( &ifp->if_snd ) ) epic_ifstart( ifp );
 
 	splx(x);
 }
diff -urN ../sys/pci/if_vr.c ./pci/if_vr.c
--- ../sys/pci/if_vr.c	Tue May 15 04:13:43 2001
+++ ./pci/if_vr.c	Tue Oct  2 22:06:22 2001
@@ -785,7 +785,8 @@
 	ifp->if_watchdog = vr_watchdog;
 	ifp->if_init = vr_init;
 	ifp->if_baudrate = 10000000;
-	ifp->if_snd.ifq_maxlen = VR_TX_LIST_CNT - 1;
+	IFQ_SET_MAXLEN(&ifp->if_snd, VR_TX_LIST_CNT - 1);
+	IFQ_SET_READY(&ifp->if_snd);
 
 	/*
 	 * Do MII setup.
@@ -1227,7 +1228,7 @@
 	/* Re-enable interrupts. */
 	CSR_WRITE_2(sc, VR_IMR, VR_INTRS);
 
-	if (ifp->if_snd.ifq_head != NULL) {
+	if (!IFQ_IS_EMPTY(&ifp->if_snd)) {
 		vr_start(ifp);
 	}
 
@@ -1334,7 +1335,7 @@
 	start_tx = sc->vr_cdata.vr_tx_free;
 
 	while(sc->vr_cdata.vr_tx_free->vr_mbuf == NULL) {
-		IF_DEQUEUE(&ifp->if_snd, m_head);
+		IFQ_DEQUEUE(&ifp->if_snd, m_head);
 		if (m_head == NULL)
 			break;
 
@@ -1570,7 +1571,7 @@
 	vr_reset(sc);
 	vr_init(sc);
 
-	if (ifp->if_snd.ifq_head != NULL)
+	if (!IFQ_IS_EMPTY(&ifp->if_snd))
 		vr_start(ifp);
 
 	return;
diff -urN ../sys/pci/if_wb.c ./pci/if_wb.c
--- ../sys/pci/if_wb.c	Sat Aug  5 08:45:28 2000
+++ ./pci/if_wb.c	Tue Oct  2 22:06:22 2001
@@ -949,7 +949,8 @@
 	ifp->if_watchdog = wb_watchdog;
 	ifp->if_init = wb_init;
 	ifp->if_baudrate = 10000000;
-	ifp->if_snd.ifq_maxlen = WB_TX_LIST_CNT - 1;
+	IFQ_SET_MAXLEN(&ifp->if_snd, WB_TX_LIST_CNT - 1);
+	IFQ_SET_READY(&ifp->if_snd);
 
 	/*
 	 * Do MII setup.
@@ -1372,7 +1373,7 @@
 	/* Re-enable interrupts. */
 	CSR_WRITE_4(sc, WB_IMR, WB_INTRS);
 
-	if (ifp->if_snd.ifq_head != NULL) {
+	if (!IFQ_IS_EMPTY(&ifp->if_snd)) {
 		wb_start(ifp);
 	}
 
@@ -1523,7 +1524,7 @@
 	start_tx = sc->wb_cdata.wb_tx_free;
 
 	while(sc->wb_cdata.wb_tx_free->wb_mbuf == NULL) {
-		IF_DEQUEUE(&ifp->if_snd, m_head);
+		IFQ_DEQUEUE(&ifp->if_snd, m_head);
 		if (m_head == NULL)
 			break;
 
@@ -1812,7 +1813,7 @@
 	wb_reset(sc);
 	wb_init(sc);
 
-	if (ifp->if_snd.ifq_head != NULL)
+	if (!IFQ_IS_EMPTY(&ifp->if_snd))
 		wb_start(ifp);
 
 	return;
diff -urN ../sys/pci/if_xl.c ./pci/if_xl.c
--- ../sys/pci/if_xl.c	Sat Jul 28 05:56:41 2001
+++ ./pci/if_xl.c	Tue Oct  2 22:06:22 2001
@@ -854,6 +854,7 @@
 {
 	struct mbuf		*m;
 	struct ifnet		*ifp;
+	int			error;
 
 	ifp = &sc->arpcom.ac_if;
 
@@ -871,7 +872,11 @@
 	mtod(m, unsigned char *)[15] = 0;
 	mtod(m, unsigned char *)[16] = 0xE3;
 	m->m_len = m->m_pkthdr.len = sizeof(struct ether_header) + 3;
-	IF_ENQUEUE(&ifp->if_snd, m);
+#ifdef ALTQ
+	IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error);
+#else
+	IFQ_ENQUEUE(&ifp->if_snd, m, error);
+#endif
 	xl_start(ifp);
 
 	return;
@@ -1414,7 +1419,8 @@
 	ifp->if_watchdog = xl_watchdog;
 	ifp->if_init = xl_init;
 	ifp->if_baudrate = 10000000;
-	ifp->if_snd.ifq_maxlen = XL_TX_LIST_CNT - 1;
+	IFQ_SET_MAXLEN(&ifp->if_snd, XL_TX_LIST_CNT - 1);
+	IFQ_SET_READY(&ifp->if_snd);
 
 	/*
 	 * Now we have to see what sort of media we have.
@@ -2069,7 +2075,7 @@
 		}
 	}
 
-	if (ifp->if_snd.ifq_head != NULL)
+	if (!IFQ_IS_EMPTY(&ifp->if_snd))
 		(*ifp->if_start)(ifp);
 
 	return;
@@ -2235,7 +2241,7 @@
 	start_tx = sc->xl_cdata.xl_tx_free;
 
 	while(sc->xl_cdata.xl_tx_free != NULL) {
-		IF_DEQUEUE(&ifp->if_snd, m_head);
+		IFQ_DEQUEUE(&ifp->if_snd, m_head);
 		if (m_head == NULL)
 			break;
 
@@ -2388,7 +2394,7 @@
 			break;
 		}
 
-		IF_DEQUEUE(&ifp->if_snd, m_head);
+		IFQ_DEQUEUE(&ifp->if_snd, m_head);
 		if (m_head == NULL)
 			break;
 
@@ -2848,7 +2854,7 @@
 	xl_reset(sc);
 	xl_init(sc);
 
-	if (ifp->if_snd.ifq_head != NULL)
+	if (!IFQ_IS_EMPTY(&ifp->if_snd))
 		(*ifp->if_start)(ifp);
 
 	return;
