Added support for generic FDDI and the DEC DEFEA and DEFPA FDDI adapters.

Submitted by:	Matt Thomas
This commit is contained in:
David Greenman 1995-03-14 09:16:07 +00:00
parent 78dfa6036a
commit d41f24e742
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=7055
12 changed files with 4463 additions and 13 deletions

View File

@ -2,7 +2,7 @@
# LINT -- config file for checking all the sources, tries to pull in
# as much of the source tree as it can.
#
# $Id: LINT,v 1.154 1995/03/12 23:43:14 swallace Exp $
# $Id: LINT,v 1.155 1995/03/13 18:49:24 swallace Exp $
#
# NB: You probably don't want to try running a kernel built from this
# file. Instead, you should start from GENERIC, and add options from
@ -144,6 +144,7 @@ options TPCONS #ISO TP class 0 over X.25
# The `ether' pseudo-device provides generic code to handle
# Ethernets; it is mandatory when a Ethernet device driver is
# configured.
# The 'fddi' pseudo-device provides generic code to support FDDI.
# The `sppp' pseudo-device serves a similar role for certain types
# of synchronous PPP links (like `cx').
# The `sl' pseudo-device implements the Serial Line IP (SLIP) service.
@ -158,6 +159,7 @@ options TPCONS #ISO TP class 0 over X.25
# The `tun' pseudo-device implements the User Process PPP (iijppp)
#
pseudo-device ether #Generic Ethernet
pseudo-device fddi #Generic FDDI
pseudo-device sppp #Generic Synchronous PPP
pseudo-device loop #Network loopback device
pseudo-device sl 2 #Serial Line IP
@ -492,6 +494,7 @@ options DSI_SOFT_MODEM #code for DSI Softmodems
# ed: Western Digital and SMC 80xx; Novell NE1000 and NE2000; 3Com 3C503
# el: 3Com 3C501 (slow!)
# ep: 3Com 3C509 (buggy)
# fea: DEC DEFEA EISA FDDI adapter
# ie: AT&T StarLAN 10 and EN100; 3Com 3C507; unknown NI5210
# le: Digital Equipment EtherWorks 2 and EtherWorks 3 (DEPCA, DE100,
# DE101, DE200, DE201, DE202, DE203, DE204, DE205, DE422)
@ -504,11 +507,12 @@ options DSI_SOFT_MODEM #code for DSI Softmodems
device cx0 at isa? port 0x240 net irq 15 drq 7 vector cxintr
device ed0 at isa? port 0x280 net irq 5 iomem 0xd8000 vector edintr
device ie0 at isa? port 0x360 net irq 7 iomem 0xd0000 vector ieintr
device lnc0 at isa? port 0x280 net irq 10 drq 0 vector lncintr
device ep0 at isa? port 0x300 net irq 10 vector epintr
device el0 at isa? port 0x300 net irq 9 vector elintr
device ep0 at isa? port 0x300 net irq 10 vector epintr
device fea0 at isa? net irq ? vector feaintr
device ie0 at isa? port 0x360 net irq 7 iomem 0xd0000 vector ieintr
device le0 at isa? port 0x300 net irq 5 iomem 0xd0000 vector le_intr
device lnc0 at isa? port 0x280 net irq 10 drq 0 vector lncintr
device ze0 at isa? port 0x300 net irq 5 iomem 0xd8000 vector zeintr
device zp0 at isa? port 0x300 net irq 10 iomem 0xd8000 vector zpintr
@ -626,10 +630,14 @@ device apm0 at isa?
# The `de' device provides support for the Digital Equipment DC21040
# self-contained Ethernet adapter.
#
# The `fpa' device provides support for the Digital DEFPA PCI FDDI
# adapter. pseudo-device fddi is also needed.
#
# The PROBE_VERBOSE option enables a long listing of chip set registers
# for supported PCI chip sets (currently only intel Saturn and Mercury).
#
controller pci0
device ncr0
device de0
device fpa0
options PROBE_VERBOSE

View File

@ -147,6 +147,7 @@ net/bpf_filter.c optional bpfilter
net/if.c standard
net/if_disc.c optional disc
net/if_ethersubr.c optional ether
net/if_fddisubr.c optional fddi
net/if_loop.c optional loop
net/if_ppp.c optional ppp
net/if_sl.c optional sl
@ -277,6 +278,10 @@ pci/if_de.c optional de device-driver
pci/ncr.c optional ncr device-driver
pci/pci.c optional pci device-driver
pci/pcisupport.c optional pci
pci/if_pdq.c optional fea device-driver
pci/pdq.c optional fea device-driver
pci/if_pdq.c optional fpa device-driver
pci/pdq.c optional fpa device-driver
scsi/cd.c optional cd
scsi/ch.c optional ch
scsi/scsi_base.c optional scbus

View File

@ -2,7 +2,7 @@
# LINT -- config file for checking all the sources, tries to pull in
# as much of the source tree as it can.
#
# $Id: LINT,v 1.154 1995/03/12 23:43:14 swallace Exp $
# $Id: LINT,v 1.155 1995/03/13 18:49:24 swallace Exp $
#
# NB: You probably don't want to try running a kernel built from this
# file. Instead, you should start from GENERIC, and add options from
@ -144,6 +144,7 @@ options TPCONS #ISO TP class 0 over X.25
# The `ether' pseudo-device provides generic code to handle
# Ethernets; it is mandatory when a Ethernet device driver is
# configured.
# The 'fddi' pseudo-device provides generic code to support FDDI.
# The `sppp' pseudo-device serves a similar role for certain types
# of synchronous PPP links (like `cx').
# The `sl' pseudo-device implements the Serial Line IP (SLIP) service.
@ -158,6 +159,7 @@ options TPCONS #ISO TP class 0 over X.25
# The `tun' pseudo-device implements the User Process PPP (iijppp)
#
pseudo-device ether #Generic Ethernet
pseudo-device fddi #Generic FDDI
pseudo-device sppp #Generic Synchronous PPP
pseudo-device loop #Network loopback device
pseudo-device sl 2 #Serial Line IP
@ -492,6 +494,7 @@ options DSI_SOFT_MODEM #code for DSI Softmodems
# ed: Western Digital and SMC 80xx; Novell NE1000 and NE2000; 3Com 3C503
# el: 3Com 3C501 (slow!)
# ep: 3Com 3C509 (buggy)
# fea: DEC DEFEA EISA FDDI adapter
# ie: AT&T StarLAN 10 and EN100; 3Com 3C507; unknown NI5210
# le: Digital Equipment EtherWorks 2 and EtherWorks 3 (DEPCA, DE100,
# DE101, DE200, DE201, DE202, DE203, DE204, DE205, DE422)
@ -504,11 +507,12 @@ options DSI_SOFT_MODEM #code for DSI Softmodems
device cx0 at isa? port 0x240 net irq 15 drq 7 vector cxintr
device ed0 at isa? port 0x280 net irq 5 iomem 0xd8000 vector edintr
device ie0 at isa? port 0x360 net irq 7 iomem 0xd0000 vector ieintr
device lnc0 at isa? port 0x280 net irq 10 drq 0 vector lncintr
device ep0 at isa? port 0x300 net irq 10 vector epintr
device el0 at isa? port 0x300 net irq 9 vector elintr
device ep0 at isa? port 0x300 net irq 10 vector epintr
device fea0 at isa? net irq ? vector feaintr
device ie0 at isa? port 0x360 net irq 7 iomem 0xd0000 vector ieintr
device le0 at isa? port 0x300 net irq 5 iomem 0xd0000 vector le_intr
device lnc0 at isa? port 0x280 net irq 10 drq 0 vector lncintr
device ze0 at isa? port 0x300 net irq 5 iomem 0xd8000 vector zeintr
device zp0 at isa? port 0x300 net irq 10 iomem 0xd8000 vector zpintr
@ -626,10 +630,14 @@ device apm0 at isa?
# The `de' device provides support for the Digital Equipment DC21040
# self-contained Ethernet adapter.
#
# The `fpa' device provides support for the Digital DEFPA PCI FDDI
# adapter. pseudo-device fddi is also needed.
#
# The PROBE_VERBOSE option enables a long listing of chip set registers
# for supported PCI chip sets (currently only intel Saturn and Mercury).
#
controller pci0
device ncr0
device de0
device fpa0
options PROBE_VERBOSE

View File

