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