diff --git a/sys/dev/tx/if_tx.c b/sys/dev/tx/if_tx.c
index 93c715b3253f..f7610c713a41 100644
--- a/sys/dev/tx/if_tx.c
+++ b/sys/dev/tx/if_tx.c
@@ -54,6 +54,8 @@
 #if defined(__FreeBSD__)
 #define NBPFILTER	1
 
+#include "vlan.h"
+
 #include <net/if.h>
 #include <net/if_arp.h>
 #include <net/ethernet.h>
@@ -61,6 +63,10 @@
 
 #include <net/bpf.h>
 
+#if NVLAN > 0
+#include <net/if_vlan_var.h>
+#endif
+
 #include <vm/vm.h>              /* for vtophys */
 #include <vm/pmap.h>            /* for vtophys */
 #include <machine/bus_memio.h>
@@ -85,6 +91,8 @@
 #else /* __OpenBSD__ */
 #include "bpfilter.h"
 
+#define	NVLAN	0	/* not sure if/how OpenBSD supports VLANs */
+
 #include <sys/device.h>
 
 #include <net/if.h>
@@ -555,6 +563,9 @@ epic_freebsd_attach(dev)
 
 	/* Attach to OS's managers */
 	ether_ifattach(ifp, ETHER_BPF_SUPPORTED);
+#if NVLAN > 0
+	ifp->if_hdrlen = sizeof(struct ether_vlan_header);
+#endif
 	callout_handle_init(&sc->stat_ch);
 
 fail:
@@ -642,9 +653,25 @@ epic_ifioctl(ifp, command, data)
 #if defined(__FreeBSD__)
 	case SIOCSIFADDR:
 	case SIOCGIFADDR:
-	case SIOCSIFMTU:
 		error = ether_ioctl(ifp, command, data);
 		break;
+	case SIOCSIFMTU:
+		if (ifp->if_mtu == ifr->ifr_mtu) 
+			break;
+
+		/* XXX Though the datasheet doesn't imply any 
+		 * limitations on RX and TX sizes beside max 64Kb
+		 * DMA transfer, seems we can't send more then 1600
+		 * data bytes per ethernet packet. (Transmitter hangs
+		 * up if more data is sent)
+		 */
+		if (ifr->ifr_mtu + ifp->if_hdrlen <= EPIC_MAX_MTU) {
+			ifp->if_mtu = ifr->ifr_mtu;
+			epic_stop(sc);
+			epic_init(sc);
+		} else
+			error = EINVAL;
+		break;
 #else /* __OpenBSD__ */
 	case SIOCSIFADDR: {
 		struct ifaddr *ifa = (struct ifaddr *)data;
@@ -1746,9 +1773,8 @@ epic_init_rings(sc)
 		}
 		desc->bufaddr = vtophys( mtod(buf->mbuf,caddr_t) );
 