@ -2,7 +2,7 @@
# LINT -- config file for checking all the sources, tries to pull in
# as much of the source tree as it can.
#
# $Id: LINT,v 1.154 1995/03/12 23:43:14 swallace Exp $
# $Id: LINT,v 1.155 1995/03/13 18:49:24 swallace Exp $
#
# NB: You probably don't want to try running a kernel built from this
# file. Instead, you should start from GENERIC, and add options from
@ -144,6 +144,7 @@ options TPCONS #ISO TP class 0 over X.25
# The `ether' pseudo-device provides generic code to handle
# Ethernets; it is mandatory when a Ethernet device driver is
# configured.
# The 'fddi' pseudo-device provides generic code to support FDDI.
# The `sppp' pseudo-device serves a similar role for certain types
# of synchronous PPP links (like `cx').
# The `sl' pseudo-device implements the Serial Line IP (SLIP) service.
@ -158,6 +159,7 @@ options TPCONS #ISO TP class 0 over X.25
# The `tun' pseudo-device implements the User Process PPP (iijppp)
#
pseudo-device ether #Generic Ethernet
pseudo-device fddi #Generic FDDI
pseudo-device sppp #Generic Synchronous PPP
pseudo-device loop #Network loopback device
pseudo-device sl 2 #Serial Line IP
@ -492,6 +494,7 @@ options DSI_SOFT_MODEM #code for DSI Softmodems
# ed: Western Digital and SMC 80xx; Novell NE1000 and NE2000; 3Com 3C503
# el: 3Com 3C501 (slow!)
# ep: 3Com 3C509 (buggy)
# fea: DEC DEFEA EISA FDDI adapter
# ie: AT&T StarLAN 10 and EN100; 3Com 3C507; unknown NI5210
# le: Digital Equipment EtherWorks 2 and EtherWorks 3 (DEPCA, DE100,
# DE101, DE200, DE201, DE202, DE203, DE204, DE205, DE422)
@ -504,11 +507,12 @@ options DSI_SOFT_MODEM #code for DSI Softmodems
device cx0 at isa? port 0x240 net irq 15 drq 7 vector cxintr
device ed0 at isa? port 0x280 net irq 5 iomem 0xd8000 vector edintr
device ie0 at isa? port 0x360 net irq 7 iomem 0xd0000 vector ieintr
device lnc0 at isa? port 0x280 net irq 10 drq 0 vector lncintr
device ep0 at isa? port 0x300 net irq 10 vector epintr
device el0 at isa? port 0x300 net irq 9 vector elintr
device ep0 at isa? port 0x300 net irq 10 vector epintr
device fea0 at isa? net irq ? vector feaintr
device ie0 at isa? port 0x360 net irq 7 iomem 0xd0000 vector ieintr
device le0 at isa? port 0x300 net irq 5 iomem 0xd0000 vector le_intr
device lnc0 at isa? port 0x280 net irq 10 drq 0 vector lncintr
device ze0 at isa? port 0x300 net irq 5 iomem 0xd8000 vector zeintr
device zp0 at isa? port 0x300 net irq 10 iomem 0xd8000 vector zpintr
@ -626,10 +630,14 @@ device apm0 at isa?
# The `de' device provides support for the Digital Equipment DC21040
# self-contained Ethernet adapter.
#
# The `fpa' device provides support for the Digital DEFPA PCI FDDI
# adapter. pseudo-device fddi is also needed.
#
# The PROBE_VERBOSE option enables a long listing of chip set registers
# for supported PCI chip sets (currently only intel Saturn and Mercury).
#
controller pci0
device ncr0
device de0
device fpa0
options PROBE_VERBOSE

View File

