This source file includes following definitions.
- pdq_ifinit
- pdq_ifwatchdog
- pdq_ifstart
- pdq_os_receive_pdu
- pdq_os_restart_transmitter
- pdq_os_transmit_done
- pdq_os_addr_fill
- pdq_ifioctl
- pdq_ifattach
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 #include <sys/param.h>
40 #include <sys/kernel.h>
41 #include <sys/mbuf.h>
42 #include <sys/protosw.h>
43 #include <sys/socket.h>
44 #include <sys/ioctl.h>
45 #include <sys/errno.h>
46 #include <sys/malloc.h>
47 #if defined(__FreeBSD__)
48 #include <sys/devconf.h>
49 #elif defined(__NetBSD__) || defined(__OpenBSD__)
50 #include <sys/device.h>
51 #endif
52
53 #include <net/if.h>
54 #include <net/if_types.h>
55 #include <net/if_dl.h>
56 #include <net/route.h>
57
58 #include "bpfilter.h"
59 #if NBPFILTER > 0
60 #include <net/bpf.h>
61 #endif
62
63 #ifdef INET
64 #include <netinet/in.h>
65 #include <netinet/in_systm.h>
66 #include <netinet/in_var.h>
67 #include <netinet/ip.h>
68 #include <netinet/if_ether.h>
69 #endif
70 #if defined(__FreeBSD__)
71 #include <netinet/if_fddi.h>
72 #else
73 #include <net/if_fddi.h>
74 #endif
75
76 #include <uvm/uvm_extern.h>
77
78 #include "pdqvar.h"
79 #include "pdqreg.h"
80
81 void
82 pdq_ifinit(
83 pdq_softc_t *sc)
84 {
85 if (sc->sc_if.if_flags & IFF_UP) {
86 sc->sc_if.if_flags |= IFF_RUNNING;
87 if (sc->sc_if.if_flags & IFF_PROMISC) {
88 sc->sc_pdq->pdq_flags |= PDQ_PROMISC;
89 } else {
90 sc->sc_pdq->pdq_flags &= ~PDQ_PROMISC;
91 }
92 if (sc->sc_if.if_flags & IFF_ALLMULTI) {
93 sc->sc_pdq->pdq_flags |= PDQ_ALLMULTI;
94 } else {
95 sc->sc_pdq->pdq_flags &= ~PDQ_ALLMULTI;
96 }
97 if (sc->sc_if.if_flags & IFF_LINK1) {
98 sc->sc_pdq->pdq_flags |= PDQ_PASS_SMT;
99 } else {
100 sc->sc_pdq->pdq_flags &= ~PDQ_PASS_SMT;
101 }
102 sc->sc_pdq->pdq_flags |= PDQ_RUNNING;
103 pdq_run(sc->sc_pdq);
104 } else {
105 sc->sc_if.if_flags &= ~IFF_RUNNING;
106 sc->sc_pdq->pdq_flags &= ~PDQ_RUNNING;
107 pdq_stop(sc->sc_pdq);
108 }
109 }
110
111 void
112 pdq_ifwatchdog(
113 struct ifnet *ifp)
114 {
115
116
117
118
119
120 ifp->if_flags &= ~IFF_OACTIVE;
121 ifp->if_timer = 0;
122 IFQ_PURGE(&ifp->if_snd);
123 }
124
125 ifnet_ret_t
126 pdq_ifstart(
127 struct ifnet *ifp)
128 {
129 pdq_softc_t *sc = (pdq_softc_t *) ((caddr_t) ifp - offsetof(pdq_softc_t, sc_arpcom.ac_if));
130 struct mbuf *m;
131 int tx = 0;
132
133 if ((ifp->if_flags & IFF_RUNNING) == 0)
134 return;
135
136 if (sc->sc_if.if_timer == 0)
137 sc->sc_if.if_timer = PDQ_OS_TX_TIMEOUT;
138
139 if ((sc->sc_pdq->pdq_flags & PDQ_TXOK) == 0) {
140 sc->sc_if.if_flags |= IFF_OACTIVE;
141 return;
142 }
143 for (;; tx = 1) {
144 IFQ_POLL(&ifp->if_snd, m);
145 if (m == NULL)
146 break;
147
148 if (pdq_queue_transmit_data(sc->sc_pdq, m) == PDQ_FALSE) {
149 ifp->if_flags |= IFF_OACTIVE;
150 break;
151 }
152
153 IFQ_DEQUEUE(&ifp->if_snd, m);
154 }
155 if (tx)
156 PDQ_DO_TYPE2_PRODUCER(sc->sc_pdq);
157 }
158
159 void
160 pdq_os_receive_pdu(
161 pdq_t *pdq,
162 struct mbuf *m,
163 size_t pktlen)
164 {
165 pdq_softc_t *sc = (pdq_softc_t *) pdq->pdq_os_ctx;
166 struct fddi_header *fh = mtod(m, struct fddi_header *);
167
168 sc->sc_if.if_ipackets++;
169 #if NBPFILTER > 0
170 if (sc->sc_bpf != NULL)
171 PDQ_BPF_MTAP(sc, m, BPF_DIRECTION_IN);
172 if ((fh->fddi_fc & (FDDIFC_L|FDDIFC_F)) != FDDIFC_LLC_ASYNC) {
173 m_freem(m);
174 return;
175 }
176 #endif
177
178 m->m_data += sizeof(struct fddi_header);
179 m->m_len -= sizeof(struct fddi_header);
180 m->m_pkthdr.len = pktlen - sizeof(struct fddi_header);
181 m->m_pkthdr.rcvif = &sc->sc_if;
182 fddi_input(&sc->sc_if, fh, m);
183 }
184
185 void
186 pdq_os_restart_transmitter(
187 pdq_t *pdq)
188 {
189 pdq_softc_t *sc = (pdq_softc_t *) pdq->pdq_os_ctx;
190 sc->sc_if.if_flags &= ~IFF_OACTIVE;
191 if (!IFQ_IS_EMPTY(&sc->sc_if.if_snd)) {
192 sc->sc_if.if_timer = PDQ_OS_TX_TIMEOUT;
193 pdq_ifstart(&sc->sc_if);
194 } else {
195 sc->sc_if.if_timer = 0;
196 }
197 }
198
199 void
200 pdq_os_transmit_done(
201 pdq_t *pdq,
202 struct mbuf *m)
203 {
204 pdq_softc_t *sc = (pdq_softc_t *) pdq->pdq_os_ctx;
205 #if NBPFILTER > 0
206 if (sc->sc_bpf != NULL)
207 PDQ_BPF_MTAP(sc, m, BPF_DIRECTION_OUT);
208 #endif
209 m_freem(m);
210 sc->sc_if.if_opackets++;
211 }
212
213 void
214 pdq_os_addr_fill(
215 pdq_t *pdq,
216 pdq_lanaddr_t *addr,
217 size_t num_addrs)
218 {
219 pdq_softc_t *sc = (pdq_softc_t *) pdq->pdq_os_ctx;
220 struct ether_multistep step;
221 struct ether_multi *enm;
222
223 ETHER_FIRST_MULTI(step, &sc->sc_arpcom, enm);
224 while (enm != NULL && num_addrs > 0) {
225 ((u_short *) addr->lanaddr_bytes)[0] = ((u_short *) enm->enm_addrlo)[0];
226 ((u_short *) addr->lanaddr_bytes)[1] = ((u_short *) enm->enm_addrlo)[1];
227 ((u_short *) addr->lanaddr_bytes)[2] = ((u_short *) enm->enm_addrlo)[2];
228 ETHER_NEXT_MULTI(step, enm);
229 addr++;
230 num_addrs--;
231 }
232 }
233
234 int
235 pdq_ifioctl(
236 struct ifnet *ifp,
237 ioctl_cmd_t cmd,
238 caddr_t data)
239 {
240 pdq_softc_t *sc = (pdq_softc_t *) ((caddr_t) ifp - offsetof(pdq_softc_t, sc_arpcom.ac_if));
241 int s, error = 0;
242
243 s = splnet();
244
245 switch (cmd) {
246 case SIOCSIFADDR: {
247 struct ifaddr *ifa = (struct ifaddr *)data;
248
249 ifp->if_flags |= IFF_UP;
250 switch(ifa->ifa_addr->sa_family) {
251 #if defined(INET)
252 case AF_INET: {
253 pdq_ifinit(sc);
254 arp_ifinit(&sc->sc_arpcom, ifa);
255 break;
256 }
257 #endif
258
259 #if defined(NS)
260
261
262
263
264 case AF_NS: {
265 struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
266 if (ns_nullhost(*ina)) {
267 ina->x_host = *(union ns_host *)(sc->sc_arpcom.ac_enaddr);
268 } else {
269 ifp->if_flags &= ~IFF_RUNNING;
270 bcopy((caddr_t)ina->x_host.c_host,
271 (caddr_t)sc->sc_arpcom.ac_enaddr,
272 sizeof sc->sc_arpcom.ac_enaddr);
273 }
274
275 pdq_ifinit(sc);
276 break;
277 }
278 #endif
279
280 default: {
281 pdq_ifinit(sc);
282 break;
283 }
284 }
285 break;
286 }
287
288 case SIOCSIFFLAGS: {
289 pdq_ifinit(sc);
290 break;
291 }
292
293 case SIOCADDMULTI:
294 case SIOCDELMULTI: {
295
296
297
298 if (cmd == SIOCADDMULTI)
299 error = ether_addmulti((struct ifreq *)data, &sc->sc_arpcom);
300 else
301 error = ether_delmulti((struct ifreq *)data, &sc->sc_arpcom);
302
303 if (error == ENETRESET) {
304 if (sc->sc_if.if_flags & IFF_RUNNING)
305 pdq_run(sc->sc_pdq);
306 error = 0;
307 }
308 break;
309 }
310
311 default: {
312 error = EINVAL;
313 break;
314 }
315 }
316
317 splx(s);
318 return error;
319 }
320
321 #ifndef IFF_NOTRAILERS
322 #define IFF_NOTRAILERS 0
323 #endif
324
325 void
326 pdq_ifattach(
327 pdq_softc_t *sc,
328 ifnet_ret_t (*ifwatchdog)(int unit))
329 {
330 struct ifnet *ifp = &sc->sc_if;
331
332 ifp->if_flags = IFF_BROADCAST|IFF_SIMPLEX|IFF_NOTRAILERS|IFF_MULTICAST;
333
334 #if (defined(__FreeBSD__) && BSD >= 199506) || defined(__NetBSD__) || \
335 defined(__OpenBSD__)
336 ifp->if_watchdog = pdq_ifwatchdog;
337 #else
338 ifp->if_watchdog = ifwatchdog;
339 #endif
340
341 ifp->if_ioctl = pdq_ifioctl;
342 ifp->if_start = pdq_ifstart;
343 IFQ_SET_READY(&ifp->if_snd);
344
345 if_attach(ifp);
346 fddi_ifattach(ifp);
347 #if NBPFILTER > 0
348 PDQ_BPFATTACH(sc, DLT_FDDI, sizeof(struct fddi_header));
349 #endif
350 }