1 /* $NetBSD: if_fw.c,v 1.21 2004/04/30 01:31:43 lukem Exp $ */
2
3 /* XXX ALTQ XXX */
4
5 /*
6 * Copyright (c) 2000 The NetBSD Foundation, Inc.
7 * All rights reserved.
8 *
9 * This code is derived from software contributed to The NetBSD Foundation
10 * by Atsushi Onoe.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. All advertising materials mentioning features or use of this software
21 * must display the following acknowledgement:
22 * This product includes software developed by the NetBSD
23 * Foundation, Inc. and its contributors.
24 * 4. Neither the name of The NetBSD Foundation nor the names of its
25 * contributors may be used to endorse or promote products derived
26 * from this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
29 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
32 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 */
40
41 #include <sys/cdefs.h>
42 __KERNEL_RCSID(0, "$NetBSD: if_fw.c,v 1.21 2004/04/30 01:31:43 lukem Exp $");
43
44 #include "opt_inet.h"
45 #include "bpfilter.h"
46
47 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/socket.h>
50 #include <sys/sockio.h>
51 #include <sys/kernel.h>
52 #include <sys/mbuf.h>
53 #include <sys/device.h>
54
55 #include <net/if.h>
56 #include <net/if_dl.h>
57 #include <net/if_ieee1394.h>
58 #include <net/if_types.h>
59 #include <net/if_media.h>
60 #include <net/route.h>
61
62 #ifdef INET
63 #include <netinet/in.h>
64 #endif /* INET */
65
66 #ifdef INET6
67 #include <netinet/in.h>
68 #include <netinet6/in6_var.h>
69 #endif /* INET6 */
70
71 #if NBPFILTER > 0
72 #include <net/bpf.h>
73 #endif
74
75 #include <machine/bus.h>
76
77 #include <dev/ieee1394/ieee1394reg.h>
78 #include <dev/ieee1394/ieee1394var.h>
79
80 struct fw_softc {
81 struct ieee1394_softc sc_sc1394;
82 struct ieee1394com sc_ic;
83
84 int sc_flags;
85
86 int (*sc_enable)(struct fw_softc *);
87 void (*sc_disable)(struct fw_softc *);
88 };
89
90 #define FWF_ATTACHED 0x0001
91 #define FWF_ENABLED 0x0002
92
93 int fw_match(struct device *, struct cfdata *, void *);
94 void fw_attach(struct device *, struct device *, void *);
95 int fw_detach(struct device *, int);
96 int fw_activate(struct device *, enum devact);
97
98 void fw_input(struct device *, struct mbuf *);
99 void fw_txint(struct device *, struct mbuf *);
100 int fw_ioctl(struct ifnet *, u_long, caddr_t);
101 void fw_start(struct ifnet *);
102 int fw_init(struct ifnet *);
103 void fw_stop(struct ifnet *, int);
104
105 CFATTACH_DECL(fw, sizeof(struct fw_softc),
106 fw_match, fw_attach, fw_detach, fw_activate);
107
108 int
109 fw_match(struct device *parent, struct cfdata *match, void *aux)
110 {
111 char *name = aux;
112
113 if (strcmp(name, "fw") == 0)
114 return 1;
115 return 0;
116 }
117
118 void
119 fw_attach(struct device *parent, struct device *self, void *aux)
120 {
121 struct fw_softc *sc = (struct fw_softc *)self;
122 struct ieee1394_softc *psc = (struct ieee1394_softc *)parent;
123 struct ifnet *ifp = &sc->sc_ic.ic_if;
124 int i, s;
125
126 s = splnet();
127
128 memcpy(&sc->sc_ic.ic_hwaddr.iha_uid, psc->sc1394_guid,
129 IEEE1394_ADDR_LEN);
130 sc->sc_ic.ic_hwaddr.iha_speed = psc->sc1394_link_speed;
131 for (i = 0; i < 32; i++) {
132 if ((psc->sc1394_max_receive >> (i + 2)) == 0)
133 break;
134 }
135 sc->sc_ic.ic_hwaddr.iha_maxrec = i;
136 sc->sc_ic.ic_hwaddr.iha_offset[0] = (FW_FIFO_HI >> 8) & 0xff;
137 sc->sc_ic.ic_hwaddr.iha_offset[1] = FW_FIFO_HI & 0xff;
138 sc->sc_ic.ic_hwaddr.iha_offset[2] = (FW_FIFO_LO >> 24) & 0xff;
139 sc->sc_ic.ic_hwaddr.iha_offset[3] = (FW_FIFO_LO >> 16) & 0xff;
140 sc->sc_ic.ic_hwaddr.iha_offset[4] = (FW_FIFO_LO >> 8) & 0xff;
141 sc->sc_ic.ic_hwaddr.iha_offset[5] = FW_FIFO_LO & 0xff;
142 printf(":");
143 for (i = 0; i < sizeof(sc->sc_ic.ic_hwaddr); i++)
144 printf("%c%02x", (i == 0 ? ' ' : ':'),
145 ((u_int8_t *)&sc->sc_ic.ic_hwaddr)[i]);
146 printf("\n");
147 if (sc->sc_ic.ic_hwaddr.iha_maxrec < 8) {
148 printf("%s: maximum receive packet (%d) is too small\n",
149 sc->sc_sc1394.sc1394_dev.dv_xname, psc->sc1394_max_receive);
150 splx(s);
151 return;
152 }
153
154 strcpy(ifp->if_xname, sc->sc_sc1394.sc1394_dev.dv_xname);
155 ifp->if_softc = sc;
156 #if __NetBSD_Version__ >= 105080000
157 ifp->if_init = fw_init;
158 ifp->if_stop = fw_stop;
159 #endif
160 ifp->if_start = fw_start;
161 ifp->if_ioctl = fw_ioctl;
162 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
163 ifp->if_baudrate = IF_Mbps(100 << sc->sc_ic.ic_hwaddr.iha_speed);
164 ifp->if_addrlen = sizeof(struct ieee1394_hwaddr);
165 IFQ_SET_READY(&ifp->if_snd);
166
167 if_attach(ifp);
168 ieee1394_ifattach(ifp, &sc->sc_ic.ic_hwaddr);
169
170 sc->sc_flags |= FWF_ATTACHED;
171
172 splx(s);
173 }
174
175 int
176 fw_detach(struct device *self, int flags)
177 {
178 struct fw_softc *sc = (struct fw_softc *)self;
179 struct ifnet *ifp = &sc->sc_ic.ic_if;
180
181 /* Succeed if there is no work to do. */
182 if ((sc->sc_flags & FWF_ATTACHED) == 0)
183 return 0;
184
185 ieee1394_ifdetach(ifp);
186 if_detach(ifp);
187 if (sc->sc_flags & FWF_ENABLED) {
188 if (sc->sc_disable)
189 (*sc->sc_disable)(sc);
190 sc->sc_flags &= ~FWF_ENABLED;
191 }
192 return 0;
193 }
194
195 int
196 fw_activate(struct device *self, enum devact act)
197 {
198 struct fw_softc *sc = (struct fw_softc *)self;
199 int s, error = 0;
200
201 s = splnet();
202 switch (act) {
203 case DVACT_ACTIVATE:
204 error = EOPNOTSUPP;
205 break;
206
207 case DVACT_DEACTIVATE:
208 if_deactivate(&sc->sc_ic.ic_if);
209 break;
210 }
211 splx(s);
212
213 return error;
214 }
215
216 int
217 fw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
218 {
219 int s, error = 0;
220
221 s = splnet();
222
223 switch (cmd) {
224 default:
225 error = ieee1394_ioctl(ifp, cmd, data);
226 break;
227 }
228 splx(s);
229 return error;
230 }
231
232 void
233 fw_start(struct ifnet *ifp)
234 {
235 struct fw_softc *sc = (struct fw_softc *)ifp->if_softc;
236 struct ieee1394_softc *psc =
237 (struct ieee1394_softc *)sc->sc_sc1394.sc1394_dev.dv_parent;
238 struct mbuf *m0;
239 int error;
240
241 if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
242 return;
243 for (;;) {
244 IFQ_DEQUEUE(&ifp->if_snd, m0);
245 if (m0 == NULL)
246 break;
247 error = (*psc->sc1394_ifoutput)
248 (sc->sc_sc1394.sc1394_dev.dv_parent, m0, fw_txint);
249 if (error)
250 break;
251 }
252 if (m0 != NULL)
253 ifp->if_flags |= IFF_OACTIVE;
254 }
255
256 void
257 fw_txint(struct device *self, struct mbuf *m0)
258 {
259 struct fw_softc *sc = (struct fw_softc *)self;
260 struct ifnet *ifp = &sc->sc_ic.ic_if;
261
262 ifp->if_opackets++;
263 m_freem(m0);
264 if (ifp->if_flags & IFF_OACTIVE) {
265 ifp->if_flags &= ~IFF_OACTIVE;
266 fw_start(ifp);
267 }
268 }
269
270 int
271 fw_init(struct ifnet *ifp)
272 {
273 struct fw_softc *sc = (struct fw_softc *)ifp->if_softc;
274 struct ieee1394_softc *psc =
275 (struct ieee1394_softc *)sc->sc_sc1394.sc1394_dev.dv_parent;
276
277 (*psc->sc1394_ifinreg)
278 (sc->sc_sc1394.sc1394_dev.dv_parent, FW_FIFO_HI, FW_FIFO_LO,
279 fw_input);
280 ifp->if_flags |= IFF_RUNNING;
281 return 0;
282 }
283
284 void
285 fw_stop(struct ifnet *ifp, int disable)
286 {
287 struct fw_softc *sc = (struct fw_softc *)ifp->if_softc;
288 struct ieee1394_softc *psc =
289 (struct ieee1394_softc *)sc->sc_sc1394.sc1394_dev.dv_parent;
290
291 (*psc->sc1394_ifinreg)
292 (sc->sc_sc1394.sc1394_dev.dv_parent, FW_FIFO_HI, FW_FIFO_LO,
293 NULL);
294 IFQ_PURGE(&ifp->if_snd);
295 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
296 }
297
298 void
299 fw_input(struct device *self, struct mbuf *m0)
300 {
301 struct fw_softc *sc = (struct fw_softc *)self;
302 struct ifnet *ifp = &sc->sc_ic.ic_if;
303
304 ifp->if_ipackets++;
305 m0->m_pkthdr.rcvif = ifp;
306 (*ifp->if_input)(ifp, m0);
307 }
Cache object: 66826ee908d7f344665acb4aa95016c4
|