@ -37,7 +37,7 @@
*
* @(#)bpf.c 8.2 (Berkeley) 3/28/94
*
* $Id: bpf.c,v 1.3 1994/08/20 03:48:55 davidg Exp $
* $Id: bpf.c,v 1.4 1994/10/09 07:35:03 davidg Exp $
*/
#include "bpfilter.h"
@ -168,9 +168,14 @@ bpf_movein(uio, linktype, mp, sockp, datlen)
break;
case DLT_FDDI:
#if defined(__FreeBSD__) || defined(__bsdi__)
sockp->sa_family = AF_IMPLINK;
hlen = 0;
#else
sockp->sa_family = AF_UNSPEC;
/* XXX 4(FORMAC)+6(dst)+6(src)+3(LLC)+5(SNAP) */
hlen = 24;
#endif
break;
case DLT_NULL:

84
sys/net/fddi.h Normal file
View File

@ -0,0 +1,84 @@
/*
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)if_fddi.h 8.1 (Berkeley) 6/10/93
* $Id: if_fddi.h,v 1.1 1995/03/10 17:43:45 thomas Exp $
*/
#ifndef _NETINET_IF_FDDI_H_
#define _NETINET_IF_FDDI_H_
/*
* Structure of an 100Mb/s FDDI header.
*/
struct fddi_header {
u_char fddi_fc;
u_char fddi_dhost[6];
u_char fddi_shost[6];
};
#define FDDIMTU 4470
#define FDDIMIN 3
#define FDDIFC_C 0x80 /* 0b10000000 */
#define FDDIFC_L 0x40 /* 0b01000000 */
#define FDDIFC_F 0x30 /* 0b00110000 */
#define FDDIFC_Z 0x0F /* 0b00001111 */
#define FDDIFC_LLC_ASYNC 0x50
#define FDDIFC_LLC_PRIO0 0
#define FDDIFC_LLC_PRIO1 1
#define FDDIFC_LLC_PRIO2 2
#define FDDIFC_LLC_PRIO3 3
#define FDDIFC_LLC_PRIO4 4
#define FDDIFC_LLC_PRIO5 5
#define FDDIFC_LLC_PRIO6 6
#define FDDIFC_LLC_PRIO7 7
#define FDDIFC_LLC_SYNC 0xd0
#define FDDIFC_SMT 0x40
#ifdef KERNEL
#define fddibroadcastaddr etherbroadcastaddr
#define fddi_ipmulticast_min ether_ipmulticast_min
#define fddi_ipmulticast_max ether_ipmulticast_max
#define fddi_addmulti ether_addmulti
#define fddi_delmulti ether_delmulti
#define fddi_sprintf ether_sprintf
void fddi_ifattach __P((struct ifnet *));
void fddi_input __P((struct ifnet *, struct fddi_header *, struct mbuf *));
int fddi_output __P((struct ifnet *,
struct mbuf *, struct sockaddr *, struct rtentry *));
#endif
#endif

567
sys/net/if_fddisubr.c Normal file
View File

@ -0,0 +1,567 @@
/*
* Copyright (c) 1982, 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)if_fddisubr.c 8.1 (Berkeley) 6/10/93
* if_fddisubr.c,v 1.5 1994/12/13 22:31:45 wollman Exp
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/errno.h>
#include <sys/syslog.h>
#include <machine/cpu.h>
#include <net/if.h>
#include <net/netisr.h>
#include <net/route.h>
#include <net/if_llc.h>
#include <net/if_dl.h>
#include <net/if_types.h>
#ifdef INET
#include <netinet/in.h>
#include <netinet/in_var.h>
#endif
#include <netinet/if_ether.h>
#include <netinet/if_fddi.h>
#ifdef NS
#include <netns/ns.h>
#include <netns/ns_if.h>
#endif
#ifdef DECNET
#include <netdnet/dn.h>
#endif
#ifdef ISO
#include <netiso/argo_debug.h>
#include <netiso/iso.h>
#include <netiso/iso_var.h>
#include <netiso/iso_snpac.h>
#endif
#include "bpfilter.h"
#ifdef LLC
#include <netccitt/dll.h>
#include <netccitt/llc_var.h>
#endif
#if defined(LLC) && defined(CCITT)
extern struct ifqueue pkintrq;
#endif
extern struct ifnet loif;
#define senderr(e) { error = (e); goto bad;}
/*
* This really should be defined in if_llc.h but in case it isn't.
*/
#ifndef llc_snap
#define llc_snap llc_un.type_snap
#endif
#ifdef __bsdi__
#define RTALLOC1(a, b) rtalloc1(a, b)
#define ARPRESOLVE(a, b, c, d, e, f) arpresolve(a, b, c, d, e)
#else
#define RTALLOC1(a, b) rtalloc1(a, b, 0UL)
#define ARPRESOLVE(a, b, c, d, e, f) arpresolve(a, b, c, d, e, f)
#endif
/*
* FDDI output routine.
* Encapsulate a packet of type family for the local net.
* Use trailer local net encapsulation if enough data in first
* packet leaves a multiple of 512 bytes of data in remainder.
* Assumes that ifp is actually pointer to arpcom structure.
*/
int
fddi_output(ifp, m0, dst, rt0)
register struct ifnet *ifp;
struct mbuf *m0;
struct sockaddr *dst;
struct rtentry *rt0;
{
short type;
int s, error = 0;
u_char edst[6];
register struct mbuf *m = m0;
register struct rtentry *rt;
struct mbuf *mcopy = (struct mbuf *)0;
register struct fddi_header *fh;
struct arpcom *ac = (struct arpcom *)ifp;
if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
senderr(ENETDOWN);
ifp->if_lastchange = time;
if (rt = rt0) {
if ((rt->rt_flags & RTF_UP) == 0) {
if (rt0 = rt = RTALLOC1(dst, 1))
rt->rt_refcnt--;
else
senderr(EHOSTUNREACH);
}
if (rt->rt_flags & RTF_GATEWAY) {
if (rt->rt_gwroute == 0)
goto lookup;
if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
rtfree(rt); rt = rt0;
lookup: rt->rt_gwroute = RTALLOC1(rt->rt_gateway, 1);
if ((rt = rt->rt_gwroute) == 0)
senderr(EHOSTUNREACH);
}
}
if (rt->rt_flags & RTF_REJECT)
if (rt->rt_rmx.rmx_expire == 0 ||
time.tv_sec < rt->rt_rmx.rmx_expire)
senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
}
switch (dst->sa_family) {
#ifdef INET
case AF_INET:
if (!ARPRESOLVE(ac, rt, m, dst, edst, rt0))
return (0); /* if not yet resolved */
/* If broadcasting on a simplex interface, loopback a copy */
if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
mcopy = m_copy(m, 0, (int)M_COPYALL);
type = ETHERTYPE_IP;
break;
#endif
#ifdef NS
case AF_NS:
type = ETHERTYPE_NS;
bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
(caddr_t)edst, sizeof (edst));
if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst)))
return (looutput(ifp, m, dst, rt));
/* If broadcasting on a simplex interface, loopback a copy */
if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
mcopy = m_copy(m, 0, (int)M_COPYALL);
break;
#endif
#ifdef ISO
case AF_ISO: {
int snpalen;
struct llc *l;
register struct sockaddr_dl *sdl;
if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) &&
sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) {
bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst));
} else if (error =
iso_snparesolve(ifp, (struct sockaddr_iso *)dst,
(char *)edst, &snpalen))
goto bad; /* Not Resolved */
/* If broadcasting on a simplex interface, loopback a copy */
if (*edst & 1)
m->m_flags |= (M_BCAST|M_MCAST);
if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) &&
(mcopy = m_copy(m, 0, (int)M_COPYALL))) {
M_PREPEND(mcopy, sizeof (*fh), M_DONTWAIT);
if (mcopy) {
fh = mtod(mcopy, struct fddi_header *);
bcopy((caddr_t)edst,
(caddr_t)fh->fddi_dhost, sizeof (edst));
bcopy((caddr_t)ac->ac_enaddr,
(caddr_t)fh->fddi_shost, sizeof (edst));
}
}
M_PREPEND(m, 3, M_DONTWAIT);
if (m == NULL)
return (0);
type = 0;
l = mtod(m, struct llc *);
l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP;
l->llc_control = LLC_UI;
IFDEBUG(D_ETHER)
int i;
printf("unoutput: sending pkt to: ");
for (i=0; i<6; i++)
printf("%x ", edst[i] & 0xff);
printf("\n");
ENDDEBUG
} break;
#endif /* ISO */
#ifdef LLC
/* case AF_NSAP: */
case AF_CCITT: {
register struct sockaddr_dl *sdl =
(struct sockaddr_dl *) rt -> rt_gateway;
if (sdl && sdl->sdl_family == AF_LINK
&& sdl->sdl_alen > 0) {
bcopy(LLADDR(sdl), (char *)edst,
sizeof(edst));
} else goto bad; /* Not a link interface ? Funny ... */
if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1) &&
(mcopy = m_copy(m, 0, (int)M_COPYALL))) {
M_PREPEND(mcopy, sizeof (*fh), M_DONTWAIT);
if (mcopy) {
fh = mtod(mcopy, struct fddi_header *);
bcopy((caddr_t)edst,
(caddr_t)fh->fddi_dhost, sizeof (edst));
bcopy((caddr_t)ac->ac_enaddr,
(caddr_t)fh->fddi_shost, sizeof (edst));
fh->fddi_fc = FDDIFC_LLC_ASYNC|FDDIFC_LLC_PRIO4;
}
}
type = 0;
#ifdef LLC_DEBUG
{
int i;
register struct llc *l = mtod(m, struct llc *);
printf("fddi_output: sending LLC2 pkt to: ");
for (i=0; i<6; i++)
printf("%x ", edst[i] & 0xff);
printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n",
type & 0xff, l->llc_dsap & 0xff, l->llc_ssap &0xff,
l->llc_control & 0xff);
}
#endif /* LLC_DEBUG */
} break;
#endif /* LLC */
case AF_UNSPEC:
{
struct ether_header *eh;
eh = (struct ether_header *)dst->sa_data;
bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst));
if (*edst & 1)
m->m_flags |= (M_BCAST|M_MCAST);
type = eh->ether_type;
break;
}
#if NBPFILTER > 0
case AF_IMPLINK:
{
fh = mtod(m, struct fddi_header *);
error = EPROTONOSUPPORT;
switch (fh->fddi_fc & (FDDIFC_C|FDDIFC_L|FDDIFC_F)) {
case FDDIFC_LLC_ASYNC: {
/* legal priorities are 0 through 7 */
if ((fh->fddi_fc & FDDIFC_Z) > 7)
goto bad;
break;
}
case FDDIFC_LLC_SYNC: {
/* FDDIFC_Z bits reserved, must be zero */
if (fh->fddi_fc & FDDIFC_Z)
goto bad;
break;
}
case FDDIFC_SMT: {
/* FDDIFC_Z bits must be non zero */
if ((fh->fddi_fc & FDDIFC_Z) == 0)
goto bad;
break;
}
default: {
/* anything else is too dangerous */
goto bad;
}
}
error = 0;
if (fh->fddi_dhost[0] & 1)
m->m_flags |= (M_BCAST|M_MCAST);
goto queue_it;
}
#endif
default:
printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit,
dst->sa_family);
senderr(EAFNOSUPPORT);
}
if (mcopy)
(void) looutput(ifp, mcopy, dst, rt);
if (type != 0) {
register struct llc *l;
M_PREPEND(m, sizeof (struct llc), M_DONTWAIT);
if (m == 0)
senderr(ENOBUFS);
l = mtod(m, struct llc *);
l->llc_control = LLC_UI;
l->llc_dsap = l->llc_ssap = LLC_SNAP_LSAP;
l->llc_snap.org_code[0] = l->llc_snap.org_code[1] = l->llc_snap.org_code[2] = 0;
type = ntohs(type);
bcopy((caddr_t) &type, (caddr_t) &l->llc_snap.ether_type,
sizeof(u_short));
}
/*
* Add local net header. If no space in first mbuf,
* allocate another.
*/
M_PREPEND(m, sizeof (struct fddi_header), M_DONTWAIT);
if (m == 0)
senderr(ENOBUFS);
fh = mtod(m, struct fddi_header *);
fh->fddi_fc = FDDIFC_LLC_ASYNC|FDDIFC_LLC_PRIO4;
bcopy((caddr_t)edst, (caddr_t)fh->fddi_dhost, sizeof (edst));
queue_it:
bcopy((caddr_t)ac->ac_enaddr, (caddr_t)fh->fddi_shost,
sizeof(fh->fddi_shost));
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);
splx(s);
senderr(ENOBUFS);
}
ifp->if_obytes += m->m_pkthdr.len;
IF_ENQUEUE(&ifp->if_snd, m);
if ((ifp->if_flags & IFF_OACTIVE) == 0)
(*ifp->if_start)(ifp);
splx(s);
if (m->m_flags & M_MCAST)
ifp->if_omcasts++;
return (error);
bad:
if (m)
m_freem(m);
return (error);
}
/*
* Process a received FDDI packet;
* the packet is in the mbuf chain m without
* the fddi header, which is provided separately.
*/
void
fddi_input(ifp, fh, m)
struct ifnet *ifp;
register struct fddi_header *fh;
struct mbuf *m;
{
register struct ifqueue *inq;
register struct llc *l;
int s;
if ((ifp->if_flags & IFF_UP) == 0) {
m_freem(m);
return;
}
ifp->if_lastchange = time;
ifp->if_ibytes += m->m_pkthdr.len + sizeof (*fh);
if (bcmp((caddr_t)fddibroadcastaddr, (caddr_t)fh->fddi_dhost,
sizeof(fddibroadcastaddr)) == 0)
m->m_flags |= M_BCAST;
else if (fh->fddi_dhost[0] & 1)
m->m_flags |= M_MCAST;
if (m->m_flags & (M_BCAST|M_MCAST))
ifp->if_imcasts++;
l = mtod(m, struct llc *);
switch (l->llc_dsap) {
#if defined(INET) || defined(NS) || defined(DECNET)
case LLC_SNAP_LSAP:
{
unsigned fddi_type;
if (l->llc_control != LLC_UI || l->llc_ssap != LLC_SNAP_LSAP)
goto dropanyway;
if (l->llc_snap.org_code[0] != 0 || l->llc_snap.org_code[1] != 0|| l->llc_snap.org_code[2] != 0)
goto dropanyway;
fddi_type = ntohs(l->llc_snap.ether_type);
m_adj(m, 8);
switch (fddi_type) {
#ifdef INET
case ETHERTYPE_IP:
schednetisr(NETISR_IP);
inq = &ipintrq;
break;
case ETHERTYPE_ARP:
schednetisr(NETISR_ARP);
inq = &arpintrq;
break;
#endif
#ifdef NS
case ETHERTYPE_NS:
schednetisr(NETISR_NS);
inq = &nsintrq;
break;
#endif
#ifdef DECNET
case ETHERTYPE_DECENT:
schednetisr(NETISR_DECNET);
inq = &decnetintrq;
break;
#endif
default:
printf("fddi_input: unknown protocol 0x%x\n", fddi_type);
ifp->if_noproto++;
goto dropanyway;
}
break;
}
#endif /* INET || NS */
#ifdef ISO
case LLC_ISO_LSAP:
switch (l->llc_control) {
case LLC_UI:
/* LLC_UI_P forbidden in class 1 service */
if ((l->llc_dsap == LLC_ISO_LSAP) &&
(l->llc_ssap == LLC_ISO_LSAP)) {
/* LSAP for ISO */
m->m_data += 3; /* XXX */
m->m_len -= 3; /* XXX */
m->m_pkthdr.len -= 3; /* XXX */
M_PREPEND(m, sizeof *fh, M_DONTWAIT);
if (m == 0)
return;
*mtod(m, struct fddi_header *) = *fh;
IFDEBUG(D_ETHER)
printf("clnp packet");
ENDDEBUG
schednetisr(NETISR_ISO);
inq = &clnlintrq;
break;
}
goto dropanyway;
case LLC_XID:
case LLC_XID_P:
if(m->m_len < 6)
goto dropanyway;
l->llc_window = 0;
l->llc_fid = 9;
l->llc_class = 1;
l->llc_dsap = l->llc_ssap = 0;
/* Fall through to */
case LLC_TEST:
case LLC_TEST_P:
{
struct sockaddr sa;
register struct ether_header *eh2;
int i;
u_char c = l->llc_dsap;
l->llc_dsap = l->llc_ssap;
l->llc_ssap = c;
if (m->m_flags & (M_BCAST | M_MCAST))
bcopy((caddr_t)ac->ac_enaddr,
(caddr_t)eh->ether_dhost, 6);
sa.sa_family = AF_UNSPEC;
sa.sa_len = sizeof(sa);
eh2 = (struct ether_header *)sa.sa_data;
for (i = 0; i < 6; i++) {
eh2->ether_shost[i] = c = eh->fddi_dhost[i];
eh2->ether_dhost[i] =
eh->ether_dhost[i] = eh->fddi_shost[i];
eh2->ether_shost[i] = c;
}
eh2->ether_type = 0;
ifp->if_output(ifp, m, &sa, NULL);
return;
}
default:
m_freem(m);
return;
}
break;
#endif /* ISO */
#ifdef LLC
case LLC_X25_LSAP:
{
M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT);
if (m == 0)
return;
if ( !sdl_sethdrif(ifp, fh->fddi_shost, LLC_X25_LSAP,
fh->fddi_dhost, LLC_X25_LSAP, 6,
mtod(m, struct sdl_hdr *)))
panic("ETHER cons addr failure");
mtod(m, struct sdl_hdr *)->sdlhdr_len = m->m_pkthdr.len - sizeof(struct sdl_hdr);
#ifdef LLC_DEBUG
printf("llc packet\n");
#endif /* LLC_DEBUG */
schednetisr(NETISR_CCITT);
inq = &llcintrq;
break;
}
#endif /* LLC */
default:
printf("fddi_input: unknown dsap 0x%x\n", l->llc_dsap);
ifp->if_noproto++;
dropanyway:
m_freem(m);
return;
}
s = splimp();
if (IF_QFULL(inq)) {
IF_DROP(inq);
m_freem(m);
} else
IF_ENQUEUE(inq, m);
splx(s);
}
/*
* Perform common duties while attaching to interface list
*/
void
fddi_ifattach(ifp)
register struct ifnet *ifp;
{
register struct ifaddr *ifa;
register struct sockaddr_dl *sdl;
ifp->if_type = IFT_FDDI;
ifp->if_addrlen = 6;
ifp->if_hdrlen = 21;
ifp->if_mtu = FDDIMTU;
for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) &&
sdl->sdl_family == AF_LINK) {
sdl->sdl_type = IFT_FDDI;
sdl->sdl_alen = ifp->if_addrlen;
bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr,
LLADDR(sdl), ifp->if_addrlen);
break;
}
}

