firewire.c revision 227843
1139749Simp/*-
2113584Ssimokawa * Copyright (c) 2003 Hidetoshi Shimokawa
3103285Sikob * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa
4103285Sikob * All rights reserved.
5103285Sikob *
6103285Sikob * Redistribution and use in source and binary forms, with or without
7103285Sikob * modification, are permitted provided that the following conditions
8103285Sikob * are met:
9103285Sikob * 1. Redistributions of source code must retain the above copyright
10103285Sikob *    notice, this list of conditions and the following disclaimer.
11103285Sikob * 2. Redistributions in binary form must reproduce the above copyright
12103285Sikob *    notice, this list of conditions and the following disclaimer in the
13103285Sikob *    documentation and/or other materials provided with the distribution.
14103285Sikob * 3. All advertising materials mentioning features or use of this software
15103285Sikob *    must display the acknowledgement as bellow:
16103285Sikob *
17103285Sikob *    This product includes software developed by K. Kobayashi and H. Shimokawa
18103285Sikob *
19103285Sikob * 4. The name of the author may not be used to endorse or promote products
20103285Sikob *    derived from this software without specific prior written permission.
21103285Sikob *
22103285Sikob * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23103285Sikob * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24103285Sikob * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25103285Sikob * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
26103285Sikob * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27103285Sikob * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28103285Sikob * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29103285Sikob * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
30103285Sikob * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31103285Sikob * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32103285Sikob * POSSIBILITY OF SUCH DAMAGE.
33103285Sikob */
34103285Sikob
35227843Smarius#include <sys/cdefs.h>
36227843Smarius__FBSDID("$FreeBSD: head/sys/dev/firewire/firewire.c 227843 2011-11-22 21:28:20Z marius $");
37227843Smarius
38103285Sikob#include <sys/param.h>
39103285Sikob#include <sys/systm.h>
40103285Sikob#include <sys/types.h>
41103285Sikob
42193066Sjamie#include <sys/jail.h>
43103285Sikob#include <sys/kernel.h>
44129879Sphk#include <sys/module.h>
45103285Sikob#include <sys/malloc.h>
46103285Sikob#include <sys/conf.h>
47103285Sikob#include <sys/sysctl.h>
48169806Ssimokawa#include <sys/kthread.h>
49103285Sikob
50170374Ssimokawa#include <sys/kdb.h>
51170374Ssimokawa
52127468Ssimokawa#if defined(__DragonFly__) || __FreeBSD_version < 500000
53117067Ssimokawa#include <machine/clock.h>	/* for DELAY() */
54117067Ssimokawa#endif
55103285Sikob
56103285Sikob#include <sys/bus.h>		/* used by smbus and newbus */
57113584Ssimokawa#include <machine/bus.h>
58103285Sikob
59127468Ssimokawa#ifdef __DragonFly__
60127468Ssimokawa#include "firewire.h"
61127468Ssimokawa#include "firewirereg.h"
62127468Ssimokawa#include "fwmem.h"
63127468Ssimokawa#include "iec13213.h"
64127468Ssimokawa#include "iec68113.h"
65127468Ssimokawa#else
66103285Sikob#include <dev/firewire/firewire.h>
67103285Sikob#include <dev/firewire/firewirereg.h>
68110072Ssimokawa#include <dev/firewire/fwmem.h>
69103285Sikob#include <dev/firewire/iec13213.h>
70103285Sikob#include <dev/firewire/iec68113.h>
71127468Ssimokawa#endif
72103285Sikob
73116376Ssimokawastruct crom_src_buf {
74116376Ssimokawa	struct crom_src	src;
75116376Ssimokawa	struct crom_chunk root;
76116376Ssimokawa	struct crom_chunk vendor;
77116376Ssimokawa	struct crom_chunk hw;
78116376Ssimokawa};
79116376Ssimokawa
80188704Ssbrunoint firewire_debug=0, try_bmr=1, hold_count=0;
81103285SikobSYSCTL_INT(_debug, OID_AUTO, firewire_debug, CTLFLAG_RW, &firewire_debug, 0,
82108281Ssimokawa	"FireWire driver debug flag");
83109736SsimokawaSYSCTL_NODE(_hw, OID_AUTO, firewire, CTLFLAG_RD, 0, "FireWire Subsystem");
84109736SsimokawaSYSCTL_INT(_hw_firewire, OID_AUTO, try_bmr, CTLFLAG_RW, &try_bmr, 0,
85109736Ssimokawa	"Try to be a bus manager");
86120850SsimokawaSYSCTL_INT(_hw_firewire, OID_AUTO, hold_count, CTLFLAG_RW, &hold_count, 0,
87120850Ssimokawa	"Number of count of bus resets for removing lost device information");
88103285Sikob
89110195SsimokawaMALLOC_DEFINE(M_FW, "firewire", "FireWire");
90110269SsimokawaMALLOC_DEFINE(M_FWXFER, "fw_xfer", "XFER/FireWire");
91110195Ssimokawa
92103285Sikob#define FW_MAXASYRTY 4
93103285Sikob
94103285Sikobdevclass_t firewire_devclass;
95103285Sikob
96125238Ssimokawastatic void firewire_identify	(driver_t *, device_t);
97125238Ssimokawastatic int firewire_probe	(device_t);
98124169Ssimokawastatic int firewire_attach      (device_t);
99124169Ssimokawastatic int firewire_detach      (device_t);
100124169Ssimokawastatic int firewire_resume      (device_t);
101170374Ssimokawastatic void firewire_xfer_timeout(void *, int);
102103285Sikob#if 0
103124169Ssimokawastatic int firewire_shutdown    (device_t);
104103285Sikob#endif
105212413Savgstatic device_t firewire_add_child(device_t, u_int, const char *, int);
106124169Ssimokawastatic void fw_try_bmr (void *);
107124169Ssimokawastatic void fw_try_bmr_callback (struct fw_xfer *);
108124169Ssimokawastatic void fw_asystart (struct fw_xfer *);
109124169Ssimokawastatic int fw_get_tlabel (struct firewire_comm *, struct fw_xfer *);
110124169Ssimokawastatic void fw_bus_probe (struct firewire_comm *);
111124169Ssimokawastatic void fw_attach_dev (struct firewire_comm *);
112169806Ssimokawastatic void fw_bus_probe_thread(void *);
113106543Ssimokawa#ifdef FW_VMACCESS
114124169Ssimokawastatic void fw_vmaccess (struct fw_xfer *);
115106543Ssimokawa#endif
116124169Ssimokawastatic int fw_bmr (struct firewire_comm *);
117170374Ssimokawastatic void fw_dump_hdr(struct fw_pkt *, char *);
118103285Sikob
119103285Sikobstatic device_method_t firewire_methods[] = {
120103285Sikob	/* Device interface */
121125238Ssimokawa	DEVMETHOD(device_identify,	firewire_identify),
122125238Ssimokawa	DEVMETHOD(device_probe,		firewire_probe),
123103285Sikob	DEVMETHOD(device_attach,	firewire_attach),
124103285Sikob	DEVMETHOD(device_detach,	firewire_detach),
125108642Ssimokawa	DEVMETHOD(device_suspend,	bus_generic_suspend),
126116978Ssimokawa	DEVMETHOD(device_resume,	firewire_resume),
127103285Sikob	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
128103285Sikob
129103285Sikob	/* Bus interface */
130103285Sikob	DEVMETHOD(bus_add_child,	firewire_add_child),
131103285Sikob
132227843Smarius	DEVMETHOD_END
133103285Sikob};
134124251Ssimokawachar *linkspeed[] = {
135124251Ssimokawa	"S100", "S200", "S400", "S800",
136124251Ssimokawa	"S1600", "S3200", "undef", "undef"
137124251Ssimokawa};
138103285Sikob
139124251Ssimokawastatic char *tcode_str[] = {
140124251Ssimokawa	"WREQQ", "WREQB", "WRES",   "undef",
141124251Ssimokawa	"RREQQ", "RREQB", "RRESQ",  "RRESB",
142124251Ssimokawa	"CYCS",  "LREQ",  "STREAM", "LRES",
143124251Ssimokawa	"undef", "undef", "PHY",    "undef"
144124251Ssimokawa};
145124251Ssimokawa
146114909Ssimokawa/* IEEE-1394a Table C-2 Gap count as a function of hops*/
147114909Ssimokawa#define MAX_GAPHOP 15
148114909Ssimokawau_int gap_cnt[] = { 5,  5,  7,  8, 10, 13, 16, 18,
149114909Ssimokawa		   21, 24, 26, 29, 32, 35, 37, 40};
150106813Ssimokawa
151103285Sikobstatic driver_t firewire_driver = {
152103285Sikob	"firewire",
153103285Sikob	firewire_methods,
154103285Sikob	sizeof(struct firewire_softc),
155103285Sikob};
156103285Sikob
157103285Sikob/*
158110072Ssimokawa * Lookup fwdev by node id.
159103285Sikob */
160106810Ssimokawastruct fw_device *
161110072Ssimokawafw_noderesolve_nodeid(struct firewire_comm *fc, int dst)
162103285Sikob{
163103285Sikob	struct fw_device *fwdev;
164110072Ssimokawa	int s;
165110072Ssimokawa
166110072Ssimokawa	s = splfw();
167110193Ssimokawa	STAILQ_FOREACH(fwdev, &fc->devices, link)
168120660Ssimokawa		if (fwdev->dst == dst && fwdev->status != FWDEVINVAL)
169103285Sikob			break;
170110072Ssimokawa	splx(s);
171110072Ssimokawa
172106810Ssimokawa	return fwdev;
173103285Sikob}
174106813Ssimokawa
175103285Sikob/*
176110072Ssimokawa * Lookup fwdev by EUI64.
177110072Ssimokawa */
178110072Ssimokawastruct fw_device *
179110582Ssimokawafw_noderesolve_eui64(struct firewire_comm *fc, struct fw_eui64 *eui)
180110072Ssimokawa{
181110072Ssimokawa	struct fw_device *fwdev;
182110072Ssimokawa	int s;
183110072Ssimokawa
184110072Ssimokawa	s = splfw();
185170374Ssimokawa	FW_GLOCK(fc);
186110193Ssimokawa	STAILQ_FOREACH(fwdev, &fc->devices, link)
187110582Ssimokawa		if (FW_EUI64_EQUAL(fwdev->eui, *eui))
188110072Ssimokawa			break;
189170374Ssimokawa	FW_GUNLOCK(fc);
190110072Ssimokawa	splx(s);
191110072Ssimokawa
192110072Ssimokawa	if(fwdev == NULL) return NULL;
193110072Ssimokawa	if(fwdev->status == FWDEVINVAL) return NULL;
194110072Ssimokawa	return fwdev;
195110072Ssimokawa}
196110072Ssimokawa
197110072Ssimokawa/*
198103285Sikob * Async. request procedure for userland application.
199103285Sikob */
200103285Sikobint
201103285Sikobfw_asyreq(struct firewire_comm *fc, int sub, struct fw_xfer *xfer)
202103285Sikob{
203103285Sikob	int err = 0;
204103285Sikob	struct fw_xferq *xferq;
205170374Ssimokawa	int len;
206103285Sikob	struct fw_pkt *fp;
207103285Sikob	int tcode;
208103285Sikob	struct tcode_info *info;
209103285Sikob
210103285Sikob	if(xfer == NULL) return EINVAL;
211167632Ssimokawa	if(xfer->hand == NULL){
212167632Ssimokawa		printf("hand == NULL\n");
213103285Sikob		return EINVAL;
214103285Sikob	}
215120660Ssimokawa	fp = &xfer->send.hdr;
216103285Sikob
217103285Sikob	tcode = fp->mode.common.tcode & 0xf;
218103285Sikob	info = &fc->tcode[tcode];
219103285Sikob	if (info->flag == 0) {
220124251Ssimokawa		printf("invalid tcode=%x\n", tcode);
221103285Sikob		return EINVAL;
222103285Sikob	}
223170425Ssimokawa
224170425Ssimokawa	/* XXX allow bus explore packets only after bus rest */
225170425Ssimokawa	if ((fc->status < FWBUSEXPLORE) &&
226170425Ssimokawa	    ((tcode != FWTCODE_RREQQ) || (fp->mode.rreqq.dest_hi != 0xffff) ||
227170425Ssimokawa	    (fp->mode.rreqq.dest_lo  < 0xf0000000) ||
228170425Ssimokawa	    (fp->mode.rreqq.dest_lo >= 0xf0001000))) {
229170425Ssimokawa		xfer->resp = EAGAIN;
230170425Ssimokawa		xfer->flag = FWXF_BUSY;
231170425Ssimokawa		return (EAGAIN);
232170425Ssimokawa	}
233170425Ssimokawa
234103285Sikob	if (info->flag & FWTI_REQ)
235103285Sikob		xferq = fc->atq;
236103285Sikob	else
237103285Sikob		xferq = fc->ats;
238103285Sikob	len = info->hdr_len;
239120660Ssimokawa	if (xfer->send.pay_len > MAXREC(fc->maxrec)) {
240120660Ssimokawa		printf("send.pay_len > maxrec\n");
241120660Ssimokawa		return EINVAL;
242120660Ssimokawa	}
243103285Sikob	if (info->flag & FWTI_BLOCK_STR)
244120660Ssimokawa		len = fp->mode.stream.len;
245103285Sikob	else if (info->flag & FWTI_BLOCK_ASY)
246120660Ssimokawa		len = fp->mode.rresb.len;
247120660Ssimokawa	else
248120660Ssimokawa		len = 0;
249120660Ssimokawa	if (len != xfer->send.pay_len){
250124251Ssimokawa		printf("len(%d) != send.pay_len(%d) %s(%x)\n",
251124251Ssimokawa		    len, xfer->send.pay_len, tcode_str[tcode], tcode);
252103285Sikob		return EINVAL;
253103285Sikob	}
254106790Ssimokawa
255103285Sikob	if(xferq->start == NULL){
256103285Sikob		printf("xferq->start == NULL\n");
257103285Sikob		return EINVAL;
258103285Sikob	}
259103285Sikob	if(!(xferq->queued < xferq->maxq)){
260108655Ssimokawa		device_printf(fc->bdev, "Discard a packet (queued=%d)\n",
261108655Ssimokawa			xferq->queued);
262170374Ssimokawa		return EAGAIN;
263103285Sikob	}
264103285Sikob
265170374Ssimokawa	xfer->tl = -1;
266103285Sikob	if (info->flag & FWTI_TLABEL) {
267170374Ssimokawa		if (fw_get_tlabel(fc, xfer) < 0)
268130460Sdfr			return EAGAIN;
269103285Sikob	}
270103285Sikob
271103285Sikob	xfer->resp = 0;
272103285Sikob	xfer->fc = fc;
273103285Sikob	xfer->q = xferq;
274103285Sikob
275103285Sikob	fw_asystart(xfer);
276103285Sikob	return err;
277103285Sikob}
278103285Sikob/*
279103285Sikob * Wakeup blocked process.
280103285Sikob */
281103285Sikobvoid
282170374Ssimokawafw_xferwake(struct fw_xfer *xfer)
283170374Ssimokawa{
284170374Ssimokawa	struct mtx *lock = &xfer->fc->wait_lock;
285170374Ssimokawa
286170374Ssimokawa	mtx_lock(lock);
287170374Ssimokawa	xfer->flag |= FWXF_WAKE;
288170374Ssimokawa	mtx_unlock(lock);
289170374Ssimokawa
290103285Sikob	wakeup(xfer);
291103285Sikob	return;
292103285Sikob}
293103285Sikob
294170374Ssimokawaint
295170374Ssimokawafw_xferwait(struct fw_xfer *xfer)
296170374Ssimokawa{
297170374Ssimokawa	struct mtx *lock = &xfer->fc->wait_lock;
298170374Ssimokawa	int err = 0;
299170374Ssimokawa
300170374Ssimokawa	mtx_lock(lock);
301170374Ssimokawa	if ((xfer->flag & FWXF_WAKE) == 0)
302170374Ssimokawa		err = msleep((void *)xfer, lock, PWAIT|PCATCH, "fw_xferwait", 0);
303170374Ssimokawa	mtx_unlock(lock);
304170374Ssimokawa
305170374Ssimokawa	return (err);
306170374Ssimokawa}
307170374Ssimokawa
308103285Sikob/*
309103285Sikob * Async. request with given xfer structure.
310103285Sikob */
311106790Ssimokawastatic void
312106790Ssimokawafw_asystart(struct fw_xfer *xfer)
313106790Ssimokawa{
314103285Sikob	struct firewire_comm *fc = xfer->fc;
315103285Sikob	int s;
316170374Ssimokawa	s = splfw();
317170374Ssimokawa	/* Protect from interrupt/timeout */
318170374Ssimokawa	FW_GLOCK(fc);
319170374Ssimokawa	xfer->flag = FWXF_INQ;
320103285Sikob	STAILQ_INSERT_TAIL(&xfer->q->q, xfer, link);
321170374Ssimokawa#if 0
322103285Sikob	xfer->q->queued ++;
323170374Ssimokawa#endif
324170374Ssimokawa	FW_GUNLOCK(fc);
325103285Sikob	splx(s);
326103285Sikob	/* XXX just queue for mbuf */
327103285Sikob	if (xfer->mbuf == NULL)
328103285Sikob		xfer->q->start(fc);
329103285Sikob	return;
330103285Sikob}
331106790Ssimokawa
332125238Ssimokawastatic void
333125238Ssimokawafirewire_identify(driver_t *driver, device_t parent)
334125238Ssimokawa{
335125238Ssimokawa	BUS_ADD_CHILD(parent, 0, "firewire", -1);
336125238Ssimokawa}
337125238Ssimokawa
338103285Sikobstatic int
339125238Ssimokawafirewire_probe(device_t dev)
340103285Sikob{
341108281Ssimokawa	device_set_desc(dev, "IEEE1394(FireWire) bus");
342125238Ssimokawa	return (0);
343103285Sikob}
344106790Ssimokawa
345110577Ssimokawastatic void
346170374Ssimokawafirewire_xfer_timeout(void *arg, int pending)
347110577Ssimokawa{
348170374Ssimokawa	struct firewire_comm *fc = (struct firewire_comm *)arg;
349170374Ssimokawa	struct fw_xfer *xfer, *txfer;
350110577Ssimokawa	struct timeval tv;
351110577Ssimokawa	struct timeval split_timeout;
352170374Ssimokawa	STAILQ_HEAD(, fw_xfer) xfer_timeout;
353111040Ssimokawa	int i, s;
354110577Ssimokawa
355120660Ssimokawa	split_timeout.tv_sec = 0;
356120660Ssimokawa	split_timeout.tv_usec = 200 * 1000;	 /* 200 msec */
357110577Ssimokawa
358110577Ssimokawa	microtime(&tv);
359110577Ssimokawa	timevalsub(&tv, &split_timeout);
360170374Ssimokawa	STAILQ_INIT(&xfer_timeout);
361110577Ssimokawa
362111040Ssimokawa	s = splfw();
363171513Ssimokawa	mtx_lock(&fc->tlabel_lock);
364110577Ssimokawa	for (i = 0; i < 0x40; i ++) {
365169119Ssimokawa		while ((xfer = STAILQ_FIRST(&fc->tlabels[i])) != NULL) {
366170427Ssimokawa			if ((xfer->flag & FWXF_SENT) == 0)
367170427Ssimokawa				/* not sent yet */
368170427Ssimokawa				break;
369110577Ssimokawa			if (timevalcmp(&xfer->tv, &tv, >))
370110577Ssimokawa				/* the rests are newer than this */
371110577Ssimokawa				break;
372110577Ssimokawa			device_printf(fc->bdev,
373170374Ssimokawa				"split transaction timeout: "
374170374Ssimokawa				"tl=0x%x flag=0x%02x\n", i, xfer->flag);
375170374Ssimokawa			fw_dump_hdr(&xfer->send.hdr, "send");
376110577Ssimokawa			xfer->resp = ETIMEDOUT;
377170374Ssimokawa			STAILQ_REMOVE_HEAD(&fc->tlabels[i], tlabel);
378170374Ssimokawa			STAILQ_INSERT_TAIL(&xfer_timeout, xfer, tlabel);
379110577Ssimokawa		}
380110577Ssimokawa	}
381171513Ssimokawa	mtx_unlock(&fc->tlabel_lock);
382111040Ssimokawa	splx(s);
383170374Ssimokawa	fc->timeout(fc);
384170374Ssimokawa
385170374Ssimokawa	STAILQ_FOREACH_SAFE(xfer, &xfer_timeout, tlabel, txfer)
386170374Ssimokawa		xfer->hand(xfer);
387110577Ssimokawa}
388110577Ssimokawa
389170374Ssimokawa#define WATCHDOG_HZ 10
390110577Ssimokawastatic void
391110577Ssimokawafirewire_watchdog(void *arg)
392110577Ssimokawa{
393110577Ssimokawa	struct firewire_comm *fc;
394170374Ssimokawa	static int watchdog_clock = 0;
395110577Ssimokawa
396110577Ssimokawa	fc = (struct firewire_comm *)arg;
397121463Ssimokawa
398121463Ssimokawa	/*
399121463Ssimokawa	 * At boot stage, the device interrupt is disabled and
400121463Ssimokawa	 * We encounter a timeout easily. To avoid this,
401121463Ssimokawa	 * ignore clock interrupt for a while.
402121463Ssimokawa	 */
403170374Ssimokawa	if (watchdog_clock > WATCHDOG_HZ * 15)
404170374Ssimokawa		taskqueue_enqueue(fc->taskqueue, &fc->task_timeout);
405170374Ssimokawa	else
406170374Ssimokawa		watchdog_clock ++;
407121463Ssimokawa
408170374Ssimokawa	callout_reset(&fc->timeout_callout, hz / WATCHDOG_HZ,
409110577Ssimokawa			(void *)firewire_watchdog, (void *)fc);
410110577Ssimokawa}
411110577Ssimokawa
412103285Sikob/*
413103285Sikob * The attach routine.
414103285Sikob */
415103285Sikobstatic int
416118455Ssimokawafirewire_attach(device_t dev)
417103285Sikob{
418118455Ssimokawa	int unit;
419103285Sikob	struct firewire_softc *sc = device_get_softc(dev);
420103285Sikob	device_t pa = device_get_parent(dev);
421103285Sikob	struct firewire_comm *fc;
422103285Sikob
423103285Sikob	fc = (struct firewire_comm *)device_get_softc(pa);
424103285Sikob	sc->fc = fc;
425116978Ssimokawa	fc->status = FWBUSNOTREADY;
426103285Sikob
427118455Ssimokawa	unit = device_get_unit(dev);
428118455Ssimokawa	if( fc->nisodma > FWMAXNDMA) fc->nisodma = FWMAXNDMA;
429103285Sikob
430118455Ssimokawa	fwdev_makedev(sc);
431118455Ssimokawa
432187993Ssbruno	fc->crom_src_buf = (struct crom_src_buf *)malloc(
433187993Ssbruno				sizeof(struct crom_src_buf),
434187993Ssbruno				M_FW, M_NOWAIT | M_ZERO);
435187993Ssbruno	if (fc->crom_src_buf == NULL) {
436187993Ssbruno		device_printf(fc->dev, "%s: Malloc Failure crom src buff\n", __func__);
437187993Ssbruno		return ENOMEM;
438187993Ssbruno	}
439187993Ssbruno	fc->topology_map = (struct fw_topology_map *)malloc(
440187993Ssbruno				sizeof(struct fw_topology_map),
441187993Ssbruno				M_FW, M_NOWAIT | M_ZERO);
442187993Ssbruno	if (fc->topology_map == NULL) {
443187993Ssbruno		device_printf(fc->dev, "%s: Malloc Failure topology map\n", __func__);
444187993Ssbruno		free(fc->crom_src_buf, M_FW);
445187993Ssbruno		return ENOMEM;
446187993Ssbruno	}
447187993Ssbruno	fc->speed_map = (struct fw_speed_map *)malloc(
448187993Ssbruno				sizeof(struct fw_speed_map),
449187993Ssbruno				M_FW, M_NOWAIT | M_ZERO);
450187993Ssbruno	if (fc->speed_map == NULL) {
451187993Ssbruno		device_printf(fc->dev, "%s: Malloc Failure speed map\n", __func__);
452187993Ssbruno		free(fc->crom_src_buf, M_FW);
453187993Ssbruno		free(fc->topology_map, M_FW);
454187993Ssbruno		return ENOMEM;
455187993Ssbruno	}
456187993Ssbruno
457170374Ssimokawa	mtx_init(&fc->wait_lock, "fwwait", NULL, MTX_DEF);
458171513Ssimokawa	mtx_init(&fc->tlabel_lock, "fwtlabel", NULL, MTX_DEF);
459170374Ssimokawa	CALLOUT_INIT(&fc->timeout_callout);
460170374Ssimokawa	CALLOUT_INIT(&fc->bmr_callout);
461170374Ssimokawa	CALLOUT_INIT(&fc->busprobe_callout);
462170374Ssimokawa	TASK_INIT(&fc->task_timeout, 0, firewire_xfer_timeout, (void *)fc);
463108853Ssimokawa
464110577Ssimokawa	callout_reset(&sc->fc->timeout_callout, hz,
465110577Ssimokawa			(void *)firewire_watchdog, (void *)sc->fc);
466110193Ssimokawa
467169806Ssimokawa	/* create thread */
468172836Sjulian	kproc_create(fw_bus_probe_thread, (void *)fc, &fc->probe_thread,
469169806Ssimokawa		0, 0, "fw%d_probe", unit);
470169806Ssimokawa
471103285Sikob	/* Locate our children */
472103285Sikob	bus_generic_probe(dev);
473103285Sikob
474103285Sikob	/* launch attachement of the added children */
475103285Sikob	bus_generic_attach(dev);
476103285Sikob
477103285Sikob	/* bus_reset */
478187993Ssbruno	FW_GLOCK(fc);
479169117Ssimokawa	fw_busreset(fc, FWBUSNOTREADY);
480187993Ssbruno	FW_GUNLOCK(fc);
481103285Sikob	fc->ibr(fc);
482103285Sikob
483103285Sikob	return 0;
484103285Sikob}
485103285Sikob
486103285Sikob/*
487103285Sikob * Attach it as child.
488103285Sikob */
489103285Sikobstatic device_t
490212413Savgfirewire_add_child(device_t dev, u_int order, const char *name, int unit)
491103285Sikob{
492103285Sikob        device_t child;
493103285Sikob	struct firewire_softc *sc;
494103285Sikob
495103285Sikob	sc = (struct firewire_softc *)device_get_softc(dev);
496103285Sikob	child = device_add_child(dev, name, unit);
497103285Sikob	if (child) {
498103285Sikob		device_set_ivars(child, sc->fc);
499103285Sikob		device_probe_and_attach(child);
500103285Sikob	}
501103285Sikob
502103285Sikob	return child;
503103285Sikob}
504106790Ssimokawa
505116978Ssimokawastatic int
506116978Ssimokawafirewire_resume(device_t dev)
507116978Ssimokawa{
508116978Ssimokawa	struct firewire_softc *sc;
509116978Ssimokawa
510116978Ssimokawa	sc = (struct firewire_softc *)device_get_softc(dev);
511116978Ssimokawa	sc->fc->status = FWBUSNOTREADY;
512116978Ssimokawa
513116978Ssimokawa	bus_generic_resume(dev);
514116978Ssimokawa
515116978Ssimokawa	return(0);
516116978Ssimokawa}
517116978Ssimokawa
518103285Sikob/*
519103285Sikob * Dettach it.
520103285Sikob */
521103285Sikobstatic int
522118455Ssimokawafirewire_detach(device_t dev)
523103285Sikob{
524103285Sikob	struct firewire_softc *sc;
525169806Ssimokawa	struct firewire_comm *fc;
526111078Ssimokawa	struct fw_device *fwdev, *fwdev_next;
527118455Ssimokawa	int err;
528103285Sikob
529103285Sikob	sc = (struct firewire_softc *)device_get_softc(dev);
530169806Ssimokawa	fc = sc->fc;
531170374Ssimokawa	mtx_lock(&fc->wait_lock);
532169806Ssimokawa	fc->status = FWBUSDETACH;
533170374Ssimokawa	wakeup(fc);
534170374Ssimokawa	if (msleep(fc->probe_thread, &fc->wait_lock, PWAIT, "fwthr", hz * 60))
535170374Ssimokawa		printf("firewire probe thread didn't die\n");
536170374Ssimokawa	mtx_unlock(&fc->wait_lock);
537169806Ssimokawa
538178915Ssimokawa	if (fc->arq !=0 && fc->arq->maxq > 0)
539178915Ssimokawa		fw_drain_txq(fc);
540178915Ssimokawa
541118455Ssimokawa	if ((err = fwdev_destroydev(sc)) != 0)
542118455Ssimokawa		return err;
543106790Ssimokawa
544118455Ssimokawa	if ((err = bus_generic_detach(dev)) != 0)
545118455Ssimokawa		return err;
546111078Ssimokawa
547169806Ssimokawa	callout_stop(&fc->timeout_callout);
548169806Ssimokawa	callout_stop(&fc->bmr_callout);
549169806Ssimokawa	callout_stop(&fc->busprobe_callout);
550111078Ssimokawa
551178915Ssimokawa	/* XXX xfer_free and untimeout on all xfers */
552169806Ssimokawa	for (fwdev = STAILQ_FIRST(&fc->devices); fwdev != NULL;
553111078Ssimokawa							fwdev = fwdev_next) {
554111078Ssimokawa		fwdev_next = STAILQ_NEXT(fwdev, link);
555111078Ssimokawa		free(fwdev, M_FW);
556111078Ssimokawa	}
557169806Ssimokawa	free(fc->topology_map, M_FW);
558169806Ssimokawa	free(fc->speed_map, M_FW);
559169806Ssimokawa	free(fc->crom_src_buf, M_FW);
560169806Ssimokawa
561171513Ssimokawa	mtx_destroy(&fc->tlabel_lock);
562170374Ssimokawa	mtx_destroy(&fc->wait_lock);
563103285Sikob	return(0);
564103285Sikob}
565103285Sikob#if 0
566103285Sikobstatic int
567103285Sikobfirewire_shutdown( device_t dev )
568103285Sikob{
569103285Sikob	return 0;
570103285Sikob}
571103285Sikob#endif
572106790Ssimokawa
573110577Ssimokawa
574110577Ssimokawastatic void
575110798Ssimokawafw_xferq_drain(struct fw_xferq *xferq)
576110577Ssimokawa{
577110577Ssimokawa	struct fw_xfer *xfer;
578110577Ssimokawa
579110577Ssimokawa	while ((xfer = STAILQ_FIRST(&xferq->q)) != NULL) {
580110577Ssimokawa		STAILQ_REMOVE_HEAD(&xferq->q, link);
581170374Ssimokawa#if 0
582111942Ssimokawa		xferq->queued --;
583170374Ssimokawa#endif
584110577Ssimokawa		xfer->resp = EAGAIN;
585170374Ssimokawa		xfer->flag = FWXF_SENTERR;
586113584Ssimokawa		fw_xfer_done(xfer);
587110577Ssimokawa	}
588110577Ssimokawa}
589110577Ssimokawa
590110798Ssimokawavoid
591110798Ssimokawafw_drain_txq(struct firewire_comm *fc)
592110798Ssimokawa{
593170374Ssimokawa	struct fw_xfer *xfer, *txfer;
594170374Ssimokawa	STAILQ_HEAD(, fw_xfer) xfer_drain;
595110798Ssimokawa	int i;
596110798Ssimokawa
597170374Ssimokawa	STAILQ_INIT(&xfer_drain);
598170374Ssimokawa
599170374Ssimokawa	FW_GLOCK(fc);
600110798Ssimokawa	fw_xferq_drain(fc->atq);
601110798Ssimokawa	fw_xferq_drain(fc->ats);
602110798Ssimokawa	for(i = 0; i < fc->nisodma; i++)
603110798Ssimokawa		fw_xferq_drain(fc->it[i]);
604171513Ssimokawa	FW_GUNLOCK(fc);
605170374Ssimokawa
606171513Ssimokawa	mtx_lock(&fc->tlabel_lock);
607170374Ssimokawa	for (i = 0; i < 0x40; i ++)
608170374Ssimokawa		while ((xfer = STAILQ_FIRST(&fc->tlabels[i])) != NULL) {
609170374Ssimokawa			if (firewire_debug)
610170374Ssimokawa				printf("tl=%d flag=%d\n", i, xfer->flag);
611170374Ssimokawa			xfer->resp = EAGAIN;
612170374Ssimokawa			STAILQ_REMOVE_HEAD(&fc->tlabels[i], tlabel);
613170374Ssimokawa			STAILQ_INSERT_TAIL(&xfer_drain, xfer, tlabel);
614170374Ssimokawa		}
615171513Ssimokawa	mtx_unlock(&fc->tlabel_lock);
616170374Ssimokawa
617170374Ssimokawa	STAILQ_FOREACH_SAFE(xfer, &xfer_drain, tlabel, txfer)
618170374Ssimokawa		xfer->hand(xfer);
619110798Ssimokawa}
620110798Ssimokawa
621116376Ssimokawastatic void
622116376Ssimokawafw_reset_csr(struct firewire_comm *fc)
623103285Sikob{
624103285Sikob	int i;
625103285Sikob
626103285Sikob	CSRARC(fc, STATE_CLEAR)
627103285Sikob			= 1 << 23 | 0 << 17 | 1 << 16 | 1 << 15 | 1 << 14 ;
628103285Sikob	CSRARC(fc, STATE_SET) = CSRARC(fc, STATE_CLEAR);
629103285Sikob	CSRARC(fc, NODE_IDS) = 0x3f;
630103285Sikob
631103285Sikob	CSRARC(fc, TOPO_MAP + 8) = 0;
632103285Sikob	fc->irm = -1;
633103285Sikob
634103285Sikob	fc->max_node = -1;
635103285Sikob
636103285Sikob	for(i = 2; i < 0x100/4 - 2 ; i++){
637103285Sikob		CSRARC(fc, SPED_MAP + i * 4) = 0;
638103285Sikob	}
639103285Sikob	CSRARC(fc, STATE_CLEAR) = 1 << 23 | 0 << 17 | 1 << 16 | 1 << 15 | 1 << 14 ;
640103285Sikob	CSRARC(fc, STATE_SET) = CSRARC(fc, STATE_CLEAR);
641103285Sikob	CSRARC(fc, RESET_START) = 0;
642103285Sikob	CSRARC(fc, SPLIT_TIMEOUT_HI) = 0;
643103285Sikob	CSRARC(fc, SPLIT_TIMEOUT_LO) = 800 << 19;
644103285Sikob	CSRARC(fc, CYCLE_TIME) = 0x0;
645103285Sikob	CSRARC(fc, BUS_TIME) = 0x0;
646103285Sikob	CSRARC(fc, BUS_MGR_ID) = 0x3f;
647103285Sikob	CSRARC(fc, BANDWIDTH_AV) = 4915;
648103285Sikob	CSRARC(fc, CHANNELS_AV_HI) = 0xffffffff;
649103285Sikob	CSRARC(fc, CHANNELS_AV_LO) = 0xffffffff;
650103285Sikob	CSRARC(fc, IP_CHANNELS) = (1 << 31);
651103285Sikob
652103285Sikob	CSRARC(fc, CONF_ROM) = 0x04 << 24;
653103285Sikob	CSRARC(fc, CONF_ROM + 4) = 0x31333934; /* means strings 1394 */
654103285Sikob	CSRARC(fc, CONF_ROM + 8) = 1 << 31 | 1 << 30 | 1 << 29 |
655103285Sikob				1 << 28 | 0xff << 16 | 0x09 << 8;
656103285Sikob	CSRARC(fc, CONF_ROM + 0xc) = 0;
657103285Sikob
658103285Sikob/* DV depend CSRs see blue book */
659103285Sikob	CSRARC(fc, oPCR) &= ~DV_BROADCAST_ON;
660103285Sikob	CSRARC(fc, iPCR) &= ~DV_BROADCAST_ON;
661103285Sikob
662103285Sikob	CSRARC(fc, STATE_CLEAR) &= ~(1 << 23 | 1 << 15 | 1 << 14 );
663103285Sikob	CSRARC(fc, STATE_SET) = CSRARC(fc, STATE_CLEAR);
664116376Ssimokawa}
665113584Ssimokawa
666116376Ssimokawastatic void
667116376Ssimokawafw_init_crom(struct firewire_comm *fc)
668116376Ssimokawa{
669116376Ssimokawa	struct crom_src *src;
670116376Ssimokawa
671116376Ssimokawa	src = &fc->crom_src_buf->src;
672116376Ssimokawa	bzero(src, sizeof(struct crom_src));
673116376Ssimokawa
674116376Ssimokawa	/* BUS info sample */
675116376Ssimokawa	src->hdr.info_len = 4;
676116376Ssimokawa
677116376Ssimokawa	src->businfo.bus_name = CSR_BUS_NAME_IEEE1394;
678116376Ssimokawa
679116376Ssimokawa	src->businfo.irmc = 1;
680116376Ssimokawa	src->businfo.cmc = 1;
681116376Ssimokawa	src->businfo.isc = 1;
682116376Ssimokawa	src->businfo.bmc = 1;
683116376Ssimokawa	src->businfo.pmc = 0;
684116376Ssimokawa	src->businfo.cyc_clk_acc = 100;
685116376Ssimokawa	src->businfo.max_rec = fc->maxrec;
686116376Ssimokawa	src->businfo.max_rom = MAXROM_4;
687189928Ssbruno#define FW_GENERATION_CHANGEABLE 2
688189928Ssbruno	src->businfo.generation = FW_GENERATION_CHANGEABLE;
689116376Ssimokawa	src->businfo.link_spd = fc->speed;
690116376Ssimokawa
691116376Ssimokawa	src->businfo.eui64.hi = fc->eui.hi;
692116376Ssimokawa	src->businfo.eui64.lo = fc->eui.lo;
693116376Ssimokawa
694116376Ssimokawa	STAILQ_INIT(&src->chunk_list);
695116376Ssimokawa
696116376Ssimokawa	fc->crom_src = src;
697116376Ssimokawa	fc->crom_root = &fc->crom_src_buf->root;
698116376Ssimokawa}
699116376Ssimokawa
700116376Ssimokawastatic void
701116376Ssimokawafw_reset_crom(struct firewire_comm *fc)
702116376Ssimokawa{
703116376Ssimokawa	struct crom_src_buf *buf;
704116376Ssimokawa	struct crom_src *src;
705116376Ssimokawa	struct crom_chunk *root;
706116376Ssimokawa
707116376Ssimokawa	buf =  fc->crom_src_buf;
708116376Ssimokawa	src = fc->crom_src;
709116376Ssimokawa	root = fc->crom_root;
710116376Ssimokawa
711116376Ssimokawa	STAILQ_INIT(&src->chunk_list);
712116376Ssimokawa
713116376Ssimokawa	bzero(root, sizeof(struct crom_chunk));
714116376Ssimokawa	crom_add_chunk(src, NULL, root, 0);
715116376Ssimokawa	crom_add_entry(root, CSRKEY_NCAP, 0x0083c0); /* XXX */
716116376Ssimokawa	/* private company_id */
717116376Ssimokawa	crom_add_entry(root, CSRKEY_VENDOR, CSRVAL_VENDOR_PRIVATE);
718127468Ssimokawa#ifdef __DragonFly__
719127468Ssimokawa	crom_add_simple_text(src, root, &buf->vendor, "DragonFly Project");
720127468Ssimokawa	crom_add_entry(root, CSRKEY_HW, __DragonFly_cc_version);
721127468Ssimokawa#else
722116376Ssimokawa	crom_add_simple_text(src, root, &buf->vendor, "FreeBSD Project");
723116376Ssimokawa	crom_add_entry(root, CSRKEY_HW, __FreeBSD_version);
724127468Ssimokawa#endif
725193066Sjamie	mtx_lock(&prison0.pr_mtx);
726194118Sjamie	crom_add_simple_text(src, root, &buf->hw, prison0.pr_hostname);
727193066Sjamie	mtx_unlock(&prison0.pr_mtx);
728116376Ssimokawa}
729116376Ssimokawa
730116376Ssimokawa/*
731116376Ssimokawa * Called after bus reset.
732116376Ssimokawa */
733116376Ssimokawavoid
734169117Ssimokawafw_busreset(struct firewire_comm *fc, uint32_t new_status)
735116376Ssimokawa{
736116376Ssimokawa	struct firewire_dev_comm *fdc;
737117350Ssimokawa	struct crom_src *src;
738116376Ssimokawa	device_t *devlistp;
739189928Ssbruno	uint32_t *newrom;
740116376Ssimokawa	int i, devcnt;
741116376Ssimokawa
742187993Ssbruno	FW_GLOCK_ASSERT(fc);
743187993Ssbruno	if (fc->status == FWBUSMGRELECT)
744116376Ssimokawa		callout_stop(&fc->bmr_callout);
745187993Ssbruno
746169117Ssimokawa	fc->status = new_status;
747116376Ssimokawa	fw_reset_csr(fc);
748187993Ssbruno
749187993Ssbruno	if (fc->status == FWBUSNOTREADY)
750187993Ssbruno		fw_init_crom(fc);
751187993Ssbruno
752116376Ssimokawa	fw_reset_crom(fc);
753116376Ssimokawa
754113584Ssimokawa	if (device_get_children(fc->bdev, &devlistp, &devcnt) == 0) {
755113584Ssimokawa		for( i = 0 ; i < devcnt ; i++)
756113584Ssimokawa			if (device_get_state(devlistp[i]) >= DS_ATTACHED)  {
757113584Ssimokawa				fdc = device_get_softc(devlistp[i]);
758113584Ssimokawa				if (fdc->post_busreset != NULL)
759113584Ssimokawa					fdc->post_busreset(fdc);
760113584Ssimokawa			}
761113584Ssimokawa		free(devlistp, M_TEMP);
762113584Ssimokawa	}
763116376Ssimokawa
764117350Ssimokawa	src = &fc->crom_src_buf->src;
765189928Ssbruno        /*
766189928Ssbruno         * If the old config rom needs to be overwritten,
767189928Ssbruno         * bump the businfo.generation indicator to
768189928Ssbruno         * indicate that we need to be reprobed
769189928Ssbruno         * See 1394a-2000 8.3.2.5.4 for more details.
770189928Ssbruno         * generation starts at 2 and rolls over at 0xF
771189928Ssbruno         * back to 2.
772189928Ssbruno         *
773189928Ssbruno         * A generation of 0 indicates a device
774189928Ssbruno         * that is not 1394a-2000 compliant.
775189928Ssbruno         * A generation of 1 indicates a device that
776189928Ssbruno         * does not change it's Bus Info Block or
777189928Ssbruno         * Configuration ROM.
778189928Ssbruno         */
779189928Ssbruno#define FW_MAX_GENERATION 0xF
780189928Ssbruno	newrom = malloc(CROMSIZE, M_FW, M_NOWAIT | M_ZERO);
781189928Ssbruno	src = &fc->crom_src_buf->src;
782189928Ssbruno	crom_load(src, newrom, CROMSIZE);
783189928Ssbruno	if (bcmp(newrom, fc->config_rom, CROMSIZE) != 0) {
784189928Ssbruno		if ( src->businfo.generation++ > FW_MAX_GENERATION )
785189928Ssbruno			src->businfo.generation = FW_GENERATION_CHANGEABLE;
786189928Ssbruno		bcopy(newrom, (void *)fc->config_rom, CROMSIZE);
787189928Ssbruno	}
788189928Ssbruno	free(newrom, M_FW);
789189928Ssbruno
790103285Sikob}
791106790Ssimokawa
792103285Sikob/* Call once after reboot */
793106790Ssimokawavoid fw_init(struct firewire_comm *fc)
794103285Sikob{
795103285Sikob	int i;
796106543Ssimokawa#ifdef FW_VMACCESS
797103285Sikob	struct fw_xfer *xfer;
798103285Sikob	struct fw_bind *fwb;
799106543Ssimokawa#endif
800103285Sikob
801103285Sikob	fc->arq->queued = 0;
802103285Sikob	fc->ars->queued = 0;
803103285Sikob	fc->atq->queued = 0;
804103285Sikob	fc->ats->queued = 0;
805103285Sikob
806103285Sikob	fc->arq->buf = NULL;
807103285Sikob	fc->ars->buf = NULL;
808103285Sikob	fc->atq->buf = NULL;
809103285Sikob	fc->ats->buf = NULL;
810103285Sikob
811113584Ssimokawa	fc->arq->flag = 0;
812113584Ssimokawa	fc->ars->flag = 0;
813113584Ssimokawa	fc->atq->flag = 0;
814113584Ssimokawa	fc->ats->flag = 0;
815103285Sikob
816103285Sikob	STAILQ_INIT(&fc->atq->q);
817103285Sikob	STAILQ_INIT(&fc->ats->q);
818103285Sikob
819103285Sikob	for( i = 0 ; i < fc->nisodma ; i ++ ){
820103285Sikob		fc->it[i]->queued = 0;
821103285Sikob		fc->ir[i]->queued = 0;
822103285Sikob
823103285Sikob		fc->it[i]->start = NULL;
824103285Sikob		fc->ir[i]->start = NULL;
825103285Sikob
826103285Sikob		fc->it[i]->buf = NULL;
827103285Sikob		fc->ir[i]->buf = NULL;
828103285Sikob
829103285Sikob		fc->it[i]->flag = FWXFERQ_STREAM;
830103285Sikob		fc->ir[i]->flag = FWXFERQ_STREAM;
831103285Sikob
832103285Sikob		STAILQ_INIT(&fc->it[i]->q);
833103285Sikob		STAILQ_INIT(&fc->ir[i]->q);
834103285Sikob	}
835103285Sikob
836103285Sikob	fc->arq->maxq = FWMAXQUEUE;
837103285Sikob	fc->ars->maxq = FWMAXQUEUE;
838103285Sikob	fc->atq->maxq = FWMAXQUEUE;
839103285Sikob	fc->ats->maxq = FWMAXQUEUE;
840103285Sikob
841103285Sikob	for( i = 0 ; i < fc->nisodma ; i++){
842103285Sikob		fc->ir[i]->maxq = FWMAXQUEUE;
843103285Sikob		fc->it[i]->maxq = FWMAXQUEUE;
844103285Sikob	}
845187993Ssbruno
846103285Sikob	CSRARC(fc, TOPO_MAP) = 0x3f1 << 16;
847103285Sikob	CSRARC(fc, TOPO_MAP + 4) = 1;
848103285Sikob	CSRARC(fc, SPED_MAP) = 0x3f1 << 16;
849103285Sikob	CSRARC(fc, SPED_MAP + 4) = 1;
850103285Sikob
851110193Ssimokawa	STAILQ_INIT(&fc->devices);
852103285Sikob
853103285Sikob/* Initialize Async handlers */
854103285Sikob	STAILQ_INIT(&fc->binds);
855103285Sikob	for( i = 0 ; i < 0x40 ; i++){
856103285Sikob		STAILQ_INIT(&fc->tlabels[i]);
857103285Sikob	}
858103285Sikob
859103285Sikob/* DV depend CSRs see blue book */
860103285Sikob#if 0
861103285Sikob	CSRARC(fc, oMPR) = 0x3fff0001; /* # output channel = 1 */
862103285Sikob	CSRARC(fc, oPCR) = 0x8000007a;
863103285Sikob	for(i = 4 ; i < 0x7c/4 ; i+=4){
864103285Sikob		CSRARC(fc, i + oPCR) = 0x8000007a;
865103285Sikob	}
866103285Sikob
867103285Sikob	CSRARC(fc, iMPR) = 0x00ff0001; /* # input channel = 1 */
868103285Sikob	CSRARC(fc, iPCR) = 0x803f0000;
869103285Sikob	for(i = 4 ; i < 0x7c/4 ; i+=4){
870103285Sikob		CSRARC(fc, i + iPCR) = 0x0;
871103285Sikob	}
872103285Sikob#endif
873103285Sikob
874116376Ssimokawa	fc->crom_src_buf = NULL;
875103285Sikob
876106543Ssimokawa#ifdef FW_VMACCESS
877103285Sikob	xfer = fw_xfer_alloc();
878103285Sikob	if(xfer == NULL) return;
879103285Sikob
880110195Ssimokawa	fwb = (struct fw_bind *)malloc(sizeof (struct fw_bind), M_FW, M_NOWAIT);
881103285Sikob	if(fwb == NULL){
882103285Sikob		fw_xfer_free(xfer);
883139680Sjmg		return;
884103285Sikob	}
885167632Ssimokawa	xfer->hand = fw_vmaccess;
886103285Sikob	xfer->fc = fc;
887103285Sikob	xfer->sc = NULL;
888103285Sikob
889103285Sikob	fwb->start_hi = 0x2;
890103285Sikob	fwb->start_lo = 0;
891103285Sikob	fwb->addrlen = 0xffffffff;
892103285Sikob	fwb->xfer = xfer;
893103285Sikob	fw_bindadd(fc, fwb);
894106543Ssimokawa#endif
895103285Sikob}
896106790Ssimokawa
897120660Ssimokawa#define BIND_CMP(addr, fwb) (((addr) < (fwb)->start)?-1:\
898120660Ssimokawa    ((fwb)->end < (addr))?1:0)
899120660Ssimokawa
900103285Sikob/*
901129541Sdfr * To lookup bound process from IEEE1394 address.
902103285Sikob */
903106813Ssimokawastruct fw_bind *
904129585Sdfrfw_bindlookup(struct firewire_comm *fc, uint16_t dest_hi, uint32_t dest_lo)
905103285Sikob{
906120660Ssimokawa	u_int64_t addr;
907170374Ssimokawa	struct fw_bind *tfw, *r = NULL;
908120660Ssimokawa
909120660Ssimokawa	addr = ((u_int64_t)dest_hi << 32) | dest_lo;
910170374Ssimokawa	FW_GLOCK(fc);
911120660Ssimokawa	STAILQ_FOREACH(tfw, &fc->binds, fclist)
912170374Ssimokawa		if (BIND_CMP(addr, tfw) == 0) {
913170374Ssimokawa			r = tfw;
914170374Ssimokawa			break;
915170374Ssimokawa		}
916170374Ssimokawa	FW_GUNLOCK(fc);
917170374Ssimokawa	return(r);
918103285Sikob}
919106790Ssimokawa
920103285Sikob/*
921103285Sikob * To bind IEEE1394 address block to process.
922103285Sikob */
923106790Ssimokawaint
924106790Ssimokawafw_bindadd(struct firewire_comm *fc, struct fw_bind *fwb)
925103285Sikob{
926120660Ssimokawa	struct fw_bind *tfw, *prev = NULL;
927170374Ssimokawa	int r = 0;
928120660Ssimokawa
929120660Ssimokawa	if (fwb->start > fwb->end) {
930127468Ssimokawa		printf("%s: invalid range\n", __func__);
931120660Ssimokawa		return EINVAL;
932120660Ssimokawa	}
933120660Ssimokawa
934170374Ssimokawa	FW_GLOCK(fc);
935120660Ssimokawa	STAILQ_FOREACH(tfw, &fc->binds, fclist) {
936120660Ssimokawa		if (fwb->end < tfw->start)
937120660Ssimokawa			break;
938120660Ssimokawa		prev = tfw;
939120660Ssimokawa	}
940170374Ssimokawa	if (prev == NULL)
941103285Sikob		STAILQ_INSERT_HEAD(&fc->binds, fwb, fclist);
942170374Ssimokawa	else if (prev->end < fwb->start)
943120660Ssimokawa		STAILQ_INSERT_AFTER(&fc->binds, prev, fwb, fclist);
944170374Ssimokawa	else {
945170374Ssimokawa		printf("%s: bind failed\n", __func__);
946170374Ssimokawa		r = EBUSY;
947103285Sikob	}
948170374Ssimokawa	FW_GUNLOCK(fc);
949170374Ssimokawa	return (r);
950103285Sikob}
951103285Sikob
952103285Sikob/*
953103285Sikob * To free IEEE1394 address block.
954103285Sikob */
955106790Ssimokawaint
956106790Ssimokawafw_bindremove(struct firewire_comm *fc, struct fw_bind *fwb)
957103285Sikob{
958120660Ssimokawa#if 0
959120660Ssimokawa	struct fw_xfer *xfer, *next;
960120660Ssimokawa#endif
961120660Ssimokawa	struct fw_bind *tfw;
962103285Sikob	int s;
963103285Sikob
964103285Sikob	s = splfw();
965170374Ssimokawa	FW_GLOCK(fc);
966120660Ssimokawa	STAILQ_FOREACH(tfw, &fc->binds, fclist)
967120660Ssimokawa		if (tfw == fwb) {
968120660Ssimokawa			STAILQ_REMOVE(&fc->binds, fwb, fw_bind, fclist);
969120660Ssimokawa			goto found;
970120660Ssimokawa		}
971120660Ssimokawa
972129541Sdfr	printf("%s: no such binding\n", __func__);
973170374Ssimokawa	FW_GUNLOCK(fc);
974120660Ssimokawa	splx(s);
975120660Ssimokawa	return (1);
976120660Ssimokawafound:
977120660Ssimokawa#if 0
978113584Ssimokawa	/* shall we do this? */
979113584Ssimokawa	for (xfer = STAILQ_FIRST(&fwb->xferlist); xfer != NULL; xfer = next) {
980113584Ssimokawa		next = STAILQ_NEXT(xfer, link);
981113584Ssimokawa		fw_xfer_free(xfer);
982113584Ssimokawa	}
983113584Ssimokawa	STAILQ_INIT(&fwb->xferlist);
984120660Ssimokawa#endif
985170374Ssimokawa	FW_GUNLOCK(fc);
986113584Ssimokawa
987103285Sikob	splx(s);
988103285Sikob	return 0;
989103285Sikob}
990103285Sikob
991169130Ssimokawaint
992169130Ssimokawafw_xferlist_add(struct fw_xferlist *q, struct malloc_type *type,
993169130Ssimokawa    int slen, int rlen, int n,
994169130Ssimokawa    struct firewire_comm *fc, void *sc, void (*hand)(struct fw_xfer *))
995169130Ssimokawa{
996169130Ssimokawa	int i, s;
997169130Ssimokawa	struct fw_xfer *xfer;
998169130Ssimokawa
999169130Ssimokawa	for (i = 0; i < n; i++) {
1000169130Ssimokawa		xfer = fw_xfer_alloc_buf(type, slen, rlen);
1001169130Ssimokawa		if (xfer == NULL)
1002169130Ssimokawa			return (n);
1003169130Ssimokawa		xfer->fc = fc;
1004169130Ssimokawa		xfer->sc = sc;
1005169130Ssimokawa		xfer->hand = hand;
1006169130Ssimokawa		s = splfw();
1007169130Ssimokawa		STAILQ_INSERT_TAIL(q, xfer, link);
1008169130Ssimokawa		splx(s);
1009169130Ssimokawa	}
1010169130Ssimokawa	return (n);
1011169130Ssimokawa}
1012169130Ssimokawa
1013169130Ssimokawavoid
1014169130Ssimokawafw_xferlist_remove(struct fw_xferlist *q)
1015169130Ssimokawa{
1016169130Ssimokawa	struct fw_xfer *xfer, *next;
1017169130Ssimokawa
1018169130Ssimokawa	for (xfer = STAILQ_FIRST(q); xfer != NULL; xfer = next) {
1019169130Ssimokawa                next = STAILQ_NEXT(xfer, link);
1020169130Ssimokawa                fw_xfer_free_buf(xfer);
1021169130Ssimokawa        }
1022169130Ssimokawa        STAILQ_INIT(q);
1023169130Ssimokawa}
1024170374Ssimokawa/*
1025170374Ssimokawa * dump packet header
1026170374Ssimokawa */
1027170374Ssimokawastatic void
1028170374Ssimokawafw_dump_hdr(struct fw_pkt *fp, char *prefix)
1029170374Ssimokawa{
1030170374Ssimokawa	printf("%s: dst=0x%02x tl=0x%02x rt=%d tcode=0x%x pri=0x%x "
1031170374Ssimokawa	    "src=0x%03x\n", prefix,
1032170374Ssimokawa	    fp->mode.hdr.dst & 0x3f,
1033170374Ssimokawa	    fp->mode.hdr.tlrt >> 2, fp->mode.hdr.tlrt & 3,
1034170374Ssimokawa	    fp->mode.hdr.tcode, fp->mode.hdr.pri,
1035170374Ssimokawa	    fp->mode.hdr.src);
1036170374Ssimokawa}
1037169130Ssimokawa
1038103285Sikob/*
1039103285Sikob * To free transaction label.
1040103285Sikob */
1041106790Ssimokawastatic void
1042106790Ssimokawafw_tl_free(struct firewire_comm *fc, struct fw_xfer *xfer)
1043103285Sikob{
1044169119Ssimokawa	struct fw_xfer *txfer;
1045169119Ssimokawa	int s;
1046103285Sikob
1047169119Ssimokawa	if (xfer->tl < 0)
1048169119Ssimokawa		return;
1049169119Ssimokawa
1050169119Ssimokawa	s = splfw();
1051171513Ssimokawa	mtx_lock(&fc->tlabel_lock);
1052169119Ssimokawa#if 1	/* make sure the label is allocated */
1053169119Ssimokawa	STAILQ_FOREACH(txfer, &fc->tlabels[xfer->tl], tlabel)
1054169119Ssimokawa		if(txfer == xfer)
1055169119Ssimokawa			break;
1056169119Ssimokawa	if (txfer == NULL) {
1057170374Ssimokawa		printf("%s: the xfer is not in the queue "
1058170374Ssimokawa		    "(tlabel=%d, flag=0x%x)\n",
1059170374Ssimokawa		    __FUNCTION__, xfer->tl, xfer->flag);
1060170374Ssimokawa		fw_dump_hdr(&xfer->send.hdr, "send");
1061170374Ssimokawa		fw_dump_hdr(&xfer->recv.hdr, "recv");
1062170374Ssimokawa		kdb_backtrace();
1063171513Ssimokawa		mtx_unlock(&fc->tlabel_lock);
1064169119Ssimokawa		splx(s);
1065169119Ssimokawa		return;
1066103285Sikob	}
1067169119Ssimokawa#endif
1068169119Ssimokawa
1069169119Ssimokawa	STAILQ_REMOVE(&fc->tlabels[xfer->tl], xfer, fw_xfer, tlabel);
1070171513Ssimokawa	mtx_unlock(&fc->tlabel_lock);
1071103285Sikob	splx(s);
1072103285Sikob	return;
1073103285Sikob}
1074106790Ssimokawa
1075103285Sikob/*
1076103285Sikob * To obtain XFER structure by transaction label.
1077103285Sikob */
1078106790Ssimokawastatic struct fw_xfer *
1079170374Ssimokawafw_tl2xfer(struct firewire_comm *fc, int node, int tlabel, int tcode)
1080103285Sikob{
1081103285Sikob	struct fw_xfer *xfer;
1082103285Sikob	int s = splfw();
1083170374Ssimokawa	int req;
1084103285Sikob
1085171513Ssimokawa	mtx_lock(&fc->tlabel_lock);
1086169119Ssimokawa	STAILQ_FOREACH(xfer, &fc->tlabels[tlabel], tlabel)
1087169119Ssimokawa		if(xfer->send.hdr.mode.hdr.dst == node) {
1088171513Ssimokawa			mtx_unlock(&fc->tlabel_lock);
1089103285Sikob			splx(s);
1090170374Ssimokawa			KASSERT(xfer->tl == tlabel,
1091170374Ssimokawa				("xfer->tl 0x%x != 0x%x", xfer->tl, tlabel));
1092170374Ssimokawa			/* extra sanity check */
1093170374Ssimokawa			req = xfer->send.hdr.mode.hdr.tcode;
1094170374Ssimokawa			if (xfer->fc->tcode[req].valid_res != tcode) {
1095170374Ssimokawa				printf("%s: invalid response tcode "
1096170374Ssimokawa				    "(0x%x for 0x%x)\n", __FUNCTION__,
1097170374Ssimokawa				    tcode, req);
1098170374Ssimokawa				return(NULL);
1099170374Ssimokawa			}
1100170374Ssimokawa
1101110577Ssimokawa			if (firewire_debug > 2)
1102110577Ssimokawa				printf("fw_tl2xfer: found tl=%d\n", tlabel);
1103103285Sikob			return(xfer);
1104103285Sikob		}
1105171513Ssimokawa	mtx_unlock(&fc->tlabel_lock);
1106110577Ssimokawa	if (firewire_debug > 1)
1107110577Ssimokawa		printf("fw_tl2xfer: not found tl=%d\n", tlabel);
1108103285Sikob	splx(s);
1109103285Sikob	return(NULL);
1110103285Sikob}
1111106790Ssimokawa
1112103285Sikob/*
1113103285Sikob * To allocate IEEE1394 XFER structure.
1114103285Sikob */
1115106790Ssimokawastruct fw_xfer *
1116110269Ssimokawafw_xfer_alloc(struct malloc_type *type)
1117103285Sikob{
1118103285Sikob	struct fw_xfer *xfer;
1119106790Ssimokawa
1120110269Ssimokawa	xfer = malloc(sizeof(struct fw_xfer), type, M_NOWAIT | M_ZERO);
1121106790Ssimokawa	if (xfer == NULL)
1122106790Ssimokawa		return xfer;
1123106790Ssimokawa
1124110269Ssimokawa	xfer->malloc = type;
1125106790Ssimokawa
1126103285Sikob	return xfer;
1127103285Sikob}
1128106790Ssimokawa
1129113584Ssimokawastruct fw_xfer *
1130113584Ssimokawafw_xfer_alloc_buf(struct malloc_type *type, int send_len, int recv_len)
1131113584Ssimokawa{
1132113584Ssimokawa	struct fw_xfer *xfer;
1133113584Ssimokawa
1134113584Ssimokawa	xfer = fw_xfer_alloc(type);
1135126102Scperciva	if (xfer == NULL)
1136126102Scperciva		return(NULL);
1137120660Ssimokawa	xfer->send.pay_len = send_len;
1138120660Ssimokawa	xfer->recv.pay_len = recv_len;
1139120660Ssimokawa	if (send_len > 0) {
1140120660Ssimokawa		xfer->send.payload = malloc(send_len, type, M_NOWAIT | M_ZERO);
1141120660Ssimokawa		if (xfer->send.payload == NULL) {
1142113584Ssimokawa			fw_xfer_free(xfer);
1143113584Ssimokawa			return(NULL);
1144113584Ssimokawa		}
1145113584Ssimokawa	}
1146120660Ssimokawa	if (recv_len > 0) {
1147120660Ssimokawa		xfer->recv.payload = malloc(recv_len, type, M_NOWAIT);
1148120660Ssimokawa		if (xfer->recv.payload == NULL) {
1149120660Ssimokawa			if (xfer->send.payload != NULL)
1150120660Ssimokawa				free(xfer->send.payload, type);
1151113584Ssimokawa			fw_xfer_free(xfer);
1152113584Ssimokawa			return(NULL);
1153113584Ssimokawa		}
1154113584Ssimokawa	}
1155113584Ssimokawa	return(xfer);
1156113584Ssimokawa}
1157113584Ssimokawa
1158103285Sikob/*
1159103285Sikob * IEEE1394 XFER post process.
1160103285Sikob */
1161103285Sikobvoid
1162103285Sikobfw_xfer_done(struct fw_xfer *xfer)
1163103285Sikob{
1164167632Ssimokawa	if (xfer->hand == NULL) {
1165167632Ssimokawa		printf("hand == NULL\n");
1166103285Sikob		return;
1167117716Ssimokawa	}
1168103285Sikob
1169121505Ssimokawa	if (xfer->fc == NULL)
1170121505Ssimokawa		panic("fw_xfer_done: why xfer->fc is NULL?");
1171121505Ssimokawa
1172168051Ssimokawa	fw_tl_free(xfer->fc, xfer);
1173167632Ssimokawa	xfer->hand(xfer);
1174103285Sikob}
1175103285Sikob
1176106790Ssimokawavoid
1177113584Ssimokawafw_xfer_unload(struct fw_xfer* xfer)
1178103285Sikob{
1179103285Sikob	int s;
1180113584Ssimokawa
1181103285Sikob	if(xfer == NULL ) return;
1182170374Ssimokawa	if(xfer->flag & FWXF_INQ){
1183103285Sikob		printf("fw_xfer_free FWXF_INQ\n");
1184103285Sikob		s = splfw();
1185170374Ssimokawa		FW_GLOCK(xfer->fc);
1186103285Sikob		STAILQ_REMOVE(&xfer->q->q, xfer, fw_xfer, link);
1187170374Ssimokawa#if 0
1188103285Sikob		xfer->q->queued --;
1189170374Ssimokawa#endif
1190170374Ssimokawa		FW_GUNLOCK(xfer->fc);
1191103285Sikob		splx(s);
1192103285Sikob	}
1193113584Ssimokawa	if (xfer->fc != NULL) {
1194114729Ssimokawa#if 1
1195170374Ssimokawa		if(xfer->flag & FWXF_START)
1196114729Ssimokawa			/*
1197114729Ssimokawa			 * This could happen if:
1198114729Ssimokawa			 *  1. We call fwohci_arcv() before fwohci_txd().
1199114729Ssimokawa			 *  2. firewire_watch() is called.
1200114729Ssimokawa			 */
1201114729Ssimokawa			printf("fw_xfer_free FWXF_START\n");
1202103285Sikob#endif
1203103285Sikob	}
1204170374Ssimokawa	xfer->flag = FWXF_INIT;
1205113584Ssimokawa	xfer->resp = 0;
1206113584Ssimokawa}
1207113584Ssimokawa/*
1208113584Ssimokawa * To free IEEE1394 XFER structure.
1209113584Ssimokawa */
1210113584Ssimokawavoid
1211120660Ssimokawafw_xfer_free_buf( struct fw_xfer* xfer)
1212113584Ssimokawa{
1213120660Ssimokawa	if (xfer == NULL) {
1214127468Ssimokawa		printf("%s: xfer == NULL\n", __func__);
1215120660Ssimokawa		return;
1216120660Ssimokawa	}
1217113584Ssimokawa	fw_xfer_unload(xfer);
1218120660Ssimokawa	if(xfer->send.payload != NULL){
1219120660Ssimokawa		free(xfer->send.payload, xfer->malloc);
1220103285Sikob	}
1221120660Ssimokawa	if(xfer->recv.payload != NULL){
1222120660Ssimokawa		free(xfer->recv.payload, xfer->malloc);
1223103285Sikob	}
1224110269Ssimokawa	free(xfer, xfer->malloc);
1225103285Sikob}
1226103285Sikob
1227120660Ssimokawavoid
1228120660Ssimokawafw_xfer_free( struct fw_xfer* xfer)
1229120660Ssimokawa{
1230120660Ssimokawa	if (xfer == NULL) {
1231127468Ssimokawa		printf("%s: xfer == NULL\n", __func__);
1232120660Ssimokawa		return;
1233120660Ssimokawa	}
1234120660Ssimokawa	fw_xfer_unload(xfer);
1235120660Ssimokawa	free(xfer, xfer->malloc);
1236120660Ssimokawa}
1237120660Ssimokawa
1238120660Ssimokawavoid
1239110072Ssimokawafw_asy_callback_free(struct fw_xfer *xfer)
1240103285Sikob{
1241103285Sikob#if 0
1242170374Ssimokawa	printf("asyreq done flag=0x%02x resp=%d\n",
1243170374Ssimokawa				xfer->flag, xfer->resp);
1244103285Sikob#endif
1245103285Sikob	fw_xfer_free(xfer);
1246103285Sikob}
1247103285Sikob
1248103285Sikob/*
1249103285Sikob * To configure PHY.
1250103285Sikob */
1251103285Sikobstatic void
1252103285Sikobfw_phy_config(struct firewire_comm *fc, int root_node, int gap_count)
1253103285Sikob{
1254103285Sikob	struct fw_xfer *xfer;
1255103285Sikob	struct fw_pkt *fp;
1256103285Sikob
1257103285Sikob	fc->status = FWBUSPHYCONF;
1258103285Sikob
1259120660Ssimokawa	xfer = fw_xfer_alloc(M_FWXFER);
1260113584Ssimokawa	if (xfer == NULL)
1261113584Ssimokawa		return;
1262103285Sikob	xfer->fc = fc;
1263167632Ssimokawa	xfer->hand = fw_asy_callback_free;
1264103285Sikob
1265120660Ssimokawa	fp = &xfer->send.hdr;
1266103285Sikob	fp->mode.ld[1] = 0;
1267103285Sikob	if (root_node >= 0)
1268113584Ssimokawa		fp->mode.ld[1] |= (root_node & 0x3f) << 24 | 1 << 23;
1269103285Sikob	if (gap_count >= 0)
1270113584Ssimokawa		fp->mode.ld[1] |= 1 << 22 | (gap_count & 0x3f) << 16;
1271103285Sikob	fp->mode.ld[2] = ~fp->mode.ld[1];
1272103285Sikob/* XXX Dangerous, how to pass PHY packet to device driver */
1273103285Sikob	fp->mode.common.tcode |= FWTCODE_PHY;
1274103285Sikob
1275107653Ssimokawa	if (firewire_debug)
1276188722Ssbruno		device_printf(fc->bdev, "%s: root_node=%d gap_count=%d\n",
1277188722Ssbruno					__func__, root_node, gap_count);
1278103285Sikob	fw_asyreq(fc, -1, xfer);
1279103285Sikob}
1280103285Sikob
1281103285Sikob/*
1282103285Sikob * Dump self ID.
1283103285Sikob */
1284103285Sikobstatic void
1285129585Sdfrfw_print_sid(uint32_t sid)
1286103285Sikob{
1287103285Sikob	union fw_self_id *s;
1288103285Sikob	s = (union fw_self_id *) &sid;
1289188726Ssbruno	if ( s->p0.sequel ) {
1290188726Ssbruno		if ( s->p1.sequence_num == FW_SELF_ID_PAGE0 ) {
1291188726Ssbruno			printf("node:%d p3:%d p4:%d p5:%d p6:%d p7:%d"
1292188726Ssbruno				"p8:%d p9:%d p10:%d\n",
1293188726Ssbruno				s->p1.phy_id, s->p1.port3, s->p1.port4,
1294188726Ssbruno				s->p1.port5, s->p1.port6, s->p1.port7,
1295188726Ssbruno				s->p1.port8, s->p1.port9, s->p1.port10);
1296188726Ssbruno		} else if (s->p2.sequence_num == FW_SELF_ID_PAGE1 ){
1297188726Ssbruno			printf("node:%d p11:%d p12:%d p13:%d p14:%d p15:%d\n",
1298188726Ssbruno				s->p2.phy_id, s->p2.port11, s->p2.port12,
1299188726Ssbruno				s->p2.port13, s->p2.port14, s->p2.port15);
1300188726Ssbruno		} else {
1301188726Ssbruno			printf("node:%d Unknown Self ID Page number %d\n",
1302188726Ssbruno				s->p1.phy_id, s->p1.sequence_num);
1303188726Ssbruno		}
1304188726Ssbruno	} else {
1305188726Ssbruno		printf("node:%d link:%d gap:%d spd:%d con:%d pwr:%d"
1306188726Ssbruno			" p0:%d p1:%d p2:%d i:%d m:%d\n",
1307188726Ssbruno			s->p0.phy_id, s->p0.link_active, s->p0.gap_count,
1308188726Ssbruno			s->p0.phy_speed, s->p0.contender,
1309188726Ssbruno			s->p0.power_class, s->p0.port0, s->p0.port1,
1310188726Ssbruno			s->p0.port2, s->p0.initiated_reset, s->p0.more_packets);
1311188726Ssbruno	}
1312103285Sikob}
1313103285Sikob
1314103285Sikob/*
1315103285Sikob * To receive self ID.
1316103285Sikob */
1317129585Sdfrvoid fw_sidrcv(struct firewire_comm* fc, uint32_t *sid, u_int len)
1318103285Sikob{
1319129585Sdfr	uint32_t *p;
1320103285Sikob	union fw_self_id *self_id;
1321103285Sikob	u_int i, j, node, c_port = 0, i_branch = 0;
1322103285Sikob
1323129585Sdfr	fc->sid_cnt = len /(sizeof(uint32_t) * 2);
1324103285Sikob	fc->max_node = fc->nodeid & 0x3f;
1325129585Sdfr	CSRARC(fc, NODE_IDS) = ((uint32_t)fc->nodeid) << 16;
1326103285Sikob	fc->status = FWBUSCYMELECT;
1327103285Sikob	fc->topology_map->crc_len = 2;
1328103285Sikob	fc->topology_map->generation ++;
1329103285Sikob	fc->topology_map->self_id_count = 0;
1330103285Sikob	fc->topology_map->node_count = 0;
1331103285Sikob	fc->speed_map->generation ++;
1332103285Sikob	fc->speed_map->crc_len = 1 + (64*64 + 3) / 4;
1333103285Sikob	self_id = &fc->topology_map->self_id[0];
1334103285Sikob	for(i = 0; i < fc->sid_cnt; i ++){
1335103285Sikob		if (sid[1] != ~sid[0]) {
1336188722Ssbruno			device_printf(fc->bdev, "%s: ERROR invalid self-id packet\n",
1337188722Ssbruno						__func__);
1338103285Sikob			sid += 2;
1339103285Sikob			continue;
1340103285Sikob		}
1341103285Sikob		*self_id = *((union fw_self_id *)sid);
1342103285Sikob		fc->topology_map->crc_len++;
1343103285Sikob		if(self_id->p0.sequel == 0){
1344103285Sikob			fc->topology_map->node_count ++;
1345103285Sikob			c_port = 0;
1346188722Ssbruno			if (firewire_debug)
1347188722Ssbruno				fw_print_sid(sid[0]);
1348103285Sikob			node = self_id->p0.phy_id;
1349103285Sikob			if(fc->max_node < node){
1350103285Sikob				fc->max_node = self_id->p0.phy_id;
1351103285Sikob			}
1352103285Sikob			/* XXX I'm not sure this is the right speed_map */
1353103285Sikob			fc->speed_map->speed[node][node]
1354103285Sikob					= self_id->p0.phy_speed;
1355103285Sikob			for (j = 0; j < node; j ++) {
1356103285Sikob				fc->speed_map->speed[j][node]
1357103285Sikob					= fc->speed_map->speed[node][j]
1358103285Sikob					= min(fc->speed_map->speed[j][j],
1359103285Sikob							self_id->p0.phy_speed);
1360103285Sikob			}
1361103285Sikob			if ((fc->irm == -1 || self_id->p0.phy_id > fc->irm) &&
1362103285Sikob			  (self_id->p0.link_active && self_id->p0.contender)) {
1363103285Sikob				fc->irm = self_id->p0.phy_id;
1364103285Sikob			}
1365103285Sikob			if(self_id->p0.port0 >= 0x2){
1366103285Sikob				c_port++;
1367103285Sikob			}
1368103285Sikob			if(self_id->p0.port1 >= 0x2){
1369103285Sikob				c_port++;
1370103285Sikob			}
1371103285Sikob			if(self_id->p0.port2 >= 0x2){
1372103285Sikob				c_port++;
1373103285Sikob			}
1374103285Sikob		}
1375103285Sikob		if(c_port > 2){
1376103285Sikob			i_branch += (c_port - 2);
1377103285Sikob		}
1378103285Sikob		sid += 2;
1379103285Sikob		self_id++;
1380103285Sikob		fc->topology_map->self_id_count ++;
1381103285Sikob	}
1382103285Sikob	/* CRC */
1383103285Sikob	fc->topology_map->crc = fw_crc16(
1384129585Sdfr			(uint32_t *)&fc->topology_map->generation,
1385103285Sikob			fc->topology_map->crc_len * 4);
1386103285Sikob	fc->speed_map->crc = fw_crc16(
1387129585Sdfr			(uint32_t *)&fc->speed_map->generation,
1388103285Sikob			fc->speed_map->crc_len * 4);
1389103285Sikob	/* byteswap and copy to CSR */
1390129585Sdfr	p = (uint32_t *)fc->topology_map;
1391103285Sikob	for (i = 0; i <= fc->topology_map->crc_len; i++)
1392103285Sikob		CSRARC(fc, TOPO_MAP + i * 4) = htonl(*p++);
1393129585Sdfr	p = (uint32_t *)fc->speed_map;
1394103285Sikob	CSRARC(fc, SPED_MAP) = htonl(*p++);
1395103285Sikob	CSRARC(fc, SPED_MAP + 4) = htonl(*p++);
1396129585Sdfr	/* don't byte-swap uint8_t array */
1397103285Sikob	bcopy(p, &CSRARC(fc, SPED_MAP + 8), (fc->speed_map->crc_len - 1)*4);
1398103285Sikob
1399103285Sikob	fc->max_hop = fc->max_node - i_branch;
1400188722Ssbruno	device_printf(fc->bdev, "%d nodes, maxhop <= %d %s irm(%d) %s\n",
1401188722Ssbruno			fc->max_node + 1, fc->max_hop,
1402188722Ssbruno			(fc->irm == -1) ? "Not IRM capable" : "cable IRM",
1403188722Ssbruno			fc->irm,
1404188722Ssbruno			(fc->irm == fc->nodeid) ? " (me) " : "");
1405103285Sikob
1406109736Ssimokawa	if (try_bmr && (fc->irm != -1) && (CSRARC(fc, BUS_MGR_ID) == 0x3f)) {
1407114909Ssimokawa		if (fc->irm == fc->nodeid) {
1408103285Sikob			fc->status = FWBUSMGRDONE;
1409103285Sikob			CSRARC(fc, BUS_MGR_ID) = fc->set_bmr(fc, fc->irm);
1410114909Ssimokawa			fw_bmr(fc);
1411109736Ssimokawa		} else {
1412103285Sikob			fc->status = FWBUSMGRELECT;
1413110193Ssimokawa			callout_reset(&fc->bmr_callout, hz/8,
1414110193Ssimokawa				(void *)fw_try_bmr, (void *)fc);
1415103285Sikob		}
1416114909Ssimokawa	} else
1417103285Sikob		fc->status = FWBUSMGRDONE;
1418114909Ssimokawa
1419108853Ssimokawa	callout_reset(&fc->busprobe_callout, hz/4,
1420108853Ssimokawa			(void *)fw_bus_probe, (void *)fc);
1421103285Sikob}
1422106790Ssimokawa
1423103285Sikob/*
1424103285Sikob * To probe devices on the IEEE1394 bus.
1425103285Sikob */
1426106790Ssimokawastatic void
1427106790Ssimokawafw_bus_probe(struct firewire_comm *fc)
1428103285Sikob{
1429103285Sikob	int s;
1430120850Ssimokawa	struct fw_device *fwdev;
1431103285Sikob
1432103285Sikob	s = splfw();
1433103285Sikob	fc->status = FWBUSEXPLORE;
1434103285Sikob
1435120850Ssimokawa	/* Invalidate all devices, just after bus reset. */
1436188722Ssbruno	if (firewire_debug)
1437188722Ssbruno		device_printf(fc->bdev, "%s:"
1438188722Ssbruno			"iterate and invalidate all nodes\n",
1439188722Ssbruno			__func__);
1440120850Ssimokawa	STAILQ_FOREACH(fwdev, &fc->devices, link)
1441110193Ssimokawa		if (fwdev->status != FWDEVINVAL) {
1442103285Sikob			fwdev->status = FWDEVINVAL;
1443103285Sikob			fwdev->rcnt = 0;
1444188722Ssbruno			if (firewire_debug)
1445188722Ssbruno				device_printf(fc->bdev, "%s:"
1446188722Ssbruno					"Invalidate Dev ID: %08x%08x\n",
1447188722Ssbruno					__func__, fwdev->eui.hi, fwdev->eui.lo);
1448188722Ssbruno		} else {
1449188722Ssbruno			if (firewire_debug)
1450188722Ssbruno				device_printf(fc->bdev, "%s:"
1451188722Ssbruno					"Dev ID: %08x%08x already invalid\n",
1452188722Ssbruno					__func__, fwdev->eui.hi, fwdev->eui.lo);
1453103285Sikob		}
1454169806Ssimokawa	splx(s);
1455120850Ssimokawa
1456169806Ssimokawa	wakeup((void *)fc);
1457103285Sikob}
1458106790Ssimokawa
1459169806Ssimokawastatic int
1460169806Ssimokawafw_explore_read_quads(struct fw_device *fwdev, int offset,
1461188722Ssbruno    uint32_t *quad, int length)
1462129274Sdfr{
1463169806Ssimokawa	struct fw_xfer *xfer;
1464169806Ssimokawa	uint32_t tmp;
1465169806Ssimokawa	int i, error;
1466129274Sdfr
1467188722Ssbruno	for (i = 0; i < length; i ++, offset += sizeof(uint32_t)) {
1468169806Ssimokawa		xfer = fwmem_read_quad(fwdev, NULL, -1,
1469169806Ssimokawa		    0xffff, 0xf0000000 | offset, (void *)&tmp,
1470170374Ssimokawa		    fw_xferwake);
1471169806Ssimokawa		if (xfer == NULL)
1472169806Ssimokawa			return (-1);
1473170374Ssimokawa		fw_xferwait(xfer);
1474169806Ssimokawa
1475169806Ssimokawa		if (xfer->resp == 0)
1476169806Ssimokawa			quad[i] = ntohl(tmp);
1477169806Ssimokawa
1478169806Ssimokawa		error = xfer->resp;
1479169806Ssimokawa		fw_xfer_free(xfer);
1480169806Ssimokawa		if (error)
1481169806Ssimokawa			return (error);
1482169806Ssimokawa	}
1483169806Ssimokawa	return (0);
1484169806Ssimokawa}
1485169806Ssimokawa
1486169806Ssimokawa
1487169806Ssimokawastatic int
1488169806Ssimokawafw_explore_csrblock(struct fw_device *fwdev, int offset, int recur)
1489169806Ssimokawa{
1490169806Ssimokawa	int err, i, off;
1491169806Ssimokawa	struct csrdirectory *dir;
1492169806Ssimokawa	struct csrreg *reg;
1493169806Ssimokawa
1494169806Ssimokawa	dir = (struct csrdirectory *)&fwdev->csrrom[offset/sizeof(uint32_t)];
1495169806Ssimokawa	err = fw_explore_read_quads(fwdev, CSRROMOFF + offset,
1496169806Ssimokawa	    (uint32_t *)dir, 1);
1497169806Ssimokawa	if (err)
1498169806Ssimokawa		return (-1);
1499169806Ssimokawa
1500169806Ssimokawa	offset += sizeof(uint32_t);
1501169806Ssimokawa	reg = (struct csrreg *)&fwdev->csrrom[offset/sizeof(uint32_t)];
1502169806Ssimokawa	err = fw_explore_read_quads(fwdev, CSRROMOFF + offset,
1503169806Ssimokawa	    (uint32_t *)reg, dir->crc_len);
1504169806Ssimokawa	if (err)
1505169806Ssimokawa		return (-1);
1506169806Ssimokawa
1507169806Ssimokawa	/* XXX check CRC */
1508169806Ssimokawa
1509169806Ssimokawa	off = CSRROMOFF + offset + sizeof(uint32_t) * (dir->crc_len - 1);
1510169806Ssimokawa	if (fwdev->rommax < off)
1511169806Ssimokawa		fwdev->rommax = off;
1512169806Ssimokawa
1513169806Ssimokawa	if (recur == 0)
1514169806Ssimokawa		return (0);
1515169806Ssimokawa
1516169806Ssimokawa	for (i = 0; i < dir->crc_len; i ++, offset += sizeof(uint32_t)) {
1517171302Ssimokawa		if ((reg[i].key & CSRTYPE_MASK) == CSRTYPE_D)
1518169806Ssimokawa			recur = 1;
1519171302Ssimokawa		else if ((reg[i].key & CSRTYPE_MASK) == CSRTYPE_L)
1520169806Ssimokawa			recur = 0;
1521169806Ssimokawa		else
1522129274Sdfr			continue;
1523169806Ssimokawa
1524169806Ssimokawa		off = offset + reg[i].val * sizeof(uint32_t);
1525169806Ssimokawa		if (off > CROMSIZE) {
1526169806Ssimokawa			printf("%s: invalid offset %d\n", __FUNCTION__, off);
1527169806Ssimokawa			return(-1);
1528169806Ssimokawa		}
1529169806Ssimokawa		err = fw_explore_csrblock(fwdev, off, recur);
1530169806Ssimokawa		if (err)
1531169806Ssimokawa			return (-1);
1532129274Sdfr	}
1533169806Ssimokawa	return (0);
1534129274Sdfr}
1535129274Sdfr
1536169806Ssimokawastatic int
1537169806Ssimokawafw_explore_node(struct fw_device *dfwdev)
1538103285Sikob{
1539169806Ssimokawa	struct firewire_comm *fc;
1540110179Ssimokawa	struct fw_device *fwdev, *pfwdev, *tfwdev;
1541169806Ssimokawa	uint32_t *csr;
1542169806Ssimokawa	struct csrhdr *hdr;
1543169806Ssimokawa	struct bus_info *binfo;
1544188704Ssbruno	int err, node;
1545188704Ssbruno	uint32_t speed_test = 0;
1546103285Sikob
1547169806Ssimokawa	fc = dfwdev->fc;
1548169806Ssimokawa	csr = dfwdev->csrrom;
1549169806Ssimokawa	node = dfwdev->dst;
1550103285Sikob
1551169806Ssimokawa	/* First quad */
1552169806Ssimokawa	err = fw_explore_read_quads(dfwdev, CSRROMOFF, &csr[0], 1);
1553188704Ssbruno	if (err) {
1554188704Ssbruno		device_printf(fc->bdev, "%s: node%d: explore_read_quads failure\n",
1555188704Ssbruno		    __func__, node);
1556188704Ssbruno		dfwdev->status = FWDEVINVAL;
1557169806Ssimokawa		return (-1);
1558188704Ssbruno	}
1559169806Ssimokawa	hdr = (struct csrhdr *)&csr[0];
1560169806Ssimokawa	if (hdr->info_len != 4) {
1561169806Ssimokawa		if (firewire_debug)
1562188722Ssbruno			device_printf(fc->bdev, "%s: node%d: wrong bus info len(%d)\n",
1563188722Ssbruno			    __func__, node, hdr->info_len);
1564188722Ssbruno		dfwdev->status = FWDEVINVAL;
1565169806Ssimokawa		return (-1);
1566169806Ssimokawa	}
1567103285Sikob
1568169806Ssimokawa	/* bus info */
1569169806Ssimokawa	err = fw_explore_read_quads(dfwdev, CSRROMOFF + 0x04, &csr[1], 4);
1570188722Ssbruno	if (err) {
1571188722Ssbruno		device_printf(fc->bdev, "%s: node%d: error reading 0x04\n",
1572188722Ssbruno		    __func__, node);
1573188722Ssbruno		dfwdev->status = FWDEVINVAL;
1574169806Ssimokawa		return (-1);
1575188722Ssbruno	}
1576169806Ssimokawa	binfo = (struct bus_info *)&csr[1];
1577169806Ssimokawa	if (binfo->bus_name != CSR_BUS_NAME_IEEE1394) {
1578188722Ssbruno		device_printf(fc->bdev, "%s: node%d: invalid bus name 0x%08x\n",
1579188722Ssbruno		    __func__, node, binfo->bus_name);
1580188722Ssbruno		dfwdev->status = FWDEVINVAL;
1581169806Ssimokawa		return (-1);
1582103285Sikob	}
1583188704Ssbruno
1584188704Ssbruno	if (firewire_debug)
1585188704Ssbruno		device_printf(fc->bdev, "%s: node(%d) BUS INFO BLOCK:\n"
1586188704Ssbruno					"irmc(%d) cmc(%d) isc(%d) bmc(%d) pmc(%d) "
1587188704Ssbruno					"cyc_clk_acc(%d) max_rec(%d) max_rom(%d) "
1588188704Ssbruno					"generation(%d) link_spd(%d)\n",
1589188704Ssbruno					__func__, node,
1590188704Ssbruno					binfo->irmc, binfo->cmc, binfo->isc,
1591188704Ssbruno					binfo->bmc, binfo->pmc, binfo->cyc_clk_acc,
1592188704Ssbruno					binfo->max_rec, binfo->max_rom,
1593188704Ssbruno					binfo->generation, binfo->link_spd);
1594188704Ssbruno
1595169806Ssimokawa	STAILQ_FOREACH(fwdev, &fc->devices, link)
1596169806Ssimokawa		if (FW_EUI64_EQUAL(fwdev->eui, binfo->eui64))
1597169806Ssimokawa			break;
1598169806Ssimokawa	if (fwdev == NULL) {
1599169806Ssimokawa		/* new device */
1600169806Ssimokawa		fwdev = malloc(sizeof(struct fw_device), M_FW,
1601169806Ssimokawa						M_NOWAIT | M_ZERO);
1602169806Ssimokawa		if (fwdev == NULL) {
1603188722Ssbruno			device_printf(fc->bdev, "%s: node%d: no memory\n",
1604188722Ssbruno					__func__, node);
1605169806Ssimokawa			return (-1);
1606103285Sikob		}
1607106810Ssimokawa		fwdev->fc = fc;
1608169806Ssimokawa		fwdev->eui = binfo->eui64;
1609189928Ssbruno		fwdev->dst = dfwdev->dst;
1610189928Ssbruno		fwdev->maxrec = dfwdev->maxrec;
1611189928Ssbruno		fwdev->status = dfwdev->status;
1612189928Ssbruno
1613188704Ssbruno		/*
1614188704Ssbruno		 * Pre-1394a-2000 didn't have link_spd in
1615188704Ssbruno		 * the Bus Info block, so try and use the
1616188704Ssbruno		 * speed map value.
1617188704Ssbruno		 * 1394a-2000 compliant devices only use
1618188704Ssbruno		 * the Bus Info Block link spd value, so
1619188704Ssbruno		 * ignore the speed map alltogether. SWB
1620188704Ssbruno		 */
1621188704Ssbruno		if ( binfo->link_spd == FWSPD_S100 /* 0 */) {
1622189928Ssbruno			device_printf(fc->bdev, "%s: "
1623188704Ssbruno				"Pre 1394a-2000 detected\n",
1624188704Ssbruno				__func__);
1625188704Ssbruno			fwdev->speed = fc->speed_map->speed[fc->nodeid][node];
1626188704Ssbruno		} else
1627188704Ssbruno			fwdev->speed = binfo->link_spd;
1628188704Ssbruno		/*
1629188704Ssbruno		 * Test this speed with a read to the CSRROM.
1630188704Ssbruno		 * If it fails, slow down the speed and retry.
1631188704Ssbruno		 */
1632189928Ssbruno		while (fwdev->speed > FWSPD_S100 /* 0 */) {
1633188704Ssbruno			err = fw_explore_read_quads(fwdev, CSRROMOFF,
1634188704Ssbruno            				&speed_test, 1);
1635189928Ssbruno			if (err) {
1636189928Ssbruno				device_printf(fc->bdev, "%s: fwdev->speed(%s)"
1637189928Ssbruno						" decremented due to negotiation\n",
1638189928Ssbruno						__func__,
1639189928Ssbruno						linkspeed[fwdev->speed]);
1640188704Ssbruno				fwdev->speed--;
1641189928Ssbruno			} else
1642188704Ssbruno				break;
1643188704Ssbruno
1644188704Ssbruno		}
1645190792Ssbruno
1646190792Ssbruno		/*
1647190792Ssbruno		 * If the fwdev is not found in the
1648190792Ssbruno		 * fc->devices TAILQ, then we will add it.
1649190792Ssbruno		 */
1650110179Ssimokawa		pfwdev = NULL;
1651110193Ssimokawa		STAILQ_FOREACH(tfwdev, &fc->devices, link) {
1652110179Ssimokawa			if (tfwdev->eui.hi > fwdev->eui.hi ||
1653169806Ssimokawa				(tfwdev->eui.hi == fwdev->eui.hi &&
1654169806Ssimokawa				tfwdev->eui.lo > fwdev->eui.lo))
1655110179Ssimokawa				break;
1656110179Ssimokawa			pfwdev = tfwdev;
1657103285Sikob		}
1658110179Ssimokawa		if (pfwdev == NULL)
1659110193Ssimokawa			STAILQ_INSERT_HEAD(&fc->devices, fwdev, link);
1660110179Ssimokawa		else
1661110193Ssimokawa			STAILQ_INSERT_AFTER(&fc->devices, pfwdev, fwdev, link);
1662103285Sikob
1663108655Ssimokawa		device_printf(fc->bdev, "New %s device ID:%08x%08x\n",
1664188704Ssbruno		    linkspeed[fwdev->speed],
1665169806Ssimokawa		    fwdev->eui.hi, fwdev->eui.lo);
1666189928Ssbruno	} else {
1667189928Ssbruno		fwdev->dst = node;
1668189928Ssbruno		fwdev->status = FWDEVINIT;
1669189928Ssbruno		/* unchanged ? */
1670189928Ssbruno		if (bcmp(&csr[0], &fwdev->csrrom[0], sizeof(uint32_t) * 5) == 0) {
1671189928Ssbruno			if (firewire_debug)
1672189928Ssbruno				device_printf(fc->dev, "node%d: crom unchanged\n", node);
1673189928Ssbruno			return (0);
1674189928Ssbruno		}
1675103285Sikob	}
1676103285Sikob
1677169806Ssimokawa	bzero(&fwdev->csrrom[0], CROMSIZE);
1678106790Ssimokawa
1679169806Ssimokawa	/* copy first quad and bus info block */
1680169806Ssimokawa	bcopy(&csr[0], &fwdev->csrrom[0], sizeof(uint32_t) * 5);
1681169806Ssimokawa	fwdev->rommax = CSRROMOFF + sizeof(uint32_t) * 4;
1682103285Sikob
1683169806Ssimokawa	err = fw_explore_csrblock(fwdev, 0x14, 1); /* root directory */
1684113584Ssimokawa
1685169806Ssimokawa	if (err) {
1686189928Ssbruno		if (firewire_debug)
1687189928Ssbruno			device_printf(fc->dev, "%s: explore csrblock failed err(%d)\n",
1688189928Ssbruno					__func__, err);
1689169806Ssimokawa		fwdev->status = FWDEVINVAL;
1690169806Ssimokawa		fwdev->csrrom[0] = 0;
1691103285Sikob	}
1692169806Ssimokawa	return (err);
1693103285Sikob
1694103285Sikob}
1695106790Ssimokawa
1696103285Sikob/*
1697169806Ssimokawa * Find the self_id packet for a node, ignoring sequels.
1698103285Sikob */
1699169806Ssimokawastatic union fw_self_id *
1700169806Ssimokawafw_find_self_id(struct firewire_comm *fc, int node)
1701106790Ssimokawa{
1702169806Ssimokawa	uint32_t i;
1703169806Ssimokawa	union fw_self_id *s;
1704103285Sikob
1705169806Ssimokawa	for (i = 0; i < fc->topology_map->self_id_count; i++) {
1706169806Ssimokawa		s = &fc->topology_map->self_id[i];
1707169806Ssimokawa		if (s->p0.sequel)
1708169806Ssimokawa			continue;
1709169806Ssimokawa		if (s->p0.phy_id == node)
1710169806Ssimokawa			return s;
1711110577Ssimokawa	}
1712169806Ssimokawa	return 0;
1713169806Ssimokawa}
1714110577Ssimokawa
1715169806Ssimokawastatic void
1716169806Ssimokawafw_explore(struct firewire_comm *fc)
1717169806Ssimokawa{
1718169806Ssimokawa	int node, err, s, i, todo, todo2, trys;
1719169806Ssimokawa	char nodes[63];
1720169806Ssimokawa	struct fw_device dfwdev;
1721169829Ssimokawa	union fw_self_id *fwsid;
1722110577Ssimokawa
1723169806Ssimokawa	todo = 0;
1724169806Ssimokawa	/* setup dummy fwdev */
1725169806Ssimokawa	dfwdev.fc = fc;
1726169806Ssimokawa	dfwdev.speed = 0;
1727169806Ssimokawa	dfwdev.maxrec = 8; /* 512 */
1728169806Ssimokawa	dfwdev.status = FWDEVINIT;
1729103285Sikob
1730169806Ssimokawa	for (node = 0; node <= fc->max_node; node ++) {
1731169806Ssimokawa		/* We don't probe myself and linkdown nodes */
1732188722Ssbruno		if (node == fc->nodeid) {
1733188722Ssbruno			if (firewire_debug)
1734188722Ssbruno				device_printf(fc->bdev, "%s:"
1735188722Ssbruno					"found myself node(%d) fc->nodeid(%d) fc->max_node(%d)\n",
1736188722Ssbruno					__func__, node, fc->nodeid, fc->max_node);
1737169806Ssimokawa			continue;
1738188722Ssbruno		} else if (firewire_debug) {
1739188722Ssbruno			device_printf(fc->bdev, "%s:"
1740188722Ssbruno				"node(%d) fc->max_node(%d) found\n",
1741188722Ssbruno				__func__, node, fc->max_node);
1742188722Ssbruno		}
1743169829Ssimokawa		fwsid = fw_find_self_id(fc, node);
1744169829Ssimokawa		if (!fwsid || !fwsid->p0.link_active) {
1745169806Ssimokawa			if (firewire_debug)
1746188722Ssbruno				device_printf(fc->bdev, "%s: node%d: link down\n",
1747188722Ssbruno							__func__, node);
1748169806Ssimokawa			continue;
1749103285Sikob		}
1750169806Ssimokawa		nodes[todo++] = node;
1751103285Sikob	}
1752103285Sikob
1753169806Ssimokawa	s = splfw();
1754169806Ssimokawa	for (trys = 0; todo > 0 && trys < 3; trys ++) {
1755169806Ssimokawa		todo2 = 0;
1756169806Ssimokawa		for (i = 0; i < todo; i ++) {
1757169806Ssimokawa			dfwdev.dst = nodes[i];
1758169806Ssimokawa			err = fw_explore_node(&dfwdev);
1759169806Ssimokawa			if (err)
1760169806Ssimokawa				nodes[todo2++] = nodes[i];
1761169806Ssimokawa			if (firewire_debug)
1762188722Ssbruno				device_printf(fc->bdev, "%s: node %d, err = %d\n",
1763188722Ssbruno					__func__, node, err);
1764103285Sikob		}
1765169806Ssimokawa		todo = todo2;
1766103285Sikob	}
1767169806Ssimokawa	splx(s);
1768169806Ssimokawa}
1769169806Ssimokawa
1770169806Ssimokawa
1771169806Ssimokawastatic void
1772169806Ssimokawafw_bus_probe_thread(void *arg)
1773169806Ssimokawa{
1774169806Ssimokawa	struct firewire_comm *fc;
1775169806Ssimokawa
1776169806Ssimokawa	fc = (struct firewire_comm *)arg;
1777169806Ssimokawa
1778170374Ssimokawa	mtx_lock(&fc->wait_lock);
1779170374Ssimokawa	while (fc->status != FWBUSDETACH) {
1780169806Ssimokawa		if (fc->status == FWBUSEXPLORE) {
1781170374Ssimokawa			mtx_unlock(&fc->wait_lock);
1782169806Ssimokawa			fw_explore(fc);
1783169806Ssimokawa			fc->status = FWBUSEXPDONE;
1784169806Ssimokawa			if (firewire_debug)
1785169806Ssimokawa				printf("bus_explore done\n");
1786169806Ssimokawa			fw_attach_dev(fc);
1787170374Ssimokawa			mtx_lock(&fc->wait_lock);
1788170374Ssimokawa		}
1789170374Ssimokawa		msleep((void *)fc, &fc->wait_lock, PWAIT|PCATCH, "-", 0);
1790127468Ssimokawa	}
1791170374Ssimokawa	mtx_unlock(&fc->wait_lock);
1792172836Sjulian	kproc_exit(0);
1793103285Sikob}
1794103285Sikob
1795103285Sikob/*
1796103285Sikob * To attach sub-devices layer onto IEEE1394 bus.
1797103285Sikob */
1798106815Ssimokawastatic void
1799106815Ssimokawafw_attach_dev(struct firewire_comm *fc)
1800103285Sikob{
1801120850Ssimokawa	struct fw_device *fwdev, *next;
1802103285Sikob	int i, err;
1803103285Sikob	device_t *devlistp;
1804103285Sikob	int devcnt;
1805103285Sikob	struct firewire_dev_comm *fdc;
1806103285Sikob
1807120850Ssimokawa	for (fwdev = STAILQ_FIRST(&fc->devices); fwdev != NULL; fwdev = next) {
1808120850Ssimokawa		next = STAILQ_NEXT(fwdev, link);
1809120850Ssimokawa		if (fwdev->status == FWDEVINIT) {
1810114069Ssimokawa			fwdev->status = FWDEVATTACHED;
1811120850Ssimokawa		} else if (fwdev->status == FWDEVINVAL) {
1812120850Ssimokawa			fwdev->rcnt ++;
1813188722Ssbruno			if (firewire_debug)
1814188722Ssbruno				device_printf(fc->bdev, "%s:"
1815188722Ssbruno					"fwdev->rcnt(%d), hold_count(%d)\n",
1816188722Ssbruno					__func__, fwdev->rcnt, hold_count);
1817120850Ssimokawa			if (fwdev->rcnt > hold_count) {
1818120850Ssimokawa				/*
1819120850Ssimokawa				 * Remove devices which have not been seen
1820120850Ssimokawa				 * for a while.
1821120850Ssimokawa				 */
1822188722Ssbruno				device_printf(fc->bdev, "%s:"
1823188722Ssbruno					"Removing missing device ID:%08x%08x\n",
1824188722Ssbruno					__func__, fwdev->eui.hi, fwdev->eui.lo);
1825120850Ssimokawa				STAILQ_REMOVE(&fc->devices, fwdev, fw_device,
1826120850Ssimokawa				    link);
1827120850Ssimokawa				free(fwdev, M_FW);
1828120850Ssimokawa			}
1829120850Ssimokawa		}
1830120850Ssimokawa	}
1831103285Sikob
1832108773Ssimokawa	err = device_get_children(fc->bdev, &devlistp, &devcnt);
1833188722Ssbruno	if( err == 0 ) {
1834188722Ssbruno		for( i = 0 ; i < devcnt ; i++){
1835188722Ssbruno			if (device_get_state(devlistp[i]) >= DS_ATTACHED)  {
1836188722Ssbruno				fdc = device_get_softc(devlistp[i]);
1837188722Ssbruno				if (fdc->post_explore != NULL)
1838188722Ssbruno					fdc->post_explore(fdc);
1839188722Ssbruno			}
1840103285Sikob		}
1841188722Ssbruno		free(devlistp, M_TEMP);
1842103285Sikob	}
1843103285Sikob
1844103285Sikob	return;
1845103285Sikob}
1846106815Ssimokawa
1847103285Sikob/*
1848129541Sdfr * To allocate unique transaction label.
1849103285Sikob */
1850106815Ssimokawastatic int
1851106815Ssimokawafw_get_tlabel(struct firewire_comm *fc, struct fw_xfer *xfer)
1852103285Sikob{
1853171457Ssimokawa	u_int dst, new_tlabel;
1854169119Ssimokawa	struct fw_xfer *txfer;
1855103285Sikob	int s;
1856103285Sikob
1857171457Ssimokawa	dst = xfer->send.hdr.mode.hdr.dst & 0x3f;
1858103285Sikob	s = splfw();
1859171513Ssimokawa	mtx_lock(&fc->tlabel_lock);
1860171457Ssimokawa	new_tlabel = (fc->last_tlabel[dst] + 1) & 0x3f;
1861171457Ssimokawa	STAILQ_FOREACH(txfer, &fc->tlabels[new_tlabel], tlabel)
1862171457Ssimokawa		if ((txfer->send.hdr.mode.hdr.dst & 0x3f) == dst)
1863120660Ssimokawa				break;
1864171457Ssimokawa	if(txfer == NULL) {
1865171457Ssimokawa		fc->last_tlabel[dst] = new_tlabel;
1866171457Ssimokawa		STAILQ_INSERT_TAIL(&fc->tlabels[new_tlabel], xfer, tlabel);
1867171513Ssimokawa		mtx_unlock(&fc->tlabel_lock);
1868171457Ssimokawa		splx(s);
1869171457Ssimokawa		xfer->tl = new_tlabel;
1870171457Ssimokawa		xfer->send.hdr.mode.hdr.tlrt = new_tlabel << 2;
1871171457Ssimokawa		if (firewire_debug > 1)
1872171457Ssimokawa			printf("fw_get_tlabel: dst=%d tl=%d\n", dst, new_tlabel);
1873171457Ssimokawa		return (new_tlabel);
1874103285Sikob	}
1875171513Ssimokawa	mtx_unlock(&fc->tlabel_lock);
1876103285Sikob	splx(s);
1877103285Sikob
1878130460Sdfr	if (firewire_debug > 1)
1879130460Sdfr		printf("fw_get_tlabel: no free tlabel\n");
1880171457Ssimokawa	return (-1);
1881103285Sikob}
1882106815Ssimokawa
1883113584Ssimokawastatic void
1884120660Ssimokawafw_rcv_copy(struct fw_rcv_buf *rb)
1885113584Ssimokawa{
1886120660Ssimokawa	struct fw_pkt *pkt;
1887120660Ssimokawa	u_char *p;
1888120660Ssimokawa	struct tcode_info *tinfo;
1889120660Ssimokawa	u_int res, i, len, plen;
1890113584Ssimokawa
1891169127Ssimokawa	rb->xfer->recv.spd = rb->spd;
1892120660Ssimokawa
1893120660Ssimokawa	pkt = (struct fw_pkt *)rb->vec->iov_base;
1894120660Ssimokawa	tinfo = &rb->fc->tcode[pkt->mode.hdr.tcode];
1895120660Ssimokawa
1896120660Ssimokawa	/* Copy header */
1897120660Ssimokawa	p = (u_char *)&rb->xfer->recv.hdr;
1898120660Ssimokawa	bcopy(rb->vec->iov_base, p, tinfo->hdr_len);
1899132771Skan	rb->vec->iov_base = (u_char *)rb->vec->iov_base + tinfo->hdr_len;
1900120660Ssimokawa	rb->vec->iov_len -= tinfo->hdr_len;
1901120660Ssimokawa
1902120660Ssimokawa	/* Copy payload */
1903120660Ssimokawa	p = (u_char *)rb->xfer->recv.payload;
1904120660Ssimokawa	res = rb->xfer->recv.pay_len;
1905120660Ssimokawa
1906120660Ssimokawa	/* special handling for RRESQ */
1907120660Ssimokawa	if (pkt->mode.hdr.tcode == FWTCODE_RRESQ &&
1908129585Sdfr	    p != NULL && res >= sizeof(uint32_t)) {
1909129585Sdfr		*(uint32_t *)p = pkt->mode.rresq.data;
1910129585Sdfr		rb->xfer->recv.pay_len = sizeof(uint32_t);
1911120660Ssimokawa		return;
1912120660Ssimokawa	}
1913120660Ssimokawa
1914120660Ssimokawa	if ((tinfo->flag & FWTI_BLOCK_ASY) == 0)
1915120660Ssimokawa		return;
1916120660Ssimokawa
1917120660Ssimokawa	plen = pkt->mode.rresb.len;
1918120660Ssimokawa
1919120660Ssimokawa	for (i = 0; i < rb->nvec; i++, rb->vec++) {
1920120660Ssimokawa		len = MIN(rb->vec->iov_len, plen);
1921113584Ssimokawa		if (res < len) {
1922188722Ssbruno			device_printf(rb->fc->bdev, "%s:"
1923188722Ssbruno				" rcv buffer(%d) is %d bytes short.\n",
1924188722Ssbruno				__func__, rb->xfer->recv.pay_len, len - res);
1925113584Ssimokawa			len = res;
1926113584Ssimokawa		}
1927120660Ssimokawa		bcopy(rb->vec->iov_base, p, len);
1928113584Ssimokawa		p += len;
1929113584Ssimokawa		res -= len;
1930120660Ssimokawa		plen -= len;
1931120660Ssimokawa		if (res == 0 || plen == 0)
1932113584Ssimokawa			break;
1933113584Ssimokawa	}
1934120660Ssimokawa	rb->xfer->recv.pay_len -= res;
1935120660Ssimokawa
1936113584Ssimokawa}
1937113584Ssimokawa
1938103285Sikob/*
1939129541Sdfr * Generic packet receiving process.
1940103285Sikob */
1941106815Ssimokawavoid
1942120660Ssimokawafw_rcv(struct fw_rcv_buf *rb)
1943103285Sikob{
1944103285Sikob	struct fw_pkt *fp, *resfp;
1945103285Sikob	struct fw_bind *bind;
1946169130Ssimokawa	int tcode;
1947113584Ssimokawa	int i, len, oldstate;
1948103285Sikob#if 0
1949103285Sikob	{
1950129585Sdfr		uint32_t *qld;
1951103285Sikob		int i;
1952129585Sdfr		qld = (uint32_t *)buf;
1953103285Sikob		printf("spd %d len:%d\n", spd, len);
1954103285Sikob		for( i = 0 ; i <= len && i < 32; i+= 4){
1955103285Sikob			printf("0x%08x ", ntohl(qld[i/4]));
1956103285Sikob			if((i % 16) == 15) printf("\n");
1957103285Sikob		}
1958103285Sikob		if((i % 16) != 15) printf("\n");
1959103285Sikob	}
1960103285Sikob#endif
1961120660Ssimokawa	fp = (struct fw_pkt *)rb->vec[0].iov_base;
1962113584Ssimokawa	tcode = fp->mode.common.tcode;
1963113584Ssimokawa	switch (tcode) {
1964103285Sikob	case FWTCODE_WRES:
1965103285Sikob	case FWTCODE_RRESQ:
1966103285Sikob	case FWTCODE_RRESB:
1967103285Sikob	case FWTCODE_LRES:
1968120660Ssimokawa		rb->xfer = fw_tl2xfer(rb->fc, fp->mode.hdr.src,
1969170374Ssimokawa				fp->mode.hdr.tlrt >> 2, fp->mode.hdr.tcode);
1970120660Ssimokawa		if(rb->xfer == NULL) {
1971188722Ssbruno			device_printf(rb->fc->bdev, "%s: "
1972188722Ssbruno				"unknown response "
1973188722Ssbruno			    	"%s(%x) src=0x%x tl=0x%x rt=%d data=0x%x\n",
1974188722Ssbruno				__func__,
1975188722Ssbruno			    	tcode_str[tcode], tcode,
1976188722Ssbruno				fp->mode.hdr.src,
1977188722Ssbruno				fp->mode.hdr.tlrt >> 2,
1978188722Ssbruno				fp->mode.hdr.tlrt & 3,
1979188722Ssbruno				fp->mode.rresq.data);
1980170374Ssimokawa#if 0
1981103285Sikob			printf("try ad-hoc work around!!\n");
1982120660Ssimokawa			rb->xfer = fw_tl2xfer(rb->fc, fp->mode.hdr.src,
1983103285Sikob					(fp->mode.hdr.tlrt >> 2)^3);
1984120660Ssimokawa			if (rb->xfer == NULL) {
1985103285Sikob				printf("no use...\n");
1986169131Ssimokawa				return;
1987103285Sikob			}
1988103285Sikob#else
1989169131Ssimokawa			return;
1990103285Sikob#endif
1991103285Sikob		}
1992120660Ssimokawa		fw_rcv_copy(rb);
1993120660Ssimokawa		if (rb->xfer->recv.hdr.mode.wres.rtcode != RESP_CMP)
1994120660Ssimokawa			rb->xfer->resp = EIO;
1995120660Ssimokawa		else
1996120660Ssimokawa			rb->xfer->resp = 0;
1997113584Ssimokawa		/* make sure the packet is drained in AT queue */
1998170374Ssimokawa		oldstate = rb->xfer->flag;
1999170374Ssimokawa		rb->xfer->flag = FWXF_RCVD;
2000113584Ssimokawa		switch (oldstate) {
2001113584Ssimokawa		case FWXF_SENT:
2002120660Ssimokawa			fw_xfer_done(rb->xfer);
2003103285Sikob			break;
2004113584Ssimokawa		case FWXF_START:
2005119289Ssimokawa#if 0
2006113584Ssimokawa			if (firewire_debug)
2007120660Ssimokawa				printf("not sent yet tl=%x\n", rb->xfer->tl);
2008119289Ssimokawa#endif
2009113584Ssimokawa			break;
2010103285Sikob		default:
2011188722Ssbruno			device_printf(rb->fc->bdev, "%s: "
2012188722Ssbruno				"unexpected flag 0x%02x\n", __func__, rb->xfer->flag);
2013103285Sikob		}
2014113584Ssimokawa		return;
2015103285Sikob	case FWTCODE_WREQQ:
2016103285Sikob	case FWTCODE_WREQB:
2017103285Sikob	case FWTCODE_RREQQ:
2018103285Sikob	case FWTCODE_RREQB:
2019103285Sikob	case FWTCODE_LREQ:
2020120660Ssimokawa		bind = fw_bindlookup(rb->fc, fp->mode.rreqq.dest_hi,
2021113584Ssimokawa			fp->mode.rreqq.dest_lo);
2022103285Sikob		if(bind == NULL){
2023188722Ssbruno			device_printf(rb->fc->bdev, "%s: "
2024188722Ssbruno				"Unknown service addr 0x%04x:0x%08x %s(%x)"
2025127468Ssimokawa#if defined(__DragonFly__) || __FreeBSD_version < 500000
2026188722Ssbruno				" src=0x%x data=%lx\n",
2027127468Ssimokawa#else
2028188722Ssbruno				" src=0x%x data=%x\n",
2029113962Ssimokawa#endif
2030188722Ssbruno				__func__,
2031188722Ssbruno				fp->mode.wreqq.dest_hi,
2032188722Ssbruno				fp->mode.wreqq.dest_lo,
2033188722Ssbruno				tcode_str[tcode], tcode,
2034188722Ssbruno				fp->mode.hdr.src,
2035188722Ssbruno				ntohl(fp->mode.wreqq.data));
2036188722Ssbruno
2037170425Ssimokawa			if (rb->fc->status == FWBUSINIT) {
2038188722Ssbruno				device_printf(rb->fc->bdev, "%s: cannot respond(bus reset)!\n",
2039188722Ssbruno						__func__);
2040169131Ssimokawa				return;
2041103285Sikob			}
2042120660Ssimokawa			rb->xfer = fw_xfer_alloc(M_FWXFER);
2043120660Ssimokawa			if(rb->xfer == NULL){
2044103285Sikob				return;
2045103285Sikob			}
2046120660Ssimokawa			rb->xfer->send.spd = rb->spd;
2047120660Ssimokawa			rb->xfer->send.pay_len = 0;
2048120660Ssimokawa			resfp = &rb->xfer->send.hdr;
2049113584Ssimokawa			switch (tcode) {
2050103285Sikob			case FWTCODE_WREQQ:
2051103285Sikob			case FWTCODE_WREQB:
2052103285Sikob				resfp->mode.hdr.tcode = FWTCODE_WRES;
2053103285Sikob				break;
2054103285Sikob			case FWTCODE_RREQQ:
2055103285Sikob				resfp->mode.hdr.tcode = FWTCODE_RRESQ;
2056103285Sikob				break;
2057103285Sikob			case FWTCODE_RREQB:
2058103285Sikob				resfp->mode.hdr.tcode = FWTCODE_RRESB;
2059103285Sikob				break;
2060103285Sikob			case FWTCODE_LREQ:
2061103285Sikob				resfp->mode.hdr.tcode = FWTCODE_LRES;
2062103285Sikob				break;
2063103285Sikob			}
2064103285Sikob			resfp->mode.hdr.dst = fp->mode.hdr.src;
2065103285Sikob			resfp->mode.hdr.tlrt = fp->mode.hdr.tlrt;
2066103285Sikob			resfp->mode.hdr.pri = fp->mode.hdr.pri;
2067120660Ssimokawa			resfp->mode.rresb.rtcode = RESP_ADDRESS_ERROR;
2068103285Sikob			resfp->mode.rresb.extcode = 0;
2069103285Sikob			resfp->mode.rresb.len = 0;
2070103285Sikob/*
2071170374Ssimokawa			rb->xfer->hand = fw_xferwake;
2072103285Sikob*/
2073167632Ssimokawa			rb->xfer->hand = fw_xfer_free;
2074120660Ssimokawa			if(fw_asyreq(rb->fc, -1, rb->xfer)){
2075120660Ssimokawa				fw_xfer_free(rb->xfer);
2076103285Sikob				return;
2077103285Sikob			}
2078169131Ssimokawa			return;
2079103285Sikob		}
2080113584Ssimokawa		len = 0;
2081120660Ssimokawa		for (i = 0; i < rb->nvec; i ++)
2082120660Ssimokawa			len += rb->vec[i].iov_len;
2083169130Ssimokawa		rb->xfer = STAILQ_FIRST(&bind->xferlist);
2084169130Ssimokawa		if (rb->xfer == NULL) {
2085188722Ssbruno			device_printf(rb->fc->bdev, "%s: "
2086188722Ssbruno				"Discard a packet for this bind.\n",
2087188722Ssbruno				__func__);
2088169131Ssimokawa			return;
2089103285Sikob		}
2090169130Ssimokawa		STAILQ_REMOVE_HEAD(&bind->xferlist, link);
2091169130Ssimokawa		fw_rcv_copy(rb);
2092169130Ssimokawa		rb->xfer->hand(rb->xfer);
2093169130Ssimokawa		return;
2094120660Ssimokawa#if 0 /* shouldn't happen ?? or for GASP */
2095103285Sikob	case FWTCODE_STREAM:
2096103285Sikob	{
2097103285Sikob		struct fw_xferq *xferq;
2098103285Sikob
2099120660Ssimokawa		xferq = rb->fc->ir[sub];
2100103285Sikob#if 0
2101103285Sikob		printf("stream rcv dma %d len %d off %d spd %d\n",
2102103285Sikob			sub, len, off, spd);
2103103285Sikob#endif
2104103285Sikob		if(xferq->queued >= xferq->maxq) {
2105103285Sikob			printf("receive queue is full\n");
2106169131Ssimokawa			return;
2107103285Sikob		}
2108113584Ssimokawa		/* XXX get xfer from xfer queue, we don't need copy for
2109113584Ssimokawa			per packet mode */
2110120660Ssimokawa		rb->xfer = fw_xfer_alloc_buf(M_FWXFER, 0, /* XXX */
2111113584Ssimokawa						vec[0].iov_len);
2112169131Ssimokawa		if (rb->xfer == NULL)
2113169131Ssimokawa			return;
2114120660Ssimokawa		fw_rcv_copy(rb)
2115103285Sikob		s = splfw();
2116103285Sikob		xferq->queued++;
2117120660Ssimokawa		STAILQ_INSERT_TAIL(&xferq->q, rb->xfer, link);
2118103285Sikob		splx(s);
2119120660Ssimokawa		sc = device_get_softc(rb->fc->bdev);
2120127468Ssimokawa#if defined(__DragonFly__) || __FreeBSD_version < 500000
2121127468Ssimokawa		if (&xferq->rsel.si_pid != 0)
2122127468Ssimokawa#else
2123103285Sikob		if (SEL_WAITING(&xferq->rsel))
2124103285Sikob#endif
2125122352Stanimura			selwakeuppri(&xferq->rsel, FWPRI);
2126103285Sikob		if (xferq->flag & FWXFERQ_WAKEUP) {
2127103285Sikob			xferq->flag &= ~FWXFERQ_WAKEUP;
2128103285Sikob			wakeup((caddr_t)xferq);
2129103285Sikob		}
2130103285Sikob		if (xferq->flag & FWXFERQ_HANDLER) {
2131103285Sikob			xferq->hand(xferq);
2132103285Sikob		}
2133103285Sikob		return;
2134103285Sikob		break;
2135103285Sikob	}
2136120660Ssimokawa#endif
2137103285Sikob	default:
2138188722Ssbruno		device_printf(rb->fc->bdev,"%s: unknown tcode %d\n",
2139188722Ssbruno				__func__, tcode);
2140103285Sikob		break;
2141103285Sikob	}
2142103285Sikob}
2143106815Ssimokawa
2144103285Sikob/*
2145103285Sikob * Post process for Bus Manager election process.
2146103285Sikob */
2147103285Sikobstatic void
2148103285Sikobfw_try_bmr_callback(struct fw_xfer *xfer)
2149103285Sikob{
2150103285Sikob	struct firewire_comm *fc;
2151109422Ssimokawa	int bmr;
2152103285Sikob
2153109422Ssimokawa	if (xfer == NULL)
2154109422Ssimokawa		return;
2155103285Sikob	fc = xfer->fc;
2156109422Ssimokawa	if (xfer->resp != 0)
2157103285Sikob		goto error;
2158120660Ssimokawa	if (xfer->recv.payload == NULL)
2159103285Sikob		goto error;
2160120660Ssimokawa	if (xfer->recv.hdr.mode.lres.rtcode != FWRCODE_COMPLETE)
2161103285Sikob		goto error;
2162109422Ssimokawa
2163120660Ssimokawa	bmr = ntohl(xfer->recv.payload[0]);
2164109422Ssimokawa	if (bmr == 0x3f)
2165109422Ssimokawa		bmr = fc->nodeid;
2166109422Ssimokawa
2167109422Ssimokawa	CSRARC(fc, BUS_MGR_ID) = fc->set_bmr(fc, bmr & 0x3f);
2168120660Ssimokawa	fw_xfer_free_buf(xfer);
2169114909Ssimokawa	fw_bmr(fc);
2170114909Ssimokawa	return;
2171114909Ssimokawa
2172103285Sikoberror:
2173114909Ssimokawa	device_printf(fc->bdev, "bus manager election failed\n");
2174120660Ssimokawa	fw_xfer_free_buf(xfer);
2175103285Sikob}
2176106815Ssimokawa
2177113584Ssimokawa
2178103285Sikob/*
2179103285Sikob * To candidate Bus Manager election process.
2180103285Sikob */
2181110270Ssimokawastatic void
2182106815Ssimokawafw_try_bmr(void *arg)
2183103285Sikob{
2184103285Sikob	struct fw_xfer *xfer;
2185103285Sikob	struct firewire_comm *fc = (struct firewire_comm *)arg;
2186103285Sikob	struct fw_pkt *fp;
2187103285Sikob	int err = 0;
2188103285Sikob
2189120660Ssimokawa	xfer = fw_xfer_alloc_buf(M_FWXFER, 8, 4);
2190103285Sikob	if(xfer == NULL){
2191103285Sikob		return;
2192103285Sikob	}
2193120660Ssimokawa	xfer->send.spd = 0;
2194103285Sikob	fc->status = FWBUSMGRELECT;
2195103285Sikob
2196120660Ssimokawa	fp = &xfer->send.hdr;
2197113584Ssimokawa	fp->mode.lreq.dest_hi = 0xffff;
2198103285Sikob	fp->mode.lreq.tlrt = 0;
2199103285Sikob	fp->mode.lreq.tcode = FWTCODE_LREQ;
2200103285Sikob	fp->mode.lreq.pri = 0;
2201103285Sikob	fp->mode.lreq.src = 0;
2202113584Ssimokawa	fp->mode.lreq.len = 8;
2203120660Ssimokawa	fp->mode.lreq.extcode = EXTCODE_CMP_SWAP;
2204120660Ssimokawa	fp->mode.lreq.dst = FWLOCALBUS | fc->irm;
2205113584Ssimokawa	fp->mode.lreq.dest_lo = 0xf0000000 | BUS_MGR_ID;
2206120660Ssimokawa	xfer->send.payload[0] = htonl(0x3f);
2207120660Ssimokawa	xfer->send.payload[1] = htonl(fc->nodeid);
2208167632Ssimokawa	xfer->hand = fw_try_bmr_callback;
2209103285Sikob
2210103285Sikob	err = fw_asyreq(fc, -1, xfer);
2211103285Sikob	if(err){
2212120660Ssimokawa		fw_xfer_free_buf(xfer);
2213103285Sikob		return;
2214103285Sikob	}
2215103285Sikob	return;
2216103285Sikob}
2217106543Ssimokawa
2218106543Ssimokawa#ifdef FW_VMACCESS
2219103285Sikob/*
2220103285Sikob * Software implementation for physical memory block access.
2221103285Sikob * XXX:Too slow, usef for debug purpose only.
2222103285Sikob */
2223106815Ssimokawastatic void
2224106815Ssimokawafw_vmaccess(struct fw_xfer *xfer){
2225103285Sikob	struct fw_pkt *rfp, *sfp = NULL;
2226129585Sdfr	uint32_t *ld = (uint32_t *)xfer->recv.buf;
2227103285Sikob
2228113584Ssimokawa	printf("vmaccess spd:%2x len:%03x data:%08x %08x %08x %08x\n",
2229113584Ssimokawa			xfer->spd, xfer->recv.len, ntohl(ld[0]), ntohl(ld[1]), ntohl(ld[2]), ntohl(ld[3]));
2230103285Sikob	printf("vmaccess          data:%08x %08x %08x %08x\n", ntohl(ld[4]), ntohl(ld[5]), ntohl(ld[6]), ntohl(ld[7]));
2231103285Sikob	if(xfer->resp != 0){
2232103285Sikob		fw_xfer_free( xfer);
2233103285Sikob		return;
2234103285Sikob	}
2235103285Sikob	if(xfer->recv.buf == NULL){
2236103285Sikob		fw_xfer_free( xfer);
2237103285Sikob		return;
2238103285Sikob	}
2239103285Sikob	rfp = (struct fw_pkt *)xfer->recv.buf;
2240103285Sikob	switch(rfp->mode.hdr.tcode){
2241103285Sikob		/* XXX need fix for 64bit arch */
2242103285Sikob		case FWTCODE_WREQB:
2243110195Ssimokawa			xfer->send.buf = malloc(12, M_FW, M_NOWAIT);
2244103285Sikob			xfer->send.len = 12;
2245103285Sikob			sfp = (struct fw_pkt *)xfer->send.buf;
2246103285Sikob			bcopy(rfp->mode.wreqb.payload,
2247103285Sikob				(caddr_t)ntohl(rfp->mode.wreqb.dest_lo), ntohs(rfp->mode.wreqb.len));
2248103285Sikob			sfp->mode.wres.tcode = FWTCODE_WRES;
2249103285Sikob			sfp->mode.wres.rtcode = 0;
2250103285Sikob			break;
2251103285Sikob		case FWTCODE_WREQQ:
2252110195Ssimokawa			xfer->send.buf = malloc(12, M_FW, M_NOWAIT);
2253103285Sikob			xfer->send.len = 12;
2254103285Sikob			sfp->mode.wres.tcode = FWTCODE_WRES;
2255129585Sdfr			*((uint32_t *)(ntohl(rfp->mode.wreqb.dest_lo))) = rfp->mode.wreqq.data;
2256103285Sikob			sfp->mode.wres.rtcode = 0;
2257103285Sikob			break;
2258103285Sikob		case FWTCODE_RREQB:
2259110195Ssimokawa			xfer->send.buf = malloc(16 + rfp->mode.rreqb.len, M_FW, M_NOWAIT);
2260103285Sikob			xfer->send.len = 16 + ntohs(rfp->mode.rreqb.len);
2261103285Sikob			sfp = (struct fw_pkt *)xfer->send.buf;
2262103285Sikob			bcopy((caddr_t)ntohl(rfp->mode.rreqb.dest_lo),
2263129585Sdfr				sfp->mode.rresb.payload, (uint16_t)ntohs(rfp->mode.rreqb.len));
2264103285Sikob			sfp->mode.rresb.tcode = FWTCODE_RRESB;
2265103285Sikob			sfp->mode.rresb.len = rfp->mode.rreqb.len;
2266103285Sikob			sfp->mode.rresb.rtcode = 0;
2267103285Sikob			sfp->mode.rresb.extcode = 0;
2268103285Sikob			break;
2269103285Sikob		case FWTCODE_RREQQ:
2270110195Ssimokawa			xfer->send.buf = malloc(16, M_FW, M_NOWAIT);
2271103285Sikob			xfer->send.len = 16;
2272103285Sikob			sfp = (struct fw_pkt *)xfer->send.buf;
2273129585Sdfr			sfp->mode.rresq.data = *(uint32_t *)(ntohl(rfp->mode.rreqq.dest_lo));
2274103285Sikob			sfp->mode.wres.tcode = FWTCODE_RRESQ;
2275103285Sikob			sfp->mode.rresb.rtcode = 0;
2276103285Sikob			break;
2277103285Sikob		default:
2278103285Sikob			fw_xfer_free( xfer);
2279103285Sikob			return;
2280103285Sikob	}
2281103285Sikob	sfp->mode.hdr.dst = rfp->mode.hdr.src;
2282103285Sikob	xfer->dst = ntohs(rfp->mode.hdr.src);
2283167632Ssimokawa	xfer->hand = fw_xfer_free;
2284103285Sikob
2285103285Sikob	sfp->mode.hdr.tlrt = rfp->mode.hdr.tlrt;
2286103285Sikob	sfp->mode.hdr.pri = 0;
2287103285Sikob
2288103285Sikob	fw_asyreq(xfer->fc, -1, xfer);
2289103285Sikob/**/
2290103285Sikob	return;
2291103285Sikob}
2292106543Ssimokawa#endif
2293106543Ssimokawa
2294103285Sikob/*
2295103285Sikob * CRC16 check-sum for IEEE1394 register blocks.
2296103285Sikob */
2297129585Sdfruint16_t
2298129585Sdfrfw_crc16(uint32_t *ptr, uint32_t len){
2299129585Sdfr	uint32_t i, sum, crc = 0;
2300103285Sikob	int shift;
2301103285Sikob	len = (len + 3) & ~3;
2302103285Sikob	for(i = 0 ; i < len ; i+= 4){
2303103285Sikob		for( shift = 28 ; shift >= 0 ; shift -= 4){
2304103285Sikob			sum = ((crc >> 12) ^ (ptr[i/4] >> shift)) & 0xf;
2305103285Sikob			crc = (crc << 4) ^ ( sum << 12 ) ^ ( sum << 5) ^ sum;
2306103285Sikob		}
2307103285Sikob		crc &= 0xffff;
2308103285Sikob	}
2309129585Sdfr	return((uint16_t) crc);
2310103285Sikob}
2311106815Ssimokawa
2312188722Ssbruno/*
2313188722Ssbruno * Find the root node, if it is not
2314188722Ssbruno * Cycle Master Capable, then we should
2315188722Ssbruno * override this and become the Cycle
2316188722Ssbruno * Master
2317188722Ssbruno */
2318110270Ssimokawastatic int
2319110072Ssimokawafw_bmr(struct firewire_comm *fc)
2320110072Ssimokawa{
2321110072Ssimokawa	struct fw_device fwdev;
2322113584Ssimokawa	union fw_self_id *self_id;
2323110072Ssimokawa	int cmstr;
2324129585Sdfr	uint32_t quad;
2325110072Ssimokawa
2326113584Ssimokawa	/* Check to see if the current root node is cycle master capable */
2327129274Sdfr	self_id = fw_find_self_id(fc, fc->max_node);
2328113584Ssimokawa	if (fc->max_node > 0) {
2329114909Ssimokawa		/* XXX check cmc bit of businfo block rather than contender */
2330114909Ssimokawa		if (self_id->p0.link_active && self_id->p0.contender)
2331113584Ssimokawa			cmstr = fc->max_node;
2332114909Ssimokawa		else {
2333114909Ssimokawa			device_printf(fc->bdev,
2334114909Ssimokawa				"root node is not cycle master capable\n");
2335114909Ssimokawa			/* XXX shall we be the cycle master? */
2336113584Ssimokawa			cmstr = fc->nodeid;
2337114909Ssimokawa			/* XXX need bus reset */
2338114909Ssimokawa		}
2339113584Ssimokawa	} else
2340113584Ssimokawa		cmstr = -1;
2341114909Ssimokawa
2342188722Ssbruno	device_printf(fc->bdev, "bus manager %d %s\n",
2343188722Ssbruno		CSRARC(fc, BUS_MGR_ID),
2344188722Ssbruno		(CSRARC(fc, BUS_MGR_ID) != fc->nodeid) ? "(me)" : "");
2345114909Ssimokawa	if(CSRARC(fc, BUS_MGR_ID) != fc->nodeid) {
2346114909Ssimokawa		/* We are not the bus manager */
2347114909Ssimokawa		return(0);
2348114909Ssimokawa	}
2349114909Ssimokawa
2350114909Ssimokawa	/* Optimize gapcount */
2351113584Ssimokawa	if(fc->max_hop <= MAX_GAPHOP )
2352113584Ssimokawa		fw_phy_config(fc, cmstr, gap_cnt[fc->max_hop]);
2353110072Ssimokawa	/* If we are the cycle master, nothing to do */
2354113584Ssimokawa	if (cmstr == fc->nodeid || cmstr == -1)
2355110072Ssimokawa		return 0;
2356110072Ssimokawa	/* Bus probe has not finished, make dummy fwdev for cmstr */
2357110072Ssimokawa	bzero(&fwdev, sizeof(fwdev));
2358110072Ssimokawa	fwdev.fc = fc;
2359110072Ssimokawa	fwdev.dst = cmstr;
2360110072Ssimokawa	fwdev.speed = 0;
2361110072Ssimokawa	fwdev.maxrec = 8; /* 512 */
2362110072Ssimokawa	fwdev.status = FWDEVINIT;
2363110072Ssimokawa	/* Set cmstr bit on the cycle master */
2364120660Ssimokawa	quad = htonl(1 << 8);
2365110072Ssimokawa	fwmem_write_quad(&fwdev, NULL, 0/*spd*/,
2366120660Ssimokawa		0xffff, 0xf0000000 | STATE_SET, &quad, fw_asy_callback_free);
2367110072Ssimokawa
2368110072Ssimokawa	return 0;
2369110072Ssimokawa}
2370110072Ssimokawa
2371170374Ssimokawaint
2372170374Ssimokawafw_open_isodma(struct firewire_comm *fc, int tx)
2373170374Ssimokawa{
2374170374Ssimokawa	struct fw_xferq **xferqa;
2375170374Ssimokawa	struct fw_xferq *xferq;
2376170374Ssimokawa	int i;
2377170374Ssimokawa
2378170374Ssimokawa	if (tx)
2379170374Ssimokawa		xferqa = &fc->it[0];
2380170374Ssimokawa	else
2381170374Ssimokawa		xferqa = &fc->ir[0];
2382170374Ssimokawa
2383170374Ssimokawa	FW_GLOCK(fc);
2384170374Ssimokawa	for (i = 0; i < fc->nisodma; i ++) {
2385170374Ssimokawa		xferq = xferqa[i];
2386170374Ssimokawa		if ((xferq->flag & FWXFERQ_OPEN) == 0) {
2387170374Ssimokawa			xferq->flag |= FWXFERQ_OPEN;
2388170374Ssimokawa			break;
2389170374Ssimokawa		}
2390170374Ssimokawa	}
2391170374Ssimokawa	if (i == fc->nisodma) {
2392170374Ssimokawa		printf("no free dma channel (tx=%d)\n", tx);
2393170374Ssimokawa		i = -1;
2394170374Ssimokawa	}
2395170374Ssimokawa	FW_GUNLOCK(fc);
2396170374Ssimokawa	return (i);
2397170374Ssimokawa}
2398170374Ssimokawa
2399118455Ssimokawastatic int
2400118455Ssimokawafw_modevent(module_t mode, int type, void *data)
2401118455Ssimokawa{
2402118455Ssimokawa	int err = 0;
2403127468Ssimokawa#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
2404118455Ssimokawa	static eventhandler_tag fwdev_ehtag = NULL;
2405118455Ssimokawa#endif
2406118455Ssimokawa
2407118455Ssimokawa	switch (type) {
2408118455Ssimokawa	case MOD_LOAD:
2409127468Ssimokawa#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
2410118455Ssimokawa		fwdev_ehtag = EVENTHANDLER_REGISTER(dev_clone,
2411118455Ssimokawa						fwdev_clone, 0, 1000);
2412118455Ssimokawa#endif
2413118455Ssimokawa		break;
2414118455Ssimokawa	case MOD_UNLOAD:
2415127468Ssimokawa#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
2416118455Ssimokawa		if (fwdev_ehtag != NULL)
2417118455Ssimokawa			EVENTHANDLER_DEREGISTER(dev_clone, fwdev_ehtag);
2418118455Ssimokawa#endif
2419118455Ssimokawa		break;
2420118455Ssimokawa	case MOD_SHUTDOWN:
2421118455Ssimokawa		break;
2422132199Sphk	default:
2423132199Sphk		return (EOPNOTSUPP);
2424118455Ssimokawa	}
2425118455Ssimokawa	return (err);
2426118455Ssimokawa}
2427118455Ssimokawa
2428118455Ssimokawa
2429127468Ssimokawa#ifdef __DragonFly__
2430127468SsimokawaDECLARE_DUMMY_MODULE(firewire);
2431127468Ssimokawa#endif
2432118455SsimokawaDRIVER_MODULE(firewire,fwohci,firewire_driver,firewire_devclass,fw_modevent,0);
2433103285SikobMODULE_VERSION(firewire, 1);
2434