-		desc->buflength = ETHER_MAX_FRAME_LEN;
-		desc->status = 0x8000;			/* Give to EPIC */
-
+		desc->buflength = MCLBYTES;	/* Max RX buffer length */
+		desc->status = 0x8000;		/* Set owner bit to NIC */
 	}
 
 	for (i = 0; i < TX_RING_SIZE; i++) {
diff --git a/sys/dev/tx/if_txreg.h b/sys/dev/tx/if_txreg.h
index a9ec762161fa..7a5c82b78ee6 100644
--- a/sys/dev/tx/if_txreg.h
+++ b/sys/dev/tx/if_txreg.h
@@ -50,6 +50,8 @@
 #define RX_RING_MASK		(RX_RING_SIZE - 1)
 #define ETHER_MAX_FRAME_LEN	(ETHER_MAX_LEN + ETHER_CRC_LEN)
 
+#define	EPIC_MAX_MTU		1600	/* This is experiment-derived value */
+
 /* PCI aux configuration registers */
 #if defined(__FreeBSD__)
 #define	PCIR_BASEIO	(PCIR_MAPS + 0x0)	/* Base IO Address */
diff --git a/sys/dev/tx/if_txvar.h b/sys/dev/tx/if_txvar.h
index a9ec762161fa..7a5c82b78ee6 100644
--- a/sys/dev/tx/if_txvar.h
+++ b/sys/dev/tx/if_txvar.h
@@ -50,6 +50,8 @@
 #define RX_RING_MASK		(RX_RING_SIZE - 1)
 #define ETHER_MAX_FRAME_LEN	(ETHER_MAX_LEN + ETHER_CRC_LEN)
 
+#define	EPIC_MAX_MTU		1600	/* This is experiment-derived value */
+
 /* PCI aux configuration registers */
 #if defined(__FreeBSD__)
 #define	PCIR_BASEIO	(PCIR_MAPS + 0x0)	/* Base IO Address */
diff --git a/sys/modules/tx/Makefile b/sys/modules/tx/Makefile
index c1c1dfa0c684..b9fdd6d18e64 100644
--- a/sys/modules/tx/Makefile
+++ b/sys/modules/tx/Makefile
@@ -4,6 +4,10 @@
 
 KMOD=	if_tx
 SRCS=	if_tx.c opt_bdg.h device_if.h bus_if.h pci_if.h
-SRCS+=	miibus_if.h
+SRCS+=	miibus_if.h vlan.h
+CLEANFILES = vlan.h
+
+vlan.h:
+	touch vlan.h
 
 .include <bsd.kmod.mk>
diff --git a/sys/pci/if_tx.c b/sys/pci/if_tx.c
index 93c715b3253f..f7610c713a41 100644
--- a/sys/pci/if_tx.c
+++ b/sys/pci/if_tx.c
@@ -54,6 +54,8 @@
 #if defined(__FreeBSD__)
 #define NBPFILTER	1
 
+#include "vlan.h"
+
 #include <net/if.h>
 #include <net/if_arp.h>
 #include <net/ethernet.h>
@@ -61,6 +63,10 @@
 
 #include <net/bpf.h>
 
+#if NVLAN > 0
+#include <net/if_vlan_var.h>
+#endif
+
 #include <vm/vm.h>              /* for vtophys */
 #include <vm/pmap.h>            /* for vtophys */
 #include <machine/bus_memio.h>
@@ -85,6 +91,8 @@
 #else /* __OpenBSD__ */
 #include "bpfilter.h"
 
+#define	NVLAN	0	/* not sure if/how OpenBSD supports VLANs */
+
 #include <sys/device.h>
 
 #include <net/if.h>
@@ -555,6 +563,9 @@ epic_freebsd_attach(dev)
 
 	/* Attach to OS's managers */
 	ether_ifattach(ifp, ETHER_BPF_SUPPORTED);
+#if NVLAN > 0
+	ifp->if_hdrlen = sizeof(struct ether_vlan_header);
+#endif
 	callout_handle_init(&sc->stat_ch);
 
 fail:
@@ -642,9 +653,25 @@ epic_ifioctl(ifp, command, data)
 #if defined(__FreeBSD__)
 	case SIOCSIFADDR:
 	case SIOCGIFADDR:
-	case SIOCSIFMTU:
 		error = ether_ioctl(ifp, command, data);
 		break;
+	case SIOCSIFMTU:
+		if (ifp->if_mtu == ifr->ifr_mtu) 
+			break;
+
+		/* XXX Though the datasheet doesn't imply any 
+		 * limitations on RX and TX sizes beside max 64Kb
+		 * DMA transfer, seems we can't send more then 1600
+		 * data bytes per ethernet packet. (Transmitter hangs
+		 * up if more data is sent)
+		 */
+		if (ifr->ifr_mtu + ifp->if_hdrlen <= EPIC_MAX_MTU) {
+			ifp->if_mtu = ifr->ifr_mtu;
+			epic_stop(sc);
+			epic_init(sc);
+		} else
+			error = EINVAL;
+		break;
 #else /* __OpenBSD__ */
 	case SIOCSIFADDR: {
 		struct ifaddr *ifa = (struct ifaddr *)data;
@@ -1746,9 +1773,8 @@ epic_init_rings(sc)
 		}
 		desc->bufaddr = vtophys( mtod(buf->mbuf,caddr_t) );
 
-		desc->buflength = ETHER_MAX_FRAME_LEN;
-		desc->status = 0x8000;			/* Give to EPIC */
-
+		desc->buflength = MCLBYTES;	/* Max RX buffer length */
+		desc->status = 0x8000;		/* Set owner bit to NIC */
 	}
 
 	for (i = 0; i < TX_RING_SIZE; i++) {
diff --git a/sys/pci/if_txvar.h b/sys/pci/if_txvar.h
index a9ec762161fa..7a5c82b78ee6 100644
--- a/sys/pci/if_txvar.h
+++ b/sys/pci/if_txvar.h
@@ -50,6 +50,8 @@
 #define RX_RING_MASK		(RX_RING_SIZE - 1)
 #define ETHER_MAX_FRAME_LEN	(ETHER_MAX_LEN + ETHER_CRC_LEN)
 
+#define	EPIC_MAX_MTU		1600	/* This is experiment-derived value */
+
 /* PCI aux configuration registers */
 #if defined(__FreeBSD__)
 #define	PCIR_BASEIO	(PCIR_MAPS + 0x0)	/* Base IO Address */