84
sys/netinet/if_fddi.h Normal file
View File

@ -0,0 +1,84 @@
/*
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)if_fddi.h 8.1 (Berkeley) 6/10/93
* $Id: if_fddi.h,v 1.1 1995/03/10 17:43:45 thomas Exp $
*/
#ifndef _NETINET_IF_FDDI_H_
#define _NETINET_IF_FDDI_H_
/*
* Structure of an 100Mb/s FDDI header.
*/
struct fddi_header {
u_char fddi_fc;
u_char fddi_dhost[6];
u_char fddi_shost[6];
};
#define FDDIMTU 4470
#define FDDIMIN 3
#define FDDIFC_C 0x80 /* 0b10000000 */
#define FDDIFC_L 0x40 /* 0b01000000 */
#define FDDIFC_F 0x30 /* 0b00110000 */
#define FDDIFC_Z 0x0F /* 0b00001111 */
#define FDDIFC_LLC_ASYNC 0x50
#define FDDIFC_LLC_PRIO0 0
#define FDDIFC_LLC_PRIO1 1
#define FDDIFC_LLC_PRIO2 2
#define FDDIFC_LLC_PRIO3 3
#define FDDIFC_LLC_PRIO4 4
#define FDDIFC_LLC_PRIO5 5
#define FDDIFC_LLC_PRIO6 6
#define FDDIFC_LLC_PRIO7 7
#define FDDIFC_LLC_SYNC 0xd0
#define FDDIFC_SMT 0x40
#ifdef KERNEL
#define fddibroadcastaddr etherbroadcastaddr
#define fddi_ipmulticast_min ether_ipmulticast_min
#define fddi_ipmulticast_max ether_ipmulticast_max
#define fddi_addmulti ether_addmulti
#define fddi_delmulti ether_delmulti
#define fddi_sprintf ether_sprintf
void fddi_ifattach __P((struct ifnet *));
void fddi_input __P((struct ifnet *, struct fddi_header *, struct mbuf *));
int fddi_output __P((struct ifnet *,
struct mbuf *, struct sockaddr *, struct rtentry *));
#endif
#endif

844
sys/pci/if_pdq.c Normal file
View File

