Add support for 802.1Q VLAN and oversized ethernet frames.

PR:		kern/29235
Submitted by:	Peter Jeremy <peter.jeremy@alcatel.com.au>
Reviewed by:	Yar Tikhiy <yar@FreeBSD.org>
MFC after:	1 week
This commit is contained in:
Semen Ustimenko 2001-08-13 18:32:39 +00:00
parent ed2879a5cf
commit 2c9067b16f
6 changed files with 71 additions and 9 deletions

View File

@ -54,6 +54,8 @@
#if defined(__FreeBSD__) #if defined(__FreeBSD__)
#define NBPFILTER 1 #define NBPFILTER 1
#include "vlan.h"
#include <net/if.h> #include <net/if.h>
#include <net/if_arp.h> #include <net/if_arp.h>
#include <net/ethernet.h> #include <net/ethernet.h>
@ -61,6 +63,10 @@
#include <net/bpf.h> #include <net/bpf.h>
#if NVLAN > 0
#include <net/if_vlan_var.h>
#endif
#include <vm/vm.h> /* for vtophys */ #include <vm/vm.h> /* for vtophys */
#include <vm/pmap.h> /* for vtophys */ #include <vm/pmap.h> /* for vtophys */
#include <machine/bus_memio.h> #include <machine/bus_memio.h>
@ -85,6 +91,8 @@
#else /* __OpenBSD__ */ #else /* __OpenBSD__ */
#include "bpfilter.h" #include "bpfilter.h"
#define NVLAN 0 /* not sure if/how OpenBSD supports VLANs */
#include <sys/device.h> #include <sys/device.h>
#include <net/if.h> #include <net/if.h>
@ -555,6 +563,9 @@ epic_freebsd_attach(dev)
/* Attach to OS's managers */ /* Attach to OS's managers */
ether_ifattach(ifp, ETHER_BPF_SUPPORTED); ether_ifattach(ifp, ETHER_BPF_SUPPORTED);
#if NVLAN > 0
ifp->if_hdrlen = sizeof(struct ether_vlan_header);
#endif
callout_handle_init(&sc->stat_ch); callout_handle_init(&sc->stat_ch);
fail: fail:
@ -642,9 +653,25 @@ epic_ifioctl(ifp, command, data)
#if defined(__FreeBSD__) #if defined(__FreeBSD__)
case SIOCSIFADDR: case SIOCSIFADDR:
case SIOCGIFADDR: case SIOCGIFADDR:
case SIOCSIFMTU:
error = ether_ioctl(ifp, command, data); error = ether_ioctl(ifp, command, data);
break; 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__ */ #else /* __OpenBSD__ */
case SIOCSIFADDR: { case SIOCSIFADDR: {
struct ifaddr *ifa = (struct ifaddr *)data; struct ifaddr *ifa = (struct ifaddr *)data;
@ -1746,9 +1773,8 @@ epic_init_rings(sc)
} }
desc->bufaddr = vtophys( mtod(buf->mbuf,caddr_t) ); desc->bufaddr = vtophys( mtod(buf->mbuf,caddr_t) );
desc->buflength = ETHER_MAX_FRAME_LEN; desc->buflength = MCLBYTES; /* Max RX buffer length */
desc->status = 0x8000; /* Give to EPIC */ desc->status = 0x8000; /* Set owner bit to NIC */
} }
for (i = 0; i < TX_RING_SIZE; i++) { for (i = 0; i < TX_RING_SIZE; i++) {

View File

@ -50,6 +50,8 @@
#define RX_RING_MASK (RX_RING_SIZE - 1) #define RX_RING_MASK (RX_RING_SIZE - 1)
#define ETHER_MAX_FRAME_LEN (ETHER_MAX_LEN + ETHER_CRC_LEN) #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 */ /* PCI aux configuration registers */
#if defined(__FreeBSD__) #if defined(__FreeBSD__)
#define PCIR_BASEIO (PCIR_MAPS + 0x0) /* Base IO Address */ #define PCIR_BASEIO (PCIR_MAPS + 0x0) /* Base IO Address */

View File

@ -50,6 +50,8 @@
#define RX_RING_MASK (RX_RING_SIZE - 1) #define RX_RING_MASK (RX_RING_SIZE - 1)
#define ETHER_MAX_FRAME_LEN (ETHER_MAX_LEN + ETHER_CRC_LEN) #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 */ /* PCI aux configuration registers */
#if defined(__FreeBSD__) #if defined(__FreeBSD__)
#define PCIR_BASEIO (PCIR_MAPS + 0x0) /* Base IO Address */ #define PCIR_BASEIO (PCIR_MAPS + 0x0) /* Base IO Address */

View File

@ -4,6 +4,10 @@
KMOD= if_tx KMOD= if_tx
SRCS= if_tx.c opt_bdg.h device_if.h bus_if.h pci_if.h 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> .include <bsd.kmod.mk>

View File

@ -54,6 +54,8 @@
#if defined(__FreeBSD__) #if defined(__FreeBSD__)
#define NBPFILTER 1 #define NBPFILTER 1
#include "vlan.h"
#include <net/if.h> #include <net/if.h>
#include <net/if_arp.h> #include <net/if_arp.h>
#include <net/ethernet.h> #include <net/ethernet.h>
@ -61,6 +63,10 @@
#include <net/bpf.h> #include <net/bpf.h>
#if NVLAN > 0
#include <net/if_vlan_var.h>
#endif
#include <vm/vm.h> /* for vtophys */ #include <vm/vm.h> /* for vtophys */
#include <vm/pmap.h> /* for vtophys */ #include <vm/pmap.h> /* for vtophys */
#include <machine/bus_memio.h> #include <machine/bus_memio.h>
@ -85,6 +91,8 @@
#else /* __OpenBSD__ */ #else /* __OpenBSD__ */
#include "bpfilter.h" #include "bpfilter.h"
#define NVLAN 0 /* not sure if/how OpenBSD supports VLANs */
#include <sys/device.h> #include <sys/device.h>
#include <net/if.h> #include <net/if.h>
@ -555,6 +563,9 @@ epic_freebsd_attach(dev)
/* Attach to OS's managers */ /* Attach to OS's managers */
ether_ifattach(ifp, ETHER_BPF_SUPPORTED); ether_ifattach(ifp, ETHER_BPF_SUPPORTED);
#if NVLAN > 0
ifp->if_hdrlen = sizeof(struct ether_vlan_header);
#endif
callout_handle_init(&sc->stat_ch); callout_handle_init(&sc->stat_ch);
fail: fail:
@ -642,9 +653,25 @@ epic_ifioctl(ifp, command, data)
#if defined(__FreeBSD__) #if defined(__FreeBSD__)
case SIOCSIFADDR: case SIOCSIFADDR:
case SIOCGIFADDR: case SIOCGIFADDR:
case SIOCSIFMTU:
error = ether_ioctl(ifp, command, data); error = ether_ioctl(ifp, command, data);
break; 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__ */ #else /* __OpenBSD__ */
case SIOCSIFADDR: { case SIOCSIFADDR: {
struct ifaddr *ifa = (struct ifaddr *)data; struct ifaddr *ifa = (struct ifaddr *)data;
@ -1746,9 +1773,8 @@ epic_init_rings(sc)
} }
desc->bufaddr = vtophys( mtod(buf->mbuf,caddr_t) ); desc->bufaddr = vtophys( mtod(buf->mbuf,caddr_t) );
desc->buflength = ETHER_MAX_FRAME_LEN; desc->buflength = MCLBYTES; /* Max RX buffer length */
desc->status = 0x8000; /* Give to EPIC */ desc->status = 0x8000; /* Set owner bit to NIC */
} }
for (i = 0; i < TX_RING_SIZE; i++) { for (i = 0; i < TX_RING_SIZE; i++) {

View File

@ -50,6 +50,8 @@
#define RX_RING_MASK (RX_RING_SIZE - 1) #define RX_RING_MASK (RX_RING_SIZE - 1)
#define ETHER_MAX_FRAME_LEN (ETHER_MAX_LEN + ETHER_CRC_LEN) #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 */ /* PCI aux configuration registers */
#if defined(__FreeBSD__) #if defined(__FreeBSD__)
#define PCIR_BASEIO (PCIR_MAPS + 0x0) /* Base IO Address */ #define PCIR_BASEIO (PCIR_MAPS + 0x0) /* Base IO Address */