2 * Copyright (c) 1995, 1996 Matt Thomas <matt@3am-software.com>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. The name of the author may not be used to endorse or promote products
11 * derived from this software withough specific prior written permission
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 * $FreeBSD: src/sys/dev/pdq/pdq_ifsubr.c,v 1.11.2.1 2000/08/02 22:39:30 peter Exp $
25 * $DragonFly: src/sys/dev/netif/pdq_layer/Attic/pdq_ifsubr.c,v 1.16 2006/11/07 06:43:23 dillon Exp $
30 * DEC PDQ FDDI Controller; code for BSD derived operating systems
32 * This module provide bus independent BSD specific O/S functions.
33 * (ie. it provides an ifnet interface to the rest of the system)
39 #include <sys/param.h>
40 #include <sys/socket.h>
41 #include <sys/sockio.h>
42 #include <sys/thread2.h>
43 #if defined(__bsdi__) || defined(__NetBSD__)
44 #include <sys/device.h>
48 #include <net/ifq_var.h>
49 #include <net/if_dl.h>
53 #if defined(__DragonFly__) || defined(__FreeBSD__)
55 #include <netinet/in.h>
56 #include <netinet/if_ether.h>
58 #include <netinet/if_fddi.h>
60 #include <net/if_fddi.h>
64 #include <machine_base/isa/isavar.h>
69 #include <netns/ns_if.h>
72 #if defined(__DragonFly__) || defined(__FreeBSD__)
80 #if defined(__bsdi__) && _BSDI_VERSION < 199506 /* XXX */
86 sc
->sc_ac
.ac_ipaddr
= IA_SIN(ifa
)->sin_addr
;
87 arpwhohas(&sc
->sc_ac
, &IA_SIN(ifa
)->sin_addr
);
88 #if _BSDI_VERSION >= 199401
89 ifa
->ifa_rtrequest
= arp_rtrequest
;
90 ifa
->ifa_flags
|= RTF_CLONING
;
100 if (sc
->sc_if
.if_flags
& IFF_UP
) {
101 sc
->sc_if
.if_flags
|= IFF_RUNNING
;
102 if (sc
->sc_if
.if_flags
& IFF_PROMISC
) {
103 sc
->sc_pdq
->pdq_flags
|= PDQ_PROMISC
;
105 sc
->sc_pdq
->pdq_flags
&= ~PDQ_PROMISC
;
107 if (sc
->sc_if
.if_flags
& IFF_ALLMULTI
) {
108 sc
->sc_pdq
->pdq_flags
|= PDQ_ALLMULTI
;
110 sc
->sc_pdq
->pdq_flags
&= ~PDQ_ALLMULTI
;
112 if (sc
->sc_if
.if_flags
& IFF_LINK1
) {
113 sc
->sc_pdq
->pdq_flags
|= PDQ_PASS_SMT
;
115 sc
->sc_pdq
->pdq_flags
&= ~PDQ_PASS_SMT
;
117 sc
->sc_pdq
->pdq_flags
|= PDQ_RUNNING
;
120 sc
->sc_if
.if_flags
&= ~IFF_RUNNING
;
121 sc
->sc_pdq
->pdq_flags
&= ~PDQ_RUNNING
;
122 pdq_stop(sc
->sc_pdq
);
131 * No progress was made on the transmit queue for PDQ_OS_TX_TRANSMIT
132 * seconds. Remove all queued packets.
135 ifp
->if_flags
&= ~IFF_OACTIVE
;
137 ifq_purge(&ifp
->if_snd
);
144 pdq_softc_t
*sc
= (pdq_softc_t
*) ((caddr_t
) ifp
- offsetof(pdq_softc_t
, sc_ac
.ac_if
));
148 if ((ifp
->if_flags
& IFF_RUNNING
) == 0)
151 if (sc
->sc_if
.if_timer
== 0)
152 sc
->sc_if
.if_timer
= PDQ_OS_TX_TIMEOUT
;
154 if ((sc
->sc_pdq
->pdq_flags
& PDQ_TXOK
) == 0) {
155 sc
->sc_if
.if_flags
|= IFF_OACTIVE
;
159 m
= ifq_poll(&ifp
->if_snd
);
163 if (pdq_queue_transmit_data(ifp
, sc
->sc_pdq
, m
) == PDQ_FALSE
) {
168 PDQ_DO_TYPE2_PRODUCER(sc
->sc_pdq
);
177 pdq_softc_t
*sc
= (pdq_softc_t
*) pdq
->pdq_os_ctx
;
178 struct fddi_header
*fh
= mtod(m
, struct fddi_header
*);
180 sc
->sc_if
.if_ipackets
++;
181 BPF_MTAP(&sc
->sc_if
, m
);
182 if ((fh
->fddi_fc
& (FDDIFC_L
|FDDIFC_F
)) != FDDIFC_LLC_ASYNC
) {
187 m
->m_pkthdr
.len
= pktlen
;
188 sc
->sc_if
.if_input(&sc
->sc_if
, m
);
192 pdq_os_restart_transmitter(
195 pdq_softc_t
*sc
= (pdq_softc_t
*) pdq
->pdq_os_ctx
;
196 sc
->sc_if
.if_flags
&= ~IFF_OACTIVE
;
197 if (ifq_is_empty(&sc
->sc_if
.if_snd
)) {
198 pdq_ifstart(&sc
->sc_if
);
199 sc
->sc_if
.if_timer
= PDQ_OS_TX_TIMEOUT
;
201 sc
->sc_if
.if_timer
= 0;
206 pdq_os_transmit_done(
210 pdq_softc_t
*sc
= (pdq_softc_t
*) pdq
->pdq_os_ctx
;
211 BPF_MTAP(&sc
->sc_if
, m
);
213 sc
->sc_if
.if_opackets
++;
222 pdq_softc_t
*sc
= (pdq_softc_t
*) pdq
->pdq_os_ctx
;
223 struct ifmultiaddr
*ifma
;
225 LIST_FOREACH(ifma
, &sc
->sc_if
.if_multiaddrs
, ifma_link
) {
227 if (ifma
->ifma_addr
->sa_family
!= AF_LINK
)
229 mcaddr
= LLADDR((struct sockaddr_dl
*)ifma
->ifma_addr
);
230 ((u_short
*) addr
->lanaddr_bytes
)[0] = ((u_short
*) mcaddr
)[0];
231 ((u_short
*) addr
->lanaddr_bytes
)[1] = ((u_short
*) mcaddr
)[1];
232 ((u_short
*) addr
->lanaddr_bytes
)[2] = ((u_short
*) mcaddr
)[2];
239 pdq_ifioctl(struct ifnet
*ifp
, ioctl_cmd_t cmd
, caddr_t data
, struct ucred
*cr
)
241 pdq_softc_t
*sc
= (pdq_softc_t
*) ((caddr_t
) ifp
- offsetof(pdq_softc_t
, sc_ac
.ac_if
));
248 struct ifaddr
*ifa
= (struct ifaddr
*)data
;
250 ifp
->if_flags
|= IFF_UP
;
251 switch(ifa
->ifa_addr
->sa_family
) {
255 arp_ifinit(&sc
->sc_ac
.ac_if
, ifa
);
261 /* This magic copied from if_is.c; I don't use XNS,
262 * so I have no way of telling if this actually
266 struct ns_addr
*ina
= &(IA_SNS(ifa
)->sns_addr
);
267 if (ns_nullhost(*ina
)) {
268 ina
->x_host
= *(union ns_host
*)(sc
->sc_ac
.ac_enaddr
);
270 ifp
->if_flags
&= ~IFF_RUNNING
;
271 bcopy((caddr_t
)ina
->x_host
.c_host
,
272 (caddr_t
)sc
->sc_ac
.ac_enaddr
,
273 sizeof sc
->sc_ac
.ac_enaddr
);
289 struct ifreq
*ifr
= (struct ifreq
*)data
;
290 bcopy((caddr_t
) sc
->sc_ac
.ac_enaddr
,
291 (caddr_t
) ((struct sockaddr
*)&ifr
->ifr_data
)->sa_data
,
304 * Update multicast listeners
306 if (sc
->sc_if
.if_flags
& IFF_RUNNING
)
311 #if defined(SIOCSIFMTU)
312 #if !defined(ifr_mtu)
313 #define ifr_mtu ifr_metric
316 struct ifreq
*ifr
= (struct ifreq
*)data
;
318 * Set the interface MTU.
320 if (ifr
->ifr_mtu
> FDDIMTU
) {
324 ifp
->if_mtu
= ifr
->ifr_mtu
;
327 #endif /* SIOCSIFMTU */
340 #ifndef IFF_NOTRAILERS
341 #define IFF_NOTRAILERS 0
347 ifnet_ret_t (*ifwatchdog
)(int unit
))
349 struct ifnet
*ifp
= &sc
->sc_if
;
351 ifp
->if_flags
= IFF_BROADCAST
|IFF_SIMPLEX
|IFF_NOTRAILERS
|IFF_MULTICAST
;
353 #if defined(__DragonFly__) || (defined(__FreeBSD__) && BSD >= 199506) || defined(__NetBSD__)
354 ifp
->if_watchdog
= pdq_ifwatchdog
;
356 ifp
->if_watchdog
= ifwatchdog
;
359 ifp
->if_ioctl
= pdq_ifioctl
;
360 ifp
->if_start
= pdq_ifstart
;
361 ifq_set_maxlen(&ifp
->if_snd
, IFQ_MAXLEN
);
362 ifq_set_ready(&ifp
->if_snd
);
364 fddi_ifattach(ifp
, NULL
);