@ -0,0 +1,844 @@
/*-
* Copyright (c) 1995 Matt Thomas (thomas@lkg.dec.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. The name of the author may not be used to endorse or promote products
* derived from this software withough specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id: if_pdq.c,v 1.7 1995/03/14 01:52:52 thomas Exp $
*
* $Log: if_pdq.c,v $
* Revision 1.7 1995/03/14 01:52:52 thomas
* Update for new FreeBSD PCI Interrupt interface
*
* Revision 1.6 1995/03/10 17:06:59 thomas
* Update for latest version of FreeBSD.
* Compensate for the fast that the ifp will not be first thing
* in softc on BSDI.
*
* Revision 1.5 1995/03/07 19:59:42 thomas
* First pass at BSDI EISA support
*
* Revision 1.4 1995/03/06 17:06:03 thomas
* Add transmit timeout support.
* Add support DEFEA (untested).
*
* Revision 1.3 1995/03/03 13:48:35 thomas
* more fixes
*
*
*/
/*
* DEC PDQ FDDI Controller; code for BSD derived operating systems
*
* Written by Matt Thomas
*
* This driver supports the following FDDI controllers:
*
* Device: Config file entry:
* DEC DEFPA (PCI) device fpa0
* DEC DEFEA (EISA) device fea0 at isa0 net irq ? vector feaintr
*
* Eventually, the following adapters will also be supported:
*
* DEC DEFTA (TC) device fta0 at tc? slot * vector ftaintr
* DEC DEFQA (Q-Bus) device fta0 at uba? csr 0?? vector fqaintr
* DEC DEFAA (FB+) device faa0 at fbus? slot * vector faaintr
*/
#include "fea.h" /* DEFPA EISA FDDI */
#ifndef __bsdi__
#include "fpa.h" /* DEFPA PCI FDDI */
#endif
#if NFPA > 0 || NFEA > 0
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/mbuf.h>
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/errno.h>
#include <sys/malloc.h>
#include <net/if.h>
#include <net/if_types.h>
#include <net/if_dl.h>
#include <net/route.h>
#include "bpfilter.h"
#if NBPFILTER > 0
#include <net/bpf.h>
#include <net/bpfdesc.h>
#endif
#ifdef INET
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/in_var.h>
#include <netinet/ip.h>
#include <netinet/if_ether.h>
#endif
#include <netinet/if_fddi.h>
#ifdef NS
#include <netns/ns.h>
#include <netns/ns_if.h>
#endif
#include <vm/vm.h>
#include <vm/vm_kern.h>
#include <vm/vm_param.h>
#if NFPA > 0
#include <pci/pcivar.h>
#include <i386/isa/icu.h>
#endif
#if NFEA > 0
#include <i386/isa/isa.h>
#include <i386/isa/icu.h>
#ifdef __FreeBSD__
#include <sys/devconf.h>
#include <i386/isa/isa_device.h>
#endif
#ifdef __bsdi__
#include <sys/device.h>
#include <i386/isa/isavar.h>
#include <i386/eisa/eisa.h>
#endif
#endif
#include "pdqreg.h"
#include "pdq_os.h"
typedef struct {
#ifdef __bsdi__
struct device sc_dev; /* base device */
struct isadev sc_id; /* ISA device */
struct intrhand sc_ih; /* intrrupt vectoring */
struct atshutdown sc_ats; /* shutdown routine */
#endif
struct arpcom sc_ac;
pdq_t *sc_pdq;
#if NBPFILTER > 0 && !defined(__FreeBSD__) && !defined(__bsdi__)
caddr_t sc_bpf;
#endif
#if NFEA > 0
unsigned sc_iobase;
#endif
} pdq_softc_t;
#define sc_if sc_ac.ac_if
#if defined(__FreeBSD__)
#define sc_bpf sc_if.if_bpf
typedef void ifnet_ret_t;
#elif defined(__bsdi__)
#define sc_bpf sc_if.if_bpf
typedef int ifnet_ret_t;
#endif
static void
pdq_ifreset(
pdq_softc_t *sc)
{
pdq_stop(sc->sc_pdq);
}
static void
pdq_ifinit(
pdq_softc_t *sc)
{
if (sc->sc_if.if_flags & IFF_UP) {
sc->sc_if.if_flags |= IFF_RUNNING;
if (sc->sc_if.if_flags & IFF_PROMISC) {
sc->sc_pdq->pdq_flags |= PDQ_PROMISC;
} else {
sc->sc_pdq->pdq_flags &= ~PDQ_PROMISC;
}
if (sc->sc_if.if_flags & IFF_ALLMULTI) {
sc->sc_pdq->pdq_flags |= PDQ_ALLMULTI;
} else {
sc->sc_pdq->pdq_flags &= ~PDQ_ALLMULTI;
}
if (sc->sc_if.if_flags & IFF_LINK1) {
sc->sc_pdq->pdq_flags |= PDQ_PASS_SMT;
} else {
sc->sc_pdq->pdq_flags &= ~PDQ_PASS_SMT;
}
sc->sc_pdq->pdq_flags |= PDQ_RUNNING;
pdq_run(sc->sc_pdq);
} else {
sc->sc_if.if_flags &= ~IFF_RUNNING;
sc->sc_pdq->pdq_flags &= ~PDQ_RUNNING;
pdq_stop(sc->sc_pdq);
}
}
static void
pdq_ifwatchdog(
pdq_softc_t *sc)
{
struct mbuf *m;
/*
* No progress was made on the transmit queue for PDQ_OS_TX_TRANSMIT
* seconds. Remove all queued packets.
*/
sc->sc_if.if_flags &= ~IFF_OACTIVE;
sc->sc_if.if_timer = 0;
for (;;) {
IF_DEQUEUE(&sc->sc_if.if_snd, m);
if (m == NULL)
return;
m_freem(m);
}
}
static ifnet_ret_t
pdq_ifstart(
struct ifnet *ifp)
{
pdq_softc_t *sc = (pdq_softc_t *) ((caddr_t) ifp - offsetof(pdq_softc_t, sc_ac.ac_if));
struct ifqueue *ifq = &ifp->if_snd;
struct mbuf *m;
int tx = 0;
if ((ifp->if_flags & IFF_RUNNING) == 0)
return;
if (sc->sc_if.if_timer == 0)
sc->sc_if.if_timer = PDQ_OS_TX_TIMEOUT;
if ((sc->sc_pdq->pdq_flags & PDQ_TXOK) == 0) {
sc->sc_if.if_flags |= IFF_OACTIVE;
return;
}
for (;; tx = 1) {
IF_DEQUEUE(ifq, m);
if (m == NULL)
break;
if (pdq_queue_transmit_data(sc->sc_pdq, m) == PDQ_FALSE) {
ifp->if_flags |= IFF_OACTIVE;
IF_PREPEND(ifq, m);
break;
}
}
if (tx)
PDQ_DO_TYPE2_PRODUCER(sc->sc_pdq);
}
void
pdq_os_receive_pdu(
pdq_t *pdq,
struct mbuf *m,
size_t pktlen)
{
pdq_softc_t *sc = (pdq_softc_t *) pdq->pdq_os_ctx;
struct fddi_header *fh = mtod(m, struct fddi_header *);
sc->sc_if.if_ipackets++;
#if NBPFILTER > 0
if (sc->sc_bpf != NULL)
bpf_mtap(sc->sc_bpf, m);
if ((fh->fddi_fc & (FDDIFC_L|FDDIFC_F)) != FDDIFC_LLC_ASYNC) {
m_freem(m);
return;
}
#endif
m->m_data += sizeof(struct fddi_header);
m->m_len -= sizeof(struct fddi_header);
m->m_pkthdr.len = pktlen - sizeof(struct fddi_header);
m->m_pkthdr.rcvif = &sc->sc_if;
fddi_input(&sc->sc_if, fh, m);
}
void
pdq_os_restart_transmitter(
pdq_t *pdq)
{
pdq_softc_t *sc = (pdq_softc_t *) pdq->pdq_os_ctx;
sc->sc_if.if_flags &= ~IFF_OACTIVE;
if (sc->sc_if.if_snd.ifq_head != NULL) {
sc->sc_if.if_timer = PDQ_OS_TX_TIMEOUT;
pdq_ifstart(&sc->sc_if);
} else {
sc->sc_if.if_timer = 0;
}
}
void
pdq_os_transmit_done(
pdq_t *pdq,
struct mbuf *m)
{
pdq_softc_t *sc = (pdq_softc_t *) pdq->pdq_os_ctx;
#if NBPFILTER > 0
if (sc->sc_bpf != NULL)
bpf_mtap(sc->sc_bpf, m);
#endif
m_freem(m);
sc->sc_if.if_opackets++;
}
void
pdq_os_addr_fill(
pdq_t *pdq,
pdq_lanaddr_t *addr,
size_t num_addrs)
{
pdq_softc_t *sc = (pdq_softc_t *) pdq->pdq_os_ctx;
struct ether_multistep step;
struct ether_multi *enm;
ETHER_FIRST_MULTI(step, &sc->sc_ac, enm);
while (enm != NULL && num_addrs > 0) {
((u_short *) addr->lanaddr_bytes)[0] = ((u_short *) enm->enm_addrlo)[0];
((u_short *) addr->lanaddr_bytes)[1] = ((u_short *) enm->enm_addrlo)[1];
((u_short *) addr->lanaddr_bytes)[2] = ((u_short *) enm->enm_addrlo)[2];
ETHER_NEXT_MULTI(step, enm);
addr++;
num_addrs--;
}
}
static int
pdq_ifioctl(
struct ifnet *ifp,
int cmd,
caddr_t data)
{
pdq_softc_t *sc = (pdq_softc_t *) ((caddr_t) ifp - offsetof(pdq_softc_t, sc_ac.ac_if));
int s, error = 0;
s = splimp();
switch (cmd) {
case SIOCSIFADDR: {
struct ifaddr *ifa = (struct ifaddr *)data;
ifp->if_flags |= IFF_UP;
switch(ifa->ifa_addr->sa_family) {
#ifdef INET
case AF_INET: {
((struct arpcom *)ifp)->ac_ipaddr = IA_SIN(ifa)->sin_addr;
(*ifp->if_init)(ifp->if_unit);
#ifdef __FreeBSD__
arp_ifinit((struct arpcom *)ifp, ifa);
#else
arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
#endif
break;
}
#endif /* INET */
#ifdef NS
/* This magic copied from if_is.c; I don't use XNS,
* so I have no way of telling if this actually
* works or not.
*/
case AF_NS: {
struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
if (ns_nullhost(*ina)) {
ina->x_host = *(union ns_host *)(sc->pdq_ac.ac_enaddr);
} else {
ifp->if_flags &= ~IFF_RUNNING;
bcopy((caddr_t)ina->x_host.c_host,
(caddr_t)sc->pdq_ac.ac_enaddr,
sizeof sc->pdq_ac.ac_enaddr);
}
(*ifp->if_init)(ifp->if_unit);
break;
}
#endif /* NS */
default: {
(*ifp->if_init)(ifp->if_unit);
break;
}
}
break;
}
case SIOCSIFFLAGS: {
(*ifp->if_init)(ifp->if_unit);
break;
}
case SIOCADDMULTI:
case SIOCDELMULTI: {
/*
* Update multicast listeners
*/
if (cmd == SIOCADDMULTI)
error = ether_addmulti((struct ifreq *)data, &sc->sc_ac);
else
error = ether_delmulti((struct ifreq *)data, &sc->sc_ac);
if (error == ENETRESET) {
if (sc->sc_if.if_flags & IFF_RUNNING)
pdq_run(sc->sc_pdq);
error = 0;
}
break;
}
default: {
error = EINVAL;
break;
}
}
splx(s);
return error;
}
static void
pdq_ifattach(
pdq_softc_t *sc,
ifnet_ret_t (*ifinit)(int unit),
ifnet_ret_t (*ifreset)(int unit),
ifnet_ret_t (*ifwatchdog)(int unit))
{
struct ifnet *ifp = &sc->sc_if;
ifp->if_flags = IFF_BROADCAST|IFF_SIMPLEX|IFF_NOTRAILERS|IFF_MULTICAST;
ifp->if_init = ifinit;
#ifndef __bsdi__
ifp->if_reset = ifreset;
#endif
ifp->if_watchdog = ifwatchdog;
ifp->if_ioctl = pdq_ifioctl;
ifp->if_output = fddi_output;
ifp->if_start = pdq_ifstart;
if_attach(ifp);
fddi_ifattach(ifp);
#if NBPFILTER > 0
bpfattach(&sc->sc_bpf, ifp, DLT_FDDI, sizeof(struct fddi_header));
#endif
}
#if NFPA > 0
/*
* This is the PCI configuration support. Since the PDQ is available
* on both EISA and PCI boards, one must be careful in how defines the
* PDQ in the config file.
*/
static char *pdq_pci_probe (pcici_t config_id, pcidi_t device_id);
static void pdq_pci_attach(pcici_t config_id, int unit);
static u_long pdq_pci_count;
struct pci_device fpadevice = {
"fpa",
pdq_pci_probe,
pdq_pci_attach,
&pdq_pci_count,
};
#if defined(__FreeBSD__)
static pdq_softc_t *pdqs_pci[NFPA];
#define PDQ_PCI_UNIT_TO_SOFTC(unit) (pdqs_pci[unit])
#ifdef DATA_SET
DATA_SET (pcidevice_set, fpadevice);
#endif
#endif
#define PCI_CBMA 0x10 /* Configuration Base Memory Address */
static ifnet_ret_t
pdq_pci_ifreset(
int unit)
{
pdq_ifreset(PDQ_PCI_UNIT_TO_SOFTC(unit));
}
static ifnet_ret_t
pdq_pci_ifinit(
int unit)
{
pdq_ifinit(PDQ_PCI_UNIT_TO_SOFTC(unit));
}
static ifnet_ret_t
pdq_pci_ifwatchdog(
int unit)
{
pdq_ifwatchdog(PDQ_PCI_UNIT_TO_SOFTC(unit));
}
static int
pdq_pci_ifintr(
pdq_softc_t *sc)
{
return pdq_interrupt(sc->sc_pdq);
}
static char *
pdq_pci_probe(
pcici_t config_id,
pcidi_t device_id)
{
if (device_id == 0x000f1011ul)
return "Digital DEFPA PCI FDDI Controller";
return NULL;
}
static void
pdq_pci_attach(
pcici_t config_id,
int unit)
{
pdq_softc_t *sc;
vm_offset_t va_csrs, pa_csrs;
if (unit > NFPA) {
printf("fpa%d: not configured; kernel is built for only %d device%s.\n",
unit, NFPA, NFPA == 1 ? "" : "s");
return;
}
sc = (pdq_softc_t *) malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT);
if (sc == NULL)
return;
bzero(sc, sizeof(pdq_softc_t)); /* Zero out the softc*/
if (!pci_map_mem(config_id, PCI_CBMA, &va_csrs, &pa_csrs)) {
free((void *) sc, M_DEVBUF);
return;
}
sc->sc_if.if_name = "fpa";
sc->sc_if.if_unit = unit;
sc->sc_pdq = pdq_initialize((void *) va_csrs, "fpa", unit,
(void *) sc, PDQ_DEFPA);
if (sc->sc_pdq == NULL) {
free((void *) sc, M_DEVBUF);
return;
}
bcopy((caddr_t) sc->sc_pdq->pdq_hwaddr.lanaddr_bytes, sc->sc_ac.ac_enaddr, 6);
pdqs_pci[unit] = sc;
pdq_ifattach(sc, pdq_pci_ifinit, pdq_pci_ifreset, pdq_pci_ifwatchdog);
pci_map_int(config_id, pdq_pci_ifintr, (void*) sc, &net_imask);
}
#endif /* NFPA > 0 */
#if NFEA > 0
/*
*
*/
static const int pdq_eisa_irqs[4] = { IRQ9, IRQ10, IRQ11, IRQ15 };
#ifdef __FreeBSD__
static pdq_softc_t *pdqs_eisa[NFEA];
#define PDQ_EISA_UNIT_TO_SOFTC(unit) (pdqs_eisa[unit])
#endif
#ifdef __bsdi__
extern struct cfdriver feacd;
#define PDQ_EISA_UNIT_TO_SOFTC(unit) ((pdq_softc_t *)feacd.cd_devs[unit])
#endif
static ifnet_ret_t
pdq_eisa_ifreset(
int unit)
{
pdq_ifreset(PDQ_EISA_UNIT_TO_SOFTC(unit));
}
static ifnet_ret_t
pdq_eisa_ifinit(
int unit)
{
pdq_ifinit(PDQ_EISA_UNIT_TO_SOFTC(unit));
}
static ifnet_ret_t
pdq_eisa_ifwatchdog(
int unit)
{
pdq_ifwatchdog(PDQ_EISA_UNIT_TO_SOFTC(unit));
}
int
feaintr(
int unit)
{
pdq_interrupt(PDQ_EISA_UNIT_TO_SOFTC(unit)->sc_pdq);
return unit;
}
void
pdq_eisa_subprobe(
pdq_uint32_t iobase,
pdq_uint32_t *maddr,
pdq_uint32_t *msize,
pdq_uint32_t *irq)
{
if (irq != NULL)
*irq = pdq_eisa_irqs[PDQ_OS_IORD_8(iobase + PDQ_EISA_IO_CONFIG_STAT_0) & 3];
*maddr = (PDQ_OS_IORD_8(iobase + PDQ_EISA_MEM_ADD_CMP_0) << 16)
| (PDQ_OS_IORD_8(iobase + PDQ_EISA_MEM_ADD_CMP_1) << 8);
*msize = (PDQ_OS_IORD_8(iobase + PDQ_EISA_MEM_ADD_MASK_0) + 4) << 8;
}
void
pdq_eisa_devinit(
pdq_softc_t *sc)
{
pdq_uint8_t data;
/*
* Do the standard initialization for the DEFEA registers.
*/
PDQ_OS_IOWR_8(sc->sc_iobase + PDQ_EISA_FUNCTION_CTRL, 0x23);
PDQ_OS_IOWR_8(sc->sc_iobase + PDQ_EISA_IO_CMP_1_1, (sc->sc_iobase >> 8) & 0x0F);
PDQ_OS_IOWR_8(sc->sc_iobase + PDQ_EISA_IO_CMP_1_0, (sc->sc_iobase >> 8) & 0x0F);
PDQ_OS_IOWR_8(sc->sc_iobase + PDQ_EISA_SLOT_CTRL, 0x01);
data = PDQ_OS_IORD_8(sc->sc_iobase + PDQ_EISA_BURST_HOLDOFF);
PDQ_OS_IOWR_8(sc->sc_iobase + PDQ_EISA_BURST_HOLDOFF, data | 1);
data = PDQ_OS_IORD_8(sc->sc_iobase + PDQ_EISA_IO_CONFIG_STAT_0);
PDQ_OS_IOWR_8(sc->sc_iobase + PDQ_EISA_IO_CONFIG_STAT_0, data | 8);
}
#ifdef __FreeBSD__
static struct kern_devconf kdc_fea[NFEA] = { {
0, 0, 0, /* filled in by dev_attach */
"fea", 0, { MDDT_ISA, 0, "net" },
isa_generic_externalize, 0, 0, ISA_EXTERNALLEN,
&kdc_isa0, /* parent */
0, /* parentdata */
DC_BUSY, /* host adapters are always ``in use'' */
"DEC DEFEA EISA FDDI Controller"
} };
static inline void
pdq_eisa_registerdev(
struct isa_device *id)
{
if (id->id_unit)
kdc_fea[id->id_unit] = kdc_fea[0];
kdc_fea[id->id_unit].kdc_unit = id->id_unit;
kdc_fea[id->id_unit].kdc_parentdata = id;
dev_attach(&kdc_fea[id->id_unit]);
}
static int pdq_eisa_slots = ~1;
static int
pdq_eisa_probe(
struct isa_device *id)
{
pdq_softc_t *sc;
int slot;
pdq_uint32_t data, irq, maddr, msize;
slot = 0x1000 * (ffs(pdq_eisa_slots) - 1);
for (; slot <= 0xF000; slot++) {
pdq_eisa_slots &= ~(1 << (slot >> 12));
data = PDQ_OS_IORD_32(slot + PDQ_EISA_SLOT_ID);
if ((data & 0xFFFFFF) != 0x30A310)
continue;
id->id_iobase = slot;
pdq_eisa_subprobe(slot, &maddr, &msize, &irq);
if (id->id_irq != 0 && irq != id->id_irq) {
printf("fea%d: error: desired IRQ of %d does not match device's actual IRQ (%d),\n",
id->id_unit,
ffs(id->id_irq) - 1, ffs(irq) - 1);
return 0;
}
id->id_irq = irq;
if (maddr == 0) {
printf("fea%d: error: memory not enabled! ECU reconfiguration required\n",
id->id_unit);
return 0;
}
#if 0
id->id_maddr = (char *) NULL + atdevbase + maddr;
id->id_msize = msize;
#endif
sc = (pdq_softc_t *) malloc(sizeof(pdq_softc_t), M_DEVBUF, M_WAITOK);
if (sc == NULL)
return 0;
PDQ_EISA_UNIT_TO_SOFTC(id->id_unit) = sc;
return 0x1000;
}
return 0;
}
static int
pdq_eisa_attach(
struct isa_device *id)
{
pdq_softc_t *sc = PDQ_EISA_UNIT_TO_SOFTC(id->id_unit);
vm_offset_t va_csrs;
pdq_uint32_t maddr, msize;
bzero(sc, sizeof(pdq_softc_t)); /* Zero out the softc*/
sc->sc_if.if_name = "fea";
sc->sc_if.if_unit = id->id_unit;
sc->sc_iobase = id->id_iobase;
pdq_eisa_devinit(sc);
pdq_eisa_subprobe(sc->sc_iobase, &maddr, &msize, NULL);
va_csrs = (vm_offset_t) pmap_mapdev(maddr, msize);
if (va_csrs == (vm_offset_t) 0) {
printf("fea%s: mapping of device memory failed\n", sc->sc_if.if_unit);
return 0;
}
sc->sc_pdq = pdq_initialize((void *) va_csrs, "fea", sc->sc_if.if_unit,
(void *) sc, PDQ_DEFEA);
if (sc->sc_pdq == NULL) {
printf("fea%s: initialization failed\n", sc->sc_if.if_unit);
return 0;
}
bcopy((caddr_t) sc->sc_pdq->pdq_hwaddr.lanaddr_bytes, sc->sc_ac.ac_enaddr, 6);
pdq_ifattach(sc, pdq_eisa_ifinit, pdq_eisa_ifreset, pdq_eisa_ifwatchdog);
pdq_eisa_registerdev(id);
return 1;
}
/*
*
*/
struct isa_driver feadriver = {
pdq_eisa_probe,
pdq_eisa_attach,
"fea"
};
#endif /* __FreeBSD__ */
#ifdef __bsdi__
int
pdq_eisa_probe(
struct device *parent,
struct cfdata *cf,
void *aux)
{
struct isa_attach_args *ia = (struct isa_attach_args *) aux;
int slot;
pdq_uint32_t irq, maddr, msize;
if (isa_bustype != BUS_EISA)
return (0);
if ((slot = eisa_match(cf, ia)) == 0)
return (0);
ia->ia_iobase = slot << 12;
ia->ia_iosize = EISA_NPORT;
eisa_slotalloc(slot);
pdq_eisa_subprobe(ia->ia_iobase, &maddr, &msize, &irq);
if (ia->ia_irq != IRQUNK && irq != ia->ia_irq) {
printf("fea%d: error: desired IRQ of %d does not match device's actual IRQ (%d),\n",
cf->cf_unit,
ffs(ia->ia_irq) - 1, ffs(irq) - 1);
return 0;
}
if (ia->ia_irq == IRQUNK) {
if ((irq = isa_irqalloc(irq)) == 0)
return 0;
ia->ia_irq = irq;
}
if (maddr == 0) {
printf("fea%d: error: memory not enabled! ECU reconfiguration required\n",
cf->cf_unit);
return 0;
}
/* EISA bus masters don't use host DMA channels */
ia->ia_drq = 0; /* XXX should be DRQUNK or DRQBUSMASTER? */
#if 0
ia->ia_maddr = maddr;
ia->ia_msize = msize;
#else
ia->ia_maddr = 0;
ia->ia_msize = 0;
#endif
return 1;
}
void
pdq_eisa_attach(
struct device *parent,
struct device *self,
void *aux)
{
pdq_softc_t *sc = (pdq_softc_t *) self;
register struct isa_attach_args *ia = (struct isa_attach_args *) aux;
register struct ifnet *ifp = &sc->sc_if;
int i;
sc->sc_if.if_unit = sc->sc_dev.dv_unit;
sc->sc_if.if_name = "fea";
sc->sc_if.if_flags = 0;
sc->sc_iobase = ia->ia_iobase;
sc->sc_pdq = pdq_initialize((void *) ISA_HOLE_VADDR(ia->ia_maddr), "fea",
sc->sc_if.if_unit, (void *) sc, PDQ_DEFEA);
if (sc->sc_pdq == NULL) {
printf("fea%s: initialization failed\n", sc->sc_if.if_unit);
return;
}
bcopy((caddr_t) sc->sc_pdq->pdq_hwaddr.lanaddr_bytes, sc->sc_ac.ac_enaddr, 6);
pdq_ifattach(sc, pdq_eisa_ifinit, pdq_eisa_ifreset, pdq_eisa_ifwatchdog);
isa_establish(&sc->sc_id, &sc->sc_dev);
sc->sc_ih.ih_fun = feaintr;
sc->sc_ih.ih_arg = (void *)sc;
intr_establish(ia->ia_irq, &sc->sc_ih, DV_NET);
sc->sc_ats.func = (void (*)(void *)) pdq_stop;
sc->sc_ats.arg = (void *) sc->sc_pdq;
atshutdown(&sc->sc_ats, ATSH_ADD);
}
static char *pdq_eisa_ids[] = {
"DEC3001", /* 0x0130A310 */
"DEC3002", /* 0x0230A310 */
"DEC3003", /* 0x0330A310 */
"DEC3004", /* 0x0430A310 */
};
struct cfdriver feacd = {
0, "fea", pdq_eisa_probe, pdq_eisa_attach, DV_IFNET, sizeof(pdq_softc_t),
pdq_eisa_ids
};
#endif /* __bsdi__ */
#endif /* NFEA > 0 */
#endif /* NFPA > 0 || NFEA > 0 */

