Deleted Added
full compact
if_fwip.c (165632) if_fwip.c (167630)
1/*-
2 * Copyright (c) 2004
3 * Doug Rabson
4 * Copyright (c) 2002-2003
5 * Hidetoshi Shimokawa. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 *
18 * This product includes software developed by Hidetoshi Shimokawa.
19 *
20 * 4. Neither the name of the author nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
1/*-
2 * Copyright (c) 2004
3 * Doug Rabson
4 * Copyright (c) 2002-2003
5 * Hidetoshi Shimokawa. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 *
18 * This product includes software developed by Hidetoshi Shimokawa.
19 *
20 * 4. Neither the name of the author nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * $FreeBSD: head/sys/dev/firewire/if_fwip.c 165632 2006-12-29 13:59:50Z jhb $
36 * $FreeBSD: head/sys/dev/firewire/if_fwip.c 167630 2007-03-16 05:11:42Z simokawa $
37 */
38
39#ifdef HAVE_KERNEL_OPTION_HEADERS
40#include "opt_device_polling.h"
41#include "opt_inet.h"
42#endif
43
44#include <sys/param.h>
45#include <sys/kernel.h>
46#include <sys/malloc.h>
47#include <sys/mbuf.h>
48#include <sys/socket.h>
49#include <sys/sockio.h>
50#include <sys/sysctl.h>
51#include <sys/systm.h>
52#include <sys/taskqueue.h>
53#include <sys/module.h>
54#include <sys/bus.h>
55#include <machine/bus.h>
56
57#include <net/bpf.h>
58#include <net/if.h>
59#include <net/firewire.h>
60#include <net/if_arp.h>
61#include <net/if_types.h>
62#ifdef __DragonFly__
63#include <bus/firewire/firewire.h>
64#include <bus/firewire/firewirereg.h>
65#include "if_fwipvar.h"
66#else
67#include <dev/firewire/firewire.h>
68#include <dev/firewire/firewirereg.h>
69#include <dev/firewire/iec13213.h>
70#include <dev/firewire/if_fwipvar.h>
71#endif
72
73/*
74 * We really need a mechanism for allocating regions in the FIFO
75 * address space. We pick a address in the OHCI controller's 'middle'
76 * address space. This means that the controller will automatically
77 * send responses for us, which is fine since we don't have any
78 * important information to put in the response anyway.
79 */
80#define INET_FIFO 0xfffe00000000LL
81
82#define FWIPDEBUG if (fwipdebug) if_printf
83#define TX_MAX_QUEUE (FWMAXQUEUE - 1)
84
85/* network interface */
86static void fwip_start (struct ifnet *);
87static int fwip_ioctl (struct ifnet *, u_long, caddr_t);
88static void fwip_init (void *);
89
90static void fwip_post_busreset (void *);
91static void fwip_output_callback (struct fw_xfer *);
92static void fwip_async_output (struct fwip_softc *, struct ifnet *);
93static void fwip_start_send (void *, int);
94static void fwip_stream_input (struct fw_xferq *);
95static void fwip_unicast_input(struct fw_xfer *);
96
97static int fwipdebug = 0;
98static int broadcast_channel = 0xc0 | 0x1f; /* tag | channel(XXX) */
99static int tx_speed = 2;
100static int rx_queue_len = FWMAXQUEUE;
101
102MALLOC_DEFINE(M_FWIP, "if_fwip", "IP over FireWire interface");
103SYSCTL_INT(_debug, OID_AUTO, if_fwip_debug, CTLFLAG_RW, &fwipdebug, 0, "");
104SYSCTL_DECL(_hw_firewire);
105SYSCTL_NODE(_hw_firewire, OID_AUTO, fwip, CTLFLAG_RD, 0,
106 "Firewire ip subsystem");
107SYSCTL_INT(_hw_firewire_fwip, OID_AUTO, rx_queue_len, CTLFLAG_RW, &rx_queue_len,
108 0, "Length of the receive queue");
109
110TUNABLE_INT("hw.firewire.fwip.rx_queue_len", &rx_queue_len);
111
112#ifdef DEVICE_POLLING
113static poll_handler_t fwip_poll;
114
115static void
116fwip_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
117{
118 struct fwip_softc *fwip;
119 struct firewire_comm *fc;
120
121 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
122 return;
123
124 fwip = ((struct fwip_eth_softc *)ifp->if_softc)->fwip;
125 fc = fwip->fd.fc;
126 fc->poll(fc, (cmd == POLL_AND_CHECK_STATUS)?0:1, count);
127}
128#endif /* DEVICE_POLLING */
129
130static void
131fwip_identify(driver_t *driver, device_t parent)
132{
133 BUS_ADD_CHILD(parent, 0, "fwip", device_get_unit(parent));
134}
135
136static int
137fwip_probe(device_t dev)
138{
139 device_t pa;
140
141 pa = device_get_parent(dev);
142 if(device_get_unit(dev) != device_get_unit(pa)){
143 return(ENXIO);
144 }
145
146 device_set_desc(dev, "IP over FireWire");
147 return (0);
148}
149
150static int
151fwip_attach(device_t dev)
152{
153 struct fwip_softc *fwip;
154 struct ifnet *ifp;
155 int unit, s;
156 struct fw_hwaddr *hwaddr;
157
158 fwip = ((struct fwip_softc *)device_get_softc(dev));
159 unit = device_get_unit(dev);
160 ifp = fwip->fw_softc.fwip_ifp = if_alloc(IFT_IEEE1394);
161 if (ifp == NULL)
162 return (ENOSPC);
163
164 /* XXX */
165 fwip->dma_ch = -1;
166
167 fwip->fd.fc = device_get_ivars(dev);
168 if (tx_speed < 0)
169 tx_speed = fwip->fd.fc->speed;
170
171 fwip->fd.dev = dev;
172 fwip->fd.post_explore = NULL;
173 fwip->fd.post_busreset = fwip_post_busreset;
174 fwip->fw_softc.fwip = fwip;
175 TASK_INIT(&fwip->start_send, 0, fwip_start_send, fwip);
176
177 /*
178 * Encode our hardware the way that arp likes it.
179 */
180 hwaddr = &IFP2FWC(fwip->fw_softc.fwip_ifp)->fc_hwaddr;
181 hwaddr->sender_unique_ID_hi = htonl(fwip->fd.fc->eui.hi);
182 hwaddr->sender_unique_ID_lo = htonl(fwip->fd.fc->eui.lo);
183 hwaddr->sender_max_rec = fwip->fd.fc->maxrec;
184 hwaddr->sspd = fwip->fd.fc->speed;
185 hwaddr->sender_unicast_FIFO_hi = htons((uint16_t)(INET_FIFO >> 32));
186 hwaddr->sender_unicast_FIFO_lo = htonl((uint32_t)INET_FIFO);
187
188 /* fill the rest and attach interface */
189 ifp->if_softc = &fwip->fw_softc;
190
191#if __FreeBSD_version >= 501113 || defined(__DragonFly__)
192 if_initname(ifp, device_get_name(dev), unit);
193#else
194 ifp->if_unit = unit;
195 ifp->if_name = "fwip";
196#endif
197 ifp->if_init = fwip_init;
198 ifp->if_start = fwip_start;
199 ifp->if_ioctl = fwip_ioctl;
200 ifp->if_flags = (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST|
201 IFF_NEEDSGIANT);
202 ifp->if_snd.ifq_maxlen = TX_MAX_QUEUE;
203#ifdef DEVICE_POLLING
204 ifp->if_capabilities |= IFCAP_POLLING;
205#endif
206
207 s = splimp();
208 firewire_ifattach(ifp, hwaddr);
209 splx(s);
210
211 FWIPDEBUG(ifp, "interface created\n");
212 return 0;
213}
214
215static void
216fwip_stop(struct fwip_softc *fwip)
217{
218 struct firewire_comm *fc;
219 struct fw_xferq *xferq;
220 struct ifnet *ifp = fwip->fw_softc.fwip_ifp;
221 struct fw_xfer *xfer, *next;
222 int i;
223
224 fc = fwip->fd.fc;
225
226 if (fwip->dma_ch >= 0) {
227 xferq = fc->ir[fwip->dma_ch];
228
229 if (xferq->flag & FWXFERQ_RUNNING)
230 fc->irx_disable(fc, fwip->dma_ch);
231 xferq->flag &=
232 ~(FWXFERQ_MODEMASK | FWXFERQ_OPEN | FWXFERQ_STREAM |
233 FWXFERQ_EXTBUF | FWXFERQ_HANDLER | FWXFERQ_CHTAGMASK);
234 xferq->hand = NULL;
235
236 for (i = 0; i < xferq->bnchunk; i ++)
237 m_freem(xferq->bulkxfer[i].mbuf);
238 free(xferq->bulkxfer, M_FWIP);
239
240 fw_bindremove(fc, &fwip->fwb);
241 for (xfer = STAILQ_FIRST(&fwip->fwb.xferlist); xfer != NULL;
242 xfer = next) {
243 next = STAILQ_NEXT(xfer, link);
244 fw_xfer_free(xfer);
245 }
246
247 for (xfer = STAILQ_FIRST(&fwip->xferlist); xfer != NULL;
248 xfer = next) {
249 next = STAILQ_NEXT(xfer, link);
250 fw_xfer_free(xfer);
251 }
252 STAILQ_INIT(&fwip->xferlist);
253
254 xferq->bulkxfer = NULL;
255 fwip->dma_ch = -1;
256 }
257
258#if defined(__FreeBSD__)
259 ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
260#else
261 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
262#endif
263}
264
265static int
266fwip_detach(device_t dev)
267{
268 struct fwip_softc *fwip;
269 struct ifnet *ifp;
270 int s;
271
272 fwip = (struct fwip_softc *)device_get_softc(dev);
273 ifp = fwip->fw_softc.fwip_ifp;
274
275#ifdef DEVICE_POLLING
276 if (ifp->if_capenable & IFCAP_POLLING)
277 ether_poll_deregister(ifp);
278#endif
279
280 s = splimp();
281
282 fwip_stop(fwip);
283 firewire_ifdetach(ifp);
284 if_free(ifp);
285
286 splx(s);
287 return 0;
288}
289
290static void
291fwip_init(void *arg)
292{
293 struct fwip_softc *fwip = ((struct fwip_eth_softc *)arg)->fwip;
294 struct firewire_comm *fc;
295 struct ifnet *ifp = fwip->fw_softc.fwip_ifp;
296 struct fw_xferq *xferq;
297 struct fw_xfer *xfer;
298 struct mbuf *m;
299 int i;
300
301 FWIPDEBUG(ifp, "initializing\n");
302
303 fc = fwip->fd.fc;
304#define START 0
305 if (fwip->dma_ch < 0) {
306 for (i = START; i < fc->nisodma; i ++) {
307 xferq = fc->ir[i];
308 if ((xferq->flag & FWXFERQ_OPEN) == 0)
309 goto found;
310 }
311 printf("no free dma channel\n");
312 return;
313found:
314 fwip->dma_ch = i;
315 /* allocate DMA channel and init packet mode */
316 xferq->flag |= FWXFERQ_OPEN | FWXFERQ_EXTBUF |
317 FWXFERQ_HANDLER | FWXFERQ_STREAM;
318 xferq->flag &= ~0xff;
319 xferq->flag |= broadcast_channel & 0xff;
320 /* register fwip_input handler */
321 xferq->sc = (caddr_t) fwip;
322 xferq->hand = fwip_stream_input;
323 xferq->bnchunk = rx_queue_len;
324 xferq->bnpacket = 1;
325 xferq->psize = MCLBYTES;
326 xferq->queued = 0;
327 xferq->buf = NULL;
328 xferq->bulkxfer = (struct fw_bulkxfer *) malloc(
329 sizeof(struct fw_bulkxfer) * xferq->bnchunk,
330 M_FWIP, M_WAITOK);
331 if (xferq->bulkxfer == NULL) {
332 printf("if_fwip: malloc failed\n");
333 return;
334 }
335 STAILQ_INIT(&xferq->stvalid);
336 STAILQ_INIT(&xferq->stfree);
337 STAILQ_INIT(&xferq->stdma);
338 xferq->stproc = NULL;
339 for (i = 0; i < xferq->bnchunk; i ++) {
340 m =
341#if defined(__DragonFly__) || __FreeBSD_version < 500000
342 m_getcl(M_WAIT, MT_DATA, M_PKTHDR);
343#else
344 m_getcl(M_TRYWAIT, MT_DATA, M_PKTHDR);
345#endif
346 xferq->bulkxfer[i].mbuf = m;
347 if (m != NULL) {
348 m->m_len = m->m_pkthdr.len = m->m_ext.ext_size;
349 STAILQ_INSERT_TAIL(&xferq->stfree,
350 &xferq->bulkxfer[i], link);
351 } else
352 printf("fwip_as_input: m_getcl failed\n");
353 }
354
355 fwip->fwb.start = INET_FIFO;
356 fwip->fwb.end = INET_FIFO + 16384; /* S3200 packet size */
357 fwip->fwb.act_type = FWACT_XFER;
358
359 /* pre-allocate xfer */
360 STAILQ_INIT(&fwip->fwb.xferlist);
361 for (i = 0; i < rx_queue_len; i ++) {
362 xfer = fw_xfer_alloc(M_FWIP);
363 if (xfer == NULL)
364 break;
365 m = m_getcl(M_TRYWAIT, MT_DATA, M_PKTHDR);
366 xfer->recv.payload = mtod(m, uint32_t *);
367 xfer->recv.pay_len = MCLBYTES;
368 xfer->act.hand = fwip_unicast_input;
369 xfer->fc = fc;
370 xfer->sc = (caddr_t)fwip;
371 xfer->mbuf = m;
372 STAILQ_INSERT_TAIL(&fwip->fwb.xferlist, xfer, link);
373 }
374 fw_bindadd(fc, &fwip->fwb);
375
376 STAILQ_INIT(&fwip->xferlist);
377 for (i = 0; i < TX_MAX_QUEUE; i++) {
378 xfer = fw_xfer_alloc(M_FWIP);
379 if (xfer == NULL)
380 break;
381 xfer->send.spd = tx_speed;
382 xfer->fc = fwip->fd.fc;
37 */
38
39#ifdef HAVE_KERNEL_OPTION_HEADERS
40#include "opt_device_polling.h"
41#include "opt_inet.h"
42#endif
43
44#include <sys/param.h>
45#include <sys/kernel.h>
46#include <sys/malloc.h>
47#include <sys/mbuf.h>
48#include <sys/socket.h>
49#include <sys/sockio.h>
50#include <sys/sysctl.h>
51#include <sys/systm.h>
52#include <sys/taskqueue.h>
53#include <sys/module.h>
54#include <sys/bus.h>
55#include <machine/bus.h>
56
57#include <net/bpf.h>
58#include <net/if.h>
59#include <net/firewire.h>
60#include <net/if_arp.h>
61#include <net/if_types.h>
62#ifdef __DragonFly__
63#include <bus/firewire/firewire.h>
64#include <bus/firewire/firewirereg.h>
65#include "if_fwipvar.h"
66#else
67#include <dev/firewire/firewire.h>
68#include <dev/firewire/firewirereg.h>
69#include <dev/firewire/iec13213.h>
70#include <dev/firewire/if_fwipvar.h>
71#endif
72
73/*
74 * We really need a mechanism for allocating regions in the FIFO
75 * address space. We pick a address in the OHCI controller's 'middle'
76 * address space. This means that the controller will automatically
77 * send responses for us, which is fine since we don't have any
78 * important information to put in the response anyway.
79 */
80#define INET_FIFO 0xfffe00000000LL
81
82#define FWIPDEBUG if (fwipdebug) if_printf
83#define TX_MAX_QUEUE (FWMAXQUEUE - 1)
84
85/* network interface */
86static void fwip_start (struct ifnet *);
87static int fwip_ioctl (struct ifnet *, u_long, caddr_t);
88static void fwip_init (void *);
89
90static void fwip_post_busreset (void *);
91static void fwip_output_callback (struct fw_xfer *);
92static void fwip_async_output (struct fwip_softc *, struct ifnet *);
93static void fwip_start_send (void *, int);
94static void fwip_stream_input (struct fw_xferq *);
95static void fwip_unicast_input(struct fw_xfer *);
96
97static int fwipdebug = 0;
98static int broadcast_channel = 0xc0 | 0x1f; /* tag | channel(XXX) */
99static int tx_speed = 2;
100static int rx_queue_len = FWMAXQUEUE;
101
102MALLOC_DEFINE(M_FWIP, "if_fwip", "IP over FireWire interface");
103SYSCTL_INT(_debug, OID_AUTO, if_fwip_debug, CTLFLAG_RW, &fwipdebug, 0, "");
104SYSCTL_DECL(_hw_firewire);
105SYSCTL_NODE(_hw_firewire, OID_AUTO, fwip, CTLFLAG_RD, 0,
106 "Firewire ip subsystem");
107SYSCTL_INT(_hw_firewire_fwip, OID_AUTO, rx_queue_len, CTLFLAG_RW, &rx_queue_len,
108 0, "Length of the receive queue");
109
110TUNABLE_INT("hw.firewire.fwip.rx_queue_len", &rx_queue_len);
111
112#ifdef DEVICE_POLLING
113static poll_handler_t fwip_poll;
114
115static void
116fwip_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
117{
118 struct fwip_softc *fwip;
119 struct firewire_comm *fc;
120
121 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
122 return;
123
124 fwip = ((struct fwip_eth_softc *)ifp->if_softc)->fwip;
125 fc = fwip->fd.fc;
126 fc->poll(fc, (cmd == POLL_AND_CHECK_STATUS)?0:1, count);
127}
128#endif /* DEVICE_POLLING */
129
130static void
131fwip_identify(driver_t *driver, device_t parent)
132{
133 BUS_ADD_CHILD(parent, 0, "fwip", device_get_unit(parent));
134}
135
136static int
137fwip_probe(device_t dev)
138{
139 device_t pa;
140
141 pa = device_get_parent(dev);
142 if(device_get_unit(dev) != device_get_unit(pa)){
143 return(ENXIO);
144 }
145
146 device_set_desc(dev, "IP over FireWire");
147 return (0);
148}
149
150static int
151fwip_attach(device_t dev)
152{
153 struct fwip_softc *fwip;
154 struct ifnet *ifp;
155 int unit, s;
156 struct fw_hwaddr *hwaddr;
157
158 fwip = ((struct fwip_softc *)device_get_softc(dev));
159 unit = device_get_unit(dev);
160 ifp = fwip->fw_softc.fwip_ifp = if_alloc(IFT_IEEE1394);
161 if (ifp == NULL)
162 return (ENOSPC);
163
164 /* XXX */
165 fwip->dma_ch = -1;
166
167 fwip->fd.fc = device_get_ivars(dev);
168 if (tx_speed < 0)
169 tx_speed = fwip->fd.fc->speed;
170
171 fwip->fd.dev = dev;
172 fwip->fd.post_explore = NULL;
173 fwip->fd.post_busreset = fwip_post_busreset;
174 fwip->fw_softc.fwip = fwip;
175 TASK_INIT(&fwip->start_send, 0, fwip_start_send, fwip);
176
177 /*
178 * Encode our hardware the way that arp likes it.
179 */
180 hwaddr = &IFP2FWC(fwip->fw_softc.fwip_ifp)->fc_hwaddr;
181 hwaddr->sender_unique_ID_hi = htonl(fwip->fd.fc->eui.hi);
182 hwaddr->sender_unique_ID_lo = htonl(fwip->fd.fc->eui.lo);
183 hwaddr->sender_max_rec = fwip->fd.fc->maxrec;
184 hwaddr->sspd = fwip->fd.fc->speed;
185 hwaddr->sender_unicast_FIFO_hi = htons((uint16_t)(INET_FIFO >> 32));
186 hwaddr->sender_unicast_FIFO_lo = htonl((uint32_t)INET_FIFO);
187
188 /* fill the rest and attach interface */
189 ifp->if_softc = &fwip->fw_softc;
190
191#if __FreeBSD_version >= 501113 || defined(__DragonFly__)
192 if_initname(ifp, device_get_name(dev), unit);
193#else
194 ifp->if_unit = unit;
195 ifp->if_name = "fwip";
196#endif
197 ifp->if_init = fwip_init;
198 ifp->if_start = fwip_start;
199 ifp->if_ioctl = fwip_ioctl;
200 ifp->if_flags = (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST|
201 IFF_NEEDSGIANT);
202 ifp->if_snd.ifq_maxlen = TX_MAX_QUEUE;
203#ifdef DEVICE_POLLING
204 ifp->if_capabilities |= IFCAP_POLLING;
205#endif
206
207 s = splimp();
208 firewire_ifattach(ifp, hwaddr);
209 splx(s);
210
211 FWIPDEBUG(ifp, "interface created\n");
212 return 0;
213}
214
215static void
216fwip_stop(struct fwip_softc *fwip)
217{
218 struct firewire_comm *fc;
219 struct fw_xferq *xferq;
220 struct ifnet *ifp = fwip->fw_softc.fwip_ifp;
221 struct fw_xfer *xfer, *next;
222 int i;
223
224 fc = fwip->fd.fc;
225
226 if (fwip->dma_ch >= 0) {
227 xferq = fc->ir[fwip->dma_ch];
228
229 if (xferq->flag & FWXFERQ_RUNNING)
230 fc->irx_disable(fc, fwip->dma_ch);
231 xferq->flag &=
232 ~(FWXFERQ_MODEMASK | FWXFERQ_OPEN | FWXFERQ_STREAM |
233 FWXFERQ_EXTBUF | FWXFERQ_HANDLER | FWXFERQ_CHTAGMASK);
234 xferq->hand = NULL;
235
236 for (i = 0; i < xferq->bnchunk; i ++)
237 m_freem(xferq->bulkxfer[i].mbuf);
238 free(xferq->bulkxfer, M_FWIP);
239
240 fw_bindremove(fc, &fwip->fwb);
241 for (xfer = STAILQ_FIRST(&fwip->fwb.xferlist); xfer != NULL;
242 xfer = next) {
243 next = STAILQ_NEXT(xfer, link);
244 fw_xfer_free(xfer);
245 }
246
247 for (xfer = STAILQ_FIRST(&fwip->xferlist); xfer != NULL;
248 xfer = next) {
249 next = STAILQ_NEXT(xfer, link);
250 fw_xfer_free(xfer);
251 }
252 STAILQ_INIT(&fwip->xferlist);
253
254 xferq->bulkxfer = NULL;
255 fwip->dma_ch = -1;
256 }
257
258#if defined(__FreeBSD__)
259 ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
260#else
261 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
262#endif
263}
264
265static int
266fwip_detach(device_t dev)
267{
268 struct fwip_softc *fwip;
269 struct ifnet *ifp;
270 int s;
271
272 fwip = (struct fwip_softc *)device_get_softc(dev);
273 ifp = fwip->fw_softc.fwip_ifp;
274
275#ifdef DEVICE_POLLING
276 if (ifp->if_capenable & IFCAP_POLLING)
277 ether_poll_deregister(ifp);
278#endif
279
280 s = splimp();
281
282 fwip_stop(fwip);
283 firewire_ifdetach(ifp);
284 if_free(ifp);
285
286 splx(s);
287 return 0;
288}
289
290static void
291fwip_init(void *arg)
292{
293 struct fwip_softc *fwip = ((struct fwip_eth_softc *)arg)->fwip;
294 struct firewire_comm *fc;
295 struct ifnet *ifp = fwip->fw_softc.fwip_ifp;
296 struct fw_xferq *xferq;
297 struct fw_xfer *xfer;
298 struct mbuf *m;
299 int i;
300
301 FWIPDEBUG(ifp, "initializing\n");
302
303 fc = fwip->fd.fc;
304#define START 0
305 if (fwip->dma_ch < 0) {
306 for (i = START; i < fc->nisodma; i ++) {
307 xferq = fc->ir[i];
308 if ((xferq->flag & FWXFERQ_OPEN) == 0)
309 goto found;
310 }
311 printf("no free dma channel\n");
312 return;
313found:
314 fwip->dma_ch = i;
315 /* allocate DMA channel and init packet mode */
316 xferq->flag |= FWXFERQ_OPEN | FWXFERQ_EXTBUF |
317 FWXFERQ_HANDLER | FWXFERQ_STREAM;
318 xferq->flag &= ~0xff;
319 xferq->flag |= broadcast_channel & 0xff;
320 /* register fwip_input handler */
321 xferq->sc = (caddr_t) fwip;
322 xferq->hand = fwip_stream_input;
323 xferq->bnchunk = rx_queue_len;
324 xferq->bnpacket = 1;
325 xferq->psize = MCLBYTES;
326 xferq->queued = 0;
327 xferq->buf = NULL;
328 xferq->bulkxfer = (struct fw_bulkxfer *) malloc(
329 sizeof(struct fw_bulkxfer) * xferq->bnchunk,
330 M_FWIP, M_WAITOK);
331 if (xferq->bulkxfer == NULL) {
332 printf("if_fwip: malloc failed\n");
333 return;
334 }
335 STAILQ_INIT(&xferq->stvalid);
336 STAILQ_INIT(&xferq->stfree);
337 STAILQ_INIT(&xferq->stdma);
338 xferq->stproc = NULL;
339 for (i = 0; i < xferq->bnchunk; i ++) {
340 m =
341#if defined(__DragonFly__) || __FreeBSD_version < 500000
342 m_getcl(M_WAIT, MT_DATA, M_PKTHDR);
343#else
344 m_getcl(M_TRYWAIT, MT_DATA, M_PKTHDR);
345#endif
346 xferq->bulkxfer[i].mbuf = m;
347 if (m != NULL) {
348 m->m_len = m->m_pkthdr.len = m->m_ext.ext_size;
349 STAILQ_INSERT_TAIL(&xferq->stfree,
350 &xferq->bulkxfer[i], link);
351 } else
352 printf("fwip_as_input: m_getcl failed\n");
353 }
354
355 fwip->fwb.start = INET_FIFO;
356 fwip->fwb.end = INET_FIFO + 16384; /* S3200 packet size */
357 fwip->fwb.act_type = FWACT_XFER;
358
359 /* pre-allocate xfer */
360 STAILQ_INIT(&fwip->fwb.xferlist);
361 for (i = 0; i < rx_queue_len; i ++) {
362 xfer = fw_xfer_alloc(M_FWIP);
363 if (xfer == NULL)
364 break;
365 m = m_getcl(M_TRYWAIT, MT_DATA, M_PKTHDR);
366 xfer->recv.payload = mtod(m, uint32_t *);
367 xfer->recv.pay_len = MCLBYTES;
368 xfer->act.hand = fwip_unicast_input;
369 xfer->fc = fc;
370 xfer->sc = (caddr_t)fwip;
371 xfer->mbuf = m;
372 STAILQ_INSERT_TAIL(&fwip->fwb.xferlist, xfer, link);
373 }
374 fw_bindadd(fc, &fwip->fwb);
375
376 STAILQ_INIT(&fwip->xferlist);
377 for (i = 0; i < TX_MAX_QUEUE; i++) {
378 xfer = fw_xfer_alloc(M_FWIP);
379 if (xfer == NULL)
380 break;
381 xfer->send.spd = tx_speed;
382 xfer->fc = fwip->fd.fc;
383 xfer->retry_req = fw_asybusy;
384 xfer->sc = (caddr_t)fwip;
385 xfer->act.hand = fwip_output_callback;
386 STAILQ_INSERT_TAIL(&fwip->xferlist, xfer, link);
387 }
388 } else
389 xferq = fc->ir[fwip->dma_ch];
390
391 fwip->last_dest.hi = 0;
392 fwip->last_dest.lo = 0;
393
394 /* start dma */
395 if ((xferq->flag & FWXFERQ_RUNNING) == 0)
396 fc->irx_enable(fc, fwip->dma_ch);
397
398#if defined(__FreeBSD__)
399 ifp->if_drv_flags |= IFF_DRV_RUNNING;
400 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
401#else
402 ifp->if_flags |= IFF_RUNNING;
403 ifp->if_flags &= ~IFF_OACTIVE;
404#endif
405
406#if 0
407 /* attempt to start output */
408 fwip_start(ifp);
409#endif
410}
411
412static int
413fwip_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
414{
415 struct fwip_softc *fwip = ((struct fwip_eth_softc *)ifp->if_softc)->fwip;
416 int s, error;
417
418 switch (cmd) {
419 case SIOCSIFFLAGS:
420 s = splimp();
421 if (ifp->if_flags & IFF_UP) {
422#if defined(__FreeBSD__)
423 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
424#else
425 if (!(ifp->if_flags & IFF_RUNNING))
426#endif
427 fwip_init(&fwip->fw_softc);
428 } else {
429#if defined(__FreeBSD__)
430 if (ifp->if_drv_flags & IFF_DRV_RUNNING)
431#else
432 if (ifp->if_flags & IFF_RUNNING)
433#endif
434 fwip_stop(fwip);
435 }
436 splx(s);
437 break;
438 case SIOCADDMULTI:
439 case SIOCDELMULTI:
440 break;
441 case SIOCSIFCAP:
442#ifdef DEVICE_POLLING
443 {
444 struct ifreq *ifr = (struct ifreq *) data;
445 struct firewire_comm *fc = fc = fwip->fd.fc;
446
447 if (ifr->ifr_reqcap & IFCAP_POLLING &&
448 !(ifp->if_capenable & IFCAP_POLLING)) {
449 error = ether_poll_register(fwip_poll, ifp);
450 if (error)
451 return(error);
452 /* Disable interrupts */
453 fc->set_intr(fc, 0);
454 ifp->if_capenable |= IFCAP_POLLING;
455 return (error);
456
457 }
458 if (!(ifr->ifr_reqcap & IFCAP_POLLING) &&
459 ifp->if_capenable & IFCAP_POLLING) {
460 error = ether_poll_deregister(ifp);
461 /* Enable interrupts. */
462 fc->set_intr(fc, 1);
463 ifp->if_capenable &= ~IFCAP_POLLING;
464 return (error);
465 }
466 }
467#endif /* DEVICE_POLLING */
468 break;
469#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
470 default:
471#else
472 case SIOCSIFADDR:
473 case SIOCGIFADDR:
474 case SIOCSIFMTU:
475#endif
476 s = splimp();
477 error = firewire_ioctl(ifp, cmd, data);
478 splx(s);
479 return (error);
480#if defined(__DragonFly__) || __FreeBSD_version < 500000
481 default:
482 return (EINVAL);
483#endif
484 }
485
486 return (0);
487}
488
489static void
490fwip_post_busreset(void *arg)
491{
492 struct fwip_softc *fwip = arg;
493 struct crom_src *src;
494 struct crom_chunk *root;
495
496 src = fwip->fd.fc->crom_src;
497 root = fwip->fd.fc->crom_root;
498
499 /* RFC2734 IPv4 over IEEE1394 */
500 bzero(&fwip->unit4, sizeof(struct crom_chunk));
501 crom_add_chunk(src, root, &fwip->unit4, CROM_UDIR);
502 crom_add_entry(&fwip->unit4, CSRKEY_SPEC, CSRVAL_IETF);
503 crom_add_simple_text(src, &fwip->unit4, &fwip->spec4, "IANA");
504 crom_add_entry(&fwip->unit4, CSRKEY_VER, 1);
505 crom_add_simple_text(src, &fwip->unit4, &fwip->ver4, "IPv4");
506
507 /* RFC3146 IPv6 over IEEE1394 */
508 bzero(&fwip->unit6, sizeof(struct crom_chunk));
509 crom_add_chunk(src, root, &fwip->unit6, CROM_UDIR);
510 crom_add_entry(&fwip->unit6, CSRKEY_SPEC, CSRVAL_IETF);
511 crom_add_simple_text(src, &fwip->unit6, &fwip->spec6, "IANA");
512 crom_add_entry(&fwip->unit6, CSRKEY_VER, 2);
513 crom_add_simple_text(src, &fwip->unit6, &fwip->ver6, "IPv6");
514
515 fwip->last_dest.hi = 0;
516 fwip->last_dest.lo = 0;
517 firewire_busreset(fwip->fw_softc.fwip_ifp);
518}
519
520static void
521fwip_output_callback(struct fw_xfer *xfer)
522{
523 struct fwip_softc *fwip;
524 struct ifnet *ifp;
525 int s;
526
527 GIANT_REQUIRED;
528
529 fwip = (struct fwip_softc *)xfer->sc;
530 ifp = fwip->fw_softc.fwip_ifp;
531 /* XXX error check */
532 FWIPDEBUG(ifp, "resp = %d\n", xfer->resp);
533 if (xfer->resp != 0)
534 ifp->if_oerrors ++;
535
536 m_freem(xfer->mbuf);
537 fw_xfer_unload(xfer);
538
539 s = splimp();
540 STAILQ_INSERT_TAIL(&fwip->xferlist, xfer, link);
541 splx(s);
542
543 /* for queue full */
544 if (ifp->if_snd.ifq_head != NULL)
545 fwip_start(ifp);
546}
547
548static void
549fwip_start(struct ifnet *ifp)
550{
551 struct fwip_softc *fwip = ((struct fwip_eth_softc *)ifp->if_softc)->fwip;
552 int s;
553
554 GIANT_REQUIRED;
555
556 FWIPDEBUG(ifp, "starting\n");
557
558 if (fwip->dma_ch < 0) {
559 struct mbuf *m = NULL;
560
561 FWIPDEBUG(ifp, "not ready\n");
562
563 s = splimp();
564 do {
565 IF_DEQUEUE(&ifp->if_snd, m);
566 if (m != NULL)
567 m_freem(m);
568 ifp->if_oerrors ++;
569 } while (m != NULL);
570 splx(s);
571
572 return;
573 }
574
575 s = splimp();
576#if defined(__FreeBSD__)
577 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
578#else
579 ifp->if_flags |= IFF_OACTIVE;
580#endif
581
582 if (ifp->if_snd.ifq_len != 0)
583 fwip_async_output(fwip, ifp);
584
585#if defined(__FreeBSD__)
586 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
587#else
588 ifp->if_flags &= ~IFF_OACTIVE;
589#endif
590 splx(s);
591}
592
593/* Async. stream output */
594static void
595fwip_async_output(struct fwip_softc *fwip, struct ifnet *ifp)
596{
597 struct firewire_comm *fc = fwip->fd.fc;
598 struct mbuf *m;
599 struct m_tag *mtag;
600 struct fw_hwaddr *destfw;
601 struct fw_xfer *xfer;
602 struct fw_xferq *xferq;
603 struct fw_pkt *fp;
604 uint16_t nodeid;
605 int error;
606 int i = 0;
607
608 GIANT_REQUIRED;
609
610 xfer = NULL;
611 xferq = fwip->fd.fc->atq;
612 while (xferq->queued < xferq->maxq - 1) {
613 xfer = STAILQ_FIRST(&fwip->xferlist);
614 if (xfer == NULL) {
615 printf("if_fwip: lack of xfer\n");
616 return;
617 }
618 IF_DEQUEUE(&ifp->if_snd, m);
619 if (m == NULL)
620 break;
621
622 /*
623 * Dig out the link-level address which
624 * firewire_output got via arp or neighbour
625 * discovery. If we don't have a link-level address,
626 * just stick the thing on the broadcast channel.
627 */
628 mtag = m_tag_locate(m, MTAG_FIREWIRE, MTAG_FIREWIRE_HWADDR, 0);
629 if (mtag == NULL)
630 destfw = 0;
631 else
632 destfw = (struct fw_hwaddr *) (mtag + 1);
633
634 STAILQ_REMOVE_HEAD(&fwip->xferlist, link);
635
636 /*
637 * We don't do any bpf stuff here - the generic code
638 * in firewire_output gives the packet to bpf before
639 * it adds the link-level encapsulation.
640 */
641
642 /*
643 * Put the mbuf in the xfer early in case we hit an
644 * error case below - fwip_output_callback will free
645 * the mbuf.
646 */
647 xfer->mbuf = m;
648
649 /*
650 * We use the arp result (if any) to add a suitable firewire
651 * packet header before handing off to the bus.
652 */
653 fp = &xfer->send.hdr;
654 nodeid = FWLOCALBUS | fc->nodeid;
655 if ((m->m_flags & M_BCAST) || !destfw) {
656 /*
657 * Broadcast packets are sent as GASP packets with
658 * specifier ID 0x00005e, version 1 on the broadcast
659 * channel. To be conservative, we send at the
660 * slowest possible speed.
661 */
662 uint32_t *p;
663
664 M_PREPEND(m, 2*sizeof(uint32_t), M_DONTWAIT);
665 p = mtod(m, uint32_t *);
666 fp->mode.stream.len = m->m_pkthdr.len;
667 fp->mode.stream.chtag = broadcast_channel;
668 fp->mode.stream.tcode = FWTCODE_STREAM;
669 fp->mode.stream.sy = 0;
670 xfer->send.spd = 0;
671 p[0] = htonl(nodeid << 16);
672 p[1] = htonl((0x5e << 24) | 1);
673 } else {
674 /*
675 * Unicast packets are sent as block writes to the
676 * target's unicast fifo address. If we can't
677 * find the node address, we just give up. We
678 * could broadcast it but that might overflow
679 * the packet size limitations due to the
680 * extra GASP header. Note: the hardware
681 * address is stored in network byte order to
682 * make life easier for ARP.
683 */
684 struct fw_device *fd;
685 struct fw_eui64 eui;
686
687 eui.hi = ntohl(destfw->sender_unique_ID_hi);
688 eui.lo = ntohl(destfw->sender_unique_ID_lo);
689 if (fwip->last_dest.hi != eui.hi ||
690 fwip->last_dest.lo != eui.lo) {
691 fd = fw_noderesolve_eui64(fc, &eui);
692 if (!fd) {
693 /* error */
694 ifp->if_oerrors ++;
695 /* XXX set error code */
696 fwip_output_callback(xfer);
697 continue;
698
699 }
700 fwip->last_hdr.mode.wreqb.dst = FWLOCALBUS | fd->dst;
701 fwip->last_hdr.mode.wreqb.tlrt = 0;
702 fwip->last_hdr.mode.wreqb.tcode = FWTCODE_WREQB;
703 fwip->last_hdr.mode.wreqb.pri = 0;
704 fwip->last_hdr.mode.wreqb.src = nodeid;
705 fwip->last_hdr.mode.wreqb.dest_hi =
706 ntohs(destfw->sender_unicast_FIFO_hi);
707 fwip->last_hdr.mode.wreqb.dest_lo =
708 ntohl(destfw->sender_unicast_FIFO_lo);
709 fwip->last_hdr.mode.wreqb.extcode = 0;
710 fwip->last_dest = eui;
711 }
712
713 fp->mode.wreqb = fwip->last_hdr.mode.wreqb;
714 fp->mode.wreqb.len = m->m_pkthdr.len;
715 xfer->send.spd = min(destfw->sspd, fc->speed);
716 }
717
718 xfer->send.pay_len = m->m_pkthdr.len;
719
720 error = fw_asyreq(fc, -1, xfer);
721 if (error == EAGAIN) {
722 /*
723 * We ran out of tlabels - requeue the packet
724 * for later transmission.
725 */
726 xfer->mbuf = 0;
727 STAILQ_INSERT_TAIL(&fwip->xferlist, xfer, link);
728 IF_PREPEND(&ifp->if_snd, m);
729 break;
730 }
731 if (error) {
732 /* error */
733 ifp->if_oerrors ++;
734 /* XXX set error code */
735 fwip_output_callback(xfer);
736 continue;
737 } else {
738 ifp->if_opackets ++;
739 i++;
740 }
741 }
742#if 0
743 if (i > 1)
744 printf("%d queued\n", i);
745#endif
746 if (i > 0) {
747#if 1
748 xferq->start(fc);
749#else
750 taskqueue_enqueue(taskqueue_swi_giant, &fwip->start_send);
751#endif
752 }
753}
754
755static void
756fwip_start_send (void *arg, int count)
757{
758 struct fwip_softc *fwip = arg;
759
760 GIANT_REQUIRED;
761 fwip->fd.fc->atq->start(fwip->fd.fc);
762}
763
764/* Async. stream output */
765static void
766fwip_stream_input(struct fw_xferq *xferq)
767{
768 struct mbuf *m, *m0;
769 struct m_tag *mtag;
770 struct ifnet *ifp;
771 struct fwip_softc *fwip;
772 struct fw_bulkxfer *sxfer;
773 struct fw_pkt *fp;
774 uint16_t src;
775 uint32_t *p;
776
777 GIANT_REQUIRED;
778
779 fwip = (struct fwip_softc *)xferq->sc;
780 ifp = fwip->fw_softc.fwip_ifp;
781
782 while ((sxfer = STAILQ_FIRST(&xferq->stvalid)) != NULL) {
783 STAILQ_REMOVE_HEAD(&xferq->stvalid, link);
784 fp = mtod(sxfer->mbuf, struct fw_pkt *);
785 if (fwip->fd.fc->irx_post != NULL)
786 fwip->fd.fc->irx_post(fwip->fd.fc, fp->mode.ld);
787 m = sxfer->mbuf;
788
789 /* insert new rbuf */
790 sxfer->mbuf = m0 = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
791 if (m0 != NULL) {
792 m0->m_len = m0->m_pkthdr.len = m0->m_ext.ext_size;
793 STAILQ_INSERT_TAIL(&xferq->stfree, sxfer, link);
794 } else
795 printf("fwip_as_input: m_getcl failed\n");
796
797 /*
798 * We must have a GASP header - leave the
799 * encapsulation sanity checks to the generic
800 * code. Remeber that we also have the firewire async
801 * stream header even though that isn't accounted for
802 * in mode.stream.len.
803 */
804 if (sxfer->resp != 0 || fp->mode.stream.len <
805 2*sizeof(uint32_t)) {
806 m_freem(m);
807 ifp->if_ierrors ++;
808 continue;
809 }
810 m->m_len = m->m_pkthdr.len = fp->mode.stream.len
811 + sizeof(fp->mode.stream);
812
813 /*
814 * If we received the packet on the broadcast channel,
815 * mark it as broadcast, otherwise we assume it must
816 * be multicast.
817 */
818 if (fp->mode.stream.chtag == broadcast_channel)
819 m->m_flags |= M_BCAST;
820 else
821 m->m_flags |= M_MCAST;
822
823 /*
824 * Make sure we recognise the GASP specifier and
825 * version.
826 */
827 p = mtod(m, uint32_t *);
828 if ((((ntohl(p[1]) & 0xffff) << 8) | ntohl(p[2]) >> 24) != 0x00005e
829 || (ntohl(p[2]) & 0xffffff) != 1) {
830 FWIPDEBUG(ifp, "Unrecognised GASP header %#08x %#08x\n",
831 ntohl(p[1]), ntohl(p[2]));
832 m_freem(m);
833 ifp->if_ierrors ++;
834 continue;
835 }
836
837 /*
838 * Record the sender ID for possible BPF usage.
839 */
840 src = ntohl(p[1]) >> 16;
841 if (bpf_peers_present(ifp->if_bpf)) {
842 mtag = m_tag_alloc(MTAG_FIREWIRE,
843 MTAG_FIREWIRE_SENDER_EUID,
844 2*sizeof(uint32_t), M_NOWAIT);
845 if (mtag) {
846 /* bpf wants it in network byte order */
847 struct fw_device *fd;
848 uint32_t *p = (uint32_t *) (mtag + 1);
849 fd = fw_noderesolve_nodeid(fwip->fd.fc,
850 src & 0x3f);
851 if (fd) {
852 p[0] = htonl(fd->eui.hi);
853 p[1] = htonl(fd->eui.lo);
854 } else {
855 p[0] = 0;
856 p[1] = 0;
857 }
858 m_tag_prepend(m, mtag);
859 }
860 }
861
862 /*
863 * Trim off the GASP header
864 */
865 m_adj(m, 3*sizeof(uint32_t));
866 m->m_pkthdr.rcvif = ifp;
867 firewire_input(ifp, m, src);
868 ifp->if_ipackets ++;
869 }
870 if (STAILQ_FIRST(&xferq->stfree) != NULL)
871 fwip->fd.fc->irx_enable(fwip->fd.fc, fwip->dma_ch);
872}
873
874static __inline void
875fwip_unicast_input_recycle(struct fwip_softc *fwip, struct fw_xfer *xfer)
876{
877 struct mbuf *m;
878
879 GIANT_REQUIRED;
880
881 /*
882 * We have finished with a unicast xfer. Allocate a new
883 * cluster and stick it on the back of the input queue.
884 */
885 m = m_getcl(M_TRYWAIT, MT_DATA, M_PKTHDR);
886 xfer->mbuf = m;
887 xfer->recv.payload = mtod(m, uint32_t *);
888 xfer->recv.pay_len = MCLBYTES;
889 xfer->mbuf = m;
890 STAILQ_INSERT_TAIL(&fwip->fwb.xferlist, xfer, link);
891}
892
893static void
894fwip_unicast_input(struct fw_xfer *xfer)
895{
896 uint64_t address;
897 struct mbuf *m;
898 struct m_tag *mtag;
899 struct ifnet *ifp;
900 struct fwip_softc *fwip;
901 struct fw_pkt *fp;
902 //struct fw_pkt *sfp;
903 int rtcode;
904
905 GIANT_REQUIRED;
906
907 fwip = (struct fwip_softc *)xfer->sc;
908 ifp = fwip->fw_softc.fwip_ifp;
909 m = xfer->mbuf;
910 xfer->mbuf = 0;
911 fp = &xfer->recv.hdr;
912
913 /*
914 * Check the fifo address - we only accept addresses of
915 * exactly INET_FIFO.
916 */
917 address = ((uint64_t)fp->mode.wreqb.dest_hi << 32)
918 | fp->mode.wreqb.dest_lo;
919 if (fp->mode.wreqb.tcode != FWTCODE_WREQB) {
920 rtcode = FWRCODE_ER_TYPE;
921 } else if (address != INET_FIFO) {
922 rtcode = FWRCODE_ER_ADDR;
923 } else {
924 rtcode = FWRCODE_COMPLETE;
925 }
926
927 /*
928 * Pick up a new mbuf and stick it on the back of the receive
929 * queue.
930 */
931 fwip_unicast_input_recycle(fwip, xfer);
932
933 /*
934 * If we've already rejected the packet, give up now.
935 */
936 if (rtcode != FWRCODE_COMPLETE) {
937 m_freem(m);
938 ifp->if_ierrors ++;
939 return;
940 }
941
942 if (bpf_peers_present(ifp->if_bpf)) {
943 /*
944 * Record the sender ID for possible BPF usage.
945 */
946 mtag = m_tag_alloc(MTAG_FIREWIRE, MTAG_FIREWIRE_SENDER_EUID,
947 2*sizeof(uint32_t), M_NOWAIT);
948 if (mtag) {
949 /* bpf wants it in network byte order */
950 struct fw_device *fd;
951 uint32_t *p = (uint32_t *) (mtag + 1);
952 fd = fw_noderesolve_nodeid(fwip->fd.fc,
953 fp->mode.wreqb.src & 0x3f);
954 if (fd) {
955 p[0] = htonl(fd->eui.hi);
956 p[1] = htonl(fd->eui.lo);
957 } else {
958 p[0] = 0;
959 p[1] = 0;
960 }
961 m_tag_prepend(m, mtag);
962 }
963 }
964
965 /*
966 * Hand off to the generic encapsulation code. We don't use
967 * ifp->if_input so that we can pass the source nodeid as an
968 * argument to facilitate link-level fragment reassembly.
969 */
970 m->m_len = m->m_pkthdr.len = fp->mode.wreqb.len;
971 m->m_pkthdr.rcvif = ifp;
972 firewire_input(ifp, m, fp->mode.wreqb.src);
973 ifp->if_ipackets ++;
974}
975
976static devclass_t fwip_devclass;
977
978static device_method_t fwip_methods[] = {
979 /* device interface */
980 DEVMETHOD(device_identify, fwip_identify),
981 DEVMETHOD(device_probe, fwip_probe),
982 DEVMETHOD(device_attach, fwip_attach),
983 DEVMETHOD(device_detach, fwip_detach),
984 { 0, 0 }
985};
986
987static driver_t fwip_driver = {
988 "fwip",
989 fwip_methods,
990 sizeof(struct fwip_softc),
991};
992
993
994#ifdef __DragonFly__
995DECLARE_DUMMY_MODULE(fwip);
996#endif
997DRIVER_MODULE(fwip, firewire, fwip_driver, fwip_devclass, 0, 0);
998MODULE_VERSION(fwip, 1);
999MODULE_DEPEND(fwip, firewire, 1, 1, 1);
383 xfer->sc = (caddr_t)fwip;
384 xfer->act.hand = fwip_output_callback;
385 STAILQ_INSERT_TAIL(&fwip->xferlist, xfer, link);
386 }
387 } else
388 xferq = fc->ir[fwip->dma_ch];
389
390 fwip->last_dest.hi = 0;
391 fwip->last_dest.lo = 0;
392
393 /* start dma */
394 if ((xferq->flag & FWXFERQ_RUNNING) == 0)
395 fc->irx_enable(fc, fwip->dma_ch);
396
397#if defined(__FreeBSD__)
398 ifp->if_drv_flags |= IFF_DRV_RUNNING;
399 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
400#else
401 ifp->if_flags |= IFF_RUNNING;
402 ifp->if_flags &= ~IFF_OACTIVE;
403#endif
404
405#if 0
406 /* attempt to start output */
407 fwip_start(ifp);
408#endif
409}
410
411static int
412fwip_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
413{
414 struct fwip_softc *fwip = ((struct fwip_eth_softc *)ifp->if_softc)->fwip;
415 int s, error;
416
417 switch (cmd) {
418 case SIOCSIFFLAGS:
419 s = splimp();
420 if (ifp->if_flags & IFF_UP) {
421#if defined(__FreeBSD__)
422 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
423#else
424 if (!(ifp->if_flags & IFF_RUNNING))
425#endif
426 fwip_init(&fwip->fw_softc);
427 } else {
428#if defined(__FreeBSD__)
429 if (ifp->if_drv_flags & IFF_DRV_RUNNING)
430#else
431 if (ifp->if_flags & IFF_RUNNING)
432#endif
433 fwip_stop(fwip);
434 }
435 splx(s);
436 break;
437 case SIOCADDMULTI:
438 case SIOCDELMULTI:
439 break;
440 case SIOCSIFCAP:
441#ifdef DEVICE_POLLING
442 {
443 struct ifreq *ifr = (struct ifreq *) data;
444 struct firewire_comm *fc = fc = fwip->fd.fc;
445
446 if (ifr->ifr_reqcap & IFCAP_POLLING &&
447 !(ifp->if_capenable & IFCAP_POLLING)) {
448 error = ether_poll_register(fwip_poll, ifp);
449 if (error)
450 return(error);
451 /* Disable interrupts */
452 fc->set_intr(fc, 0);
453 ifp->if_capenable |= IFCAP_POLLING;
454 return (error);
455
456 }
457 if (!(ifr->ifr_reqcap & IFCAP_POLLING) &&
458 ifp->if_capenable & IFCAP_POLLING) {
459 error = ether_poll_deregister(ifp);
460 /* Enable interrupts. */
461 fc->set_intr(fc, 1);
462 ifp->if_capenable &= ~IFCAP_POLLING;
463 return (error);
464 }
465 }
466#endif /* DEVICE_POLLING */
467 break;
468#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
469 default:
470#else
471 case SIOCSIFADDR:
472 case SIOCGIFADDR:
473 case SIOCSIFMTU:
474#endif
475 s = splimp();
476 error = firewire_ioctl(ifp, cmd, data);
477 splx(s);
478 return (error);
479#if defined(__DragonFly__) || __FreeBSD_version < 500000
480 default:
481 return (EINVAL);
482#endif
483 }
484
485 return (0);
486}
487
488static void
489fwip_post_busreset(void *arg)
490{
491 struct fwip_softc *fwip = arg;
492 struct crom_src *src;
493 struct crom_chunk *root;
494
495 src = fwip->fd.fc->crom_src;
496 root = fwip->fd.fc->crom_root;
497
498 /* RFC2734 IPv4 over IEEE1394 */
499 bzero(&fwip->unit4, sizeof(struct crom_chunk));
500 crom_add_chunk(src, root, &fwip->unit4, CROM_UDIR);
501 crom_add_entry(&fwip->unit4, CSRKEY_SPEC, CSRVAL_IETF);
502 crom_add_simple_text(src, &fwip->unit4, &fwip->spec4, "IANA");
503 crom_add_entry(&fwip->unit4, CSRKEY_VER, 1);
504 crom_add_simple_text(src, &fwip->unit4, &fwip->ver4, "IPv4");
505
506 /* RFC3146 IPv6 over IEEE1394 */
507 bzero(&fwip->unit6, sizeof(struct crom_chunk));
508 crom_add_chunk(src, root, &fwip->unit6, CROM_UDIR);
509 crom_add_entry(&fwip->unit6, CSRKEY_SPEC, CSRVAL_IETF);
510 crom_add_simple_text(src, &fwip->unit6, &fwip->spec6, "IANA");
511 crom_add_entry(&fwip->unit6, CSRKEY_VER, 2);
512 crom_add_simple_text(src, &fwip->unit6, &fwip->ver6, "IPv6");
513
514 fwip->last_dest.hi = 0;
515 fwip->last_dest.lo = 0;
516 firewire_busreset(fwip->fw_softc.fwip_ifp);
517}
518
519static void
520fwip_output_callback(struct fw_xfer *xfer)
521{
522 struct fwip_softc *fwip;
523 struct ifnet *ifp;
524 int s;
525
526 GIANT_REQUIRED;
527
528 fwip = (struct fwip_softc *)xfer->sc;
529 ifp = fwip->fw_softc.fwip_ifp;
530 /* XXX error check */
531 FWIPDEBUG(ifp, "resp = %d\n", xfer->resp);
532 if (xfer->resp != 0)
533 ifp->if_oerrors ++;
534
535 m_freem(xfer->mbuf);
536 fw_xfer_unload(xfer);
537
538 s = splimp();
539 STAILQ_INSERT_TAIL(&fwip->xferlist, xfer, link);
540 splx(s);
541
542 /* for queue full */
543 if (ifp->if_snd.ifq_head != NULL)
544 fwip_start(ifp);
545}
546
547static void
548fwip_start(struct ifnet *ifp)
549{
550 struct fwip_softc *fwip = ((struct fwip_eth_softc *)ifp->if_softc)->fwip;
551 int s;
552
553 GIANT_REQUIRED;
554
555 FWIPDEBUG(ifp, "starting\n");
556
557 if (fwip->dma_ch < 0) {
558 struct mbuf *m = NULL;
559
560 FWIPDEBUG(ifp, "not ready\n");
561
562 s = splimp();
563 do {
564 IF_DEQUEUE(&ifp->if_snd, m);
565 if (m != NULL)
566 m_freem(m);
567 ifp->if_oerrors ++;
568 } while (m != NULL);
569 splx(s);
570
571 return;
572 }
573
574 s = splimp();
575#if defined(__FreeBSD__)
576 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
577#else
578 ifp->if_flags |= IFF_OACTIVE;
579#endif
580
581 if (ifp->if_snd.ifq_len != 0)
582 fwip_async_output(fwip, ifp);
583
584#if defined(__FreeBSD__)
585 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
586#else
587 ifp->if_flags &= ~IFF_OACTIVE;
588#endif
589 splx(s);
590}
591
592/* Async. stream output */
593static void
594fwip_async_output(struct fwip_softc *fwip, struct ifnet *ifp)
595{
596 struct firewire_comm *fc = fwip->fd.fc;
597 struct mbuf *m;
598 struct m_tag *mtag;
599 struct fw_hwaddr *destfw;
600 struct fw_xfer *xfer;
601 struct fw_xferq *xferq;
602 struct fw_pkt *fp;
603 uint16_t nodeid;
604 int error;
605 int i = 0;
606
607 GIANT_REQUIRED;
608
609 xfer = NULL;
610 xferq = fwip->fd.fc->atq;
611 while (xferq->queued < xferq->maxq - 1) {
612 xfer = STAILQ_FIRST(&fwip->xferlist);
613 if (xfer == NULL) {
614 printf("if_fwip: lack of xfer\n");
615 return;
616 }
617 IF_DEQUEUE(&ifp->if_snd, m);
618 if (m == NULL)
619 break;
620
621 /*
622 * Dig out the link-level address which
623 * firewire_output got via arp or neighbour
624 * discovery. If we don't have a link-level address,
625 * just stick the thing on the broadcast channel.
626 */
627 mtag = m_tag_locate(m, MTAG_FIREWIRE, MTAG_FIREWIRE_HWADDR, 0);
628 if (mtag == NULL)
629 destfw = 0;
630 else
631 destfw = (struct fw_hwaddr *) (mtag + 1);
632
633 STAILQ_REMOVE_HEAD(&fwip->xferlist, link);
634
635 /*
636 * We don't do any bpf stuff here - the generic code
637 * in firewire_output gives the packet to bpf before
638 * it adds the link-level encapsulation.
639 */
640
641 /*
642 * Put the mbuf in the xfer early in case we hit an
643 * error case below - fwip_output_callback will free
644 * the mbuf.
645 */
646 xfer->mbuf = m;
647
648 /*
649 * We use the arp result (if any) to add a suitable firewire
650 * packet header before handing off to the bus.
651 */
652 fp = &xfer->send.hdr;
653 nodeid = FWLOCALBUS | fc->nodeid;
654 if ((m->m_flags & M_BCAST) || !destfw) {
655 /*
656 * Broadcast packets are sent as GASP packets with
657 * specifier ID 0x00005e, version 1 on the broadcast
658 * channel. To be conservative, we send at the
659 * slowest possible speed.
660 */
661 uint32_t *p;
662
663 M_PREPEND(m, 2*sizeof(uint32_t), M_DONTWAIT);
664 p = mtod(m, uint32_t *);
665 fp->mode.stream.len = m->m_pkthdr.len;
666 fp->mode.stream.chtag = broadcast_channel;
667 fp->mode.stream.tcode = FWTCODE_STREAM;
668 fp->mode.stream.sy = 0;
669 xfer->send.spd = 0;
670 p[0] = htonl(nodeid << 16);
671 p[1] = htonl((0x5e << 24) | 1);
672 } else {
673 /*
674 * Unicast packets are sent as block writes to the
675 * target's unicast fifo address. If we can't
676 * find the node address, we just give up. We
677 * could broadcast it but that might overflow
678 * the packet size limitations due to the
679 * extra GASP header. Note: the hardware
680 * address is stored in network byte order to
681 * make life easier for ARP.
682 */
683 struct fw_device *fd;
684 struct fw_eui64 eui;
685
686 eui.hi = ntohl(destfw->sender_unique_ID_hi);
687 eui.lo = ntohl(destfw->sender_unique_ID_lo);
688 if (fwip->last_dest.hi != eui.hi ||
689 fwip->last_dest.lo != eui.lo) {
690 fd = fw_noderesolve_eui64(fc, &eui);
691 if (!fd) {
692 /* error */
693 ifp->if_oerrors ++;
694 /* XXX set error code */
695 fwip_output_callback(xfer);
696 continue;
697
698 }
699 fwip->last_hdr.mode.wreqb.dst = FWLOCALBUS | fd->dst;
700 fwip->last_hdr.mode.wreqb.tlrt = 0;
701 fwip->last_hdr.mode.wreqb.tcode = FWTCODE_WREQB;
702 fwip->last_hdr.mode.wreqb.pri = 0;
703 fwip->last_hdr.mode.wreqb.src = nodeid;
704 fwip->last_hdr.mode.wreqb.dest_hi =
705 ntohs(destfw->sender_unicast_FIFO_hi);
706 fwip->last_hdr.mode.wreqb.dest_lo =
707 ntohl(destfw->sender_unicast_FIFO_lo);
708 fwip->last_hdr.mode.wreqb.extcode = 0;
709 fwip->last_dest = eui;
710 }
711
712 fp->mode.wreqb = fwip->last_hdr.mode.wreqb;
713 fp->mode.wreqb.len = m->m_pkthdr.len;
714 xfer->send.spd = min(destfw->sspd, fc->speed);
715 }
716
717 xfer->send.pay_len = m->m_pkthdr.len;
718
719 error = fw_asyreq(fc, -1, xfer);
720 if (error == EAGAIN) {
721 /*
722 * We ran out of tlabels - requeue the packet
723 * for later transmission.
724 */
725 xfer->mbuf = 0;
726 STAILQ_INSERT_TAIL(&fwip->xferlist, xfer, link);
727 IF_PREPEND(&ifp->if_snd, m);
728 break;
729 }
730 if (error) {
731 /* error */
732 ifp->if_oerrors ++;
733 /* XXX set error code */
734 fwip_output_callback(xfer);
735 continue;
736 } else {
737 ifp->if_opackets ++;
738 i++;
739 }
740 }
741#if 0
742 if (i > 1)
743 printf("%d queued\n", i);
744#endif
745 if (i > 0) {
746#if 1
747 xferq->start(fc);
748#else
749 taskqueue_enqueue(taskqueue_swi_giant, &fwip->start_send);
750#endif
751 }
752}
753
754static void
755fwip_start_send (void *arg, int count)
756{
757 struct fwip_softc *fwip = arg;
758
759 GIANT_REQUIRED;
760 fwip->fd.fc->atq->start(fwip->fd.fc);
761}
762
763/* Async. stream output */
764static void
765fwip_stream_input(struct fw_xferq *xferq)
766{
767 struct mbuf *m, *m0;
768 struct m_tag *mtag;
769 struct ifnet *ifp;
770 struct fwip_softc *fwip;
771 struct fw_bulkxfer *sxfer;
772 struct fw_pkt *fp;
773 uint16_t src;
774 uint32_t *p;
775
776 GIANT_REQUIRED;
777
778 fwip = (struct fwip_softc *)xferq->sc;
779 ifp = fwip->fw_softc.fwip_ifp;
780
781 while ((sxfer = STAILQ_FIRST(&xferq->stvalid)) != NULL) {
782 STAILQ_REMOVE_HEAD(&xferq->stvalid, link);
783 fp = mtod(sxfer->mbuf, struct fw_pkt *);
784 if (fwip->fd.fc->irx_post != NULL)
785 fwip->fd.fc->irx_post(fwip->fd.fc, fp->mode.ld);
786 m = sxfer->mbuf;
787
788 /* insert new rbuf */
789 sxfer->mbuf = m0 = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
790 if (m0 != NULL) {
791 m0->m_len = m0->m_pkthdr.len = m0->m_ext.ext_size;
792 STAILQ_INSERT_TAIL(&xferq->stfree, sxfer, link);
793 } else
794 printf("fwip_as_input: m_getcl failed\n");
795
796 /*
797 * We must have a GASP header - leave the
798 * encapsulation sanity checks to the generic
799 * code. Remeber that we also have the firewire async
800 * stream header even though that isn't accounted for
801 * in mode.stream.len.
802 */
803 if (sxfer->resp != 0 || fp->mode.stream.len <
804 2*sizeof(uint32_t)) {
805 m_freem(m);
806 ifp->if_ierrors ++;
807 continue;
808 }
809 m->m_len = m->m_pkthdr.len = fp->mode.stream.len
810 + sizeof(fp->mode.stream);
811
812 /*
813 * If we received the packet on the broadcast channel,
814 * mark it as broadcast, otherwise we assume it must
815 * be multicast.
816 */
817 if (fp->mode.stream.chtag == broadcast_channel)
818 m->m_flags |= M_BCAST;
819 else
820 m->m_flags |= M_MCAST;
821
822 /*
823 * Make sure we recognise the GASP specifier and
824 * version.
825 */
826 p = mtod(m, uint32_t *);
827 if ((((ntohl(p[1]) & 0xffff) << 8) | ntohl(p[2]) >> 24) != 0x00005e
828 || (ntohl(p[2]) & 0xffffff) != 1) {
829 FWIPDEBUG(ifp, "Unrecognised GASP header %#08x %#08x\n",
830 ntohl(p[1]), ntohl(p[2]));
831 m_freem(m);
832 ifp->if_ierrors ++;
833 continue;
834 }
835
836 /*
837 * Record the sender ID for possible BPF usage.
838 */
839 src = ntohl(p[1]) >> 16;
840 if (bpf_peers_present(ifp->if_bpf)) {
841 mtag = m_tag_alloc(MTAG_FIREWIRE,
842 MTAG_FIREWIRE_SENDER_EUID,
843 2*sizeof(uint32_t), M_NOWAIT);
844 if (mtag) {
845 /* bpf wants it in network byte order */
846 struct fw_device *fd;
847 uint32_t *p = (uint32_t *) (mtag + 1);
848 fd = fw_noderesolve_nodeid(fwip->fd.fc,
849 src & 0x3f);
850 if (fd) {
851 p[0] = htonl(fd->eui.hi);
852 p[1] = htonl(fd->eui.lo);
853 } else {
854 p[0] = 0;
855 p[1] = 0;
856 }
857 m_tag_prepend(m, mtag);
858 }
859 }
860
861 /*
862 * Trim off the GASP header
863 */
864 m_adj(m, 3*sizeof(uint32_t));
865 m->m_pkthdr.rcvif = ifp;
866 firewire_input(ifp, m, src);
867 ifp->if_ipackets ++;
868 }
869 if (STAILQ_FIRST(&xferq->stfree) != NULL)
870 fwip->fd.fc->irx_enable(fwip->fd.fc, fwip->dma_ch);
871}
872
873static __inline void
874fwip_unicast_input_recycle(struct fwip_softc *fwip, struct fw_xfer *xfer)
875{
876 struct mbuf *m;
877
878 GIANT_REQUIRED;
879
880 /*
881 * We have finished with a unicast xfer. Allocate a new
882 * cluster and stick it on the back of the input queue.
883 */
884 m = m_getcl(M_TRYWAIT, MT_DATA, M_PKTHDR);
885 xfer->mbuf = m;
886 xfer->recv.payload = mtod(m, uint32_t *);
887 xfer->recv.pay_len = MCLBYTES;
888 xfer->mbuf = m;
889 STAILQ_INSERT_TAIL(&fwip->fwb.xferlist, xfer, link);
890}
891
892static void
893fwip_unicast_input(struct fw_xfer *xfer)
894{
895 uint64_t address;
896 struct mbuf *m;
897 struct m_tag *mtag;
898 struct ifnet *ifp;
899 struct fwip_softc *fwip;
900 struct fw_pkt *fp;
901 //struct fw_pkt *sfp;
902 int rtcode;
903
904 GIANT_REQUIRED;
905
906 fwip = (struct fwip_softc *)xfer->sc;
907 ifp = fwip->fw_softc.fwip_ifp;
908 m = xfer->mbuf;
909 xfer->mbuf = 0;
910 fp = &xfer->recv.hdr;
911
912 /*
913 * Check the fifo address - we only accept addresses of
914 * exactly INET_FIFO.
915 */
916 address = ((uint64_t)fp->mode.wreqb.dest_hi << 32)
917 | fp->mode.wreqb.dest_lo;
918 if (fp->mode.wreqb.tcode != FWTCODE_WREQB) {
919 rtcode = FWRCODE_ER_TYPE;
920 } else if (address != INET_FIFO) {
921 rtcode = FWRCODE_ER_ADDR;
922 } else {
923 rtcode = FWRCODE_COMPLETE;
924 }
925
926 /*
927 * Pick up a new mbuf and stick it on the back of the receive
928 * queue.
929 */
930 fwip_unicast_input_recycle(fwip, xfer);
931
932 /*
933 * If we've already rejected the packet, give up now.
934 */
935 if (rtcode != FWRCODE_COMPLETE) {
936 m_freem(m);
937 ifp->if_ierrors ++;
938 return;
939 }
940
941 if (bpf_peers_present(ifp->if_bpf)) {
942 /*
943 * Record the sender ID for possible BPF usage.
944 */
945 mtag = m_tag_alloc(MTAG_FIREWIRE, MTAG_FIREWIRE_SENDER_EUID,
946 2*sizeof(uint32_t), M_NOWAIT);
947 if (mtag) {
948 /* bpf wants it in network byte order */
949 struct fw_device *fd;
950 uint32_t *p = (uint32_t *) (mtag + 1);
951 fd = fw_noderesolve_nodeid(fwip->fd.fc,
952 fp->mode.wreqb.src & 0x3f);
953 if (fd) {
954 p[0] = htonl(fd->eui.hi);
955 p[1] = htonl(fd->eui.lo);
956 } else {
957 p[0] = 0;
958 p[1] = 0;
959 }
960 m_tag_prepend(m, mtag);
961 }
962 }
963
964 /*
965 * Hand off to the generic encapsulation code. We don't use
966 * ifp->if_input so that we can pass the source nodeid as an
967 * argument to facilitate link-level fragment reassembly.
968 */
969 m->m_len = m->m_pkthdr.len = fp->mode.wreqb.len;
970 m->m_pkthdr.rcvif = ifp;
971 firewire_input(ifp, m, fp->mode.wreqb.src);
972 ifp->if_ipackets ++;
973}
974
975static devclass_t fwip_devclass;
976
977static device_method_t fwip_methods[] = {
978 /* device interface */
979 DEVMETHOD(device_identify, fwip_identify),
980 DEVMETHOD(device_probe, fwip_probe),
981 DEVMETHOD(device_attach, fwip_attach),
982 DEVMETHOD(device_detach, fwip_detach),
983 { 0, 0 }
984};
985
986static driver_t fwip_driver = {
987 "fwip",
988 fwip_methods,
989 sizeof(struct fwip_softc),
990};
991
992
993#ifdef __DragonFly__
994DECLARE_DUMMY_MODULE(fwip);
995#endif
996DRIVER_MODULE(fwip, firewire, fwip_driver, fwip_devclass, 0, 0);
997MODULE_VERSION(fwip, 1);
998MODULE_DEPEND(fwip, firewire, 1, 1, 1);