firewire.c revision 110016
1/*
2 * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the acknowledgement as bellow:
15 *
16 *    This product includes software developed by K. Kobayashi and H. Shimokawa
17 *
18 * 4. The name of the author may not be used to endorse or promote products
19 *    derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 *
33 * $FreeBSD: head/sys/dev/firewire/firewire.c 110016 2003-01-29 02:13:31Z simokawa $
34 *
35 */
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/types.h>
40#include <sys/mbuf.h>
41#include <sys/socket.h>
42#include <sys/socketvar.h>
43
44#include <sys/kernel.h>
45#include <sys/malloc.h>
46#include <sys/conf.h>
47#include <sys/uio.h>
48#include <sys/sysctl.h>
49
50#include <machine/cpufunc.h>    /* for rdtsc proto for clock.h below */
51#include <machine/clock.h>
52
53#include <sys/bus.h>		/* used by smbus and newbus */
54
55#include <dev/firewire/firewire.h>
56#include <dev/firewire/firewirereg.h>
57#include <dev/firewire/iec13213.h>
58#include <dev/firewire/iec68113.h>
59
60int firewire_debug=0, try_bmr=1;
61SYSCTL_INT(_debug, OID_AUTO, firewire_debug, CTLFLAG_RW, &firewire_debug, 0,
62	"FireWire driver debug flag");
63SYSCTL_NODE(_hw, OID_AUTO, firewire, CTLFLAG_RD, 0, "FireWire Subsystem");
64SYSCTL_INT(_hw_firewire, OID_AUTO, try_bmr, CTLFLAG_RW, &try_bmr, 0,
65	"Try to be a bus manager");
66
67#define FW_MAXASYRTY 4
68#define FW_MAXDEVRCNT 4
69
70#define XFER_TIMEOUT 0
71
72devclass_t firewire_devclass;
73
74static int firewire_match      __P((device_t));
75static int firewire_attach      __P((device_t));
76static int firewire_detach      __P((device_t));
77#if 0
78static int firewire_shutdown    __P((device_t));
79#endif
80static device_t firewire_add_child   __P((device_t, int, const char *, int));
81static void fw_try_bmr __P((void *));
82static void fw_try_bmr_callback __P((struct fw_xfer *));
83static void fw_asystart __P((struct fw_xfer *));
84static int fw_get_tlabel __P((struct firewire_comm *, struct fw_xfer *));
85static void fw_bus_probe __P((struct firewire_comm *));
86static void fw_bus_explore __P((struct firewire_comm *));
87static void fw_bus_explore_callback __P((struct fw_xfer *));
88static void fw_attach_dev __P((struct firewire_comm *));
89#ifdef FW_VMACCESS
90static void fw_vmaccess __P((struct fw_xfer *));
91#endif
92struct fw_xfer *asyreqq __P((struct firewire_comm *, u_int8_t, u_int8_t, u_int8_t,
93	u_int32_t, u_int32_t, void (*)__P((struct fw_xfer *))));
94
95static device_method_t firewire_methods[] = {
96	/* Device interface */
97	DEVMETHOD(device_probe,		firewire_match),
98	DEVMETHOD(device_attach,	firewire_attach),
99	DEVMETHOD(device_detach,	firewire_detach),
100	DEVMETHOD(device_suspend,	bus_generic_suspend),
101	DEVMETHOD(device_resume,	bus_generic_resume),
102	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
103
104	/* Bus interface */
105	DEVMETHOD(bus_add_child,	firewire_add_child),
106	DEVMETHOD(bus_print_child,	bus_generic_print_child),
107
108	{ 0, 0 }
109};
110char linkspeed[7][0x10]={"S100","S200","S400","S800","S1600","S3200","Unknown"};
111
112#define MAX_GAPHOP  16
113u_int gap_cnt[] = {1, 1, 4, 6, 9, 12, 14, 17,
114			20, 23, 25, 28, 31, 33, 36, 39, 42};
115
116extern struct cdevsw firewire_cdevsw;
117
118static driver_t firewire_driver = {
119	"firewire",
120	firewire_methods,
121	sizeof(struct firewire_softc),
122};
123
124/*
125 * To lookup node id. from EUI64.
126 */
127struct fw_device *
128fw_noderesolve(struct firewire_comm *fc, struct fw_eui64 eui)
129{
130	struct fw_device *fwdev;
131	for(fwdev = TAILQ_FIRST(&fc->devices); fwdev != NULL;
132		fwdev = TAILQ_NEXT(fwdev, link)){
133		if(fwdev->eui.hi == eui.hi && fwdev->eui.lo == eui.lo){
134			break;
135		}
136	}
137	if(fwdev == NULL) return NULL;
138	if(fwdev->status == FWDEVINVAL) return NULL;
139	return fwdev;
140}
141
142/*
143 * Async. request procedure for userland application.
144 */
145int
146fw_asyreq(struct firewire_comm *fc, int sub, struct fw_xfer *xfer)
147{
148	int err = 0;
149	struct fw_xferq *xferq;
150	int tl = 0, len;
151	struct fw_pkt *fp;
152	int tcode;
153	struct tcode_info *info;
154
155	if(xfer == NULL) return EINVAL;
156	if(xfer->send.len > MAXREC(fc->maxrec)){
157		printf("send.len > maxrec\n");
158		return EINVAL;
159	}
160	if(xfer->act.hand == NULL){
161		printf("act.hand == NULL\n");
162		return EINVAL;
163	}
164	fp = (struct fw_pkt *)xfer->send.buf;
165
166	tcode = fp->mode.common.tcode & 0xf;
167	info = &fc->tcode[tcode];
168	if (info->flag == 0) {
169		printf("invalid tcode=%d\n", tcode);
170		return EINVAL;
171	}
172	if (info->flag & FWTI_REQ)
173		xferq = fc->atq;
174	else
175		xferq = fc->ats;
176	len = info->hdr_len;
177	if (info->flag & FWTI_BLOCK_STR)
178		len += ntohs(fp->mode.stream.len);
179	else if (info->flag & FWTI_BLOCK_ASY)
180		len += ntohs(fp->mode.rresb.len);
181	if( len >  xfer->send.len ){
182		printf("len(%d) > send.len(%d) (tcode=%d)\n",
183				len, xfer->send.len, tcode);
184		return EINVAL;
185	}
186	xfer->send.len = len;
187
188	if(xferq->start == NULL){
189		printf("xferq->start == NULL\n");
190		return EINVAL;
191	}
192	if(!(xferq->queued < xferq->maxq)){
193		device_printf(fc->bdev, "Discard a packet (queued=%d)\n",
194			xferq->queued);
195		return EINVAL;
196	}
197
198
199	if (info->flag & FWTI_TLABEL) {
200		if((tl = fw_get_tlabel(fc, xfer)) == -1 )
201			return EIO;
202		fp->mode.hdr.tlrt = tl << 2;
203	}
204
205	xfer->tl = tl;
206	xfer->tcode = tcode;
207	xfer->resp = 0;
208	xfer->fc = fc;
209	xfer->q = xferq;
210	xfer->act_type = FWACT_XFER;
211	xfer->retry_req = fw_asybusy;
212
213	fw_asystart(xfer);
214	return err;
215}
216/*
217 * Wakeup blocked process.
218 */
219void
220fw_asy_callback(struct fw_xfer *xfer){
221	wakeup(xfer);
222	return;
223}
224/*
225 * Postpone to later retry.
226 */
227void fw_asybusy(struct fw_xfer *xfer){
228#if 1
229	printf("fw_asybusy\n");
230#endif
231#if XFER_TIMEOUT
232	untimeout(fw_xfer_timeout, (void *)xfer, xfer->ch);
233#endif
234/*
235	xfer->ch =  timeout((timeout_t *)fw_asystart, (void *)xfer, 20000);
236*/
237	DELAY(20000);
238	fw_asystart(xfer);
239	return;
240}
241#if XFER_TIMEOUT
242/*
243 * Post timeout for async. request.
244 */
245void
246fw_xfer_timeout(void *arg)
247{
248	int s;
249	struct fw_xfer *xfer;
250
251	xfer = (struct fw_xfer *)arg;
252	printf("fw_xfer_timeout status=%d resp=%d\n", xfer->state, xfer->resp);
253	/* XXX set error code */
254	s = splfw();
255	xfer->act.hand(xfer);
256	splx(s);
257}
258#endif
259/*
260 * Async. request with given xfer structure.
261 */
262static void
263fw_asystart(struct fw_xfer *xfer)
264{
265	struct firewire_comm *fc = xfer->fc;
266	int s;
267	if(xfer->retry++ >= fc->max_asyretry){
268		xfer->resp = EBUSY;
269		xfer->state = FWXF_BUSY;
270		xfer->act.hand(xfer);
271		return;
272	}
273#if 0 /* XXX allow bus explore packets only after bus rest */
274	if (fc->status < FWBUSEXPLORE) {
275		xfer->resp = EAGAIN;
276		xfer->state = FWXF_BUSY;
277		if (xfer->act.hand != NULL)
278			xfer->act.hand(xfer);
279		return;
280	}
281#endif
282	s = splfw();
283	xfer->state = FWXF_INQ;
284	STAILQ_INSERT_TAIL(&xfer->q->q, xfer, link);
285	xfer->q->queued ++;
286	splx(s);
287	/* XXX just queue for mbuf */
288	if (xfer->mbuf == NULL)
289		xfer->q->start(fc);
290#if XFER_TIMEOUT
291	if (xfer->act.hand != NULL)
292		xfer->ch = timeout(fw_xfer_timeout, (void *)xfer, hz);
293#endif
294	return;
295}
296
297static int
298firewire_match( device_t dev )
299{
300	device_set_desc(dev, "IEEE1394(FireWire) bus");
301	return -140;
302}
303
304/*
305 * The attach routine.
306 */
307static int
308firewire_attach( device_t dev )
309{
310	int i, unitmask, mn;
311	struct firewire_softc *sc = device_get_softc(dev);
312	device_t pa = device_get_parent(dev);
313	struct firewire_comm *fc;
314	dev_t d;
315
316	fc = (struct firewire_comm *)device_get_softc(pa);
317	sc->fc = fc;
318
319	unitmask = UNIT2MIN(device_get_unit(dev));
320
321	if( fc->nisodma > FWMAXNDMA) fc->nisodma = FWMAXNDMA;
322	for ( i = 0 ; i < fc->nisodma ; i++ ){
323		mn = unitmask | i;
324		/* XXX device name should be improved */
325		d = make_dev(&firewire_cdevsw, unit2minor(mn),
326			UID_ROOT, GID_OPERATOR, 0660,
327			"fw%x", mn);
328#if __FreeBSD_version >= 500000
329		if (i == 0)
330			sc->dev = d;
331		else
332			dev_depends(sc->dev, d);
333#else
334		sc->dev[i] = d;
335#endif
336	}
337	d = make_dev(&firewire_cdevsw, unit2minor(unitmask | FWMEM_FLAG),
338			UID_ROOT, GID_OPERATOR, 0660,
339			"fwmem%d", device_get_unit(dev));
340#if __FreeBSD_version >= 500000
341	dev_depends(sc->dev, d);
342#else
343	sc->dev[i] = d;
344#endif
345	sc->fc->timeouthandle = timeout((timeout_t *)sc->fc->timeout, (void *)sc->fc, hz * 10);
346
347	callout_init(&sc->fc->busprobe_callout
348#if __FreeBSD_version >= 500000
349						, /* mpsafe? */ 0);
350#else
351						);
352#endif
353
354	/* Locate our children */
355	bus_generic_probe(dev);
356
357	/* launch attachement of the added children */
358	bus_generic_attach(dev);
359
360	/* bus_reset */
361	fc->ibr(fc);
362
363	return 0;
364}
365
366/*
367 * Attach it as child.
368 */
369static device_t
370firewire_add_child(device_t dev, int order, const char *name, int unit)
371{
372        device_t child;
373	struct firewire_softc *sc;
374
375	sc = (struct firewire_softc *)device_get_softc(dev);
376	child = device_add_child(dev, name, unit);
377	if (child) {
378		device_set_ivars(child, sc->fc);
379		device_probe_and_attach(child);
380	}
381
382	return child;
383}
384
385/*
386 * Dettach it.
387 */
388static int
389firewire_detach( device_t dev )
390{
391	struct firewire_softc *sc;
392
393	sc = (struct firewire_softc *)device_get_softc(dev);
394
395#if __FreeBSD_version >= 500000
396	destroy_dev(sc->dev);
397#else
398	{
399		int j;
400		for (j = 0 ; j < sc->fc->nisodma + 1; j++)
401			destroy_dev(sc->dev[j]);
402	}
403#endif
404	/* XXX xfree_free and untimeout on all xfers */
405	untimeout((timeout_t *)sc->fc->timeout, sc->fc, sc->fc->timeouthandle);
406	free(sc->fc->topology_map, M_DEVBUF);
407	free(sc->fc->speed_map, M_DEVBUF);
408	bus_generic_detach(dev);
409	return(0);
410}
411#if 0
412static int
413firewire_shutdown( device_t dev )
414{
415	return 0;
416}
417#endif
418
419/*
420 * Called after bus reset.
421 */
422void
423fw_busreset(struct firewire_comm *fc)
424{
425	int i;
426	struct fw_xfer *xfer;
427
428	switch(fc->status){
429	case FWBUSMGRELECT:
430		untimeout((timeout_t *)fw_try_bmr, (void *)fc, fc->bmrhandle);
431		break;
432	default:
433		break;
434	}
435	fc->status = FWBUSRESET;
436/* XXX: discard all queued packet */
437	while((xfer = STAILQ_FIRST(&fc->atq->q)) != NULL){
438		STAILQ_REMOVE_HEAD(&fc->atq->q, link);
439		xfer->resp = EAGAIN;
440		switch(xfer->act_type){
441		case FWACT_XFER:
442			fw_xfer_done(xfer);
443			break;
444		default:
445			break;
446		}
447		fw_xfer_free( xfer);
448	}
449	while((xfer = STAILQ_FIRST(&fc->ats->q)) != NULL){
450		STAILQ_REMOVE_HEAD(&fc->ats->q, link);
451		xfer->resp = EAGAIN;
452		switch(xfer->act_type){
453		case FWACT_XFER:
454			fw_xfer_done(xfer);
455		default:
456			break;
457		}
458		fw_xfer_free( xfer);
459	}
460	for(i = 0; i < fc->nisodma; i++)
461		while((xfer = STAILQ_FIRST(&fc->it[i]->q)) != NULL){
462			STAILQ_REMOVE_HEAD(&fc->it[i]->q, link);
463			xfer->resp = 0;
464			switch(xfer->act_type){
465			case FWACT_XFER:
466				fw_xfer_done(xfer);
467				break;
468			default:
469				break;
470			}
471			fw_xfer_free( xfer);
472		}
473
474	CSRARC(fc, STATE_CLEAR)
475			= 1 << 23 | 0 << 17 | 1 << 16 | 1 << 15 | 1 << 14 ;
476	CSRARC(fc, STATE_SET) = CSRARC(fc, STATE_CLEAR);
477	CSRARC(fc, NODE_IDS) = 0x3f;
478
479	CSRARC(fc, TOPO_MAP + 8) = 0;
480	fc->irm = -1;
481
482	fc->max_node = -1;
483
484	for(i = 2; i < 0x100/4 - 2 ; i++){
485		CSRARC(fc, SPED_MAP + i * 4) = 0;
486	}
487	CSRARC(fc, STATE_CLEAR) = 1 << 23 | 0 << 17 | 1 << 16 | 1 << 15 | 1 << 14 ;
488	CSRARC(fc, STATE_SET) = CSRARC(fc, STATE_CLEAR);
489	CSRARC(fc, RESET_START) = 0;
490	CSRARC(fc, SPLIT_TIMEOUT_HI) = 0;
491	CSRARC(fc, SPLIT_TIMEOUT_LO) = 800 << 19;
492	CSRARC(fc, CYCLE_TIME) = 0x0;
493	CSRARC(fc, BUS_TIME) = 0x0;
494	CSRARC(fc, BUS_MGR_ID) = 0x3f;
495	CSRARC(fc, BANDWIDTH_AV) = 4915;
496	CSRARC(fc, CHANNELS_AV_HI) = 0xffffffff;
497	CSRARC(fc, CHANNELS_AV_LO) = 0xffffffff;
498	CSRARC(fc, IP_CHANNELS) = (1 << 31);
499
500	CSRARC(fc, CONF_ROM) = 0x04 << 24;
501	CSRARC(fc, CONF_ROM + 4) = 0x31333934; /* means strings 1394 */
502	CSRARC(fc, CONF_ROM + 8) = 1 << 31 | 1 << 30 | 1 << 29 |
503				1 << 28 | 0xff << 16 | 0x09 << 8;
504	CSRARC(fc, CONF_ROM + 0xc) = 0;
505
506/* DV depend CSRs see blue book */
507	CSRARC(fc, oPCR) &= ~DV_BROADCAST_ON;
508	CSRARC(fc, iPCR) &= ~DV_BROADCAST_ON;
509
510	CSRARC(fc, STATE_CLEAR) &= ~(1 << 23 | 1 << 15 | 1 << 14 );
511	CSRARC(fc, STATE_SET) = CSRARC(fc, STATE_CLEAR);
512}
513
514/* Call once after reboot */
515void fw_init(struct firewire_comm *fc)
516{
517	int i;
518	struct csrdir *csrd;
519#ifdef FW_VMACCESS
520	struct fw_xfer *xfer;
521	struct fw_bind *fwb;
522#endif
523
524	fc->max_asyretry = FW_MAXASYRTY;
525
526	fc->arq->queued = 0;
527	fc->ars->queued = 0;
528	fc->atq->queued = 0;
529	fc->ats->queued = 0;
530
531	fc->arq->psize = PAGE_SIZE;
532	fc->ars->psize = PAGE_SIZE;
533	fc->atq->psize = 0;
534	fc->ats->psize = 0;
535
536
537	fc->arq->buf = NULL;
538	fc->ars->buf = NULL;
539	fc->atq->buf = NULL;
540	fc->ats->buf = NULL;
541
542	fc->arq->flag = FWXFERQ_PACKET;
543	fc->ars->flag = FWXFERQ_PACKET;
544	fc->atq->flag = FWXFERQ_PACKET;
545	fc->ats->flag = FWXFERQ_PACKET;
546
547	STAILQ_INIT(&fc->atq->q);
548	STAILQ_INIT(&fc->ats->q);
549
550	for( i = 0 ; i < fc->nisodma ; i ++ ){
551		fc->it[i]->queued = 0;
552		fc->ir[i]->queued = 0;
553
554		fc->it[i]->start = NULL;
555		fc->ir[i]->start = NULL;
556
557		fc->it[i]->buf = NULL;
558		fc->ir[i]->buf = NULL;
559
560		fc->it[i]->flag = FWXFERQ_STREAM;
561		fc->ir[i]->flag = FWXFERQ_STREAM;
562
563		STAILQ_INIT(&fc->it[i]->q);
564		STAILQ_INIT(&fc->ir[i]->q);
565
566		STAILQ_INIT(&fc->it[i]->binds);
567		STAILQ_INIT(&fc->ir[i]->binds);
568	}
569
570	fc->arq->maxq = FWMAXQUEUE;
571	fc->ars->maxq = FWMAXQUEUE;
572	fc->atq->maxq = FWMAXQUEUE;
573	fc->ats->maxq = FWMAXQUEUE;
574
575	for( i = 0 ; i < fc->nisodma ; i++){
576		fc->ir[i]->maxq = FWMAXQUEUE;
577		fc->it[i]->maxq = FWMAXQUEUE;
578	}
579/* Initialize csr registers */
580	fc->topology_map = (struct fw_topology_map *)malloc(
581				sizeof(struct fw_topology_map),
582				M_DEVBUF, M_NOWAIT | M_ZERO);
583	fc->speed_map = (struct fw_speed_map *)malloc(
584				sizeof(struct fw_speed_map),
585				M_DEVBUF, M_NOWAIT | M_ZERO);
586	CSRARC(fc, TOPO_MAP) = 0x3f1 << 16;
587	CSRARC(fc, TOPO_MAP + 4) = 1;
588	CSRARC(fc, SPED_MAP) = 0x3f1 << 16;
589	CSRARC(fc, SPED_MAP + 4) = 1;
590
591	TAILQ_INIT(&fc->devices);
592	STAILQ_INIT(&fc->pending);
593
594/* Initialize csr ROM work space */
595	SLIST_INIT(&fc->ongocsr);
596	SLIST_INIT(&fc->csrfree);
597	for( i = 0 ; i < FWMAXCSRDIR ; i++){
598		csrd = (struct csrdir *) malloc(sizeof(struct csrdir), M_DEVBUF,M_NOWAIT);
599		if(csrd == NULL) break;
600		SLIST_INSERT_HEAD(&fc->csrfree, csrd, link);
601	}
602
603/* Initialize Async handlers */
604	STAILQ_INIT(&fc->binds);
605	for( i = 0 ; i < 0x40 ; i++){
606		STAILQ_INIT(&fc->tlabels[i]);
607	}
608
609/* DV depend CSRs see blue book */
610#if 0
611	CSRARC(fc, oMPR) = 0x3fff0001; /* # output channel = 1 */
612	CSRARC(fc, oPCR) = 0x8000007a;
613	for(i = 4 ; i < 0x7c/4 ; i+=4){
614		CSRARC(fc, i + oPCR) = 0x8000007a;
615	}
616
617	CSRARC(fc, iMPR) = 0x00ff0001; /* # input channel = 1 */
618	CSRARC(fc, iPCR) = 0x803f0000;
619	for(i = 4 ; i < 0x7c/4 ; i+=4){
620		CSRARC(fc, i + iPCR) = 0x0;
621	}
622#endif
623
624
625#ifdef FW_VMACCESS
626	xfer = fw_xfer_alloc();
627	if(xfer == NULL) return;
628
629	fwb = (struct fw_bind *)malloc(sizeof (struct fw_bind), M_DEVBUF, M_NOWAIT);
630	if(fwb == NULL){
631		fw_xfer_free(xfer);
632	}
633	xfer->act.hand = fw_vmaccess;
634	xfer->act_type = FWACT_XFER;
635	xfer->fc = fc;
636	xfer->sc = NULL;
637
638	fwb->start_hi = 0x2;
639	fwb->start_lo = 0;
640	fwb->addrlen = 0xffffffff;
641	fwb->xfer = xfer;
642	fw_bindadd(fc, fwb);
643#endif
644}
645
646/*
647 * To lookup binded process from IEEE1394 address.
648 */
649struct fw_bind *
650fw_bindlookup(struct firewire_comm *fc, u_int32_t dest_hi, u_int32_t dest_lo)
651{
652	struct fw_bind *tfw;
653	for(tfw = STAILQ_FIRST(&fc->binds) ; tfw != NULL ;
654		tfw = STAILQ_NEXT(tfw, fclist)){
655		if(tfw->xfer->act_type != FWACT_NULL &&
656			tfw->start_hi == dest_hi &&
657			tfw->start_lo <= dest_lo &&
658			(tfw->start_lo + tfw->addrlen) > dest_lo){
659			return(tfw);
660		}
661	}
662	return(NULL);
663}
664
665/*
666 * To bind IEEE1394 address block to process.
667 */
668int
669fw_bindadd(struct firewire_comm *fc, struct fw_bind *fwb)
670{
671	struct fw_bind *tfw, *tfw2 = NULL;
672	int err = 0;
673	tfw = STAILQ_FIRST(&fc->binds);
674	if(tfw == NULL){
675		STAILQ_INSERT_HEAD(&fc->binds, fwb, fclist);
676		goto out;
677	}
678	if((tfw->start_hi > fwb->start_hi) ||
679		(tfw->start_hi == fwb->start_hi &&
680		(tfw->start_lo > (fwb->start_lo + fwb->addrlen)))){
681		STAILQ_INSERT_HEAD(&fc->binds, fwb, fclist);
682		goto out;
683	}
684	for(; tfw != NULL; tfw = STAILQ_NEXT(tfw, fclist)){
685		if((tfw->start_hi < fwb->start_hi) ||
686		   (tfw->start_hi == fwb->start_hi &&
687		    (tfw->start_lo + tfw->addrlen) < fwb->start_lo)){
688		   tfw2 = STAILQ_NEXT(tfw, fclist);
689			if(tfw2 == NULL)
690				break;
691			if((tfw2->start_hi > fwb->start_hi) ||
692			   (tfw2->start_hi == fwb->start_hi &&
693			    tfw2->start_lo > (fwb->start_lo + fwb->addrlen))){
694				break;
695			}else{
696				err = EBUSY;
697				goto out;
698			}
699		}
700	}
701	if(tfw != NULL){
702		STAILQ_INSERT_AFTER(&fc->binds, tfw, fwb, fclist);
703	}else{
704		STAILQ_INSERT_TAIL(&fc->binds, fwb, fclist);
705	}
706out:
707	if(!err && fwb->xfer->act_type == FWACT_CH){
708		STAILQ_INSERT_HEAD(&fc->ir[fwb->xfer->sub]->binds, fwb, chlist);
709	}
710	return err;
711}
712
713/*
714 * To free IEEE1394 address block.
715 */
716int
717fw_bindremove(struct firewire_comm *fc, struct fw_bind *fwb)
718{
719	int s;
720
721	s = splfw();
722	/* shall we check the existance? */
723	STAILQ_REMOVE(&fc->binds, fwb, fw_bind, fclist);
724	splx(s);
725	if (fwb->xfer)
726		fw_xfer_free(fwb->xfer);
727
728	return 0;
729}
730
731/*
732 * To free transaction label.
733 */
734static void
735fw_tl_free(struct firewire_comm *fc, struct fw_xfer *xfer)
736{
737	struct tlabel *tl;
738	int s = splfw();
739
740	for( tl = STAILQ_FIRST(&fc->tlabels[xfer->tl]); tl != NULL;
741		tl = STAILQ_NEXT(tl, link)){
742		if(tl->xfer == xfer){
743			STAILQ_REMOVE(&fc->tlabels[xfer->tl], tl, tlabel, link);
744			free(tl, M_DEVBUF);
745			splx(s);
746			return;
747		}
748	}
749	splx(s);
750	return;
751}
752
753/*
754 * To obtain XFER structure by transaction label.
755 */
756static struct fw_xfer *
757fw_tl2xfer(struct firewire_comm *fc, int node, int tlabel)
758{
759	struct fw_xfer *xfer;
760	struct tlabel *tl;
761	int s = splfw();
762
763	for( tl = STAILQ_FIRST(&fc->tlabels[tlabel]); tl != NULL;
764		tl = STAILQ_NEXT(tl, link)){
765		if(tl->xfer->dst == node){
766			xfer = tl->xfer;
767			splx(s);
768			return(xfer);
769		}
770	}
771	splx(s);
772	return(NULL);
773}
774
775/*
776 * To allocate IEEE1394 XFER structure.
777 */
778struct fw_xfer *
779fw_xfer_alloc()
780{
781	struct fw_xfer *xfer;
782
783	xfer = malloc(sizeof(struct fw_xfer), M_DEVBUF, M_NOWAIT | M_ZERO);
784	if (xfer == NULL)
785		return xfer;
786
787	xfer->time = time_second;
788	xfer->sub = -1;
789
790	return xfer;
791}
792
793/*
794 * IEEE1394 XFER post process.
795 */
796void
797fw_xfer_done(struct fw_xfer *xfer)
798{
799	if (xfer->act.hand == NULL)
800		return;
801
802#if XFER_TIMEOUT
803	untimeout(fw_xfer_timeout, (void *)xfer, xfer->ch);
804#endif
805
806	if (xfer->fc->status != FWBUSRESET)
807		xfer->act.hand(xfer);
808	else {
809		printf("fw_xfer_done: pending\n");
810		if (xfer->fc != NULL)
811			STAILQ_INSERT_TAIL(&xfer->fc->pending, xfer, link);
812		else
813			panic("fw_xfer_done: why xfer->fc is NULL?");
814	}
815}
816
817/*
818 * To free IEEE1394 XFER structure.
819 */
820void
821fw_xfer_free( struct fw_xfer* xfer)
822{
823	int s;
824	if(xfer == NULL ) return;
825	if(xfer->state == FWXF_INQ){
826		printf("fw_xfer_free FWXF_INQ\n");
827		s = splfw();
828		STAILQ_REMOVE(&xfer->q->q, xfer, fw_xfer, link);
829		xfer->q->queued --;
830		splx(s);
831	}
832	if(xfer->fc != NULL){
833		if(xfer->state == FWXF_START){
834#if 0 /* this could happen if we call fwohci_arcv() before fwohci_txd() */
835			printf("fw_xfer_free FWXF_START\n");
836#endif
837			s = splfw();
838			xfer->q->drain(xfer->fc, xfer);
839			splx(s);
840		}
841	}
842	if(xfer->send.buf != NULL){
843		free(xfer->send.buf, M_DEVBUF);
844	}
845	if(xfer->recv.buf != NULL){
846		free(xfer->recv.buf, M_DEVBUF);
847	}
848	if(xfer->fc != NULL){
849		fw_tl_free(xfer->fc, xfer);
850	}
851	free(xfer, M_DEVBUF);
852}
853
854/*
855 * Callback for PHY configuration.
856 */
857static void
858fw_phy_config_callback(struct fw_xfer *xfer)
859{
860#if 0
861	printf("phy_config done state=%d resp=%d\n",
862				xfer->state, xfer->resp);
863#endif
864	fw_xfer_free(xfer);
865	/* XXX need bus reset ?? */
866	/* sc->fc->ibr(xfer->fc);  LOOP */
867}
868
869/*
870 * To configure PHY.
871 */
872static void
873fw_phy_config(struct firewire_comm *fc, int root_node, int gap_count)
874{
875	struct fw_xfer *xfer;
876	struct fw_pkt *fp;
877
878	fc->status = FWBUSPHYCONF;
879
880#if 0
881	DELAY(100000);
882#endif
883	xfer = fw_xfer_alloc();
884	xfer->send.len = 12;
885	xfer->send.off = 0;
886	xfer->fc = fc;
887	xfer->retry_req = fw_asybusy;
888	xfer->act.hand = fw_phy_config_callback;
889
890	xfer->send.buf = malloc(sizeof(u_int32_t),
891					M_DEVBUF, M_NOWAIT | M_ZERO);
892	fp = (struct fw_pkt *)xfer->send.buf;
893	fp->mode.ld[1] = 0;
894	if (root_node >= 0)
895		fp->mode.ld[1] |= htonl((root_node & 0x3f) << 24 | 1 << 23);
896	if (gap_count >= 0)
897		fp->mode.ld[1] |= htonl(1 << 22 | (gap_count & 0x3f) << 16);
898	fp->mode.ld[2] = ~fp->mode.ld[1];
899/* XXX Dangerous, how to pass PHY packet to device driver */
900	fp->mode.common.tcode |= FWTCODE_PHY;
901
902	if (firewire_debug)
903		printf("send phy_config root_node=%d gap_count=%d\n",
904						root_node, gap_count);
905	fw_asyreq(fc, -1, xfer);
906}
907
908#if 0
909/*
910 * Dump self ID.
911 */
912static void
913fw_print_sid(u_int32_t sid)
914{
915	union fw_self_id *s;
916	s = (union fw_self_id *) &sid;
917	printf("node:%d link:%d gap:%d spd:%d del:%d con:%d pwr:%d"
918		" p0:%d p1:%d p2:%d i:%d m:%d\n",
919		s->p0.phy_id, s->p0.link_active, s->p0.gap_count,
920		s->p0.phy_speed, s->p0.phy_delay, s->p0.contender,
921		s->p0.power_class, s->p0.port0, s->p0.port1,
922		s->p0.port2, s->p0.initiated_reset, s->p0.more_packets);
923}
924#endif
925
926/*
927 * To receive self ID.
928 */
929void fw_sidrcv(struct firewire_comm* fc, caddr_t buf, u_int len, u_int off)
930{
931	u_int32_t *p, *sid = (u_int32_t *)(buf + off);
932	union fw_self_id *self_id;
933	u_int i, j, node, c_port = 0, i_branch = 0;
934
935	fc->sid_cnt = len /(sizeof(u_int32_t) * 2);
936	fc->status = FWBUSINIT;
937	fc->max_node = fc->nodeid & 0x3f;
938	CSRARC(fc, NODE_IDS) = ((u_int32_t)fc->nodeid) << 16;
939	fc->status = FWBUSCYMELECT;
940	fc->topology_map->crc_len = 2;
941	fc->topology_map->generation ++;
942	fc->topology_map->self_id_count = 0;
943	fc->topology_map->node_count = 0;
944	fc->speed_map->generation ++;
945	fc->speed_map->crc_len = 1 + (64*64 + 3) / 4;
946	self_id = &fc->topology_map->self_id[0];
947	for(i = 0; i < fc->sid_cnt; i ++){
948		if (sid[1] != ~sid[0]) {
949			printf("fw_sidrcv: invalid self-id packet\n");
950			sid += 2;
951			continue;
952		}
953		*self_id = *((union fw_self_id *)sid);
954		fc->topology_map->crc_len++;
955		if(self_id->p0.sequel == 0){
956			fc->topology_map->node_count ++;
957			c_port = 0;
958#if 0
959			fw_print_sid(sid[0]);
960#endif
961			node = self_id->p0.phy_id;
962			if(fc->max_node < node){
963				fc->max_node = self_id->p0.phy_id;
964			}
965			/* XXX I'm not sure this is the right speed_map */
966			fc->speed_map->speed[node][node]
967					= self_id->p0.phy_speed;
968			for (j = 0; j < node; j ++) {
969				fc->speed_map->speed[j][node]
970					= fc->speed_map->speed[node][j]
971					= min(fc->speed_map->speed[j][j],
972							self_id->p0.phy_speed);
973			}
974			if ((fc->irm == -1 || self_id->p0.phy_id > fc->irm) &&
975			  (self_id->p0.link_active && self_id->p0.contender)) {
976				fc->irm = self_id->p0.phy_id;
977			}
978			if(self_id->p0.port0 >= 0x2){
979				c_port++;
980			}
981			if(self_id->p0.port1 >= 0x2){
982				c_port++;
983			}
984			if(self_id->p0.port2 >= 0x2){
985				c_port++;
986			}
987		}
988		if(c_port > 2){
989			i_branch += (c_port - 2);
990		}
991		sid += 2;
992		self_id++;
993		fc->topology_map->self_id_count ++;
994	}
995	device_printf(fc->bdev, "%d nodes", fc->max_node + 1);
996	/* CRC */
997	fc->topology_map->crc = fw_crc16(
998			(u_int32_t *)&fc->topology_map->generation,
999			fc->topology_map->crc_len * 4);
1000	fc->speed_map->crc = fw_crc16(
1001			(u_int32_t *)&fc->speed_map->generation,
1002			fc->speed_map->crc_len * 4);
1003	/* byteswap and copy to CSR */
1004	p = (u_int32_t *)fc->topology_map;
1005	for (i = 0; i <= fc->topology_map->crc_len; i++)
1006		CSRARC(fc, TOPO_MAP + i * 4) = htonl(*p++);
1007	p = (u_int32_t *)fc->speed_map;
1008	CSRARC(fc, SPED_MAP) = htonl(*p++);
1009	CSRARC(fc, SPED_MAP + 4) = htonl(*p++);
1010	/* don't byte-swap u_int8_t array */
1011	bcopy(p, &CSRARC(fc, SPED_MAP + 8), (fc->speed_map->crc_len - 1)*4);
1012
1013	fc->max_hop = fc->max_node - i_branch;
1014#if 1
1015	printf(", maxhop <= %d", fc->max_hop);
1016#endif
1017
1018	if(fc->irm == -1 ){
1019		printf(", Not found IRM capable node");
1020	}else{
1021		printf(", cable IRM = %d", fc->irm);
1022		if (fc->irm == fc->nodeid)
1023			printf(" (me)");
1024	}
1025	printf("\n");
1026
1027	if (try_bmr && (fc->irm != -1) && (CSRARC(fc, BUS_MGR_ID) == 0x3f)) {
1028		if (fc->irm == ((CSRARC(fc, NODE_IDS) >> 16 ) & 0x3f)) {
1029			fc->status = FWBUSMGRDONE;
1030			CSRARC(fc, BUS_MGR_ID) = fc->set_bmr(fc, fc->irm);
1031		} else {
1032			fc->status = FWBUSMGRELECT;
1033			fc->bmrhandle = timeout((timeout_t *)fw_try_bmr,
1034							(void *)fc, hz / 8);
1035		}
1036	} else {
1037		fc->status = FWBUSMGRDONE;
1038#if 0
1039		device_printf(fc->bdev, "BMR = %x\n",
1040				CSRARC(fc, BUS_MGR_ID));
1041#endif
1042	}
1043	free(buf, M_DEVBUF);
1044	/* Optimize gap_count, if I am BMGR */
1045	if(fc->irm == ((CSRARC(fc, NODE_IDS) >> 16 ) & 0x3f)){
1046		fw_phy_config(fc, -1, gap_cnt[fc->max_hop]);
1047	}
1048	callout_reset(&fc->busprobe_callout, hz/4,
1049			(void *)fw_bus_probe, (void *)fc);
1050}
1051
1052/*
1053 * To probe devices on the IEEE1394 bus.
1054 */
1055static void
1056fw_bus_probe(struct firewire_comm *fc)
1057{
1058	int s;
1059	struct fw_device *fwdev, *next;
1060
1061	s = splfw();
1062	fc->status = FWBUSEXPLORE;
1063	fc->retry_count = 0;
1064
1065/*
1066 * Invalidate all devices, just after bus reset. Devices
1067 * to be removed has not been seen longer time.
1068 */
1069	for(fwdev = TAILQ_FIRST(&fc->devices); fwdev != NULL; fwdev = next) {
1070		next = TAILQ_NEXT(fwdev, link);
1071		if(fwdev->status != FWDEVINVAL){
1072			fwdev->status = FWDEVINVAL;
1073			fwdev->rcnt = 0;
1074		}else if(fwdev->rcnt < FW_MAXDEVRCNT){
1075			fwdev->rcnt ++;
1076		}else{
1077			TAILQ_REMOVE(&fc->devices, fwdev, link);
1078			free(fwdev, M_DEVBUF);
1079		}
1080	}
1081	fc->ongonode = 0;
1082	fc->ongoaddr = CSRROMOFF;
1083	fc->ongodev = NULL;
1084	fc->ongoeui.hi = 0xffffffff; fc->ongoeui.lo = 0xffffffff;
1085	fw_bus_explore(fc);
1086	splx(s);
1087}
1088
1089/*
1090 * To collect device informations on the IEEE1394 bus.
1091 */
1092static void
1093fw_bus_explore(struct firewire_comm *fc )
1094{
1095	int err = 0;
1096	struct fw_device *fwdev, *tfwdev;
1097	u_int32_t addr;
1098	struct fw_xfer *xfer;
1099	struct fw_pkt *fp;
1100
1101	if(fc->status != FWBUSEXPLORE)
1102		return;
1103
1104loop:
1105	if(fc->ongonode == fc->nodeid) fc->ongonode++;
1106
1107	if(fc->ongonode > fc->max_node) goto done;
1108	if(fc->ongonode >= 0x3f) goto done;
1109
1110	/* check link */
1111	/* XXX we need to check phy_id first */
1112	if (!fc->topology_map->self_id[fc->ongonode].p0.link_active) {
1113		printf("fw_bus_explore: node %d link down\n", fc->ongonode);
1114		fc->ongonode++;
1115		goto loop;
1116	}
1117
1118	if(fc->ongoaddr <= CSRROMOFF &&
1119		fc->ongoeui.hi == 0xffffffff &&
1120		fc->ongoeui.lo == 0xffffffff ){
1121		fc->ongoaddr = CSRROMOFF;
1122		addr = 0xf0000000 | fc->ongoaddr;
1123	}else if(fc->ongoeui.hi == 0xffffffff ){
1124		fc->ongoaddr = CSRROMOFF + 0xc;
1125		addr = 0xf0000000 | fc->ongoaddr;
1126	}else if(fc->ongoeui.lo == 0xffffffff ){
1127		fc->ongoaddr = CSRROMOFF + 0x10;
1128		addr = 0xf0000000 | fc->ongoaddr;
1129	}else if(fc->ongodev == NULL){
1130		for(fwdev = TAILQ_FIRST(&fc->devices); fwdev != NULL;
1131			fwdev = TAILQ_NEXT(fwdev, link)){
1132			if(fwdev->eui.hi == fc->ongoeui.hi && fwdev->eui.lo == fc->ongoeui.lo){
1133				break;
1134			}
1135		}
1136		if(fwdev != NULL){
1137			fwdev->dst = fc->ongonode;
1138			fwdev->status = FWDEVATTACHED;
1139			fc->ongonode++;
1140			fc->ongoaddr = CSRROMOFF;
1141			fc->ongodev = NULL;
1142			fc->ongoeui.hi = 0xffffffff; fc->ongoeui.lo = 0xffffffff;
1143			goto loop;
1144		}
1145		fwdev = malloc(sizeof(struct fw_device), M_DEVBUF, M_NOWAIT);
1146		if(fwdev == NULL)
1147			return;
1148		fwdev->fc = fc;
1149		fwdev->rommax = 0;
1150		fwdev->dst = fc->ongonode;
1151		fwdev->eui.hi = fc->ongoeui.hi; fwdev->eui.lo = fc->ongoeui.lo;
1152		fwdev->status = FWDEVINIT;
1153#if 0
1154		fwdev->speed = CSRARC(fc, SPED_MAP + 8 + fc->ongonode / 4)
1155			>> ((3 - (fc->ongonode % 4)) * 8);
1156#else
1157		fwdev->speed = fc->speed_map->speed[fc->nodeid][fc->ongonode];
1158#endif
1159
1160		tfwdev = TAILQ_FIRST(&fc->devices);
1161		while( tfwdev != NULL &&
1162			(tfwdev->eui.hi > fwdev->eui.hi) &&
1163			((tfwdev->eui.hi == fwdev->eui.hi) &&
1164				tfwdev->eui.lo > fwdev->eui.lo)){
1165			tfwdev = TAILQ_NEXT( tfwdev, link);
1166		}
1167		if(tfwdev == NULL){
1168			TAILQ_INSERT_TAIL(&fc->devices, fwdev, link);
1169		}else{
1170			TAILQ_INSERT_BEFORE(tfwdev, fwdev, link);
1171		}
1172
1173		device_printf(fc->bdev, "New %s device ID:%08x%08x\n",
1174			linkspeed[fwdev->speed],
1175			fc->ongoeui.hi, fc->ongoeui.lo);
1176
1177		fc->ongodev = fwdev;
1178		fc->ongoaddr = CSRROMOFF;
1179		addr = 0xf0000000 | fc->ongoaddr;
1180	}else{
1181		addr = 0xf0000000 | fc->ongoaddr;
1182	}
1183#if 0
1184	xfer = asyreqq(fc, FWSPD_S100, 0, 0,
1185		((FWLOCALBUS | fc->ongonode) << 16) | 0xffff , addr,
1186		fw_bus_explore_callback);
1187	if(xfer == NULL) goto done;
1188#else
1189	xfer = fw_xfer_alloc();
1190	if(xfer == NULL){
1191		goto done;
1192	}
1193	xfer->send.len = 16;
1194	xfer->spd = 0;
1195	xfer->send.buf = malloc(16, M_DEVBUF, M_NOWAIT);
1196	if(xfer->send.buf == NULL){
1197		fw_xfer_free( xfer);
1198		return;
1199	}
1200
1201	xfer->send.off = 0;
1202	fp = (struct fw_pkt *)xfer->send.buf;
1203	fp->mode.rreqq.dest_hi = htons(0xffff);
1204	fp->mode.rreqq.tlrt = 0;
1205	fp->mode.rreqq.tcode = FWTCODE_RREQQ;
1206	fp->mode.rreqq.pri = 0;
1207	fp->mode.rreqq.src = 0;
1208	xfer->dst = FWLOCALBUS | fc->ongonode;
1209	fp->mode.rreqq.dst = htons(xfer->dst);
1210	fp->mode.rreqq.dest_lo = htonl(addr);
1211	xfer->act.hand = fw_bus_explore_callback;
1212
1213	err = fw_asyreq(fc, -1, xfer);
1214	if(err){
1215		fw_xfer_free( xfer);
1216		return;
1217	}
1218#endif
1219	return;
1220done:
1221	/* fw_attach_devs */
1222	fc->status = FWBUSEXPDONE;
1223	if (firewire_debug)
1224		printf("bus_explore done\n");
1225	fw_attach_dev(fc);
1226	return;
1227
1228}
1229
1230/* Portable Async. request read quad */
1231struct fw_xfer *
1232asyreqq(struct firewire_comm *fc, u_int8_t spd, u_int8_t tl, u_int8_t rt,
1233	u_int32_t addr_hi, u_int32_t addr_lo,
1234	void (*hand) __P((struct fw_xfer*)))
1235{
1236	struct fw_xfer *xfer;
1237	struct fw_pkt *fp;
1238	int err;
1239
1240	xfer = fw_xfer_alloc();
1241	if(xfer == NULL){
1242		return NULL;
1243	}
1244	xfer->send.len = 16;
1245	xfer->spd = spd; /* XXX:min(spd, fc->spd) */
1246	xfer->send.buf = malloc(16, M_DEVBUF, M_NOWAIT);
1247	if(xfer->send.buf == NULL){
1248		fw_xfer_free( xfer);
1249		return NULL;
1250	}
1251
1252	xfer->send.off = 0;
1253	fp = (struct fw_pkt *)xfer->send.buf;
1254	fp->mode.rreqq.dest_hi = htons(addr_hi & 0xffff);
1255	if(tl & FWP_TL_VALID){
1256		fp->mode.rreqq.tlrt = (tl & 0x3f) << 2;
1257	}else{
1258		fp->mode.rreqq.tlrt = 0;
1259	}
1260	fp->mode.rreqq.tlrt |= rt & 0x3;
1261	fp->mode.rreqq.tcode = FWTCODE_RREQQ;
1262	fp->mode.rreqq.pri = 0;
1263	fp->mode.rreqq.src = 0;
1264	xfer->dst = addr_hi >> 16;
1265	fp->mode.rreqq.dst = htons(xfer->dst);
1266	fp->mode.rreqq.dest_lo = htonl(addr_lo);
1267	xfer->act.hand = hand;
1268
1269	err = fw_asyreq(fc, -1, xfer);
1270	if(err){
1271		fw_xfer_free( xfer);
1272		return NULL;
1273	}
1274	return xfer;
1275}
1276
1277/*
1278 * Callback for the IEEE1394 bus information collection.
1279 */
1280static void
1281fw_bus_explore_callback(struct fw_xfer *xfer)
1282{
1283	struct firewire_comm *fc;
1284	struct fw_pkt *sfp,*rfp;
1285	struct csrhdr *chdr;
1286	struct csrdir *csrd;
1287	struct csrreg *csrreg;
1288	u_int32_t offset;
1289
1290
1291	if(xfer == NULL) return;
1292	fc = xfer->fc;
1293	if(xfer->resp != 0){
1294		printf("resp != 0: node=%d addr=0x%x\n",
1295			fc->ongonode, fc->ongoaddr);
1296		fc->retry_count++;
1297		goto nextnode;
1298	}
1299
1300	if(xfer->send.buf == NULL){
1301		printf("send.buf == NULL: node=%d addr=0x%x\n",
1302			fc->ongonode, fc->ongoaddr);
1303		printf("send.buf == NULL\n");
1304		fc->retry_count++;
1305		goto nextnode;
1306	}
1307	sfp = (struct fw_pkt *)xfer->send.buf;
1308
1309	if(xfer->recv.buf == NULL){
1310		printf("recv.buf == NULL: node=%d addr=0x%x\n",
1311			fc->ongonode, fc->ongoaddr);
1312		fc->retry_count++;
1313		goto nextnode;
1314	}
1315	rfp = (struct fw_pkt *)xfer->recv.buf;
1316#if 0
1317	{
1318		u_int32_t *qld;
1319		int i;
1320		qld = (u_int32_t *)xfer->recv.buf;
1321		printf("len:%d\n", xfer->recv.len);
1322		for( i = 0 ; i <= xfer->recv.len && i < 32; i+= 4){
1323			printf("0x%08x ", ntohl(rfp->mode.ld[i/4]));
1324			if((i % 16) == 15) printf("\n");
1325		}
1326		if((i % 16) != 15) printf("\n");
1327	}
1328#endif
1329	if(fc->ongodev == NULL){
1330		if(sfp->mode.rreqq.dest_lo == htonl((0xf0000000 | CSRROMOFF))){
1331			rfp->mode.rresq.data = ntohl(rfp->mode.rresq.data);
1332			chdr = (struct csrhdr *)(&rfp->mode.rresq.data);
1333/* If CSR is minimul confinguration, more investgation is not needed. */
1334			if(chdr->info_len == 1){
1335				goto nextnode;
1336			}else{
1337				fc->ongoaddr = CSRROMOFF + 0xc;
1338			}
1339		}else if(sfp->mode.rreqq.dest_lo == htonl((0xf0000000 |(CSRROMOFF + 0xc)))){
1340			fc->ongoeui.hi = ntohl(rfp->mode.rresq.data);
1341			fc->ongoaddr = CSRROMOFF + 0x10;
1342		}else if(sfp->mode.rreqq.dest_lo == htonl((0xf0000000 |(CSRROMOFF + 0x10)))){
1343			fc->ongoeui.lo = ntohl(rfp->mode.rresq.data);
1344			if (fc->ongoeui.hi == 0 && fc->ongoeui.lo == 0)
1345				goto nextnode;
1346			fc->ongoaddr = CSRROMOFF;
1347		}
1348	}else{
1349		fc->ongodev->csrrom[(fc->ongoaddr - CSRROMOFF)/4] = ntohl(rfp->mode.rresq.data);
1350		if(fc->ongoaddr > fc->ongodev->rommax){
1351			fc->ongodev->rommax = fc->ongoaddr;
1352		}
1353		csrd = SLIST_FIRST(&fc->ongocsr);
1354		if((csrd = SLIST_FIRST(&fc->ongocsr)) == NULL){
1355			chdr = (struct csrhdr *)(fc->ongodev->csrrom);
1356			offset = CSRROMOFF;
1357		}else{
1358			chdr = (struct csrhdr *)&fc->ongodev->csrrom[(csrd->off - CSRROMOFF)/4];
1359			offset = csrd->off;
1360		}
1361		if(fc->ongoaddr > (CSRROMOFF + 0x14) && fc->ongoaddr != offset){
1362			csrreg = (struct csrreg *)&fc->ongodev->csrrom[(fc->ongoaddr - CSRROMOFF)/4];
1363			if( csrreg->key == 0x81 || csrreg->key == 0xd1){
1364				csrd = SLIST_FIRST(&fc->csrfree);
1365				if(csrd == NULL){
1366					goto nextnode;
1367				}else{
1368					csrd->ongoaddr = fc->ongoaddr;
1369					fc->ongoaddr += csrreg->val * 4;
1370					csrd->off = fc->ongoaddr;
1371					SLIST_REMOVE_HEAD(&fc->csrfree, link);
1372					SLIST_INSERT_HEAD(&fc->ongocsr, csrd, link);
1373					goto nextaddr;
1374				}
1375			}
1376		}
1377		fc->ongoaddr += 4;
1378		if(((fc->ongoaddr - offset)/4 > chdr->crc_len) &&
1379				(fc->ongodev->rommax < 0x414)){
1380			if(fc->ongodev->rommax <= 0x414){
1381				csrd = SLIST_FIRST(&fc->csrfree);
1382				if(csrd == NULL) goto nextnode;
1383				csrd->off = fc->ongoaddr;
1384				csrd->ongoaddr = fc->ongoaddr;
1385				SLIST_REMOVE_HEAD(&fc->csrfree, link);
1386				SLIST_INSERT_HEAD(&fc->ongocsr, csrd, link);
1387			}
1388			goto nextaddr;
1389		}
1390
1391		while(((fc->ongoaddr - offset)/4 > chdr->crc_len)){
1392			if(csrd == NULL){
1393				goto nextnode;
1394			};
1395			fc->ongoaddr = csrd->ongoaddr + 4;
1396			SLIST_REMOVE_HEAD(&fc->ongocsr, link);
1397			SLIST_INSERT_HEAD(&fc->csrfree, csrd, link);
1398			csrd = SLIST_FIRST(&fc->ongocsr);
1399			if((csrd = SLIST_FIRST(&fc->ongocsr)) == NULL){
1400				chdr = (struct csrhdr *)(fc->ongodev->csrrom);
1401				offset = CSRROMOFF;
1402			}else{
1403				chdr = (struct csrhdr *)&(fc->ongodev->csrrom[(csrd->off - CSRROMOFF)/4]);
1404				offset = csrd->off;
1405			}
1406		}
1407		if((fc->ongoaddr - CSRROMOFF) > CSRROMSIZE){
1408			goto nextnode;
1409		}
1410	}
1411nextaddr:
1412	fw_xfer_free( xfer);
1413	fw_bus_explore(fc);
1414	return;
1415nextnode:
1416	fw_xfer_free( xfer);
1417	fc->ongonode++;
1418/* housekeeping work space */
1419	fc->ongoaddr = CSRROMOFF;
1420	fc->ongodev = NULL;
1421	fc->ongoeui.hi = 0xffffffff; fc->ongoeui.lo = 0xffffffff;
1422	while((csrd = SLIST_FIRST(&fc->ongocsr)) != NULL){
1423		SLIST_REMOVE_HEAD(&fc->ongocsr, link);
1424		SLIST_INSERT_HEAD(&fc->csrfree, csrd, link);
1425	}
1426	fw_bus_explore(fc);
1427	return;
1428}
1429
1430/*
1431 * To obtain CSR register values.
1432 */
1433u_int32_t
1434getcsrdata(struct fw_device *fwdev, u_int8_t key)
1435{
1436	int i;
1437	struct csrhdr *chdr;
1438	struct csrreg *creg;
1439	chdr = (struct csrhdr *)&fwdev->csrrom[0];
1440	for( i = chdr->info_len + 4; i <= fwdev->rommax - CSRROMOFF; i+=4){
1441		creg = (struct csrreg *)&fwdev->csrrom[i/4];
1442		if(creg->key == key){
1443			return (u_int32_t)creg->val;
1444		}
1445	}
1446	return 0;
1447}
1448
1449/*
1450 * To attach sub-devices layer onto IEEE1394 bus.
1451 */
1452static void
1453fw_attach_dev(struct firewire_comm *fc)
1454{
1455	struct fw_device *fwdev;
1456	struct fw_xfer *xfer;
1457	int i, err;
1458	device_t *devlistp;
1459	int devcnt;
1460	struct firewire_dev_comm *fdc;
1461	u_int32_t spec, ver;
1462
1463	for(fwdev = TAILQ_FIRST(&fc->devices); fwdev != NULL;
1464			fwdev = TAILQ_NEXT(fwdev, link)){
1465		if(fwdev->status == FWDEVINIT){
1466			spec = getcsrdata(fwdev, CSRKEY_SPEC);
1467			if(spec == 0)
1468				continue;
1469			ver = getcsrdata(fwdev, CSRKEY_VER);
1470			if(ver == 0)
1471				continue;
1472			fwdev->maxrec = (fwdev->csrrom[2] >> 12) & 0xf;
1473
1474			device_printf(fc->bdev, "Device ");
1475			switch(spec){
1476			case CSRVAL_ANSIT10:
1477				switch(ver){
1478				case CSRVAL_T10SBP2:
1479					printf("SBP-II");
1480					break;
1481				default:
1482					break;
1483				}
1484				break;
1485			case CSRVAL_1394TA:
1486				switch(ver){
1487				case CSR_PROTAVC:
1488					printf("AV/C");
1489					break;
1490				case CSR_PROTCAL:
1491					printf("CAL");
1492					break;
1493				case CSR_PROTEHS:
1494					printf("EHS");
1495					break;
1496				case CSR_PROTHAVI:
1497					printf("HAVi");
1498					break;
1499				case CSR_PROTCAM104:
1500					printf("1394 Cam 1.04");
1501					break;
1502				case CSR_PROTCAM120:
1503					printf("1394 Cam 1.20");
1504					break;
1505				case CSR_PROTCAM130:
1506					printf("1394 Cam 1.30");
1507					break;
1508				case CSR_PROTDPP:
1509					printf("1394 Direct print");
1510					break;
1511				case CSR_PROTIICP:
1512					printf("Industrial & Instrument");
1513					break;
1514				default:
1515					printf("unknown 1394TA");
1516					break;
1517				}
1518				break;
1519			default:
1520				printf("unknown spec");
1521				break;
1522			}
1523			fwdev->status = FWDEVATTACHED;
1524			printf("\n");
1525		}
1526	}
1527	err = device_get_children(fc->bdev, &devlistp, &devcnt);
1528	if( err != 0 )
1529		return;
1530	for( i = 0 ; i < devcnt ; i++){
1531		if (device_get_state(devlistp[i]) >= DS_ATTACHED)  {
1532			fdc = device_get_softc(devlistp[i]);
1533			if (fdc->post_explore != NULL)
1534				fdc->post_explore(fdc);
1535		}
1536	}
1537	free(devlistp, M_TEMP);
1538
1539	/* call pending handlers */
1540	i = 0;
1541	while ((xfer = STAILQ_FIRST(&fc->pending))) {
1542		STAILQ_REMOVE_HEAD(&fc->pending, link);
1543		i++;
1544		if (xfer->act.hand)
1545			xfer->act.hand(xfer);
1546	}
1547	if (i > 0)
1548		printf("fw_attach_dev: %d pending handlers called\n", i);
1549	if (fc->retry_count > 0) {
1550		printf("retry_count = %d\n", fc->retry_count);
1551		fc->retry_probe_handle = timeout((timeout_t *)fc->ibr,
1552							(void *)fc, hz*2);
1553	}
1554	return;
1555}
1556
1557/*
1558 * To allocate uniq transaction label.
1559 */
1560static int
1561fw_get_tlabel(struct firewire_comm *fc, struct fw_xfer *xfer)
1562{
1563	u_int i;
1564	struct tlabel *tl, *tmptl;
1565	int s;
1566	static u_int32_t label = 0;
1567
1568	s = splfw();
1569	for( i = 0 ; i < 0x40 ; i ++){
1570		label = (label + 1) & 0x3f;
1571		for(tmptl = STAILQ_FIRST(&fc->tlabels[label]);
1572			tmptl != NULL; tmptl = STAILQ_NEXT(tmptl, link)){
1573			if(tmptl->xfer->dst == xfer->dst) break;
1574		}
1575		if(tmptl == NULL) {
1576			tl = malloc(sizeof(struct tlabel),M_DEVBUF,M_NOWAIT);
1577			if (tl == NULL) {
1578				splx(s);
1579				return (-1);
1580			}
1581			tl->xfer = xfer;
1582			STAILQ_INSERT_TAIL(&fc->tlabels[label], tl, link);
1583			splx(s);
1584			return(label);
1585		}
1586	}
1587	splx(s);
1588
1589	printf("fw_get_tlabel: no free tlabel\n");
1590	return(-1);
1591}
1592
1593/*
1594 * Generic packet receving process.
1595 */
1596void
1597fw_rcv(struct firewire_comm* fc, caddr_t buf, u_int len, u_int sub, u_int off, u_int spd)
1598{
1599	struct fw_pkt *fp, *resfp;
1600	struct fw_xfer *xfer;
1601	struct fw_bind *bind;
1602	struct firewire_softc *sc;
1603	int s;
1604#if 0
1605	{
1606		u_int32_t *qld;
1607		int i;
1608		qld = (u_int32_t *)buf;
1609		printf("spd %d len:%d\n", spd, len);
1610		for( i = 0 ; i <= len && i < 32; i+= 4){
1611			printf("0x%08x ", ntohl(qld[i/4]));
1612			if((i % 16) == 15) printf("\n");
1613		}
1614		if((i % 16) != 15) printf("\n");
1615	}
1616#endif
1617	fp = (struct fw_pkt *)(buf + off);
1618	switch(fp->mode.common.tcode){
1619	case FWTCODE_WRES:
1620	case FWTCODE_RRESQ:
1621	case FWTCODE_RRESB:
1622	case FWTCODE_LRES:
1623		xfer = fw_tl2xfer(fc, ntohs(fp->mode.hdr.src),
1624					fp->mode.hdr.tlrt >> 2);
1625		if(xfer == NULL) {
1626			printf("fw_rcv: unknown response "
1627					"tcode=%d src=0x%x tl=%x rt=%d data=0x%x\n",
1628					fp->mode.common.tcode,
1629					ntohs(fp->mode.hdr.src),
1630					fp->mode.hdr.tlrt >> 2,
1631					fp->mode.hdr.tlrt & 3,
1632					fp->mode.rresq.data);
1633#if 1
1634			printf("try ad-hoc work around!!\n");
1635			xfer = fw_tl2xfer(fc, ntohs(fp->mode.hdr.src),
1636					(fp->mode.hdr.tlrt >> 2)^3);
1637			if (xfer == NULL) {
1638				printf("no use...\n");
1639				goto err;
1640			}
1641#else
1642			goto err;
1643#endif
1644		}
1645		switch(xfer->act_type){
1646		case FWACT_XFER:
1647			if((xfer->sub >= 0) &&
1648				((fc->ir[xfer->sub]->flag & FWXFERQ_MODEMASK ) == 0)){
1649				xfer->resp = EINVAL;
1650				fw_xfer_done(xfer);
1651				goto err;
1652			}
1653			xfer->recv.len = len;
1654			xfer->recv.off = off;
1655			xfer->recv.buf = buf;
1656			xfer->resp = 0;
1657			fw_xfer_done(xfer);
1658			return;
1659			break;
1660		case FWACT_CH:
1661		default:
1662			goto err;
1663			break;
1664		}
1665		break;
1666	case FWTCODE_WREQQ:
1667	case FWTCODE_WREQB:
1668	case FWTCODE_RREQQ:
1669	case FWTCODE_RREQB:
1670	case FWTCODE_LREQ:
1671		bind = fw_bindlookup(fc, ntohs(fp->mode.rreqq.dest_hi),
1672			ntohl(fp->mode.rreqq.dest_lo));
1673		if(bind == NULL){
1674#if __FreeBSD_version >= 500000
1675			printf("Unknown service addr 0x%08x:0x%08x tcode=%x\n",
1676#else
1677			printf("Unknown service addr 0x%08x:0x%08lx tcode=%x\n",
1678#endif
1679				ntohs(fp->mode.rreqq.dest_hi),
1680				ntohl(fp->mode.rreqq.dest_lo),
1681				fp->mode.common.tcode);
1682			if (fc->status == FWBUSRESET) {
1683				printf("fw_rcv: cannot response(bus reset)!\n");
1684				goto err;
1685			}
1686			xfer = fw_xfer_alloc();
1687			if(xfer == NULL){
1688				return;
1689			}
1690			xfer->spd = spd;
1691			xfer->send.buf = malloc(16, M_DEVBUF, M_NOWAIT);
1692			resfp = (struct fw_pkt *)xfer->send.buf;
1693			switch(fp->mode.common.tcode){
1694			case FWTCODE_WREQQ:
1695			case FWTCODE_WREQB:
1696				resfp->mode.hdr.tcode = FWTCODE_WRES;
1697				xfer->send.len = 12;
1698				break;
1699			case FWTCODE_RREQQ:
1700				resfp->mode.hdr.tcode = FWTCODE_RRESQ;
1701				xfer->send.len = 16;
1702				break;
1703			case FWTCODE_RREQB:
1704				resfp->mode.hdr.tcode = FWTCODE_RRESB;
1705				xfer->send.len = 16;
1706				break;
1707			case FWTCODE_LREQ:
1708				resfp->mode.hdr.tcode = FWTCODE_LRES;
1709				xfer->send.len = 16;
1710				break;
1711			}
1712			resfp->mode.hdr.dst = fp->mode.hdr.src;
1713			resfp->mode.hdr.tlrt = fp->mode.hdr.tlrt;
1714			resfp->mode.hdr.pri = fp->mode.hdr.pri;
1715			resfp->mode.rresb.rtcode = 7;
1716			resfp->mode.rresb.extcode = 0;
1717			resfp->mode.rresb.len = 0;
1718/*
1719			xfer->act.hand = fw_asy_callback;
1720*/
1721			xfer->act.hand = fw_xfer_free;
1722			if(fw_asyreq(fc, -1, xfer)){
1723				fw_xfer_free( xfer);
1724				return;
1725			}
1726			goto err;
1727		}
1728		switch(bind->xfer->act_type){
1729		case FWACT_XFER:
1730			xfer = fw_xfer_alloc();
1731			if(xfer == NULL) goto err;
1732			xfer->fc = bind->xfer->fc;
1733			xfer->sc = bind->xfer->sc;
1734			xfer->recv.buf = buf;
1735			xfer->recv.len = len;
1736			xfer->recv.off = off;
1737			xfer->spd = spd;
1738			xfer->act.hand = bind->xfer->act.hand;
1739			if (fc->status != FWBUSRESET)
1740				xfer->act.hand(xfer);
1741			else
1742				STAILQ_INSERT_TAIL(&fc->pending, xfer, link);
1743			return;
1744			break;
1745		case FWACT_CH:
1746			if(fc->ir[bind->xfer->sub]->queued >=
1747				fc->ir[bind->xfer->sub]->maxq){
1748				device_printf(fc->bdev,
1749					"Discard a packet %x %d\n",
1750					bind->xfer->sub,
1751					fc->ir[bind->xfer->sub]->queued);
1752				goto err;
1753			}
1754			xfer = fw_xfer_alloc();
1755			if(xfer == NULL) goto err;
1756			xfer->recv.buf = buf;
1757			xfer->recv.len = len;
1758			xfer->recv.off = off;
1759			xfer->spd = spd;
1760			s = splfw();
1761			fc->ir[bind->xfer->sub]->queued++;
1762			STAILQ_INSERT_TAIL(&fc->ir[bind->xfer->sub]->q, xfer, link);
1763			splx(s);
1764
1765			wakeup((caddr_t)fc->ir[bind->xfer->sub]);
1766
1767			return;
1768			break;
1769		default:
1770			goto err;
1771			break;
1772		}
1773		break;
1774	case FWTCODE_STREAM:
1775	{
1776		struct fw_xferq *xferq;
1777
1778		xferq = fc->ir[sub];
1779#if 0
1780		printf("stream rcv dma %d len %d off %d spd %d\n",
1781			sub, len, off, spd);
1782#endif
1783		if(xferq->queued >= xferq->maxq) {
1784			printf("receive queue is full\n");
1785			goto err;
1786		}
1787		xfer = fw_xfer_alloc();
1788		if(xfer == NULL) goto err;
1789		xfer->recv.buf = buf;
1790		xfer->recv.len = len;
1791		xfer->recv.off = off;
1792		xfer->spd = spd;
1793		s = splfw();
1794		xferq->queued++;
1795		STAILQ_INSERT_TAIL(&xferq->q, xfer, link);
1796		splx(s);
1797		sc = device_get_softc(fc->bdev);
1798#if __FreeBSD_version >= 500000
1799		if (SEL_WAITING(&xferq->rsel))
1800#else
1801		if (&xferq->rsel.si_pid != 0)
1802#endif
1803			selwakeup(&xferq->rsel);
1804		if (xferq->flag & FWXFERQ_WAKEUP) {
1805			xferq->flag &= ~FWXFERQ_WAKEUP;
1806			wakeup((caddr_t)xferq);
1807		}
1808		if (xferq->flag & FWXFERQ_HANDLER) {
1809			xferq->hand(xferq);
1810		}
1811		return;
1812		break;
1813	}
1814	default:
1815		printf("fw_rcv: unknow tcode\n");
1816		break;
1817	}
1818err:
1819	free(buf, M_DEVBUF);
1820}
1821
1822/*
1823 * Post process for Bus Manager election process.
1824 */
1825static void
1826fw_try_bmr_callback(struct fw_xfer *xfer)
1827{
1828	struct fw_pkt *rfp;
1829	struct firewire_comm *fc;
1830	int bmr;
1831
1832	if (xfer == NULL)
1833		return;
1834	fc = xfer->fc;
1835	if (xfer->resp != 0)
1836		goto error;
1837	if (xfer->send.buf == NULL)
1838		goto error;
1839	if (xfer->recv.buf == NULL)
1840		goto error;
1841	rfp = (struct fw_pkt *)xfer->recv.buf;
1842	if (rfp->mode.lres.rtcode != FWRCODE_COMPLETE)
1843		goto error;
1844
1845	bmr = ntohl(rfp->mode.lres.payload[0]);
1846	if (bmr == 0x3f)
1847		bmr = fc->nodeid;
1848
1849	CSRARC(fc, BUS_MGR_ID) = fc->set_bmr(fc, bmr & 0x3f);
1850	device_printf(fc->bdev, "new bus manager %d ",
1851		CSRARC(fc, BUS_MGR_ID));
1852	if(bmr == fc->nodeid){
1853		printf("(me)\n");
1854/* If I am bus manager, optimize gapcount */
1855		if(fc->max_hop <= MAX_GAPHOP ){
1856			fw_phy_config(fc, -1, gap_cnt[fc->max_hop]);
1857		}
1858	}else{
1859		printf("\n");
1860	}
1861error:
1862	fw_xfer_free(xfer);
1863}
1864
1865/*
1866 * To candidate Bus Manager election process.
1867 */
1868void
1869fw_try_bmr(void *arg)
1870{
1871	struct fw_xfer *xfer;
1872	struct firewire_comm *fc = (struct firewire_comm *)arg;
1873	struct fw_pkt *fp;
1874	int err = 0;
1875
1876	xfer = fw_xfer_alloc();
1877	if(xfer == NULL){
1878		return;
1879	}
1880	xfer->send.len = 24;
1881	xfer->spd = 0;
1882	xfer->send.buf = malloc(24, M_DEVBUF, M_NOWAIT);
1883	if(xfer->send.buf == NULL){
1884		fw_xfer_free( xfer);
1885		return;
1886	}
1887
1888	fc->status = FWBUSMGRELECT;
1889
1890	xfer->send.off = 0;
1891	fp = (struct fw_pkt *)xfer->send.buf;
1892	fp->mode.lreq.dest_hi = htons(0xffff);
1893	fp->mode.lreq.tlrt = 0;
1894	fp->mode.lreq.tcode = FWTCODE_LREQ;
1895	fp->mode.lreq.pri = 0;
1896	fp->mode.lreq.src = 0;
1897	fp->mode.lreq.len = htons(8);
1898	fp->mode.lreq.extcode = htons(FW_LREQ_CMPSWAP);
1899	xfer->dst = FWLOCALBUS | fc->irm;
1900	fp->mode.lreq.dst = htons(xfer->dst);
1901	fp->mode.lreq.dest_lo = htonl(0xf0000000 | BUS_MGR_ID);
1902	fp->mode.lreq.payload[0] = htonl(0x3f);
1903	fp->mode.lreq.payload[1] = htonl(fc->nodeid);
1904	xfer->act_type = FWACT_XFER;
1905	xfer->act.hand = fw_try_bmr_callback;
1906
1907	err = fw_asyreq(fc, -1, xfer);
1908	if(err){
1909		fw_xfer_free( xfer);
1910		return;
1911	}
1912	return;
1913}
1914
1915#ifdef FW_VMACCESS
1916/*
1917 * Software implementation for physical memory block access.
1918 * XXX:Too slow, usef for debug purpose only.
1919 */
1920static void
1921fw_vmaccess(struct fw_xfer *xfer){
1922	struct fw_pkt *rfp, *sfp = NULL;
1923	u_int32_t *ld = (u_int32_t *)(xfer->recv.buf + xfer->recv.off);
1924
1925	printf("vmaccess spd:%2x len:%03x %d data:%08x %08x %08x %08x\n",
1926			xfer->spd, xfer->recv.len, xfer->recv.off, ntohl(ld[0]), ntohl(ld[1]), ntohl(ld[2]), ntohl(ld[3]));
1927	printf("vmaccess          data:%08x %08x %08x %08x\n", ntohl(ld[4]), ntohl(ld[5]), ntohl(ld[6]), ntohl(ld[7]));
1928	if(xfer->resp != 0){
1929		fw_xfer_free( xfer);
1930		return;
1931	}
1932	if(xfer->recv.buf == NULL){
1933		fw_xfer_free( xfer);
1934		return;
1935	}
1936	rfp = (struct fw_pkt *)xfer->recv.buf;
1937	switch(rfp->mode.hdr.tcode){
1938		/* XXX need fix for 64bit arch */
1939		case FWTCODE_WREQB:
1940			xfer->send.buf = malloc(12, M_DEVBUF, M_NOWAIT);
1941			xfer->send.len = 12;
1942			sfp = (struct fw_pkt *)xfer->send.buf;
1943			bcopy(rfp->mode.wreqb.payload,
1944				(caddr_t)ntohl(rfp->mode.wreqb.dest_lo), ntohs(rfp->mode.wreqb.len));
1945			sfp->mode.wres.tcode = FWTCODE_WRES;
1946			sfp->mode.wres.rtcode = 0;
1947			break;
1948		case FWTCODE_WREQQ:
1949			xfer->send.buf = malloc(12, M_DEVBUF, M_NOWAIT);
1950			xfer->send.len = 12;
1951			sfp->mode.wres.tcode = FWTCODE_WRES;
1952			*((u_int32_t *)(ntohl(rfp->mode.wreqb.dest_lo))) = rfp->mode.wreqq.data;
1953			sfp->mode.wres.rtcode = 0;
1954			break;
1955		case FWTCODE_RREQB:
1956			xfer->send.buf = malloc(16 + rfp->mode.rreqb.len, M_DEVBUF, M_NOWAIT);
1957			xfer->send.len = 16 + ntohs(rfp->mode.rreqb.len);
1958			sfp = (struct fw_pkt *)xfer->send.buf;
1959			bcopy((caddr_t)ntohl(rfp->mode.rreqb.dest_lo),
1960				sfp->mode.rresb.payload, (u_int16_t)ntohs(rfp->mode.rreqb.len));
1961			sfp->mode.rresb.tcode = FWTCODE_RRESB;
1962			sfp->mode.rresb.len = rfp->mode.rreqb.len;
1963			sfp->mode.rresb.rtcode = 0;
1964			sfp->mode.rresb.extcode = 0;
1965			break;
1966		case FWTCODE_RREQQ:
1967			xfer->send.buf = malloc(16, M_DEVBUF, M_NOWAIT);
1968			xfer->send.len = 16;
1969			sfp = (struct fw_pkt *)xfer->send.buf;
1970			sfp->mode.rresq.data = *(u_int32_t *)(ntohl(rfp->mode.rreqq.dest_lo));
1971			sfp->mode.wres.tcode = FWTCODE_RRESQ;
1972			sfp->mode.rresb.rtcode = 0;
1973			break;
1974		default:
1975			fw_xfer_free( xfer);
1976			return;
1977	}
1978	xfer->send.off = 0;
1979	sfp->mode.hdr.dst = rfp->mode.hdr.src;
1980	xfer->dst = ntohs(rfp->mode.hdr.src);
1981	xfer->act.hand = fw_xfer_free;
1982	xfer->retry_req = fw_asybusy;
1983
1984	sfp->mode.hdr.tlrt = rfp->mode.hdr.tlrt;
1985	sfp->mode.hdr.pri = 0;
1986
1987	fw_asyreq(xfer->fc, -1, xfer);
1988/**/
1989	return;
1990}
1991#endif
1992
1993/*
1994 * CRC16 check-sum for IEEE1394 register blocks.
1995 */
1996u_int16_t
1997fw_crc16(u_int32_t *ptr, u_int32_t len){
1998	u_int32_t i, sum, crc = 0;
1999	int shift;
2000	len = (len + 3) & ~3;
2001	for(i = 0 ; i < len ; i+= 4){
2002		for( shift = 28 ; shift >= 0 ; shift -= 4){
2003			sum = ((crc >> 12) ^ (ptr[i/4] >> shift)) & 0xf;
2004			crc = (crc << 4) ^ ( sum << 12 ) ^ ( sum << 5) ^ sum;
2005		}
2006		crc &= 0xffff;
2007	}
2008	return((u_int16_t) crc);
2009}
2010
2011DRIVER_MODULE(firewire,fwohci,firewire_driver,firewire_devclass,0,0);
2012MODULE_VERSION(firewire, 1);
2013