From 2c9067b16fca8383611b81033ad4d01fba52f4f5 Mon Sep 17 00:00:00 2001 From: Semen Ustimenko Date: Mon, 13 Aug 2001 18:32:39 +0000 Subject: [PATCH] Add support for 802.1Q VLAN and oversized ethernet frames. PR: kern/29235 Submitted by: Peter Jeremy Reviewed by: Yar Tikhiy MFC after: 1 week --- sys/dev/tx/if_tx.c | 34 ++++++++++++++++++++++++++++++---- sys/dev/tx/if_txreg.h | 2 ++ sys/dev/tx/if_txvar.h | 2 ++ sys/modules/tx/Makefile | 6 +++++- sys/pci/if_tx.c | 34 ++++++++++++++++++++++++++++++---- sys/pci/if_txvar.h | 2 ++ 6 files changed, 71 insertions(+), 9 deletions(-) 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 #include #include @@ -61,6 +63,10 @@ #include +#if NVLAN > 0 +#include +#endif + #include /* for vtophys */ #include /* for vtophys */ #include @@ -85,6 +91,8 @@ #else /* __OpenBSD__ */ #include "bpfilter.h" +#define NVLAN 0 /* not sure if/how OpenBSD supports VLANs */ + #include #include @@ -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 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 #include #include @@ -61,6 +63,10 @@ #include +#if NVLAN > 0 +#include +#endif + #include /* for vtophys */ #include /* for vtophys */ #include @@ -85,6 +91,8 @@ #else /* __OpenBSD__ */ #include "bpfilter.h" +#define NVLAN 0 /* not sure if/how OpenBSD supports VLANs */ + #include #include @@ -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 */