firewire.c revision 110195
1185377Ssam/*
2187831Ssam * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa
3185377Ssam * All rights reserved.
4185377Ssam *
5185377Ssam * Redistribution and use in source and binary forms, with or without
6185377Ssam * modification, are permitted provided that the following conditions
7185377Ssam * are met:
8185377Ssam * 1. Redistributions of source code must retain the above copyright
9185377Ssam *    notice, this list of conditions and the following disclaimer.
10185377Ssam * 2. Redistributions in binary form must reproduce the above copyright
11185377Ssam *    notice, this list of conditions and the following disclaimer in the
12185377Ssam *    documentation and/or other materials provided with the distribution.
13185377Ssam * 3. All advertising materials mentioning features or use of this software
14185377Ssam *    must display the acknowledgement as bellow:
15185377Ssam *
16185377Ssam *    This product includes software developed by K. Kobayashi and H. Shimokawa
17187831Ssam *
18185377Ssam * 4. The name of the author may not be used to endorse or promote products
19185377Ssam *    derived from this software without specific prior written permission.
20185377Ssam *
21185377Ssam * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22185377Ssam * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23185377Ssam * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24185377Ssam * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25185377Ssam * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26185377Ssam * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27185377Ssam * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28185377Ssam * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29185377Ssam * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30185377Ssam * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31185377Ssam * POSSIBILITY OF SUCH DAMAGE.
32185377Ssam *
33185377Ssam * $FreeBSD: head/sys/dev/firewire/firewire.c 110195 2003-02-01 15:04:33Z simokawa $
34185377Ssam *
35185377Ssam */
36185377Ssam
37185377Ssam#include <sys/param.h>
38185377Ssam#include <sys/systm.h>
39185377Ssam#include <sys/types.h>
40185377Ssam#include <sys/mbuf.h>
41185377Ssam#include <sys/socket.h>
42185377Ssam#include <sys/socketvar.h>
43185377Ssam
44185377Ssam#include <sys/kernel.h>
45185377Ssam#include <sys/malloc.h>
46185377Ssam#include <sys/conf.h>
47185377Ssam#include <sys/uio.h>
48185377Ssam#include <sys/sysctl.h>
49185377Ssam
50185377Ssam#include <machine/cpufunc.h>    /* for rdtsc proto for clock.h below */
51185377Ssam#include <machine/clock.h>
52185377Ssam
53185377Ssam#include <sys/bus.h>		/* used by smbus and newbus */
54185377Ssam
55185377Ssam#include <dev/firewire/firewire.h>
56185377Ssam#include <dev/firewire/firewirereg.h>
57185377Ssam#include <dev/firewire/fwmem.h>
58185377Ssam#include <dev/firewire/iec13213.h>
59185377Ssam#include <dev/firewire/iec68113.h>
60185377Ssam
61185377Ssamint firewire_debug=0, try_bmr=1;
62185377SsamSYSCTL_INT(_debug, OID_AUTO, firewire_debug, CTLFLAG_RW, &firewire_debug, 0,
63185377Ssam	"FireWire driver debug flag");
64185377SsamSYSCTL_NODE(_hw, OID_AUTO, firewire, CTLFLAG_RD, 0, "FireWire Subsystem");
65185377SsamSYSCTL_INT(_hw_firewire, OID_AUTO, try_bmr, CTLFLAG_RW, &try_bmr, 0,
66185377Ssam	"Try to be a bus manager");
67185377Ssam
68185377SsamMALLOC_DEFINE(M_FW, "firewire", "FireWire");
69185377Ssam
70185377Ssam#define FW_MAXASYRTY 4
71185377Ssam#define FW_MAXDEVRCNT 4
72185377Ssam
73185377Ssam#define XFER_TIMEOUT 0
74185377Ssam
75185377Ssamdevclass_t firewire_devclass;
76185377Ssam
77185377Ssamstatic int firewire_match      __P((device_t));
78185377Ssamstatic int firewire_attach      __P((device_t));
79185377Ssamstatic int firewire_detach      __P((device_t));
80185377Ssam#if 0
81185377Ssamstatic int firewire_shutdown    __P((device_t));
82185377Ssam#endif
83185377Ssamstatic device_t firewire_add_child   __P((device_t, int, const char *, int));
84185377Ssamstatic void fw_try_bmr __P((void *));
85185377Ssamstatic void fw_try_bmr_callback __P((struct fw_xfer *));
86185377Ssamstatic void fw_asystart __P((struct fw_xfer *));
87185377Ssamstatic int fw_get_tlabel __P((struct firewire_comm *, struct fw_xfer *));
88185377Ssamstatic void fw_bus_probe __P((struct firewire_comm *));
89185377Ssamstatic void fw_bus_explore __P((struct firewire_comm *));
90185377Ssamstatic void fw_bus_explore_callback __P((struct fw_xfer *));
91185377Ssamstatic void fw_attach_dev __P((struct firewire_comm *));
92185377Ssam#ifdef FW_VMACCESS
93185377Ssamstatic void fw_vmaccess __P((struct fw_xfer *));
94185377Ssam#endif
95185377Ssamstruct fw_xfer *asyreqq __P((struct firewire_comm *, u_int8_t, u_int8_t, u_int8_t,
96185377Ssam	u_int32_t, u_int32_t, void (*)__P((struct fw_xfer *))));
97185377Ssamstatic int fw_bmr __P((struct firewire_comm *));
98185377Ssam
99185377Ssamstatic device_method_t firewire_methods[] = {
100185377Ssam	/* Device interface */
101185377Ssam	DEVMETHOD(device_probe,		firewire_match),
102185377Ssam	DEVMETHOD(device_attach,	firewire_attach),
103185377Ssam	DEVMETHOD(device_detach,	firewire_detach),
104185377Ssam	DEVMETHOD(device_suspend,	bus_generic_suspend),
105185377Ssam	DEVMETHOD(device_resume,	bus_generic_resume),
106185377Ssam	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
107185377Ssam
108185377Ssam	/* Bus interface */
109185377Ssam	DEVMETHOD(bus_add_child,	firewire_add_child),
110185377Ssam	DEVMETHOD(bus_print_child,	bus_generic_print_child),
111185377Ssam
112185377Ssam	{ 0, 0 }
113185377Ssam};
114185377Ssamchar linkspeed[7][0x10]={"S100","S200","S400","S800","S1600","S3200","Unknown"};
115185377Ssam
116185377Ssam#define MAX_GAPHOP  16
117185377Ssamu_int gap_cnt[] = {1, 1, 4, 6, 9, 12, 14, 17,
118185377Ssam			20, 23, 25, 28, 31, 33, 36, 39, 42};
119185377Ssam
120185377Ssamextern struct cdevsw firewire_cdevsw;
121185377Ssam
122185377Ssamstatic driver_t firewire_driver = {
123185377Ssam	"firewire",
124185377Ssam	firewire_methods,
125185377Ssam	sizeof(struct firewire_softc),
126185377Ssam};
127185377Ssam
128185377Ssam/*
129185377Ssam * Lookup fwdev by node id.
130185377Ssam */
131185377Ssamstruct fw_device *
132185377Ssamfw_noderesolve_nodeid(struct firewire_comm *fc, int dst)
133185377Ssam{
134185377Ssam	struct fw_device *fwdev;
135187831Ssam	int s;
136185377Ssam
137187831Ssam	s = splfw();
138187831Ssam	STAILQ_FOREACH(fwdev, &fc->devices, link)
139185377Ssam		if (fwdev->dst == dst)
140187831Ssam			break;
141185377Ssam	splx(s);
142185377Ssam
143185377Ssam	if(fwdev == NULL) return NULL;
144187831Ssam	if(fwdev->status == FWDEVINVAL) return NULL;
145187831Ssam	return fwdev;
146187831Ssam}
147185377Ssam
148185377Ssam/*
149185377Ssam * Lookup fwdev by EUI64.
150185377Ssam */
151185377Ssamstruct fw_device *
152185377Ssamfw_noderesolve_eui64(struct firewire_comm *fc, struct fw_eui64 eui)
153185377Ssam{
154185377Ssam	struct fw_device *fwdev;
155185377Ssam	int s;
156185377Ssam
157185377Ssam	s = splfw();
158185377Ssam	STAILQ_FOREACH(fwdev, &fc->devices, link)
159185377Ssam		if (FW_EUI64_EQUAL(fwdev->eui, eui))
160185377Ssam			break;
161185377Ssam	splx(s);
162185377Ssam
163185377Ssam	if(fwdev == NULL) return NULL;
164185377Ssam	if(fwdev->status == FWDEVINVAL) return NULL;
165185377Ssam	return fwdev;
166185377Ssam}
167185377Ssam
168185377Ssam/*
169185377Ssam * Async. request procedure for userland application.
170185377Ssam */
171185377Ssamint
172185377Ssamfw_asyreq(struct firewire_comm *fc, int sub, struct fw_xfer *xfer)
173185377Ssam{
174185377Ssam	int err = 0;
175185377Ssam	struct fw_xferq *xferq;
176185377Ssam	int tl = 0, len;
177185377Ssam	struct fw_pkt *fp;
178185377Ssam	int tcode;
179185377Ssam	struct tcode_info *info;
180185377Ssam
181185377Ssam	if(xfer == NULL) return EINVAL;
182185377Ssam	if(xfer->send.len > MAXREC(fc->maxrec)){
183185377Ssam		printf("send.len > maxrec\n");
184185377Ssam		return EINVAL;
185185377Ssam	}
186185377Ssam	if(xfer->act.hand == NULL){
187185377Ssam		printf("act.hand == NULL\n");
188185377Ssam		return EINVAL;
189185377Ssam	}
190185377Ssam	fp = (struct fw_pkt *)xfer->send.buf;
191185377Ssam
192185377Ssam	tcode = fp->mode.common.tcode & 0xf;
193185377Ssam	info = &fc->tcode[tcode];
194185377Ssam	if (info->flag == 0) {
195185377Ssam		printf("invalid tcode=%d\n", tcode);
196185377Ssam		return EINVAL;
197185377Ssam	}
198185377Ssam	if (info->flag & FWTI_REQ)
199185377Ssam		xferq = fc->atq;
200185377Ssam	else
201185377Ssam		xferq = fc->ats;
202185377Ssam	len = info->hdr_len;
203185377Ssam	if (info->flag & FWTI_BLOCK_STR)
204185377Ssam		len += ntohs(fp->mode.stream.len);
205185377Ssam	else if (info->flag & FWTI_BLOCK_ASY)
206185377Ssam		len += ntohs(fp->mode.rresb.len);
207185377Ssam	if( len >  xfer->send.len ){
208185377Ssam		printf("len(%d) > send.len(%d) (tcode=%d)\n",
209185377Ssam				len, xfer->send.len, tcode);
210185377Ssam		return EINVAL;
211185377Ssam	}
212185377Ssam	xfer->send.len = len;
213185377Ssam
214185377Ssam	if(xferq->start == NULL){
215185377Ssam		printf("xferq->start == NULL\n");
216185377Ssam		return EINVAL;
217185377Ssam	}
218185377Ssam	if(!(xferq->queued < xferq->maxq)){
219185377Ssam		device_printf(fc->bdev, "Discard a packet (queued=%d)\n",
220185377Ssam			xferq->queued);
221185377Ssam		return EINVAL;
222185377Ssam	}
223185377Ssam
224185377Ssam
225185377Ssam	if (info->flag & FWTI_TLABEL) {
226185377Ssam		if((tl = fw_get_tlabel(fc, xfer)) == -1 )
227185377Ssam			return EIO;
228185377Ssam		fp->mode.hdr.tlrt = tl << 2;
229185377Ssam	}
230185377Ssam
231185377Ssam	xfer->tl = tl;
232185377Ssam	xfer->tcode = tcode;
233185377Ssam	xfer->resp = 0;
234185377Ssam	xfer->fc = fc;
235185377Ssam	xfer->q = xferq;
236185377Ssam	xfer->act_type = FWACT_XFER;
237185377Ssam	xfer->retry_req = fw_asybusy;
238185377Ssam
239185377Ssam	fw_asystart(xfer);
240185377Ssam	return err;
241185377Ssam}
242185377Ssam/*
243185377Ssam * Wakeup blocked process.
244185377Ssam */
245185377Ssamvoid
246185377Ssamfw_asy_callback(struct fw_xfer *xfer){
247185377Ssam	wakeup(xfer);
248185377Ssam	return;
249185377Ssam}
250185377Ssam/*
251185377Ssam * Postpone to later retry.
252185377Ssam */
253185377Ssamvoid fw_asybusy(struct fw_xfer *xfer){
254185377Ssam#if 1
255226760Sadrian	printf("fw_asybusy\n");
256185377Ssam#endif
257185377Ssam#if XFER_TIMEOUT
258185377Ssam	untimeout(fw_xfer_timeout, (void *)xfer, xfer->ch);
259185377Ssam#endif
260185377Ssam/*
261185377Ssam	xfer->ch =  timeout((timeout_t *)fw_asystart, (void *)xfer, 20000);
262185377Ssam*/
263185377Ssam	DELAY(20000);
264185377Ssam	fw_asystart(xfer);
265185377Ssam	return;
266185377Ssam}
267185377Ssam#if XFER_TIMEOUT
268185377Ssam/*
269185377Ssam * Post timeout for async. request.
270185380Ssam */
271185377Ssamvoid
272185380Ssamfw_xfer_timeout(void *arg)
273185377Ssam{
274185380Ssam	int s;
275185380Ssam	struct fw_xfer *xfer;
276185377Ssam
277185377Ssam	xfer = (struct fw_xfer *)arg;
278185377Ssam	printf("fw_xfer_timeout status=%d resp=%d\n", xfer->state, xfer->resp);
279185377Ssam	/* XXX set error code */
280185377Ssam	s = splfw();
281185377Ssam	xfer->act.hand(xfer);
282185377Ssam	splx(s);
283185377Ssam}
284185377Ssam#endif
285185377Ssam/*
286185377Ssam * Async. request with given xfer structure.
287185377Ssam */
288185380Ssamstatic void
289185380Ssamfw_asystart(struct fw_xfer *xfer)
290185377Ssam{
291185377Ssam	struct firewire_comm *fc = xfer->fc;
292185377Ssam	int s;
293185377Ssam	if(xfer->retry++ >= fc->max_asyretry){
294185377Ssam		xfer->resp = EBUSY;
295185377Ssam		xfer->state = FWXF_BUSY;
296185377Ssam		xfer->act.hand(xfer);
297185377Ssam		return;
298185377Ssam	}
299185377Ssam#if 0 /* XXX allow bus explore packets only after bus rest */
300185377Ssam	if (fc->status < FWBUSEXPLORE) {
301185377Ssam		xfer->resp = EAGAIN;
302185377Ssam		xfer->state = FWXF_BUSY;
303185377Ssam		if (xfer->act.hand != NULL)
304185377Ssam			xfer->act.hand(xfer);
305185377Ssam		return;
306185377Ssam	}
307185377Ssam#endif
308185377Ssam	s = splfw();
309185377Ssam	xfer->state = FWXF_INQ;
310185377Ssam	STAILQ_INSERT_TAIL(&xfer->q->q, xfer, link);
311185377Ssam	xfer->q->queued ++;
312185377Ssam	splx(s);
313185377Ssam	/* XXX just queue for mbuf */
314185377Ssam	if (xfer->mbuf == NULL)
315185377Ssam		xfer->q->start(fc);
316185377Ssam#if XFER_TIMEOUT
317185377Ssam	if (xfer->act.hand != NULL)
318185377Ssam		xfer->ch = timeout(fw_xfer_timeout, (void *)xfer, hz);
319185377Ssam#endif
320185377Ssam	return;
321185377Ssam}
322187831Ssam
323234774Sadrianstatic int
324185377Ssamfirewire_match( device_t dev )
325222265Sadrian{
326222265Sadrian	device_set_desc(dev, "IEEE1394(FireWire) bus");
327222265Sadrian	return -140;
328185377Ssam}
329185377Ssam
330185377Ssam/*
331185377Ssam * The attach routine.
332185377Ssam */
333185377Ssamstatic int
334218012Sadrianfirewire_attach( device_t dev )
335204579Srpaulo{
336204579Srpaulo	int i, unitmask, mn;
337204579Srpaulo	struct firewire_softc *sc = device_get_softc(dev);
338185377Ssam	device_t pa = device_get_parent(dev);
339185377Ssam	struct firewire_comm *fc;
340185377Ssam	dev_t d;
341185380Ssam
342185380Ssam	fc = (struct firewire_comm *)device_get_softc(pa);
343185380Ssam	sc->fc = fc;
344185380Ssam
345185380Ssam	unitmask = UNIT2MIN(device_get_unit(dev));
346185380Ssam
347185380Ssam	if( fc->nisodma > FWMAXNDMA) fc->nisodma = FWMAXNDMA;
348185377Ssam	for ( i = 0 ; i < fc->nisodma ; i++ ){
349185377Ssam		mn = unitmask | i;
350185377Ssam		/* XXX device name should be improved */
351185377Ssam		d = make_dev(&firewire_cdevsw, unit2minor(mn),
352185377Ssam			UID_ROOT, GID_OPERATOR, 0660,
353185377Ssam			"fw%x", mn);
354185377Ssam#if __FreeBSD_version >= 500000
355185377Ssam		if (i == 0)
356185377Ssam			sc->dev = d;
357185377Ssam		else
358185377Ssam			dev_depends(sc->dev, d);
359185377Ssam#else
360185377Ssam		sc->dev[i] = d;
361185377Ssam#endif
362185377Ssam	}
363185377Ssam	d = make_dev(&firewire_cdevsw, unit2minor(unitmask | FWMEM_FLAG),
364185377Ssam			UID_ROOT, GID_OPERATOR, 0660,
365185377Ssam			"fwmem%d", device_get_unit(dev));
366185377Ssam#if __FreeBSD_version >= 500000
367185380Ssam	dev_depends(sc->dev, d);
368185380Ssam#else
369185380Ssam	sc->dev[i] = d;
370185380Ssam#endif
371185380Ssam#if __FreeBSD_version >= 500000
372185380Ssam#define CALLOUT_INIT(x) callout_init(x, 0 /* mpsafe */)
373185380Ssam#else
374185380Ssam#define CALLOUT_INIT(x) callout_init(x)
375185380Ssam#endif
376185380Ssam	CALLOUT_INIT(&sc->fc->timeout_callout);
377185380Ssam	CALLOUT_INIT(&sc->fc->bmr_callout);
378185380Ssam	CALLOUT_INIT(&sc->fc->retry_probe_callout);
379185380Ssam	CALLOUT_INIT(&sc->fc->busprobe_callout);
380185380Ssam
381185380Ssam	callout_reset(&sc->fc->timeout_callout, hz * 10,
382185380Ssam			(void *)sc->fc->timeout, (void *)sc->fc);
383185380Ssam
384185380Ssam	/* Locate our children */
385185380Ssam	bus_generic_probe(dev);
386185380Ssam
387185380Ssam	/* launch attachement of the added children */
388185380Ssam	bus_generic_attach(dev);
389185380Ssam
390185377Ssam	/* bus_reset */
391185377Ssam	fc->ibr(fc);
392185377Ssam
393185377Ssam	return 0;
394185377Ssam}
395185377Ssam
396185377Ssam/*
397185377Ssam * Attach it as child.
398185377Ssam */
399185377Ssamstatic device_t
400185377Ssamfirewire_add_child(device_t dev, int order, const char *name, int unit)
401185377Ssam{
402185377Ssam        device_t child;
403187831Ssam	struct firewire_softc *sc;
404187831Ssam
405187831Ssam	sc = (struct firewire_softc *)device_get_softc(dev);
406185377Ssam	child = device_add_child(dev, name, unit);
407188012Ssam	if (child) {
408188012Ssam		device_set_ivars(child, sc->fc);
409185377Ssam		device_probe_and_attach(child);
410185377Ssam	}
411188012Ssam
412187831Ssam	return child;
413187831Ssam}
414185377Ssam
415185377Ssam/*
416185377Ssam * Dettach it.
417185377Ssam */
418185377Ssamstatic int
419185377Ssamfirewire_detach( device_t dev )
420185377Ssam{
421185377Ssam	struct firewire_softc *sc;
422185377Ssam
423185377Ssam	sc = (struct firewire_softc *)device_get_softc(dev);
424185377Ssam
425185377Ssam#if __FreeBSD_version >= 500000
426185377Ssam	destroy_dev(sc->dev);
427185377Ssam#else
428185377Ssam	{
429185377Ssam		int j;
430185377Ssam		for (j = 0 ; j < sc->fc->nisodma + 1; j++)
431185377Ssam			destroy_dev(sc->dev[j]);
432185377Ssam	}
433185377Ssam#endif
434185377Ssam	/* XXX xfree_free and untimeout on all xfers */
435225444Sadrian	callout_stop(&sc->fc->timeout_callout);
436185377Ssam	callout_stop(&sc->fc->bmr_callout);
437185377Ssam	callout_stop(&sc->fc->retry_probe_callout);
438185377Ssam	callout_stop(&sc->fc->busprobe_callout);
439185377Ssam	free(sc->fc->topology_map, M_FW);
440185377Ssam	free(sc->fc->speed_map, M_FW);
441185377Ssam	bus_generic_detach(dev);
442185377Ssam	return(0);
443185377Ssam}
444185377Ssam#if 0
445185377Ssamstatic int
446185377Ssamfirewire_shutdown( device_t dev )
447185377Ssam{
448185377Ssam	return 0;
449185377Ssam}
450185377Ssam#endif
451185377Ssam
452185377Ssam/*
453185377Ssam * Called after bus reset.
454185377Ssam */
455185377Ssamvoid
456185377Ssamfw_busreset(struct firewire_comm *fc)
457185377Ssam{
458185377Ssam	int i;
459185377Ssam	struct fw_xfer *xfer;
460188974Ssam
461188974Ssam	switch(fc->status){
462185377Ssam	case FWBUSMGRELECT:
463185377Ssam		callout_stop(&fc->bmr_callout);
464185377Ssam		break;
465185377Ssam	default:
466185377Ssam		break;
467185377Ssam	}
468185377Ssam	fc->status = FWBUSRESET;
469185377Ssam/* XXX: discard all queued packet */
470185377Ssam	while((xfer = STAILQ_FIRST(&fc->atq->q)) != NULL){
471219419Sadrian		STAILQ_REMOVE_HEAD(&fc->atq->q, link);
472185377Ssam		xfer->resp = EAGAIN;
473185377Ssam		switch(xfer->act_type){
474185377Ssam		case FWACT_XFER:
475185377Ssam			fw_xfer_done(xfer);
476185377Ssam			break;
477185377Ssam		default:
478185377Ssam			break;
479185377Ssam		}
480185377Ssam		fw_xfer_free( xfer);
481185377Ssam	}
482185377Ssam	while((xfer = STAILQ_FIRST(&fc->ats->q)) != NULL){
483185377Ssam		STAILQ_REMOVE_HEAD(&fc->ats->q, link);
484185377Ssam		xfer->resp = EAGAIN;
485185377Ssam		switch(xfer->act_type){
486185377Ssam		case FWACT_XFER:
487185377Ssam			fw_xfer_done(xfer);
488185377Ssam		default:
489185377Ssam			break;
490185377Ssam		}
491185377Ssam		fw_xfer_free( xfer);
492185377Ssam	}
493185377Ssam	for(i = 0; i < fc->nisodma; i++)
494185377Ssam		while((xfer = STAILQ_FIRST(&fc->it[i]->q)) != NULL){
495185377Ssam			STAILQ_REMOVE_HEAD(&fc->it[i]->q, link);
496185377Ssam			xfer->resp = 0;
497185377Ssam			switch(xfer->act_type){
498185377Ssam			case FWACT_XFER:
499185377Ssam				fw_xfer_done(xfer);
500185377Ssam				break;
501185377Ssam			default:
502185377Ssam				break;
503185377Ssam			}
504185377Ssam			fw_xfer_free( xfer);
505185377Ssam		}
506185377Ssam
507185377Ssam	CSRARC(fc, STATE_CLEAR)
508185377Ssam			= 1 << 23 | 0 << 17 | 1 << 16 | 1 << 15 | 1 << 14 ;
509185377Ssam	CSRARC(fc, STATE_SET) = CSRARC(fc, STATE_CLEAR);
510185377Ssam	CSRARC(fc, NODE_IDS) = 0x3f;
511185377Ssam
512222644Sadrian	CSRARC(fc, TOPO_MAP + 8) = 0;
513222644Sadrian	fc->irm = -1;
514234873Sadrian
515234873Sadrian	fc->max_node = -1;
516185377Ssam
517185377Ssam	for(i = 2; i < 0x100/4 - 2 ; i++){
518185377Ssam		CSRARC(fc, SPED_MAP + i * 4) = 0;
519185377Ssam	}
520185377Ssam	CSRARC(fc, STATE_CLEAR) = 1 << 23 | 0 << 17 | 1 << 16 | 1 << 15 | 1 << 14 ;
521185377Ssam	CSRARC(fc, STATE_SET) = CSRARC(fc, STATE_CLEAR);
522185377Ssam	CSRARC(fc, RESET_START) = 0;
523185377Ssam	CSRARC(fc, SPLIT_TIMEOUT_HI) = 0;
524185377Ssam	CSRARC(fc, SPLIT_TIMEOUT_LO) = 800 << 19;
525185377Ssam	CSRARC(fc, CYCLE_TIME) = 0x0;
526185377Ssam	CSRARC(fc, BUS_TIME) = 0x0;
527185377Ssam	CSRARC(fc, BUS_MGR_ID) = 0x3f;
528185377Ssam	CSRARC(fc, BANDWIDTH_AV) = 4915;
529185377Ssam	CSRARC(fc, CHANNELS_AV_HI) = 0xffffffff;
530185377Ssam	CSRARC(fc, CHANNELS_AV_LO) = 0xffffffff;
531185377Ssam	CSRARC(fc, IP_CHANNELS) = (1 << 31);
532185377Ssam
533185377Ssam	CSRARC(fc, CONF_ROM) = 0x04 << 24;
534185377Ssam	CSRARC(fc, CONF_ROM + 4) = 0x31333934; /* means strings 1394 */
535185377Ssam	CSRARC(fc, CONF_ROM + 8) = 1 << 31 | 1 << 30 | 1 << 29 |
536185377Ssam				1 << 28 | 0xff << 16 | 0x09 << 8;
537185377Ssam	CSRARC(fc, CONF_ROM + 0xc) = 0;
538185377Ssam
539185377Ssam/* DV depend CSRs see blue book */
540185377Ssam	CSRARC(fc, oPCR) &= ~DV_BROADCAST_ON;
541187831Ssam	CSRARC(fc, iPCR) &= ~DV_BROADCAST_ON;
542187831Ssam
543187831Ssam	CSRARC(fc, STATE_CLEAR) &= ~(1 << 23 | 1 << 15 | 1 << 14 );
544187831Ssam	CSRARC(fc, STATE_SET) = CSRARC(fc, STATE_CLEAR);
545185377Ssam}
546185377Ssam
547185377Ssam/* Call once after reboot */
548187831Ssamvoid fw_init(struct firewire_comm *fc)
549187831Ssam{
550187831Ssam	int i;
551187831Ssam	struct csrdir *csrd;
552187831Ssam#ifdef FW_VMACCESS
553187831Ssam	struct fw_xfer *xfer;
554187831Ssam	struct fw_bind *fwb;
555187831Ssam#endif
556187831Ssam
557185377Ssam	fc->max_asyretry = FW_MAXASYRTY;
558185377Ssam
559185377Ssam	fc->arq->queued = 0;
560187831Ssam	fc->ars->queued = 0;
561187831Ssam	fc->atq->queued = 0;
562185377Ssam	fc->ats->queued = 0;
563187831Ssam
564185377Ssam	fc->arq->psize = PAGE_SIZE;
565185377Ssam	fc->ars->psize = PAGE_SIZE;
566187831Ssam	fc->atq->psize = 0;
567185377Ssam	fc->ats->psize = 0;
568185377Ssam
569185380Ssam
570185377Ssam	fc->arq->buf = NULL;
571185377Ssam	fc->ars->buf = NULL;
572185377Ssam	fc->atq->buf = NULL;
573185377Ssam	fc->ats->buf = NULL;
574185377Ssam
575185377Ssam	fc->arq->flag = FWXFERQ_PACKET;
576185377Ssam	fc->ars->flag = FWXFERQ_PACKET;
577185377Ssam	fc->atq->flag = FWXFERQ_PACKET;
578185377Ssam	fc->ats->flag = FWXFERQ_PACKET;
579185377Ssam
580185377Ssam	STAILQ_INIT(&fc->atq->q);
581185377Ssam	STAILQ_INIT(&fc->ats->q);
582185377Ssam
583185377Ssam	for( i = 0 ; i < fc->nisodma ; i ++ ){
584185377Ssam		fc->it[i]->queued = 0;
585185377Ssam		fc->ir[i]->queued = 0;
586185377Ssam
587185377Ssam		fc->it[i]->start = NULL;
588185377Ssam		fc->ir[i]->start = NULL;
589185377Ssam
590185377Ssam		fc->it[i]->buf = NULL;
591185377Ssam		fc->ir[i]->buf = NULL;
592185377Ssam
593185377Ssam		fc->it[i]->flag = FWXFERQ_STREAM;
594185377Ssam		fc->ir[i]->flag = FWXFERQ_STREAM;
595185377Ssam
596185377Ssam		STAILQ_INIT(&fc->it[i]->q);
597185377Ssam		STAILQ_INIT(&fc->ir[i]->q);
598185377Ssam
599185377Ssam		STAILQ_INIT(&fc->it[i]->binds);
600185377Ssam		STAILQ_INIT(&fc->ir[i]->binds);
601185377Ssam	}
602185377Ssam
603217621Sadrian	fc->arq->maxq = FWMAXQUEUE;
604217621Sadrian	fc->ars->maxq = FWMAXQUEUE;
605185377Ssam	fc->atq->maxq = FWMAXQUEUE;
606185377Ssam	fc->ats->maxq = FWMAXQUEUE;
607185377Ssam
608185377Ssam	for( i = 0 ; i < fc->nisodma ; i++){
609185377Ssam		fc->ir[i]->maxq = FWMAXQUEUE;
610185377Ssam		fc->it[i]->maxq = FWMAXQUEUE;
611185377Ssam	}
612185377Ssam/* Initialize csr registers */
613185377Ssam	fc->topology_map = (struct fw_topology_map *)malloc(
614185377Ssam				sizeof(struct fw_topology_map),
615185377Ssam				M_FW, M_NOWAIT | M_ZERO);
616185377Ssam	fc->speed_map = (struct fw_speed_map *)malloc(
617185377Ssam				sizeof(struct fw_speed_map),
618185377Ssam				M_FW, M_NOWAIT | M_ZERO);
619185377Ssam	CSRARC(fc, TOPO_MAP) = 0x3f1 << 16;
620217684Sadrian	CSRARC(fc, TOPO_MAP + 4) = 1;
621187831Ssam	CSRARC(fc, SPED_MAP) = 0x3f1 << 16;
622217684Sadrian	CSRARC(fc, SPED_MAP + 4) = 1;
623187831Ssam
624185377Ssam	STAILQ_INIT(&fc->devices);
625211206Sadrian	STAILQ_INIT(&fc->pending);
626211206Sadrian
627211206Sadrian/* Initialize csr ROM work space */
628222584Sadrian	SLIST_INIT(&fc->ongocsr);
629222584Sadrian	SLIST_INIT(&fc->csrfree);
630222815Sadrian	for( i = 0 ; i < FWMAXCSRDIR ; i++){
631222815Sadrian		csrd = (struct csrdir *) malloc(sizeof(struct csrdir), M_FW,M_NOWAIT);
632222815Sadrian		if(csrd == NULL) break;
633224709Sadrian		SLIST_INSERT_HEAD(&fc->csrfree, csrd, link);
634230791Sadrian	}
635211206Sadrian
636185377Ssam/* Initialize Async handlers */
637	STAILQ_INIT(&fc->binds);
638	for( i = 0 ; i < 0x40 ; i++){
639		STAILQ_INIT(&fc->tlabels[i]);
640	}
641
642/* DV depend CSRs see blue book */
643#if 0
644	CSRARC(fc, oMPR) = 0x3fff0001; /* # output channel = 1 */
645	CSRARC(fc, oPCR) = 0x8000007a;
646	for(i = 4 ; i < 0x7c/4 ; i+=4){
647		CSRARC(fc, i + oPCR) = 0x8000007a;
648	}
649
650	CSRARC(fc, iMPR) = 0x00ff0001; /* # input channel = 1 */
651	CSRARC(fc, iPCR) = 0x803f0000;
652	for(i = 4 ; i < 0x7c/4 ; i+=4){
653		CSRARC(fc, i + iPCR) = 0x0;
654	}
655#endif
656
657
658#ifdef FW_VMACCESS
659	xfer = fw_xfer_alloc();
660	if(xfer == NULL) return;
661
662	fwb = (struct fw_bind *)malloc(sizeof (struct fw_bind), M_FW, M_NOWAIT);
663	if(fwb == NULL){
664		fw_xfer_free(xfer);
665	}
666	xfer->act.hand = fw_vmaccess;
667	xfer->act_type = FWACT_XFER;
668	xfer->fc = fc;
669	xfer->sc = NULL;
670
671	fwb->start_hi = 0x2;
672	fwb->start_lo = 0;
673	fwb->addrlen = 0xffffffff;
674	fwb->xfer = xfer;
675	fw_bindadd(fc, fwb);
676#endif
677}
678
679/*
680 * To lookup binded process from IEEE1394 address.
681 */
682struct fw_bind *
683fw_bindlookup(struct firewire_comm *fc, u_int32_t dest_hi, u_int32_t dest_lo)
684{
685	struct fw_bind *tfw;
686	for(tfw = STAILQ_FIRST(&fc->binds) ; tfw != NULL ;
687		tfw = STAILQ_NEXT(tfw, fclist)){
688		if(tfw->xfer->act_type != FWACT_NULL &&
689			tfw->start_hi == dest_hi &&
690			tfw->start_lo <= dest_lo &&
691			(tfw->start_lo + tfw->addrlen) > dest_lo){
692			return(tfw);
693		}
694	}
695	return(NULL);
696}
697
698/*
699 * To bind IEEE1394 address block to process.
700 */
701int
702fw_bindadd(struct firewire_comm *fc, struct fw_bind *fwb)
703{
704	struct fw_bind *tfw, *tfw2 = NULL;
705	int err = 0;
706	tfw = STAILQ_FIRST(&fc->binds);
707	if(tfw == NULL){
708		STAILQ_INSERT_HEAD(&fc->binds, fwb, fclist);
709		goto out;
710	}
711	if((tfw->start_hi > fwb->start_hi) ||
712		(tfw->start_hi == fwb->start_hi &&
713		(tfw->start_lo > (fwb->start_lo + fwb->addrlen)))){
714		STAILQ_INSERT_HEAD(&fc->binds, fwb, fclist);
715		goto out;
716	}
717	for(; tfw != NULL; tfw = STAILQ_NEXT(tfw, fclist)){
718		if((tfw->start_hi < fwb->start_hi) ||
719		   (tfw->start_hi == fwb->start_hi &&
720		    (tfw->start_lo + tfw->addrlen) < fwb->start_lo)){
721		   tfw2 = STAILQ_NEXT(tfw, fclist);
722			if(tfw2 == NULL)
723				break;
724			if((tfw2->start_hi > fwb->start_hi) ||
725			   (tfw2->start_hi == fwb->start_hi &&
726			    tfw2->start_lo > (fwb->start_lo + fwb->addrlen))){
727				break;
728			}else{
729				err = EBUSY;
730				goto out;
731			}
732		}
733	}
734	if(tfw != NULL){
735		STAILQ_INSERT_AFTER(&fc->binds, tfw, fwb, fclist);
736	}else{
737		STAILQ_INSERT_TAIL(&fc->binds, fwb, fclist);
738	}
739out:
740	if(!err && fwb->xfer->act_type == FWACT_CH){
741		STAILQ_INSERT_HEAD(&fc->ir[fwb->xfer->sub]->binds, fwb, chlist);
742	}
743	return err;
744}
745
746/*
747 * To free IEEE1394 address block.
748 */
749int
750fw_bindremove(struct firewire_comm *fc, struct fw_bind *fwb)
751{
752	int s;
753
754	s = splfw();
755	/* shall we check the existance? */
756	STAILQ_REMOVE(&fc->binds, fwb, fw_bind, fclist);
757	splx(s);
758	if (fwb->xfer)
759		fw_xfer_free(fwb->xfer);
760
761	return 0;
762}
763
764/*
765 * To free transaction label.
766 */
767static void
768fw_tl_free(struct firewire_comm *fc, struct fw_xfer *xfer)
769{
770	struct tlabel *tl;
771	int s = splfw();
772
773	for( tl = STAILQ_FIRST(&fc->tlabels[xfer->tl]); tl != NULL;
774		tl = STAILQ_NEXT(tl, link)){
775		if(tl->xfer == xfer){
776			STAILQ_REMOVE(&fc->tlabels[xfer->tl], tl, tlabel, link);
777			free(tl, M_FW);
778			splx(s);
779			return;
780		}
781	}
782	splx(s);
783	return;
784}
785
786/*
787 * To obtain XFER structure by transaction label.
788 */
789static struct fw_xfer *
790fw_tl2xfer(struct firewire_comm *fc, int node, int tlabel)
791{
792	struct fw_xfer *xfer;
793	struct tlabel *tl;
794	int s = splfw();
795
796	for( tl = STAILQ_FIRST(&fc->tlabels[tlabel]); tl != NULL;
797		tl = STAILQ_NEXT(tl, link)){
798		if(tl->xfer->dst == node){
799			xfer = tl->xfer;
800			splx(s);
801			return(xfer);
802		}
803	}
804	splx(s);
805	return(NULL);
806}
807
808/*
809 * To allocate IEEE1394 XFER structure.
810 */
811struct fw_xfer *
812fw_xfer_alloc()
813{
814	struct fw_xfer *xfer;
815
816	xfer = malloc(sizeof(struct fw_xfer), M_FW, M_NOWAIT | M_ZERO);
817	if (xfer == NULL)
818		return xfer;
819
820	xfer->time = time_second;
821	xfer->sub = -1;
822
823	return xfer;
824}
825
826/*
827 * IEEE1394 XFER post process.
828 */
829void
830fw_xfer_done(struct fw_xfer *xfer)
831{
832	if (xfer->act.hand == NULL)
833		return;
834
835#if XFER_TIMEOUT
836	untimeout(fw_xfer_timeout, (void *)xfer, xfer->ch);
837#endif
838
839	if (xfer->fc->status != FWBUSRESET)
840		xfer->act.hand(xfer);
841	else {
842		printf("fw_xfer_done: pending\n");
843		if (xfer->fc != NULL)
844			STAILQ_INSERT_TAIL(&xfer->fc->pending, xfer, link);
845		else
846			panic("fw_xfer_done: why xfer->fc is NULL?");
847	}
848}
849
850/*
851 * To free IEEE1394 XFER structure.
852 */
853void
854fw_xfer_free( struct fw_xfer* xfer)
855{
856	int s;
857	if(xfer == NULL ) return;
858	if(xfer->state == FWXF_INQ){
859		printf("fw_xfer_free FWXF_INQ\n");
860		s = splfw();
861		STAILQ_REMOVE(&xfer->q->q, xfer, fw_xfer, link);
862		xfer->q->queued --;
863		splx(s);
864	}
865	if(xfer->fc != NULL){
866		if(xfer->state == FWXF_START){
867#if 0 /* this could happen if we call fwohci_arcv() before fwohci_txd() */
868			printf("fw_xfer_free FWXF_START\n");
869#endif
870			s = splfw();
871			xfer->q->drain(xfer->fc, xfer);
872			splx(s);
873		}
874	}
875	if(xfer->send.buf != NULL){
876		free(xfer->send.buf, M_FW);
877	}
878	if(xfer->recv.buf != NULL){
879		free(xfer->recv.buf, M_FW);
880	}
881	if(xfer->fc != NULL){
882		fw_tl_free(xfer->fc, xfer);
883	}
884	free(xfer, M_FW);
885}
886
887static void
888fw_asy_callback_free(struct fw_xfer *xfer)
889{
890#if 0
891	printf("asyreq done state=%d resp=%d\n",
892				xfer->state, xfer->resp);
893#endif
894	fw_xfer_free(xfer);
895}
896
897/*
898 * To configure PHY.
899 */
900static void
901fw_phy_config(struct firewire_comm *fc, int root_node, int gap_count)
902{
903	struct fw_xfer *xfer;
904	struct fw_pkt *fp;
905
906	fc->status = FWBUSPHYCONF;
907
908#if 0
909	DELAY(100000);
910#endif
911	xfer = fw_xfer_alloc();
912	xfer->send.len = 12;
913	xfer->send.off = 0;
914	xfer->fc = fc;
915	xfer->retry_req = fw_asybusy;
916	xfer->act.hand = fw_asy_callback_free;
917
918	xfer->send.buf = malloc(sizeof(u_int32_t),
919					M_FW, M_NOWAIT | M_ZERO);
920	fp = (struct fw_pkt *)xfer->send.buf;
921	fp->mode.ld[1] = 0;
922	if (root_node >= 0)
923		fp->mode.ld[1] |= htonl((root_node & 0x3f) << 24 | 1 << 23);
924	if (gap_count >= 0)
925		fp->mode.ld[1] |= htonl(1 << 22 | (gap_count & 0x3f) << 16);
926	fp->mode.ld[2] = ~fp->mode.ld[1];
927/* XXX Dangerous, how to pass PHY packet to device driver */
928	fp->mode.common.tcode |= FWTCODE_PHY;
929
930	if (firewire_debug)
931		printf("send phy_config root_node=%d gap_count=%d\n",
932						root_node, gap_count);
933	fw_asyreq(fc, -1, xfer);
934}
935
936#if 0
937/*
938 * Dump self ID.
939 */
940static void
941fw_print_sid(u_int32_t sid)
942{
943	union fw_self_id *s;
944	s = (union fw_self_id *) &sid;
945	printf("node:%d link:%d gap:%d spd:%d del:%d con:%d pwr:%d"
946		" p0:%d p1:%d p2:%d i:%d m:%d\n",
947		s->p0.phy_id, s->p0.link_active, s->p0.gap_count,
948		s->p0.phy_speed, s->p0.phy_delay, s->p0.contender,
949		s->p0.power_class, s->p0.port0, s->p0.port1,
950		s->p0.port2, s->p0.initiated_reset, s->p0.more_packets);
951}
952#endif
953
954/*
955 * To receive self ID.
956 */
957void fw_sidrcv(struct firewire_comm* fc, caddr_t buf, u_int len, u_int off)
958{
959	u_int32_t *p, *sid = (u_int32_t *)(buf + off);
960	union fw_self_id *self_id;
961	u_int i, j, node, c_port = 0, i_branch = 0;
962
963	fc->sid_cnt = len /(sizeof(u_int32_t) * 2);
964	fc->status = FWBUSINIT;
965	fc->max_node = fc->nodeid & 0x3f;
966	CSRARC(fc, NODE_IDS) = ((u_int32_t)fc->nodeid) << 16;
967	fc->status = FWBUSCYMELECT;
968	fc->topology_map->crc_len = 2;
969	fc->topology_map->generation ++;
970	fc->topology_map->self_id_count = 0;
971	fc->topology_map->node_count = 0;
972	fc->speed_map->generation ++;
973	fc->speed_map->crc_len = 1 + (64*64 + 3) / 4;
974	self_id = &fc->topology_map->self_id[0];
975	for(i = 0; i < fc->sid_cnt; i ++){
976		if (sid[1] != ~sid[0]) {
977			printf("fw_sidrcv: invalid self-id packet\n");
978			sid += 2;
979			continue;
980		}
981		*self_id = *((union fw_self_id *)sid);
982		fc->topology_map->crc_len++;
983		if(self_id->p0.sequel == 0){
984			fc->topology_map->node_count ++;
985			c_port = 0;
986#if 0
987			fw_print_sid(sid[0]);
988#endif
989			node = self_id->p0.phy_id;
990			if(fc->max_node < node){
991				fc->max_node = self_id->p0.phy_id;
992			}
993			/* XXX I'm not sure this is the right speed_map */
994			fc->speed_map->speed[node][node]
995					= self_id->p0.phy_speed;
996			for (j = 0; j < node; j ++) {
997				fc->speed_map->speed[j][node]
998					= fc->speed_map->speed[node][j]
999					= min(fc->speed_map->speed[j][j],
1000							self_id->p0.phy_speed);
1001			}
1002			if ((fc->irm == -1 || self_id->p0.phy_id > fc->irm) &&
1003			  (self_id->p0.link_active && self_id->p0.contender)) {
1004				fc->irm = self_id->p0.phy_id;
1005			}
1006			if(self_id->p0.port0 >= 0x2){
1007				c_port++;
1008			}
1009			if(self_id->p0.port1 >= 0x2){
1010				c_port++;
1011			}
1012			if(self_id->p0.port2 >= 0x2){
1013				c_port++;
1014			}
1015		}
1016		if(c_port > 2){
1017			i_branch += (c_port - 2);
1018		}
1019		sid += 2;
1020		self_id++;
1021		fc->topology_map->self_id_count ++;
1022	}
1023	device_printf(fc->bdev, "%d nodes", fc->max_node + 1);
1024	/* CRC */
1025	fc->topology_map->crc = fw_crc16(
1026			(u_int32_t *)&fc->topology_map->generation,
1027			fc->topology_map->crc_len * 4);
1028	fc->speed_map->crc = fw_crc16(
1029			(u_int32_t *)&fc->speed_map->generation,
1030			fc->speed_map->crc_len * 4);
1031	/* byteswap and copy to CSR */
1032	p = (u_int32_t *)fc->topology_map;
1033	for (i = 0; i <= fc->topology_map->crc_len; i++)
1034		CSRARC(fc, TOPO_MAP + i * 4) = htonl(*p++);
1035	p = (u_int32_t *)fc->speed_map;
1036	CSRARC(fc, SPED_MAP) = htonl(*p++);
1037	CSRARC(fc, SPED_MAP + 4) = htonl(*p++);
1038	/* don't byte-swap u_int8_t array */
1039	bcopy(p, &CSRARC(fc, SPED_MAP + 8), (fc->speed_map->crc_len - 1)*4);
1040
1041	fc->max_hop = fc->max_node - i_branch;
1042#if 1
1043	printf(", maxhop <= %d", fc->max_hop);
1044#endif
1045
1046	if(fc->irm == -1 ){
1047		printf(", Not found IRM capable node");
1048	}else{
1049		printf(", cable IRM = %d", fc->irm);
1050		if (fc->irm == fc->nodeid)
1051			printf(" (me)");
1052	}
1053	printf("\n");
1054
1055	if (try_bmr && (fc->irm != -1) && (CSRARC(fc, BUS_MGR_ID) == 0x3f)) {
1056		if (fc->irm == ((CSRARC(fc, NODE_IDS) >> 16 ) & 0x3f)) {
1057			fc->status = FWBUSMGRDONE;
1058			CSRARC(fc, BUS_MGR_ID) = fc->set_bmr(fc, fc->irm);
1059		} else {
1060			fc->status = FWBUSMGRELECT;
1061			callout_reset(&fc->bmr_callout, hz/8,
1062				(void *)fw_try_bmr, (void *)fc);
1063		}
1064	} else {
1065		fc->status = FWBUSMGRDONE;
1066#if 0
1067		device_printf(fc->bdev, "BMR = %x\n",
1068				CSRARC(fc, BUS_MGR_ID));
1069#endif
1070	}
1071	free(buf, M_FW);
1072	if(fc->irm == ((CSRARC(fc, NODE_IDS) >> 16 ) & 0x3f)){
1073		/* I am BMGR */
1074		fw_bmr(fc);
1075	}
1076	callout_reset(&fc->busprobe_callout, hz/4,
1077			(void *)fw_bus_probe, (void *)fc);
1078}
1079
1080/*
1081 * To probe devices on the IEEE1394 bus.
1082 */
1083static void
1084fw_bus_probe(struct firewire_comm *fc)
1085{
1086	int s;
1087	struct fw_device *fwdev, *next;
1088
1089	s = splfw();
1090	fc->status = FWBUSEXPLORE;
1091	fc->retry_count = 0;
1092
1093/*
1094 * Invalidate all devices, just after bus reset. Devices
1095 * to be removed has not been seen longer time.
1096 */
1097	for (fwdev = STAILQ_FIRST(&fc->devices); fwdev != NULL; fwdev = next) {
1098		next = STAILQ_NEXT(fwdev, link);
1099		if (fwdev->status != FWDEVINVAL) {
1100			fwdev->status = FWDEVINVAL;
1101			fwdev->rcnt = 0;
1102		} else if(fwdev->rcnt < FW_MAXDEVRCNT) {
1103			fwdev->rcnt ++;
1104		} else {
1105			STAILQ_REMOVE(&fc->devices, fwdev, fw_device, link);
1106			free(fwdev, M_FW);
1107		}
1108	}
1109	fc->ongonode = 0;
1110	fc->ongoaddr = CSRROMOFF;
1111	fc->ongodev = NULL;
1112	fc->ongoeui.hi = 0xffffffff; fc->ongoeui.lo = 0xffffffff;
1113	fw_bus_explore(fc);
1114	splx(s);
1115}
1116
1117/*
1118 * To collect device informations on the IEEE1394 bus.
1119 */
1120static void
1121fw_bus_explore(struct firewire_comm *fc )
1122{
1123	int err = 0;
1124	struct fw_device *fwdev, *pfwdev, *tfwdev;
1125	u_int32_t addr;
1126	struct fw_xfer *xfer;
1127	struct fw_pkt *fp;
1128
1129	if(fc->status != FWBUSEXPLORE)
1130		return;
1131
1132loop:
1133	if(fc->ongonode == fc->nodeid) fc->ongonode++;
1134
1135	if(fc->ongonode > fc->max_node) goto done;
1136	if(fc->ongonode >= 0x3f) goto done;
1137
1138	/* check link */
1139	/* XXX we need to check phy_id first */
1140	if (!fc->topology_map->self_id[fc->ongonode].p0.link_active) {
1141		printf("fw_bus_explore: node %d link down\n", fc->ongonode);
1142		fc->ongonode++;
1143		goto loop;
1144	}
1145
1146	if(fc->ongoaddr <= CSRROMOFF &&
1147		fc->ongoeui.hi == 0xffffffff &&
1148		fc->ongoeui.lo == 0xffffffff ){
1149		fc->ongoaddr = CSRROMOFF;
1150		addr = 0xf0000000 | fc->ongoaddr;
1151	}else if(fc->ongoeui.hi == 0xffffffff ){
1152		fc->ongoaddr = CSRROMOFF + 0xc;
1153		addr = 0xf0000000 | fc->ongoaddr;
1154	}else if(fc->ongoeui.lo == 0xffffffff ){
1155		fc->ongoaddr = CSRROMOFF + 0x10;
1156		addr = 0xf0000000 | fc->ongoaddr;
1157	}else if(fc->ongodev == NULL){
1158		STAILQ_FOREACH(fwdev, &fc->devices, link)
1159			if (FW_EUI64_EQUAL(fwdev->eui, fc->ongoeui))
1160				break;
1161		if(fwdev != NULL){
1162			fwdev->dst = fc->ongonode;
1163			fwdev->status = FWDEVATTACHED;
1164			fc->ongonode++;
1165			fc->ongoaddr = CSRROMOFF;
1166			fc->ongodev = NULL;
1167			fc->ongoeui.hi = 0xffffffff; fc->ongoeui.lo = 0xffffffff;
1168			goto loop;
1169		}
1170		fwdev = malloc(sizeof(struct fw_device), M_FW, M_NOWAIT);
1171		if(fwdev == NULL)
1172			return;
1173		fwdev->fc = fc;
1174		fwdev->rommax = 0;
1175		fwdev->dst = fc->ongonode;
1176		fwdev->eui.hi = fc->ongoeui.hi; fwdev->eui.lo = fc->ongoeui.lo;
1177		fwdev->status = FWDEVINIT;
1178#if 0
1179		fwdev->speed = CSRARC(fc, SPED_MAP + 8 + fc->ongonode / 4)
1180			>> ((3 - (fc->ongonode % 4)) * 8);
1181#else
1182		fwdev->speed = fc->speed_map->speed[fc->nodeid][fc->ongonode];
1183#endif
1184
1185		pfwdev = NULL;
1186		STAILQ_FOREACH(tfwdev, &fc->devices, link) {
1187			if (tfwdev->eui.hi > fwdev->eui.hi ||
1188					(tfwdev->eui.hi == fwdev->eui.hi &&
1189					tfwdev->eui.lo > fwdev->eui.lo))
1190				break;
1191			pfwdev = tfwdev;
1192		}
1193		if (pfwdev == NULL)
1194			STAILQ_INSERT_HEAD(&fc->devices, fwdev, link);
1195		else
1196			STAILQ_INSERT_AFTER(&fc->devices, pfwdev, fwdev, link);
1197
1198		device_printf(fc->bdev, "New %s device ID:%08x%08x\n",
1199			linkspeed[fwdev->speed],
1200			fc->ongoeui.hi, fc->ongoeui.lo);
1201
1202		fc->ongodev = fwdev;
1203		fc->ongoaddr = CSRROMOFF;
1204		addr = 0xf0000000 | fc->ongoaddr;
1205	}else{
1206		addr = 0xf0000000 | fc->ongoaddr;
1207	}
1208#if 0
1209	xfer = asyreqq(fc, FWSPD_S100, 0, 0,
1210		((FWLOCALBUS | fc->ongonode) << 16) | 0xffff , addr,
1211		fw_bus_explore_callback);
1212	if(xfer == NULL) goto done;
1213#else
1214	xfer = fw_xfer_alloc();
1215	if(xfer == NULL){
1216		goto done;
1217	}
1218	xfer->send.len = 16;
1219	xfer->spd = 0;
1220	xfer->send.buf = malloc(16, M_FW, M_NOWAIT);
1221	if(xfer->send.buf == NULL){
1222		fw_xfer_free( xfer);
1223		return;
1224	}
1225
1226	xfer->send.off = 0;
1227	fp = (struct fw_pkt *)xfer->send.buf;
1228	fp->mode.rreqq.dest_hi = htons(0xffff);
1229	fp->mode.rreqq.tlrt = 0;
1230	fp->mode.rreqq.tcode = FWTCODE_RREQQ;
1231	fp->mode.rreqq.pri = 0;
1232	fp->mode.rreqq.src = 0;
1233	xfer->dst = FWLOCALBUS | fc->ongonode;
1234	fp->mode.rreqq.dst = htons(xfer->dst);
1235	fp->mode.rreqq.dest_lo = htonl(addr);
1236	xfer->act.hand = fw_bus_explore_callback;
1237
1238	err = fw_asyreq(fc, -1, xfer);
1239	if(err){
1240		fw_xfer_free( xfer);
1241		return;
1242	}
1243#endif
1244	return;
1245done:
1246	/* fw_attach_devs */
1247	fc->status = FWBUSEXPDONE;
1248	if (firewire_debug)
1249		printf("bus_explore done\n");
1250	fw_attach_dev(fc);
1251	return;
1252
1253}
1254
1255/* Portable Async. request read quad */
1256struct fw_xfer *
1257asyreqq(struct firewire_comm *fc, u_int8_t spd, u_int8_t tl, u_int8_t rt,
1258	u_int32_t addr_hi, u_int32_t addr_lo,
1259	void (*hand) __P((struct fw_xfer*)))
1260{
1261	struct fw_xfer *xfer;
1262	struct fw_pkt *fp;
1263	int err;
1264
1265	xfer = fw_xfer_alloc();
1266	if(xfer == NULL){
1267		return NULL;
1268	}
1269	xfer->send.len = 16;
1270	xfer->spd = spd; /* XXX:min(spd, fc->spd) */
1271	xfer->send.buf = malloc(16, M_FW, M_NOWAIT);
1272	if(xfer->send.buf == NULL){
1273		fw_xfer_free( xfer);
1274		return NULL;
1275	}
1276
1277	xfer->send.off = 0;
1278	fp = (struct fw_pkt *)xfer->send.buf;
1279	fp->mode.rreqq.dest_hi = htons(addr_hi & 0xffff);
1280	if(tl & FWP_TL_VALID){
1281		fp->mode.rreqq.tlrt = (tl & 0x3f) << 2;
1282	}else{
1283		fp->mode.rreqq.tlrt = 0;
1284	}
1285	fp->mode.rreqq.tlrt |= rt & 0x3;
1286	fp->mode.rreqq.tcode = FWTCODE_RREQQ;
1287	fp->mode.rreqq.pri = 0;
1288	fp->mode.rreqq.src = 0;
1289	xfer->dst = addr_hi >> 16;
1290	fp->mode.rreqq.dst = htons(xfer->dst);
1291	fp->mode.rreqq.dest_lo = htonl(addr_lo);
1292	xfer->act.hand = hand;
1293
1294	err = fw_asyreq(fc, -1, xfer);
1295	if(err){
1296		fw_xfer_free( xfer);
1297		return NULL;
1298	}
1299	return xfer;
1300}
1301
1302/*
1303 * Callback for the IEEE1394 bus information collection.
1304 */
1305static void
1306fw_bus_explore_callback(struct fw_xfer *xfer)
1307{
1308	struct firewire_comm *fc;
1309	struct fw_pkt *sfp,*rfp;
1310	struct csrhdr *chdr;
1311	struct csrdir *csrd;
1312	struct csrreg *csrreg;
1313	u_int32_t offset;
1314
1315
1316	if(xfer == NULL) return;
1317	fc = xfer->fc;
1318	if(xfer->resp != 0){
1319		printf("resp != 0: node=%d addr=0x%x\n",
1320			fc->ongonode, fc->ongoaddr);
1321		fc->retry_count++;
1322		goto nextnode;
1323	}
1324
1325	if(xfer->send.buf == NULL){
1326		printf("send.buf == NULL: node=%d addr=0x%x\n",
1327			fc->ongonode, fc->ongoaddr);
1328		printf("send.buf == NULL\n");
1329		fc->retry_count++;
1330		goto nextnode;
1331	}
1332	sfp = (struct fw_pkt *)xfer->send.buf;
1333
1334	if(xfer->recv.buf == NULL){
1335		printf("recv.buf == NULL: node=%d addr=0x%x\n",
1336			fc->ongonode, fc->ongoaddr);
1337		fc->retry_count++;
1338		goto nextnode;
1339	}
1340	rfp = (struct fw_pkt *)xfer->recv.buf;
1341#if 0
1342	{
1343		u_int32_t *qld;
1344		int i;
1345		qld = (u_int32_t *)xfer->recv.buf;
1346		printf("len:%d\n", xfer->recv.len);
1347		for( i = 0 ; i <= xfer->recv.len && i < 32; i+= 4){
1348			printf("0x%08x ", ntohl(rfp->mode.ld[i/4]));
1349			if((i % 16) == 15) printf("\n");
1350		}
1351		if((i % 16) != 15) printf("\n");
1352	}
1353#endif
1354	if(fc->ongodev == NULL){
1355		if(sfp->mode.rreqq.dest_lo == htonl((0xf0000000 | CSRROMOFF))){
1356			rfp->mode.rresq.data = ntohl(rfp->mode.rresq.data);
1357			chdr = (struct csrhdr *)(&rfp->mode.rresq.data);
1358/* If CSR is minimul confinguration, more investgation is not needed. */
1359			if(chdr->info_len == 1){
1360				goto nextnode;
1361			}else{
1362				fc->ongoaddr = CSRROMOFF + 0xc;
1363			}
1364		}else if(sfp->mode.rreqq.dest_lo == htonl((0xf0000000 |(CSRROMOFF + 0xc)))){
1365			fc->ongoeui.hi = ntohl(rfp->mode.rresq.data);
1366			fc->ongoaddr = CSRROMOFF + 0x10;
1367		}else if(sfp->mode.rreqq.dest_lo == htonl((0xf0000000 |(CSRROMOFF + 0x10)))){
1368			fc->ongoeui.lo = ntohl(rfp->mode.rresq.data);
1369			if (fc->ongoeui.hi == 0 && fc->ongoeui.lo == 0)
1370				goto nextnode;
1371			fc->ongoaddr = CSRROMOFF;
1372		}
1373	}else{
1374		fc->ongodev->csrrom[(fc->ongoaddr - CSRROMOFF)/4] = ntohl(rfp->mode.rresq.data);
1375		if(fc->ongoaddr > fc->ongodev->rommax){
1376			fc->ongodev->rommax = fc->ongoaddr;
1377		}
1378		csrd = SLIST_FIRST(&fc->ongocsr);
1379		if((csrd = SLIST_FIRST(&fc->ongocsr)) == NULL){
1380			chdr = (struct csrhdr *)(fc->ongodev->csrrom);
1381			offset = CSRROMOFF;
1382		}else{
1383			chdr = (struct csrhdr *)&fc->ongodev->csrrom[(csrd->off - CSRROMOFF)/4];
1384			offset = csrd->off;
1385		}
1386		if(fc->ongoaddr > (CSRROMOFF + 0x14) && fc->ongoaddr != offset){
1387			csrreg = (struct csrreg *)&fc->ongodev->csrrom[(fc->ongoaddr - CSRROMOFF)/4];
1388			if( csrreg->key == 0x81 || csrreg->key == 0xd1){
1389				csrd = SLIST_FIRST(&fc->csrfree);
1390				if(csrd == NULL){
1391					goto nextnode;
1392				}else{
1393					csrd->ongoaddr = fc->ongoaddr;
1394					fc->ongoaddr += csrreg->val * 4;
1395					csrd->off = fc->ongoaddr;
1396					SLIST_REMOVE_HEAD(&fc->csrfree, link);
1397					SLIST_INSERT_HEAD(&fc->ongocsr, csrd, link);
1398					goto nextaddr;
1399				}
1400			}
1401		}
1402		fc->ongoaddr += 4;
1403		if(((fc->ongoaddr - offset)/4 > chdr->crc_len) &&
1404				(fc->ongodev->rommax < 0x414)){
1405			if(fc->ongodev->rommax <= 0x414){
1406				csrd = SLIST_FIRST(&fc->csrfree);
1407				if(csrd == NULL) goto nextnode;
1408				csrd->off = fc->ongoaddr;
1409				csrd->ongoaddr = fc->ongoaddr;
1410				SLIST_REMOVE_HEAD(&fc->csrfree, link);
1411				SLIST_INSERT_HEAD(&fc->ongocsr, csrd, link);
1412			}
1413			goto nextaddr;
1414		}
1415
1416		while(((fc->ongoaddr - offset)/4 > chdr->crc_len)){
1417			if(csrd == NULL){
1418				goto nextnode;
1419			};
1420			fc->ongoaddr = csrd->ongoaddr + 4;
1421			SLIST_REMOVE_HEAD(&fc->ongocsr, link);
1422			SLIST_INSERT_HEAD(&fc->csrfree, csrd, link);
1423			csrd = SLIST_FIRST(&fc->ongocsr);
1424			if((csrd = SLIST_FIRST(&fc->ongocsr)) == NULL){
1425				chdr = (struct csrhdr *)(fc->ongodev->csrrom);
1426				offset = CSRROMOFF;
1427			}else{
1428				chdr = (struct csrhdr *)&(fc->ongodev->csrrom[(csrd->off - CSRROMOFF)/4]);
1429				offset = csrd->off;
1430			}
1431		}
1432		if((fc->ongoaddr - CSRROMOFF) > CSRROMSIZE){
1433			goto nextnode;
1434		}
1435	}
1436nextaddr:
1437	fw_xfer_free( xfer);
1438	fw_bus_explore(fc);
1439	return;
1440nextnode:
1441	fw_xfer_free( xfer);
1442	fc->ongonode++;
1443/* housekeeping work space */
1444	fc->ongoaddr = CSRROMOFF;
1445	fc->ongodev = NULL;
1446	fc->ongoeui.hi = 0xffffffff; fc->ongoeui.lo = 0xffffffff;
1447	while((csrd = SLIST_FIRST(&fc->ongocsr)) != NULL){
1448		SLIST_REMOVE_HEAD(&fc->ongocsr, link);
1449		SLIST_INSERT_HEAD(&fc->csrfree, csrd, link);
1450	}
1451	fw_bus_explore(fc);
1452	return;
1453}
1454
1455/*
1456 * To obtain CSR register values.
1457 */
1458u_int32_t
1459getcsrdata(struct fw_device *fwdev, u_int8_t key)
1460{
1461	int i;
1462	struct csrhdr *chdr;
1463	struct csrreg *creg;
1464	chdr = (struct csrhdr *)&fwdev->csrrom[0];
1465	for( i = chdr->info_len + 4; i <= fwdev->rommax - CSRROMOFF; i+=4){
1466		creg = (struct csrreg *)&fwdev->csrrom[i/4];
1467		if(creg->key == key){
1468			return (u_int32_t)creg->val;
1469		}
1470	}
1471	return 0;
1472}
1473
1474/*
1475 * To attach sub-devices layer onto IEEE1394 bus.
1476 */
1477static void
1478fw_attach_dev(struct firewire_comm *fc)
1479{
1480	struct fw_device *fwdev;
1481	struct fw_xfer *xfer;
1482	int i, err;
1483	device_t *devlistp;
1484	int devcnt;
1485	struct firewire_dev_comm *fdc;
1486	u_int32_t spec, ver;
1487
1488	STAILQ_FOREACH(fwdev, &fc->devices, link) {
1489		if(fwdev->status == FWDEVINIT){
1490			spec = getcsrdata(fwdev, CSRKEY_SPEC);
1491			if(spec == 0)
1492				continue;
1493			ver = getcsrdata(fwdev, CSRKEY_VER);
1494			if(ver == 0)
1495				continue;
1496			fwdev->maxrec = (fwdev->csrrom[2] >> 12) & 0xf;
1497
1498			device_printf(fc->bdev, "Device ");
1499			switch(spec){
1500			case CSRVAL_ANSIT10:
1501				switch(ver){
1502				case CSRVAL_T10SBP2:
1503					printf("SBP-II");
1504					break;
1505				default:
1506					break;
1507				}
1508				break;
1509			case CSRVAL_1394TA:
1510				switch(ver){
1511				case CSR_PROTAVC:
1512					printf("AV/C");
1513					break;
1514				case CSR_PROTCAL:
1515					printf("CAL");
1516					break;
1517				case CSR_PROTEHS:
1518					printf("EHS");
1519					break;
1520				case CSR_PROTHAVI:
1521					printf("HAVi");
1522					break;
1523				case CSR_PROTCAM104:
1524					printf("1394 Cam 1.04");
1525					break;
1526				case CSR_PROTCAM120:
1527					printf("1394 Cam 1.20");
1528					break;
1529				case CSR_PROTCAM130:
1530					printf("1394 Cam 1.30");
1531					break;
1532				case CSR_PROTDPP:
1533					printf("1394 Direct print");
1534					break;
1535				case CSR_PROTIICP:
1536					printf("Industrial & Instrument");
1537					break;
1538				default:
1539					printf("unknown 1394TA");
1540					break;
1541				}
1542				break;
1543			default:
1544				printf("unknown spec");
1545				break;
1546			}
1547			fwdev->status = FWDEVATTACHED;
1548			printf("\n");
1549		}
1550	}
1551	err = device_get_children(fc->bdev, &devlistp, &devcnt);
1552	if( err != 0 )
1553		return;
1554	for( i = 0 ; i < devcnt ; i++){
1555		if (device_get_state(devlistp[i]) >= DS_ATTACHED)  {
1556			fdc = device_get_softc(devlistp[i]);
1557			if (fdc->post_explore != NULL)
1558				fdc->post_explore(fdc);
1559		}
1560	}
1561	free(devlistp, M_TEMP);
1562
1563	/* call pending handlers */
1564	i = 0;
1565	while ((xfer = STAILQ_FIRST(&fc->pending))) {
1566		STAILQ_REMOVE_HEAD(&fc->pending, link);
1567		i++;
1568		if (xfer->act.hand)
1569			xfer->act.hand(xfer);
1570	}
1571	if (i > 0)
1572		printf("fw_attach_dev: %d pending handlers called\n", i);
1573	if (fc->retry_count > 0) {
1574		printf("retry_count = %d\n", fc->retry_count);
1575		callout_reset(&fc->retry_probe_callout, hz*2,
1576					(void *)fc->ibr, (void *)fc);
1577	}
1578	return;
1579}
1580
1581/*
1582 * To allocate uniq transaction label.
1583 */
1584static int
1585fw_get_tlabel(struct firewire_comm *fc, struct fw_xfer *xfer)
1586{
1587	u_int i;
1588	struct tlabel *tl, *tmptl;
1589	int s;
1590	static u_int32_t label = 0;
1591
1592	s = splfw();
1593	for( i = 0 ; i < 0x40 ; i ++){
1594		label = (label + 1) & 0x3f;
1595		for(tmptl = STAILQ_FIRST(&fc->tlabels[label]);
1596			tmptl != NULL; tmptl = STAILQ_NEXT(tmptl, link)){
1597			if(tmptl->xfer->dst == xfer->dst) break;
1598		}
1599		if(tmptl == NULL) {
1600			tl = malloc(sizeof(struct tlabel),M_FW,M_NOWAIT);
1601			if (tl == NULL) {
1602				splx(s);
1603				return (-1);
1604			}
1605			tl->xfer = xfer;
1606			STAILQ_INSERT_TAIL(&fc->tlabels[label], tl, link);
1607			splx(s);
1608			return(label);
1609		}
1610	}
1611	splx(s);
1612
1613	printf("fw_get_tlabel: no free tlabel\n");
1614	return(-1);
1615}
1616
1617/*
1618 * Generic packet receving process.
1619 */
1620void
1621fw_rcv(struct firewire_comm* fc, caddr_t buf, u_int len, u_int sub, u_int off, u_int spd)
1622{
1623	struct fw_pkt *fp, *resfp;
1624	struct fw_xfer *xfer;
1625	struct fw_bind *bind;
1626	struct firewire_softc *sc;
1627	int s;
1628#if 0
1629	{
1630		u_int32_t *qld;
1631		int i;
1632		qld = (u_int32_t *)buf;
1633		printf("spd %d len:%d\n", spd, len);
1634		for( i = 0 ; i <= len && i < 32; i+= 4){
1635			printf("0x%08x ", ntohl(qld[i/4]));
1636			if((i % 16) == 15) printf("\n");
1637		}
1638		if((i % 16) != 15) printf("\n");
1639	}
1640#endif
1641	fp = (struct fw_pkt *)(buf + off);
1642	switch(fp->mode.common.tcode){
1643	case FWTCODE_WRES:
1644	case FWTCODE_RRESQ:
1645	case FWTCODE_RRESB:
1646	case FWTCODE_LRES:
1647		xfer = fw_tl2xfer(fc, ntohs(fp->mode.hdr.src),
1648					fp->mode.hdr.tlrt >> 2);
1649		if(xfer == NULL) {
1650			printf("fw_rcv: unknown response "
1651					"tcode=%d src=0x%x tl=%x rt=%d data=0x%x\n",
1652					fp->mode.common.tcode,
1653					ntohs(fp->mode.hdr.src),
1654					fp->mode.hdr.tlrt >> 2,
1655					fp->mode.hdr.tlrt & 3,
1656					fp->mode.rresq.data);
1657#if 1
1658			printf("try ad-hoc work around!!\n");
1659			xfer = fw_tl2xfer(fc, ntohs(fp->mode.hdr.src),
1660					(fp->mode.hdr.tlrt >> 2)^3);
1661			if (xfer == NULL) {
1662				printf("no use...\n");
1663				goto err;
1664			}
1665#else
1666			goto err;
1667#endif
1668		}
1669		switch(xfer->act_type){
1670		case FWACT_XFER:
1671			if((xfer->sub >= 0) &&
1672				((fc->ir[xfer->sub]->flag & FWXFERQ_MODEMASK ) == 0)){
1673				xfer->resp = EINVAL;
1674				fw_xfer_done(xfer);
1675				goto err;
1676			}
1677			xfer->recv.len = len;
1678			xfer->recv.off = off;
1679			xfer->recv.buf = buf;
1680			xfer->resp = 0;
1681			fw_xfer_done(xfer);
1682			return;
1683			break;
1684		case FWACT_CH:
1685		default:
1686			goto err;
1687			break;
1688		}
1689		break;
1690	case FWTCODE_WREQQ:
1691	case FWTCODE_WREQB:
1692	case FWTCODE_RREQQ:
1693	case FWTCODE_RREQB:
1694	case FWTCODE_LREQ:
1695		bind = fw_bindlookup(fc, ntohs(fp->mode.rreqq.dest_hi),
1696			ntohl(fp->mode.rreqq.dest_lo));
1697		if(bind == NULL){
1698#if __FreeBSD_version >= 500000
1699			printf("Unknown service addr 0x%08x:0x%08x tcode=%x\n",
1700#else
1701			printf("Unknown service addr 0x%08x:0x%08lx tcode=%x\n",
1702#endif
1703				ntohs(fp->mode.rreqq.dest_hi),
1704				ntohl(fp->mode.rreqq.dest_lo),
1705				fp->mode.common.tcode);
1706			if (fc->status == FWBUSRESET) {
1707				printf("fw_rcv: cannot response(bus reset)!\n");
1708				goto err;
1709			}
1710			xfer = fw_xfer_alloc();
1711			if(xfer == NULL){
1712				return;
1713			}
1714			xfer->spd = spd;
1715			xfer->send.buf = malloc(16, M_FW, M_NOWAIT);
1716			resfp = (struct fw_pkt *)xfer->send.buf;
1717			switch(fp->mode.common.tcode){
1718			case FWTCODE_WREQQ:
1719			case FWTCODE_WREQB:
1720				resfp->mode.hdr.tcode = FWTCODE_WRES;
1721				xfer->send.len = 12;
1722				break;
1723			case FWTCODE_RREQQ:
1724				resfp->mode.hdr.tcode = FWTCODE_RRESQ;
1725				xfer->send.len = 16;
1726				break;
1727			case FWTCODE_RREQB:
1728				resfp->mode.hdr.tcode = FWTCODE_RRESB;
1729				xfer->send.len = 16;
1730				break;
1731			case FWTCODE_LREQ:
1732				resfp->mode.hdr.tcode = FWTCODE_LRES;
1733				xfer->send.len = 16;
1734				break;
1735			}
1736			resfp->mode.hdr.dst = fp->mode.hdr.src;
1737			resfp->mode.hdr.tlrt = fp->mode.hdr.tlrt;
1738			resfp->mode.hdr.pri = fp->mode.hdr.pri;
1739			resfp->mode.rresb.rtcode = 7;
1740			resfp->mode.rresb.extcode = 0;
1741			resfp->mode.rresb.len = 0;
1742/*
1743			xfer->act.hand = fw_asy_callback;
1744*/
1745			xfer->act.hand = fw_xfer_free;
1746			if(fw_asyreq(fc, -1, xfer)){
1747				fw_xfer_free( xfer);
1748				return;
1749			}
1750			goto err;
1751		}
1752		switch(bind->xfer->act_type){
1753		case FWACT_XFER:
1754			xfer = fw_xfer_alloc();
1755			if(xfer == NULL) goto err;
1756			xfer->fc = bind->xfer->fc;
1757			xfer->sc = bind->xfer->sc;
1758			xfer->recv.buf = buf;
1759			xfer->recv.len = len;
1760			xfer->recv.off = off;
1761			xfer->spd = spd;
1762			xfer->act.hand = bind->xfer->act.hand;
1763			if (fc->status != FWBUSRESET)
1764				xfer->act.hand(xfer);
1765			else
1766				STAILQ_INSERT_TAIL(&fc->pending, xfer, link);
1767			return;
1768			break;
1769		case FWACT_CH:
1770			if(fc->ir[bind->xfer->sub]->queued >=
1771				fc->ir[bind->xfer->sub]->maxq){
1772				device_printf(fc->bdev,
1773					"Discard a packet %x %d\n",
1774					bind->xfer->sub,
1775					fc->ir[bind->xfer->sub]->queued);
1776				goto err;
1777			}
1778			xfer = fw_xfer_alloc();
1779			if(xfer == NULL) goto err;
1780			xfer->recv.buf = buf;
1781			xfer->recv.len = len;
1782			xfer->recv.off = off;
1783			xfer->spd = spd;
1784			s = splfw();
1785			fc->ir[bind->xfer->sub]->queued++;
1786			STAILQ_INSERT_TAIL(&fc->ir[bind->xfer->sub]->q, xfer, link);
1787			splx(s);
1788
1789			wakeup((caddr_t)fc->ir[bind->xfer->sub]);
1790
1791			return;
1792			break;
1793		default:
1794			goto err;
1795			break;
1796		}
1797		break;
1798	case FWTCODE_STREAM:
1799	{
1800		struct fw_xferq *xferq;
1801
1802		xferq = fc->ir[sub];
1803#if 0
1804		printf("stream rcv dma %d len %d off %d spd %d\n",
1805			sub, len, off, spd);
1806#endif
1807		if(xferq->queued >= xferq->maxq) {
1808			printf("receive queue is full\n");
1809			goto err;
1810		}
1811		xfer = fw_xfer_alloc();
1812		if(xfer == NULL) goto err;
1813		xfer->recv.buf = buf;
1814		xfer->recv.len = len;
1815		xfer->recv.off = off;
1816		xfer->spd = spd;
1817		s = splfw();
1818		xferq->queued++;
1819		STAILQ_INSERT_TAIL(&xferq->q, xfer, link);
1820		splx(s);
1821		sc = device_get_softc(fc->bdev);
1822#if __FreeBSD_version >= 500000
1823		if (SEL_WAITING(&xferq->rsel))
1824#else
1825		if (&xferq->rsel.si_pid != 0)
1826#endif
1827			selwakeup(&xferq->rsel);
1828		if (xferq->flag & FWXFERQ_WAKEUP) {
1829			xferq->flag &= ~FWXFERQ_WAKEUP;
1830			wakeup((caddr_t)xferq);
1831		}
1832		if (xferq->flag & FWXFERQ_HANDLER) {
1833			xferq->hand(xferq);
1834		}
1835		return;
1836		break;
1837	}
1838	default:
1839		printf("fw_rcv: unknow tcode\n");
1840		break;
1841	}
1842err:
1843	free(buf, M_FW);
1844}
1845
1846/*
1847 * Post process for Bus Manager election process.
1848 */
1849static void
1850fw_try_bmr_callback(struct fw_xfer *xfer)
1851{
1852	struct fw_pkt *rfp;
1853	struct firewire_comm *fc;
1854	int bmr;
1855
1856	if (xfer == NULL)
1857		return;
1858	fc = xfer->fc;
1859	if (xfer->resp != 0)
1860		goto error;
1861	if (xfer->send.buf == NULL)
1862		goto error;
1863	if (xfer->recv.buf == NULL)
1864		goto error;
1865	rfp = (struct fw_pkt *)xfer->recv.buf;
1866	if (rfp->mode.lres.rtcode != FWRCODE_COMPLETE)
1867		goto error;
1868
1869	bmr = ntohl(rfp->mode.lres.payload[0]);
1870	if (bmr == 0x3f)
1871		bmr = fc->nodeid;
1872
1873	CSRARC(fc, BUS_MGR_ID) = fc->set_bmr(fc, bmr & 0x3f);
1874	device_printf(fc->bdev, "new bus manager %d ",
1875		CSRARC(fc, BUS_MGR_ID));
1876	if(bmr == fc->nodeid){
1877		printf("(me)\n");
1878		fw_bmr(fc);
1879	}else{
1880		printf("\n");
1881	}
1882error:
1883	fw_xfer_free(xfer);
1884}
1885
1886/*
1887 * To candidate Bus Manager election process.
1888 */
1889void
1890fw_try_bmr(void *arg)
1891{
1892	struct fw_xfer *xfer;
1893	struct firewire_comm *fc = (struct firewire_comm *)arg;
1894	struct fw_pkt *fp;
1895	int err = 0;
1896
1897	xfer = fw_xfer_alloc();
1898	if(xfer == NULL){
1899		return;
1900	}
1901	xfer->send.len = 24;
1902	xfer->spd = 0;
1903	xfer->send.buf = malloc(24, M_FW, M_NOWAIT);
1904	if(xfer->send.buf == NULL){
1905		fw_xfer_free( xfer);
1906		return;
1907	}
1908
1909	fc->status = FWBUSMGRELECT;
1910
1911	xfer->send.off = 0;
1912	fp = (struct fw_pkt *)xfer->send.buf;
1913	fp->mode.lreq.dest_hi = htons(0xffff);
1914	fp->mode.lreq.tlrt = 0;
1915	fp->mode.lreq.tcode = FWTCODE_LREQ;
1916	fp->mode.lreq.pri = 0;
1917	fp->mode.lreq.src = 0;
1918	fp->mode.lreq.len = htons(8);
1919	fp->mode.lreq.extcode = htons(FW_LREQ_CMPSWAP);
1920	xfer->dst = FWLOCALBUS | fc->irm;
1921	fp->mode.lreq.dst = htons(xfer->dst);
1922	fp->mode.lreq.dest_lo = htonl(0xf0000000 | BUS_MGR_ID);
1923	fp->mode.lreq.payload[0] = htonl(0x3f);
1924	fp->mode.lreq.payload[1] = htonl(fc->nodeid);
1925	xfer->act_type = FWACT_XFER;
1926	xfer->act.hand = fw_try_bmr_callback;
1927
1928	err = fw_asyreq(fc, -1, xfer);
1929	if(err){
1930		fw_xfer_free( xfer);
1931		return;
1932	}
1933	return;
1934}
1935
1936#ifdef FW_VMACCESS
1937/*
1938 * Software implementation for physical memory block access.
1939 * XXX:Too slow, usef for debug purpose only.
1940 */
1941static void
1942fw_vmaccess(struct fw_xfer *xfer){
1943	struct fw_pkt *rfp, *sfp = NULL;
1944	u_int32_t *ld = (u_int32_t *)(xfer->recv.buf + xfer->recv.off);
1945
1946	printf("vmaccess spd:%2x len:%03x %d data:%08x %08x %08x %08x\n",
1947			xfer->spd, xfer->recv.len, xfer->recv.off, ntohl(ld[0]), ntohl(ld[1]), ntohl(ld[2]), ntohl(ld[3]));
1948	printf("vmaccess          data:%08x %08x %08x %08x\n", ntohl(ld[4]), ntohl(ld[5]), ntohl(ld[6]), ntohl(ld[7]));
1949	if(xfer->resp != 0){
1950		fw_xfer_free( xfer);
1951		return;
1952	}
1953	if(xfer->recv.buf == NULL){
1954		fw_xfer_free( xfer);
1955		return;
1956	}
1957	rfp = (struct fw_pkt *)xfer->recv.buf;
1958	switch(rfp->mode.hdr.tcode){
1959		/* XXX need fix for 64bit arch */
1960		case FWTCODE_WREQB:
1961			xfer->send.buf = malloc(12, M_FW, M_NOWAIT);
1962			xfer->send.len = 12;
1963			sfp = (struct fw_pkt *)xfer->send.buf;
1964			bcopy(rfp->mode.wreqb.payload,
1965				(caddr_t)ntohl(rfp->mode.wreqb.dest_lo), ntohs(rfp->mode.wreqb.len));
1966			sfp->mode.wres.tcode = FWTCODE_WRES;
1967			sfp->mode.wres.rtcode = 0;
1968			break;
1969		case FWTCODE_WREQQ:
1970			xfer->send.buf = malloc(12, M_FW, M_NOWAIT);
1971			xfer->send.len = 12;
1972			sfp->mode.wres.tcode = FWTCODE_WRES;
1973			*((u_int32_t *)(ntohl(rfp->mode.wreqb.dest_lo))) = rfp->mode.wreqq.data;
1974			sfp->mode.wres.rtcode = 0;
1975			break;
1976		case FWTCODE_RREQB:
1977			xfer->send.buf = malloc(16 + rfp->mode.rreqb.len, M_FW, M_NOWAIT);
1978			xfer->send.len = 16 + ntohs(rfp->mode.rreqb.len);
1979			sfp = (struct fw_pkt *)xfer->send.buf;
1980			bcopy((caddr_t)ntohl(rfp->mode.rreqb.dest_lo),
1981				sfp->mode.rresb.payload, (u_int16_t)ntohs(rfp->mode.rreqb.len));
1982			sfp->mode.rresb.tcode = FWTCODE_RRESB;
1983			sfp->mode.rresb.len = rfp->mode.rreqb.len;
1984			sfp->mode.rresb.rtcode = 0;
1985			sfp->mode.rresb.extcode = 0;
1986			break;
1987		case FWTCODE_RREQQ:
1988			xfer->send.buf = malloc(16, M_FW, M_NOWAIT);
1989			xfer->send.len = 16;
1990			sfp = (struct fw_pkt *)xfer->send.buf;
1991			sfp->mode.rresq.data = *(u_int32_t *)(ntohl(rfp->mode.rreqq.dest_lo));
1992			sfp->mode.wres.tcode = FWTCODE_RRESQ;
1993			sfp->mode.rresb.rtcode = 0;
1994			break;
1995		default:
1996			fw_xfer_free( xfer);
1997			return;
1998	}
1999	xfer->send.off = 0;
2000	sfp->mode.hdr.dst = rfp->mode.hdr.src;
2001	xfer->dst = ntohs(rfp->mode.hdr.src);
2002	xfer->act.hand = fw_xfer_free;
2003	xfer->retry_req = fw_asybusy;
2004
2005	sfp->mode.hdr.tlrt = rfp->mode.hdr.tlrt;
2006	sfp->mode.hdr.pri = 0;
2007
2008	fw_asyreq(xfer->fc, -1, xfer);
2009/**/
2010	return;
2011}
2012#endif
2013
2014/*
2015 * CRC16 check-sum for IEEE1394 register blocks.
2016 */
2017u_int16_t
2018fw_crc16(u_int32_t *ptr, u_int32_t len){
2019	u_int32_t i, sum, crc = 0;
2020	int shift;
2021	len = (len + 3) & ~3;
2022	for(i = 0 ; i < len ; i+= 4){
2023		for( shift = 28 ; shift >= 0 ; shift -= 4){
2024			sum = ((crc >> 12) ^ (ptr[i/4] >> shift)) & 0xf;
2025			crc = (crc << 4) ^ ( sum << 12 ) ^ ( sum << 5) ^ sum;
2026		}
2027		crc &= 0xffff;
2028	}
2029	return((u_int16_t) crc);
2030}
2031
2032int
2033fw_bmr(struct firewire_comm *fc)
2034{
2035	struct fw_device fwdev;
2036	int cmstr;
2037
2038	/* XXX Assume that the current root node is cycle master capable */
2039	cmstr = fc->max_node;
2040	/* If I am the bus manager, optimize gapcount */
2041	if(fc->max_hop <= MAX_GAPHOP ){
2042		fw_phy_config(fc, (fc->max_node > 0)?cmstr:-1,
2043						gap_cnt[fc->max_hop]);
2044	}
2045	/* If we are the cycle master, nothing to do */
2046	if (cmstr == fc->nodeid)
2047		return 0;
2048	/* Bus probe has not finished, make dummy fwdev for cmstr */
2049	bzero(&fwdev, sizeof(fwdev));
2050	fwdev.fc = fc;
2051	fwdev.dst = cmstr;
2052	fwdev.speed = 0;
2053	fwdev.maxrec = 8; /* 512 */
2054	fwdev.status = FWDEVINIT;
2055	/* Set cmstr bit on the cycle master */
2056	fwmem_write_quad(&fwdev, NULL, 0/*spd*/,
2057		0xffff, 0xf0000000 | STATE_SET, 1 << 16,
2058		fw_asy_callback_free);
2059
2060	return 0;
2061}
2062
2063DRIVER_MODULE(firewire,fwohci,firewire_driver,firewire_devclass,0,0);
2064MODULE_VERSION(firewire, 1);
2065