1558
sys/pci/pdq.c Normal file

File diff suppressed because it is too large Load Diff

198
sys/pci/pdq_os.h Normal file
View File

@ -0,0 +1,198 @@
/*-
* Copyright (c) 1995 Matt Thomas (thomas@lkg.dec.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. The name of the author may not be used to endorse or promote products
* derived from this software withough specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id: pdq_os.h,v 1.6 1995/03/14 01:52:52 thomas Exp $
*
* $Log: pdq_os.h,v $
* Revision 1.6 1995/03/14 01:52:52 thomas
* Update for new FreeBSD PCI Interrupt interface
* Use inl/inb/... inline macros provided by FreeBSD and BSDI
*
* Revision 1.5 1995/03/10 17:42:24 thomas
* More changes for BSDI
*
* Revision 1.4 1995/03/06 17:08:56 thomas
* Add copyright/disclaimer
* Add inx/outx macros
*
* Revision 1.3 1995/03/03 13:48:35 thomas
* more fixes
*
*
*/
/*
* DEC PDQ FDDI Controller; PDQ O/S dependent definitions
*
* Written by Matt Thomas
*
*/
#ifndef _PDQ_OS_H
#define _PDQ_OS_H
#define PDQ_OS_TX_TIMEOUT 5 /* seconds */
#ifdef PDQTEST
#include <pdq_os_test.h>
#elif defined(__FreeBSD__) || defined(__bsdi__)
#include <sys/param.h>
#ifndef M_MCAST
#include <sys/mbuf.h>
#endif
#include <sys/malloc.h>
#include <vm/vm.h>
#include <vm/vm_kern.h>
#define PDQ_USE_MBUFS
#define PDQ_OS_PREFIX "%s%d: "
#define PDQ_OS_PREFIX_ARGS pdq->pdq_os_name, pdq->pdq_unit
#define PDQ_OS_PAGESIZE NBPG
#define PDQ_OS_USEC_DELAY(n) DELAY(n)
#define PDQ_OS_MEMZERO(p, n) bzero((caddr_t)(p), (n))
#define PDQ_OS_VA_TO_PA(p) vtophys(p)
#define PDQ_OS_MEMALLOC(n) malloc(n, M_DEVBUF, M_NOWAIT)
#define PDQ_OS_MEMFREE(p, n) free((void *) p, M_DEVBUF)
#ifdef __FreeBSD__
#define PDQ_OS_MEMALLOC_CONTIG(n) vm_page_alloc_contig(n, 0, 0xffffffff, PAGE_SIZE)
#define PDQ_OS_MEMFREE_CONTIG(p, n) kmem_free(kernel_map, (vm_offset_t) p, n)
#else
#define PDQ_OS_MEMALLOC_CONTIG PDQ_OS_MEMALLOC
#define PDQ_OS_MEMFREE_CONTIG PDQ_OS_MEMFREE
#endif
#if defined(__FreeBSD__)
#include <machine/cpufunc.h>
#elif defined(__bsdi__)
#include <machine/inline.h>
#endif
#define PDQ_OS_IORD_32(port) inl(port)
#define PDQ_OS_IOWR_32(port, data) outl(port, data)
#define PDQ_OS_IORD_8(port) inb(port)
#define PDQ_OS_IOWR_8(port, data) outb(port, data)
#endif
#ifdef PDQ_USE_MBUFS
#define PDQ_OS_DATABUF_SIZE (MCLBYTES)
#define PDQ_OS_DATABUF_FREE(b) (m_freem(b))
#define PDQ_OS_DATABUF_NEXT(b) ((b)->m_next)
#define PDQ_OS_DATABUF_NEXT_SET(b, b1) ((b)->m_next = (b1))
#define PDQ_OS_DATABUF_NEXTPKT(b) ((b)->m_nextpkt)
#define PDQ_OS_DATABUF_NEXTPKT_SET(b, b1) ((b)->m_nextpkt = (b1))
#define PDQ_OS_DATABUF_LEN(b) ((b)->m_len)
#define PDQ_OS_DATABUF_LEN_SET(b, n) ((b)->m_len = (n))
#define PDQ_OS_DATABUF_LEN_ADJ(b, n) ((b)->m_len += (n))
#define PDQ_OS_DATABUF_PTR(b) (mtod((b), pdq_uint8_t *))
#define PDQ_OS_DATABUF_PTR_ADJ(b, n) ((b)->m_data += (n))
typedef struct mbuf PDQ_OS_DATABUF_T;
#define PDQ_OS_DATABUF_ALLOC(b) do { \
PDQ_OS_DATABUF_T *x_m0; \
MGETHDR(x_m0, M_DONTWAIT, MT_DATA); \
if (x_m0 != NULL) { \
MCLGET(x_m0, M_DONTWAIT); \
if ((x_m0->m_flags & M_EXT) == 0) { \
m_free(x_m0); \
(b) = NULL; \
} else { \
(b) = x_m0; \
x_m0->m_len = PDQ_OS_DATABUF_SIZE; \
} \
} else { \
(b) = NULL; \
} \
} while (0)
#define PDQ_OS_DATABUF_RESET(b) ((b)->m_data = (b)->m_ext.ext_buf, (b)->m_len = MCLBYTES)
#endif /* PDQ_USE_MBUFS */
#ifdef PDQ_USE_STREAMS
#define PDQ_OS_DATABUF_FREE(b) (freemsg(b))
#define PDQ_OS_DATABUF_NEXT(b) ((b)->b_cont)
#define PDQ_OS_DATABUF_NEXTPKT(b) ((b)->b_next)
#define PDQ_OS_DATABUF_NEXTPKT_SET(b, b1) ((b)->b_next = (b1))
#define PDQ_OS_DATABUF_LEN(b) ((b)->b_wptr - (b)->b_rptr)
#define PDQ_OS_DATABUF_PTR(b) ((pdq_uint8_t *) (b)->b_rptr)
typedef mblk_t PDQ_OS_DATABUF_T;
#endif /* PDQ_USE_STREAMS */
#define PDQ_OS_TX_TRANSMIT 5
#define PDQ_OS_DATABUF_ENQUEUE(q, b) do { \
PDQ_OS_DATABUF_NEXTPKT_SET(b, NULL); \
if ((q)->q_tail == NULL) \
(q)->q_head = (b); \
else \
PDQ_OS_DATABUF_NEXTPKT_SET(((PDQ_OS_DATABUF_T *)(q)->q_tail), b); \
(q)->q_tail = (b); \
} while (0)
#define PDQ_OS_DATABUF_DEQUEUE(q, b) do { \
if (((b) = (PDQ_OS_DATABUF_T *) (q)->q_head) != NULL) { \
if (((q)->q_head = PDQ_OS_DATABUF_NEXTPKT(b)) == NULL) \
(q)->q_tail = NULL; \
PDQ_OS_DATABUF_NEXTPKT_SET(b, NULL); \
} \
} while (0)
extern void pdq_os_addr_fill(pdq_t *pdq, pdq_lanaddr_t *addrs, size_t numaddrs);
extern void pdq_os_receive_pdu(pdq_t *, PDQ_OS_DATABUF_T *pdu, size_t pdulen);
extern void pdq_os_restart_transmitter(pdq_t *pdq);
extern void pdq_os_transmit_done(pdq_t *pdq, PDQ_OS_DATABUF_T *pdu);
extern void pdq_print_fddi_chars(pdq_t *pdq, const pdq_response_status_chars_get_t *rsp);
extern void pdq_init_csrs(pdq_csrs_t *csrs, void *csrs_va, size_t csr_size);
extern void pdq_init_pci_csrs(pdq_pci_csrs_t *csrs, void *csrs_va, size_t csr_size);
extern void pdq_flush_databuf_queue(pdq_databuf_queue_t *q);
extern pdq_boolean_t pdq_do_port_control(const pdq_csrs_t * const csrs, pdq_uint32_t cmd);
extern void pdq_read_mla(const pdq_csrs_t * const csrs, pdq_lanaddr_t *hwaddr);
extern void pdq_read_fwrev(const pdq_csrs_t * const csrs, pdq_fwrev_t *fwrev);
extern pdq_boolean_t pdq_read_error_log(pdq_t *pdq, pdq_response_error_log_get_t *log_entry);
extern pdq_chip_rev_t pdq_read_chiprev(const pdq_csrs_t * const csrs);
extern void pdq_queue_commands(pdq_t *pdq);
extern void pdq_process_command_responses(pdq_t *pdq);
extern void pdq_process_unsolicited_events(pdq_t *pdq);
extern void pdq_process_received_data(pdq_t *pdq, pdq_rx_info_t *rx,
pdq_rxdesc_t *receives,
pdq_uint32_t completion_goal,
pdq_uint32_t ring_mask);
extern pdq_boolean_t pdq_queue_transmit_data(pdq_t *pdq, PDQ_OS_DATABUF_T *pdu);
extern void pdq_process_transmitted_data(pdq_t *pdq);
extern void pdq_flush_transmitter(pdq_t *pdq);
extern pdq_state_t pdq_stop(pdq_t *pdq);
extern void pdq_run(pdq_t *pdq);
extern int pdq_interrupt(pdq_t *pdq);
extern pdq_t *pdq_initialize(void *csr_va, const char *name, int unit, void *ctx, pdq_type_t type);
#endif /* _PDQ_OS_H */

1081
sys/pci/pdqreg.h Normal file

File diff suppressed because it is too large Load Diff