xref: /netbsd-src/sys/dev/ieee1394/fwohci.c (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
1 /*	$NetBSD: fwohci.c,v 1.137 2014/02/25 18:30:09 pooka Exp $	*/
2 
3 /*-
4  * Copyright (c) 2003 Hidetoshi Shimokawa
5  * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the acknowledgement as bellow:
18  *
19  *    This product includes software developed by K. Kobayashi and H. Shimokawa
20  *
21  * 4. The name of the author may not be used to endorse or promote products
22  *    derived from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
28  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
32  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  *
36  * $FreeBSD: src/sys/dev/firewire/fwohci.c,v 1.98 2009/02/13 17:44:07 sbruno Exp $
37  *
38  */
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: fwohci.c,v 1.137 2014/02/25 18:30:09 pooka Exp $");
41 
42 #include <sys/param.h>
43 #include <sys/atomic.h>
44 #include <sys/bus.h>
45 #include <sys/device.h>
46 #include <sys/errno.h>
47 #include <sys/conf.h>
48 #include <sys/kernel.h>
49 #include <sys/malloc.h>
50 #include <sys/mbuf.h>
51 #include <sys/proc.h>
52 #include <sys/reboot.h>
53 #include <sys/select.h>
54 #include <sys/sysctl.h>
55 #include <sys/systm.h>
56 
57 #include <dev/ieee1394/firewire.h>
58 #include <dev/ieee1394/firewirereg.h>
59 #include <dev/ieee1394/fwdma.h>
60 #include <dev/ieee1394/fwohcireg.h>
61 #include <dev/ieee1394/fwohcivar.h>
62 #include <dev/ieee1394/firewire_phy.h>
63 
64 #include "ioconf.h"
65 
66 #undef OHCI_DEBUG
67 
68 static int nocyclemaster = 0;
69 int firewire_phydma_enable = 1;
70 /*
71  * Setup sysctl(3) MIB, hw.fwohci.*
72  *
73  * TBD condition CTLFLAG_PERMANENT on being a module or not
74  */
75 SYSCTL_SETUP(sysctl_fwohci, "sysctl fwohci(4) subtree setup")
76 {
77 	int rc, fwohci_node_num;
78 	const struct sysctlnode *node;
79 
80 	if ((rc = sysctl_createv(clog, 0, NULL, &node,
81 	    CTLFLAG_PERMANENT, CTLTYPE_NODE, "fwohci",
82 	    SYSCTL_DESCR("fwohci controls"),
83 	    NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL)) != 0) {
84 		goto err;
85 	}
86 	fwohci_node_num = node->sysctl_num;
87 
88 	/* fwohci no cyclemaster flag */
89 	if ((rc = sysctl_createv(clog, 0, NULL, &node,
90 	    CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT,
91 	    "nocyclemaster", SYSCTL_DESCR("Do not send cycle start packets"),
92 	    NULL, 0, &nocyclemaster,
93 	    0, CTL_HW, fwohci_node_num, CTL_CREATE, CTL_EOL)) != 0) {
94 		goto err;
95 	}
96 
97 	/* fwohci physical request DMA enable */
98 	if ((rc = sysctl_createv(clog, 0, NULL, &node,
99 	    CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT, "phydma_enable",
100 	    SYSCTL_DESCR("Allow physical request DMA from firewire"),
101 	    NULL, 0, &firewire_phydma_enable,
102 	    0, CTL_HW, fwohci_node_num, CTL_CREATE, CTL_EOL)) != 0) {
103 		goto err;
104 	}
105 	return;
106 
107 err:
108 	aprint_error("%s: sysctl_createv failed (rc = %d)\n", __func__, rc);
109 }
110 
111 static const char * const dbcode[16] = {
112     "OUTM", "OUTL", "INPM", "INPL", "STOR", "LOAD", "NOP ", "STOP",
113     "", "", "", "", "", "", "", ""
114 };
115 
116 static const char * const dbkey[8] = {
117     "ST0", "ST1", "ST2", "ST3", "UNDEF", "REG", "SYS", "DEV"
118 };
119 
120 static const char * const dbcond[4] = { "NEV", "C=1", "C=0", "ALL" };
121 static const char * const fwohcicode[32] = {
122 	"No stat",	"Undef",	"long",		"miss Ack err",
123 	"FIFO underrun","FIFO overrun",	"desc err",	"data read err",
124 	"data write err","bus reset",	"timeout",	"tcode err",
125 	"Undef",	"Undef",	"unknown event","flushed",
126 	"Undef",	"ack complete",	"ack pend",	"Undef",
127 	"ack busy_X",	"ack busy_A",	"ack busy_B",	"Undef",
128 	"Undef",	"Undef",	"Undef",	"ack tardy",
129 	"Undef",	"ack data_err",	"ack type_err",	""
130 };
131 
132 #define MAX_SPEED 3
133 extern const char *fw_linkspeed[];
134 static uint32_t const tagbit[4] = { 1 << 28, 1 << 29, 1 << 30, 1 << 31 };
135 
136 static const struct tcode_info tinfo[] = {
137 /*		hdr_len block 	flag	valid_response */
138 /* 0 WREQQ  */ { 16,	FWTI_REQ | FWTI_TLABEL, FWTCODE_WRES },
139 /* 1 WREQB  */ { 16,	FWTI_REQ | FWTI_TLABEL | FWTI_BLOCK_ASY, FWTCODE_WRES },
140 /* 2 WRES   */ { 12,	FWTI_RES, 0xff },
141 /* 3 XXX    */ {  0,	0, 0xff },
142 /* 4 RREQQ  */ { 12,	FWTI_REQ | FWTI_TLABEL, FWTCODE_RRESQ },
143 /* 5 RREQB  */ { 16,	FWTI_REQ | FWTI_TLABEL, FWTCODE_RRESB },
144 /* 6 RRESQ  */ { 16,	FWTI_RES, 0xff },
145 /* 7 RRESB  */ { 16,	FWTI_RES | FWTI_BLOCK_ASY, 0xff },
146 /* 8 CYCS   */ {  0,	0, 0xff },
147 /* 9 LREQ   */ { 16,	FWTI_REQ | FWTI_TLABEL | FWTI_BLOCK_ASY, FWTCODE_LRES },
148 /* a STREAM */ {  4,	FWTI_REQ | FWTI_BLOCK_STR, 0xff },
149 /* b LRES   */ { 16,	FWTI_RES | FWTI_BLOCK_ASY, 0xff },
150 /* c XXX    */ {  0,	0, 0xff },
151 /* d XXX    */ {  0,	0, 0xff },
152 /* e PHY    */ { 12,	FWTI_REQ, 0xff },
153 /* f XXX    */ {  0,	0, 0xff }
154 };
155 
156 #define OHCI_WRITE_SIGMASK 0xffff0000
157 #define OHCI_READ_SIGMASK 0xffff0000
158 
159 
160 int fwohci_print(void *, const char *);
161 
162 static int fwohci_ioctl(dev_t, u_long, void *, int, struct lwp *);
163 
164 static uint32_t fwohci_cyctimer(struct firewire_comm *);
165 static uint32_t fwohci_set_bus_manager(struct firewire_comm *, u_int);
166 static void fwohci_ibr(struct firewire_comm *);
167 static int fwohci_irx_enable(struct firewire_comm *, int);
168 static int fwohci_irx_disable(struct firewire_comm *, int);
169 static int fwohci_itxbuf_enable(struct firewire_comm *, int);
170 static int fwohci_itx_disable(struct firewire_comm *, int);
171 static void fwohci_timeout(struct firewire_comm *fc);
172 #if BYTE_ORDER == BIG_ENDIAN
173 static void fwohci_irx_post(struct firewire_comm *, uint32_t *);
174 #endif
175 static void fwohci_set_intr(struct firewire_comm *, int);
176 
177 static uint32_t fwphy_rddata(struct fwohci_softc *, uint32_t);
178 static uint32_t fwphy_wrdata(struct fwohci_softc *, uint32_t, uint32_t);
179 static int fwohci_probe_phy(struct fwohci_softc *);
180 static void fwohci_reset(struct fwohci_softc *);
181 static void fwohci_execute_db(struct fwohcidb_tr *, bus_dmamap_t);
182 static void fwohci_start(struct fwohci_softc *, struct fwohci_dbch *);
183 static void fwohci_start_atq(struct firewire_comm *);
184 static void fwohci_start_ats(struct firewire_comm *);
185 static void fwohci_txd(struct fwohci_softc *, struct fwohci_dbch *);
186 static void fwohci_db_free(struct fwohci_softc *, struct fwohci_dbch *);
187 static void fwohci_db_init(struct fwohci_softc *, struct fwohci_dbch *);
188 static int fwohci_rx_enable(struct fwohci_softc *, struct fwohci_dbch *);
189 static int fwohci_tx_enable(struct fwohci_softc *, struct fwohci_dbch *);
190 static int fwohci_next_cycle(struct fwohci_softc *, int);
191 #ifdef OHCI_DEBUG
192 static void fwohci_dump_intr(struct fwohci_softc *, uint32_t);
193 #endif
194 static void fwohci_intr_core(struct fwohci_softc *, uint32_t);
195 static void fwohci_intr_dma(struct fwohci_softc *, uint32_t);
196 static void fwohci_task_sid(struct fwohci_softc *);
197 static void fwohci_task_dma(struct fwohci_softc *);
198 static void fwohci_tbuf_update(struct fwohci_softc *, int);
199 static void fwohci_rbuf_update(struct fwohci_softc *, int);
200 static void dump_dma(struct fwohci_softc *, uint32_t);
201 static void dump_db(struct fwohci_softc *, uint32_t);
202 static void print_db(struct fwohcidb_tr *, struct fwohcidb *, uint32_t,
203 		     uint32_t);
204 static void fwohci_txbufdb(struct fwohci_softc *, int, struct fw_bulkxfer *);
205 static int fwohci_add_tx_buf(struct fwohci_dbch *, struct fwohcidb_tr *, int);
206 static int fwohci_add_rx_buf(struct fwohci_dbch *, struct fwohcidb_tr *, int,
207 			     struct fwdma_alloc *);
208 static int fwohci_arcv_swap(struct fw_pkt *, int);
209 static int fwohci_get_plen(struct fwohci_softc *, struct fwohci_dbch *,
210 			   struct fw_pkt *);
211 static void fwohci_arcv_free_buf(struct fwohci_softc *, struct fwohci_dbch *,
212 				 struct fwohcidb_tr *, int);
213 static void fwohci_arcv(struct fwohci_softc *, struct fwohci_dbch *);
214 
215 
216 /*
217  * memory allocated for DMA programs
218  */
219 #define DMA_PROG_ALLOC		(8 * PAGE_SIZE)
220 
221 #define NDB FWMAXQUEUE
222 
223 #define	OHCI_VERSION		0x000
224 #define	OHCI_ATRETRY		0x008
225 #define	OHCI_CROMHDR		0x018
226 #define	OHCI_BUS_OPT		0x020
227 #define	OHCI_BUSIRMC		(1 << 31)
228 #define	OHCI_BUSCMC		(1 << 30)
229 #define	OHCI_BUSISC		(1 << 29)
230 #define	OHCI_BUSBMC		(1 << 28)
231 #define	OHCI_BUSPMC		(1 << 27)
232 #define OHCI_BUSFNC \
233 	(OHCI_BUSIRMC | OHCI_BUSCMC | OHCI_BUSISC | OHCI_BUSBMC | OHCI_BUSPMC)
234 
235 #define	OHCI_EUID_HI		0x024
236 #define	OHCI_EUID_LO		0x028
237 
238 #define	OHCI_CROMPTR		0x034
239 #define	OHCI_HCCCTL		0x050
240 #define	OHCI_HCCCTLCLR		0x054
241 #define	OHCI_AREQHI		0x100
242 #define	OHCI_AREQHICLR		0x104
243 #define	OHCI_AREQLO		0x108
244 #define	OHCI_AREQLOCLR		0x10c
245 #define	OHCI_PREQHI		0x110
246 #define	OHCI_PREQHICLR		0x114
247 #define	OHCI_PREQLO		0x118
248 #define	OHCI_PREQLOCLR		0x11c
249 #define	OHCI_PREQUPPER		0x120
250 
251 #define	OHCI_SID_BUF		0x064
252 #define	OHCI_SID_CNT		0x068
253 #define OHCI_SID_ERR		(1 << 31)
254 #define OHCI_SID_CNT_MASK	0xffc
255 
256 #define	OHCI_IT_STAT		0x090
257 #define	OHCI_IT_STATCLR		0x094
258 #define	OHCI_IT_MASK		0x098
259 #define	OHCI_IT_MASKCLR		0x09c
260 
261 #define	OHCI_IR_STAT		0x0a0
262 #define	OHCI_IR_STATCLR		0x0a4
263 #define	OHCI_IR_MASK		0x0a8
264 #define	OHCI_IR_MASKCLR		0x0ac
265 
266 #define	OHCI_LNKCTL		0x0e0
267 #define	OHCI_LNKCTLCLR		0x0e4
268 
269 #define	OHCI_PHYACCESS		0x0ec
270 #define	OHCI_CYCLETIMER		0x0f0
271 
272 #define	OHCI_DMACTL(off)	(off)
273 #define	OHCI_DMACTLCLR(off)	(off + 0x04)
274 #define	OHCI_DMACMD(off)	(off + 0x0c)
275 #define	OHCI_DMAMATCH(off)	(off + 0x10)
276 
277 #define OHCI_ATQOFF		0x180
278 #define OHCI_ATQCTL		OHCI_ATQOFF
279 #define OHCI_ATQCTLCLR		(OHCI_ATQOFF + 0x04)
280 #define OHCI_ATQCMD		(OHCI_ATQOFF + 0x0c)
281 #define OHCI_ATQMATCH		(OHCI_ATQOFF + 0x10)
282 
283 #define OHCI_ATSOFF		0x1a0
284 #define OHCI_ATSCTL		OHCI_ATSOFF
285 #define OHCI_ATSCTLCLR		(OHCI_ATSOFF + 0x04)
286 #define OHCI_ATSCMD		(OHCI_ATSOFF + 0x0c)
287 #define OHCI_ATSMATCH		(OHCI_ATSOFF + 0x10)
288 
289 #define OHCI_ARQOFF		0x1c0
290 #define OHCI_ARQCTL		OHCI_ARQOFF
291 #define OHCI_ARQCTLCLR		(OHCI_ARQOFF + 0x04)
292 #define OHCI_ARQCMD		(OHCI_ARQOFF + 0x0c)
293 #define OHCI_ARQMATCH		(OHCI_ARQOFF + 0x10)
294 
295 #define OHCI_ARSOFF		0x1e0
296 #define OHCI_ARSCTL		OHCI_ARSOFF
297 #define OHCI_ARSCTLCLR		(OHCI_ARSOFF + 0x04)
298 #define OHCI_ARSCMD		(OHCI_ARSOFF + 0x0c)
299 #define OHCI_ARSMATCH		(OHCI_ARSOFF + 0x10)
300 
301 #define OHCI_ITOFF(CH)		(0x200 + 0x10 * (CH))
302 #define OHCI_ITCTL(CH)		(OHCI_ITOFF(CH))
303 #define OHCI_ITCTLCLR(CH)	(OHCI_ITOFF(CH) + 0x04)
304 #define OHCI_ITCMD(CH)		(OHCI_ITOFF(CH) + 0x0c)
305 
306 #define OHCI_IROFF(CH)		(0x400 + 0x20 * (CH))
307 #define OHCI_IRCTL(CH)		(OHCI_IROFF(CH))
308 #define OHCI_IRCTLCLR(CH)	(OHCI_IROFF(CH) + 0x04)
309 #define OHCI_IRCMD(CH)		(OHCI_IROFF(CH) + 0x0c)
310 #define OHCI_IRMATCH(CH)	(OHCI_IROFF(CH) + 0x10)
311 
312 #define ATRQ_CH	 0
313 #define ATRS_CH	 1
314 #define ARRQ_CH	 2
315 #define ARRS_CH	 3
316 #define ITX_CH	 4
317 #define IRX_CH	36
318 
319 
320 /*
321  * Call fwohci_init before fwohci_attach to initialize the kernel's
322  * data structures well enough that fwohci_detach won't crash, even if
323  * fwohci_attach fails.
324  */
325 
326 void
327 fwohci_init(struct fwohci_softc *sc)
328 {
329 	sc->fc.arq = &sc->arrq.xferq;
330 	sc->fc.ars = &sc->arrs.xferq;
331 	sc->fc.atq = &sc->atrq.xferq;
332 	sc->fc.ats = &sc->atrs.xferq;
333 
334 	sc->arrq.xferq.psize = roundup2(FWPMAX_S400, PAGE_SIZE);
335 	sc->arrs.xferq.psize = roundup2(FWPMAX_S400, PAGE_SIZE);
336 	sc->atrq.xferq.psize = roundup2(FWPMAX_S400, PAGE_SIZE);
337 	sc->atrs.xferq.psize = roundup2(FWPMAX_S400, PAGE_SIZE);
338 
339 	sc->arrq.xferq.start = NULL;
340 	sc->arrs.xferq.start = NULL;
341 	sc->atrq.xferq.start = fwohci_start_atq;
342 	sc->atrs.xferq.start = fwohci_start_ats;
343 
344 	sc->arrq.xferq.buf = NULL;
345 	sc->arrs.xferq.buf = NULL;
346 	sc->atrq.xferq.buf = NULL;
347 	sc->atrs.xferq.buf = NULL;
348 
349 	sc->arrq.xferq.dmach = -1;
350 	sc->arrs.xferq.dmach = -1;
351 	sc->atrq.xferq.dmach = -1;
352 	sc->atrs.xferq.dmach = -1;
353 
354 	sc->arrq.ndesc = 1;
355 	sc->arrs.ndesc = 1;
356 	sc->atrq.ndesc = 8;	/* equal to maximum of mbuf chains */
357 	sc->atrs.ndesc = 2;
358 
359 	sc->arrq.ndb = NDB;
360 	sc->arrs.ndb = NDB / 2;
361 	sc->atrq.ndb = NDB;
362 	sc->atrs.ndb = NDB / 2;
363 
364 	sc->arrq.off = OHCI_ARQOFF;
365 	sc->arrs.off = OHCI_ARSOFF;
366 	sc->atrq.off = OHCI_ATQOFF;
367 	sc->atrs.off = OHCI_ATSOFF;
368 
369 	sc->fc.tcode = tinfo;
370 
371 	sc->fc.cyctimer = fwohci_cyctimer;
372 	sc->fc.ibr = fwohci_ibr;
373 	sc->fc.set_bmr = fwohci_set_bus_manager;
374 	sc->fc.ioctl = fwohci_ioctl;
375 	sc->fc.irx_enable = fwohci_irx_enable;
376 	sc->fc.irx_disable = fwohci_irx_disable;
377 
378 	sc->fc.itx_enable = fwohci_itxbuf_enable;
379 	sc->fc.itx_disable = fwohci_itx_disable;
380 	sc->fc.timeout = fwohci_timeout;
381 	sc->fc.set_intr = fwohci_set_intr;
382 #if BYTE_ORDER == BIG_ENDIAN
383 	sc->fc.irx_post = fwohci_irx_post;
384 #else
385 	sc->fc.irx_post = NULL;
386 #endif
387 	sc->fc.itx_post = NULL;
388 
389 	sc->intmask = sc->irstat = sc->itstat = 0;
390 
391 	fw_init(&sc->fc);
392 }
393 
394 /*
395  * Call fwohci_attach after fwohci_init to initialize the hardware and
396  * attach children.
397  */
398 
399 int
400 fwohci_attach(struct fwohci_softc *sc)
401 {
402 	uint32_t reg;
403 	uint8_t ui[8];
404 	int i, mver;
405 
406 /* OHCI version */
407 	reg = OREAD(sc, OHCI_VERSION);
408 	mver = (reg >> 16) & 0xff;
409 	aprint_normal_dev(sc->fc.dev, "OHCI version %x.%x (ROM=%d)\n",
410 	    mver, reg & 0xff, (reg >> 24) & 1);
411 	if (mver < 1 || mver > 9) {
412 		aprint_error_dev(sc->fc.dev, "invalid OHCI version\n");
413 		return ENXIO;
414 	}
415 
416 /* Available Isochronous DMA channel probe */
417 	OWRITE(sc, OHCI_IT_MASK, 0xffffffff);
418 	OWRITE(sc, OHCI_IR_MASK, 0xffffffff);
419 	reg = OREAD(sc, OHCI_IT_MASK) & OREAD(sc, OHCI_IR_MASK);
420 	OWRITE(sc, OHCI_IT_MASKCLR, 0xffffffff);
421 	OWRITE(sc, OHCI_IR_MASKCLR, 0xffffffff);
422 	for (i = 0; i < 0x20; i++)
423 		if ((reg & (1 << i)) == 0)
424 			break;
425 	sc->fc.nisodma = i;
426 	aprint_normal_dev(sc->fc.dev, "No. of Isochronous channels is %d.\n",
427 	    i);
428 	if (i == 0)
429 		return ENXIO;
430 
431 	for (i = 0; i < sc->fc.nisodma; i++) {
432 		sc->fc.it[i] = &sc->it[i].xferq;
433 		sc->fc.ir[i] = &sc->ir[i].xferq;
434 		sc->it[i].xferq.dmach = i;
435 		sc->ir[i].xferq.dmach = i;
436 		sc->it[i].ndb = 0;
437 		sc->ir[i].ndb = 0;
438 		sc->it[i].off = OHCI_ITOFF(i);
439 		sc->ir[i].off = OHCI_IROFF(i);
440 	}
441 
442 	sc->fc.config_rom = fwdma_alloc_setup(sc->fc.dev, sc->fc.dmat,
443 	    CROMSIZE, &sc->crom_dma, CROMSIZE, BUS_DMA_NOWAIT);
444 	if (sc->fc.config_rom == NULL) {
445 		aprint_error_dev(sc->fc.dev, "config_rom alloc failed.\n");
446 		return ENOMEM;
447 	}
448 
449 #if 0
450 	memset(sc->fc.config_rom, 0, CROMSIZE);
451 	sc->fc.config_rom[1] = 0x31333934;
452 	sc->fc.config_rom[2] = 0xf000a002;
453 	sc->fc.config_rom[3] = OREAD(sc, OHCI_EUID_HI);
454 	sc->fc.config_rom[4] = OREAD(sc, OHCI_EUID_LO);
455 	sc->fc.config_rom[5] = 0;
456 	sc->fc.config_rom[0] = (4 << 24) | (5 << 16);
457 
458 	sc->fc.config_rom[0] |= fw_crc16(&sc->fc.config_rom[1], 5*4);
459 #endif
460 
461 /* SID recieve buffer must align 2^11 */
462 #define	OHCI_SIDSIZE	(1 << 11)
463 	sc->sid_buf = fwdma_alloc_setup(sc->fc.dev, sc->fc.dmat, OHCI_SIDSIZE,
464 	    &sc->sid_dma, OHCI_SIDSIZE, BUS_DMA_NOWAIT);
465 	if (sc->sid_buf == NULL) {
466 		aprint_error_dev(sc->fc.dev, "sid_buf alloc failed.");
467 		return ENOMEM;
468 	}
469 
470 	fwdma_alloc_setup(sc->fc.dev, sc->fc.dmat, sizeof(uint32_t),
471 	    &sc->dummy_dma, sizeof(uint32_t), BUS_DMA_NOWAIT);
472 	if (sc->dummy_dma.v_addr == NULL) {
473 		aprint_error_dev(sc->fc.dev, "dummy_dma alloc failed.");
474 		return ENOMEM;
475 	}
476 
477 	fwohci_db_init(sc, &sc->arrq);
478 	if ((sc->arrq.flags & FWOHCI_DBCH_INIT) == 0)
479 		return ENOMEM;
480 
481 	fwohci_db_init(sc, &sc->arrs);
482 	if ((sc->arrs.flags & FWOHCI_DBCH_INIT) == 0)
483 		return ENOMEM;
484 
485 	fwohci_db_init(sc, &sc->atrq);
486 	if ((sc->atrq.flags & FWOHCI_DBCH_INIT) == 0)
487 		return ENOMEM;
488 
489 	fwohci_db_init(sc, &sc->atrs);
490 	if ((sc->atrs.flags & FWOHCI_DBCH_INIT) == 0)
491 		return ENOMEM;
492 
493 	sc->fc.eui.hi = OREAD(sc, FWOHCIGUID_H);
494 	sc->fc.eui.lo = OREAD(sc, FWOHCIGUID_L);
495 	for (i = 0; i < 8; i++)
496 		ui[i] = FW_EUI64_BYTE(&sc->fc.eui, i);
497 	aprint_normal_dev(sc->fc.dev,
498 	    "EUI64 %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
499 	    ui[0], ui[1], ui[2], ui[3], ui[4], ui[5], ui[6], ui[7]);
500 
501 	fwohci_reset(sc);
502 
503 	sc->fc.bdev =
504 	    config_found(sc->fc.dev, __UNCONST("ieee1394if"), fwohci_print);
505 
506 	return 0;
507 }
508 
509 int
510 fwohci_detach(struct fwohci_softc *sc, int flags)
511 {
512 	int i, rv;
513 
514 	if (sc->fc.bdev != NULL) {
515 		rv = config_detach(sc->fc.bdev, flags);
516 		if (rv)
517 			return rv;
518 	}
519 	if (sc->sid_buf != NULL)
520 		fwdma_free(sc->sid_dma.dma_tag, sc->sid_dma.dma_map,
521 		    sc->sid_dma.v_addr);
522 	if (sc->fc.config_rom != NULL)
523 		fwdma_free(sc->crom_dma.dma_tag, sc->crom_dma.dma_map,
524 		    sc->crom_dma.v_addr);
525 
526 	fwohci_db_free(sc, &sc->arrq);
527 	fwohci_db_free(sc, &sc->arrs);
528 	fwohci_db_free(sc, &sc->atrq);
529 	fwohci_db_free(sc, &sc->atrs);
530 	for (i = 0; i < sc->fc.nisodma; i++) {
531 		fwohci_db_free(sc, &sc->it[i]);
532 		fwohci_db_free(sc, &sc->ir[i]);
533 	}
534 
535 	fw_destroy(&sc->fc);
536 
537 	return 0;
538 }
539 
540 int
541 fwohci_intr(void *arg)
542 {
543 	struct fwohci_softc *sc = (struct fwohci_softc *)arg;
544 	uint32_t stat, irstat, itstat;
545 
546 	if (!device_is_active(sc->fc.dev))
547 		return 0;
548 
549 	if (!(sc->intmask & OHCI_INT_EN))
550 		/* polling mode? */
551 		return 0;
552 
553 	stat = OREAD(sc, FWOHCI_INTSTAT);
554 	if (stat == 0xffffffff) {
555 		aprint_error_dev(sc->fc.dev, "device physically ejected?\n");
556 		return 0;
557 	}
558 	if (stat)
559 		OWRITE(sc, FWOHCI_INTSTATCLR, stat & ~OHCI_INT_PHY_BUS_R);
560 
561 	stat &= sc->intmask;
562 	if (stat == 0)
563 		return 0;
564 
565 	atomic_swap_32(&sc->intstat, stat);
566 	if (stat & OHCI_INT_DMA_IR) {
567 		irstat = OREAD(sc, OHCI_IR_STAT);
568 		OWRITE(sc, OHCI_IR_STATCLR, irstat);
569 		atomic_swap_32(&sc->irstat, irstat);
570 	}
571 	if (stat & OHCI_INT_DMA_IT) {
572 		itstat = OREAD(sc, OHCI_IT_STAT);
573 		OWRITE(sc, OHCI_IT_STATCLR, itstat);
574 		atomic_swap_32(&sc->itstat, itstat);
575 	}
576 
577 	fwohci_intr_core(sc, stat);
578 	return 1;
579 }
580 
581 int
582 fwohci_resume(struct fwohci_softc *sc)
583 {
584 	struct fw_xferq *ir;
585 	struct fw_bulkxfer *chunk;
586 	int i;
587 	extern int firewire_resume(struct firewire_comm *);
588 
589 	fwohci_reset(sc);
590 	/* XXX resume isochronous receive automatically. (how about TX?) */
591 	for (i = 0; i < sc->fc.nisodma; i++) {
592 		ir = &sc->ir[i].xferq;
593 		if ((ir->flag & FWXFERQ_RUNNING) != 0) {
594 			aprint_normal_dev(sc->fc.dev,
595 			    "resume iso receive ch: %d\n", i);
596 			ir->flag &= ~FWXFERQ_RUNNING;
597 			/* requeue stdma to stfree */
598 			while ((chunk = STAILQ_FIRST(&ir->stdma)) != NULL) {
599 				STAILQ_REMOVE_HEAD(&ir->stdma, link);
600 				STAILQ_INSERT_TAIL(&ir->stfree, chunk, link);
601 			}
602 			sc->fc.irx_enable(&sc->fc, i);
603 		}
604 	}
605 
606 	firewire_resume(&sc->fc);
607 	sc->fc.ibr(&sc->fc);
608 	return 0;
609 }
610 
611 int
612 fwohci_stop(struct fwohci_softc *sc)
613 {
614 	u_int i;
615 
616 	fwohci_set_intr(&sc->fc, 0);
617 
618 /* Now stopping all DMA channel */
619 	OWRITE(sc, OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN);
620 	OWRITE(sc, OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN);
621 	OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN);
622 	OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
623 
624 	for (i = 0; i < sc->fc.nisodma; i++) {
625 		OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN);
626 		OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN);
627 	}
628 
629 #if 0 /* Let dcons(4) be accessed */
630 /* Stop interrupt */
631 	OWRITE(sc, FWOHCI_INTMASKCLR,
632 	    OHCI_INT_EN |
633 	    OHCI_INT_ERR |
634 	    OHCI_INT_PHY_SID |
635 	    OHCI_INT_PHY_INT |
636 	    OHCI_INT_DMA_ATRQ |
637 	    OHCI_INT_DMA_ATRS |
638 	    OHCI_INT_DMA_PRRQ |
639 	    OHCI_INT_DMA_PRRS |
640 	    OHCI_INT_DMA_ARRQ |
641 	    OHCI_INT_DMA_ARRS |
642 	    OHCI_INT_PHY_BUS_R);
643 
644 /* FLUSH FIFO and reset Transmitter/Reciever */
645 	OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_RESET);
646 #endif
647 
648 /* XXX Link down?  Bus reset? */
649 	return 0;
650 }
651 
652 
653 static int
654 fwohci_ioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *td)
655 {
656 	struct fwohci_softc *sc;
657 	struct fw_reg_req_t *reg = (struct fw_reg_req_t *)data;
658 	uint32_t *dmach = (uint32_t *)data;
659 	int err = 0;
660 
661 	sc = device_lookup_private(&fwohci_cd, DEV2UNIT(dev));
662 	if (sc == NULL)
663 		return ENXIO;
664 
665 	if (!data)
666 		return EINVAL;
667 
668 	switch (cmd) {
669 	case FWOHCI_WRREG:
670 #define OHCI_MAX_REG 0x800
671 		if (reg->addr <= OHCI_MAX_REG) {
672 			OWRITE(sc, reg->addr, reg->data);
673 			reg->data = OREAD(sc, reg->addr);
674 		} else
675 			err = EINVAL;
676 		break;
677 
678 	case FWOHCI_RDREG:
679 		if (reg->addr <= OHCI_MAX_REG)
680 			reg->data = OREAD(sc, reg->addr);
681 		else
682 			err = EINVAL;
683 		break;
684 
685 /* Read DMA descriptors for debug  */
686 	case DUMPDMA:
687 		if (*dmach <= OHCI_MAX_DMA_CH) {
688 			dump_dma(sc, *dmach);
689 			dump_db(sc, *dmach);
690 		} else
691 			err = EINVAL;
692 		break;
693 
694 /* Read/Write Phy registers */
695 #define OHCI_MAX_PHY_REG 0xf
696 	case FWOHCI_RDPHYREG:
697 		if (reg->addr <= OHCI_MAX_PHY_REG)
698 			reg->data = fwphy_rddata(sc, reg->addr);
699 		else
700 			err = EINVAL;
701 		break;
702 
703 	case FWOHCI_WRPHYREG:
704 		if (reg->addr <= OHCI_MAX_PHY_REG)
705 			reg->data = fwphy_wrdata(sc, reg->addr, reg->data);
706 		else
707 			err = EINVAL;
708 		break;
709 
710 	default:
711 		err = EINVAL;
712 		break;
713 	}
714 	return err;
715 }
716 
717 int
718 fwohci_print(void *aux, const char *pnp)
719 {
720 	struct fw_attach_args *fwa = (struct fw_attach_args *)aux;
721 
722 	if (pnp)
723 		aprint_normal("%s at %s", fwa->name, pnp);
724 
725 	return UNCONF;
726 }
727 
728 
729 static uint32_t
730 fwohci_cyctimer(struct firewire_comm *fc)
731 {
732 	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
733 
734 	return OREAD(sc, OHCI_CYCLETIMER);
735 }
736 
737 static uint32_t
738 fwohci_set_bus_manager(struct firewire_comm *fc, u_int node)
739 {
740 	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
741 	uint32_t bm;
742 	int i;
743 
744 #define OHCI_CSR_DATA	0x0c
745 #define OHCI_CSR_COMP	0x10
746 #define OHCI_CSR_CONT	0x14
747 #define OHCI_BUS_MANAGER_ID	0
748 
749 	OWRITE(sc, OHCI_CSR_DATA, node);
750 	OWRITE(sc, OHCI_CSR_COMP, 0x3f);
751 	OWRITE(sc, OHCI_CSR_CONT, OHCI_BUS_MANAGER_ID);
752  	for (i = 0; !(OREAD(sc, OHCI_CSR_CONT) & (1<<31)) && (i < 1000); i++)
753 		DELAY(10);
754 	bm = OREAD(sc, OHCI_CSR_DATA);
755 	if ((bm & 0x3f) == 0x3f)
756 		bm = node;
757 	if (firewire_debug)
758 		printf("fw_set_bus_manager: %d->%d (loop=%d)\n", bm, node, i);
759 
760 	return bm;
761 }
762 
763 static void
764 fwohci_ibr(struct firewire_comm *fc)
765 {
766 	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
767 	uint32_t fun;
768 
769 	aprint_normal_dev(fc->dev, "Initiate bus reset\n");
770 
771 	/*
772 	 * Make sure our cached values from the config rom are
773 	 * initialised.
774 	 */
775 	OWRITE(sc, OHCI_CROMHDR, ntohl(sc->fc.config_rom[0]));
776 	OWRITE(sc, OHCI_BUS_OPT, ntohl(sc->fc.config_rom[2]));
777 
778 	/*
779 	 * Set root hold-off bit so that non cyclemaster capable node
780 	 * shouldn't became the root node.
781 	 */
782 #if 1
783 	fun = fwphy_rddata(sc, FW_PHY_IBR_REG);
784 	fun |= FW_PHY_IBR | FW_PHY_RHB;
785 	fun = fwphy_wrdata(sc, FW_PHY_IBR_REG, fun);
786 #else	/* Short bus reset */
787 	fun = fwphy_rddata(sc, FW_PHY_ISBR_REG);
788 	fun |= FW_PHY_ISBR | FW_PHY_RHB;
789 	fun = fwphy_wrdata(sc, FW_PHY_ISBR_REG, fun);
790 #endif
791 }
792 
793 static int
794 fwohci_irx_enable(struct firewire_comm *fc, int dmach)
795 {
796 	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
797 	struct fwohci_dbch *dbch;
798 	struct fwohcidb_tr *db_tr;
799 	struct fw_bulkxfer *first, *prev, *chunk, *txfer;
800 	struct fw_xferq *ir;
801 	uint32_t stat;
802 	unsigned short tag, ich;
803 	int err = 0, ldesc;
804 
805 	dbch = &sc->ir[dmach];
806 	ir = &dbch->xferq;
807 
808 	if ((ir->flag & FWXFERQ_RUNNING) == 0) {
809 		tag = (ir->flag >> 6) & 3;
810 		ich = ir->flag & 0x3f;
811 		OWRITE(sc, OHCI_IRMATCH(dmach), tagbit[tag] | ich);
812 
813 		ir->queued = 0;
814 		dbch->ndb = ir->bnpacket * ir->bnchunk;
815 		dbch->ndesc = 2;
816 		fwohci_db_init(sc, dbch);
817 		if ((dbch->flags & FWOHCI_DBCH_INIT) == 0)
818 			return ENOMEM;
819 		err = fwohci_rx_enable(sc, dbch);
820 		if (err)
821 			return err;
822 	}
823 
824 	first = STAILQ_FIRST(&ir->stfree);
825 	if (first == NULL) {
826 		aprint_error_dev(fc->dev, "IR DMA no free chunk\n");
827 		return 0;
828 	}
829 
830 	ldesc = dbch->ndesc - 1;
831 	prev = NULL;
832 	STAILQ_FOREACH(txfer, &ir->stdma, link)
833 		prev = txfer;
834 	while ((chunk = STAILQ_FIRST(&ir->stfree)) != NULL) {
835 		struct fwohcidb *db;
836 
837 		if (chunk->mbuf != NULL) {
838 			db_tr = (struct fwohcidb_tr *)(chunk->start);
839 			db_tr->dbcnt = 1;
840 			err = bus_dmamap_load_mbuf(fc->dmat, db_tr->dma_map,
841 			    chunk->mbuf, BUS_DMA_NOWAIT);
842 			if (err == 0)
843 				fwohci_execute_db(db_tr, db_tr->dma_map);
844 			else
845 				aprint_error_dev(fc->dev,
846 				    "mbuf load failed: %d\n", err);
847  			FWOHCI_DMA_SET(db_tr->db[1].db.desc.cmd,
848 			    OHCI_UPDATE |
849 			    OHCI_INPUT_LAST |
850 			    OHCI_INTERRUPT_ALWAYS |
851 			    OHCI_BRANCH_ALWAYS);
852 		}
853 		db = ((struct fwohcidb_tr *)(chunk->end))->db;
854 		FWOHCI_DMA_WRITE(db[ldesc].db.desc.res, 0);
855 		FWOHCI_DMA_CLEAR(db[ldesc].db.desc.depend, 0xf);
856 		if (prev != NULL) {
857 			db = ((struct fwohcidb_tr *)(prev->end))->db;
858 			FWOHCI_DMA_SET(db[ldesc].db.desc.depend, dbch->ndesc);
859 		}
860 		STAILQ_REMOVE_HEAD(&ir->stfree, link);
861 		STAILQ_INSERT_TAIL(&ir->stdma, chunk, link);
862 		prev = chunk;
863 	}
864 	fwdma_sync_multiseg_all(dbch->am,
865 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
866 	stat = OREAD(sc, OHCI_IRCTL(dmach));
867 	if (stat & OHCI_CNTL_DMA_ACTIVE)
868 		return 0;
869 	if (stat & OHCI_CNTL_DMA_RUN) {
870 		OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
871 		aprint_error_dev(fc->dev, "IR DMA overrun (0x%08x)\n", stat);
872 	}
873 
874 	if (firewire_debug)
875 		printf("start IR DMA 0x%x\n", stat);
876 	OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach);
877 	OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach);
878 	OWRITE(sc, OHCI_IR_MASK, 1 << dmach);
879 	OWRITE(sc, OHCI_IRCTLCLR(dmach), 0xf0000000);
880 	OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_ISOHDR);
881 	OWRITE(sc, OHCI_IRCMD(dmach),
882 	    ((struct fwohcidb_tr *)(first->start))->bus_addr | dbch->ndesc);
883 	OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_DMA_RUN);
884 	OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IR);
885 #if 0
886 	dump_db(sc, IRX_CH + dmach);
887 #endif
888 	return err;
889 }
890 
891 static int
892 fwohci_irx_disable(struct firewire_comm *fc, int dmach)
893 {
894 	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
895 
896 	OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
897 	OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach);
898 	OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach);
899 	/* XXX we cannot free buffers until the DMA really stops */
900 	kpause("fwirxd", true, hz, NULL);
901 	fwohci_db_free(sc, &sc->ir[dmach]);
902 	sc->ir[dmach].xferq.flag &= ~FWXFERQ_RUNNING;
903 	return 0;
904 }
905 
906 
907 static int
908 fwohci_itxbuf_enable(struct firewire_comm *fc, int dmach)
909 {
910 	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
911 	struct fwohci_dbch *dbch;
912 	struct fw_bulkxfer *first, *chunk, *prev, *txfer;
913 	struct fw_xferq *it;
914 	uint32_t stat;
915 	int cycle_match, cycle_now, ldesc, err = 0;
916 
917 	dbch = &sc->it[dmach];
918 	it = &dbch->xferq;
919 
920 	if ((dbch->flags & FWOHCI_DBCH_INIT) == 0) {
921 		dbch->ndb = it->bnpacket * it->bnchunk;
922 		dbch->ndesc = 3;
923 		fwohci_db_init(sc, dbch);
924 		if ((dbch->flags & FWOHCI_DBCH_INIT) == 0)
925 			return ENOMEM;
926 
927 		err = fwohci_tx_enable(sc, dbch);
928 		if (err)
929 			return err;
930 	}
931 
932 	ldesc = dbch->ndesc - 1;
933 	prev = NULL;
934 	STAILQ_FOREACH(txfer, &it->stdma, link)
935 		prev = txfer;
936 	while ((chunk = STAILQ_FIRST(&it->stvalid)) != NULL) {
937 		struct fwohcidb *db;
938 
939 		fwdma_sync_multiseg(it->buf, chunk->poffset, it->bnpacket,
940 		    BUS_DMASYNC_PREWRITE);
941 		fwohci_txbufdb(sc, dmach, chunk);
942 		if (prev != NULL) {
943 			db = ((struct fwohcidb_tr *)(prev->end))->db;
944 #if 0 /* XXX necessary? */
945 			FWOHCI_DMA_SET(db[ldesc].db.desc.cmd,
946 			    OHCI_BRANCH_ALWAYS);
947 #endif
948 #if 0 /* if bulkxfer->npacket changes */
949 			db[ldesc].db.desc.depend = db[0].db.desc.depend =
950 			    ((struct fwohcidb_tr *)(chunk->start))->bus_addr |
951 								dbch->ndesc;
952 #else
953 			FWOHCI_DMA_SET(db[0].db.desc.depend, dbch->ndesc);
954 			FWOHCI_DMA_SET(db[ldesc].db.desc.depend, dbch->ndesc);
955 #endif
956 		}
957 		STAILQ_REMOVE_HEAD(&it->stvalid, link);
958 		STAILQ_INSERT_TAIL(&it->stdma, chunk, link);
959 		prev = chunk;
960 	}
961 	fwdma_sync_multiseg_all(dbch->am,
962 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
963 	stat = OREAD(sc, OHCI_ITCTL(dmach));
964 	if (firewire_debug && (stat & OHCI_CNTL_CYCMATCH_S))
965 		printf("stat 0x%x\n", stat);
966 
967 	if (stat & (OHCI_CNTL_DMA_ACTIVE | OHCI_CNTL_CYCMATCH_S))
968 		return 0;
969 
970 #if 0
971 	OWRITE(sc, OHCI_ITCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
972 #endif
973 	OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach);
974 	OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach);
975 	OWRITE(sc, OHCI_IT_MASK, 1 << dmach);
976 	OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IT);
977 
978 	first = STAILQ_FIRST(&it->stdma);
979 	OWRITE(sc, OHCI_ITCMD(dmach),
980 	    ((struct fwohcidb_tr *)(first->start))->bus_addr | dbch->ndesc);
981 	if (firewire_debug > 1) {
982 		printf("fwohci_itxbuf_enable: kick 0x%08x\n", stat);
983 #if 1
984 		dump_dma(sc, ITX_CH + dmach);
985 #endif
986 	}
987 	if ((stat & OHCI_CNTL_DMA_RUN) == 0) {
988 #if 1
989 		/* Don't start until all chunks are buffered */
990 		if (STAILQ_FIRST(&it->stfree) != NULL)
991 			goto out;
992 #endif
993 #if 1
994 		/* Clear cycle match counter bits */
995 		OWRITE(sc, OHCI_ITCTLCLR(dmach), 0xffff0000);
996 
997 		/* 2bit second + 13bit cycle */
998 		cycle_now = (fc->cyctimer(fc) >> 12) & 0x7fff;
999 		cycle_match = fwohci_next_cycle(sc, cycle_now);
1000 
1001 		OWRITE(sc, OHCI_ITCTL(dmach),
1002 		    OHCI_CNTL_CYCMATCH_S | (cycle_match << 16) |
1003 							OHCI_CNTL_DMA_RUN);
1004 #else
1005 		OWRITE(sc, OHCI_ITCTL(dmach), OHCI_CNTL_DMA_RUN);
1006 #endif
1007 		if (firewire_debug > 1) {
1008 			printf("cycle_match: 0x%04x->0x%04x\n",
1009 			    cycle_now, cycle_match);
1010 			dump_dma(sc, ITX_CH + dmach);
1011 			dump_db(sc, ITX_CH + dmach);
1012 		}
1013 	} else if ((stat & OHCI_CNTL_CYCMATCH_S) == 0) {
1014 		aprint_error_dev(fc->dev, "IT DMA underrun (0x%08x)\n", stat);
1015 		OWRITE(sc, OHCI_ITCTL(dmach), OHCI_CNTL_DMA_WAKE);
1016 	}
1017 out:
1018 	return err;
1019 }
1020 
1021 static int
1022 fwohci_itx_disable(struct firewire_comm *fc, int dmach)
1023 {
1024 	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1025 
1026 	OWRITE(sc, OHCI_ITCTLCLR(dmach),
1027 	    OHCI_CNTL_DMA_RUN | OHCI_CNTL_CYCMATCH_S);
1028 	OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach);
1029 	OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach);
1030 	/* XXX we cannot free buffers until the DMA really stops */
1031 	kpause("fwitxd", true, hz, NULL);
1032 	fwohci_db_free(sc, &sc->it[dmach]);
1033 	sc->it[dmach].xferq.flag &= ~FWXFERQ_RUNNING;
1034 	return 0;
1035 }
1036 
1037 static void
1038 fwohci_timeout(struct firewire_comm *fc)
1039 {
1040 #if 0
1041 	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1042 #endif
1043 	/* nothing? */
1044 }
1045 
1046 #if BYTE_ORDER == BIG_ENDIAN
1047 static void
1048 fwohci_irx_post (struct firewire_comm *fc, uint32_t *qld)
1049 {
1050 
1051 	qld[0] = FWOHCI_DMA_READ(qld[0]);
1052 	return;
1053 }
1054 #endif
1055 
1056 static void
1057 fwohci_set_intr(struct firewire_comm *fc, int enable)
1058 {
1059 	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1060 
1061 	if (firewire_debug)
1062 		printf("fwohci_set_intr: %d\n", enable);
1063 	if (enable) {
1064 		sc->intmask |= OHCI_INT_EN;
1065 		OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_EN);
1066 	} else {
1067 		sc->intmask &= ~OHCI_INT_EN;
1068 		OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_EN);
1069 	}
1070 }
1071 
1072 /*
1073  * Communication with PHY device
1074  */
1075 /* XXX need lock for phy access */
1076 static uint32_t
1077 fwphy_rddata(struct fwohci_softc *sc, u_int addr)
1078 {
1079 	uint32_t fun, stat;
1080 	u_int i, retry = 0;
1081 
1082 	addr &= 0xf;
1083 #define MAX_RETRY 100
1084 again:
1085 	OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_REG_FAIL);
1086 	fun = PHYDEV_RDCMD | (addr << PHYDEV_REGADDR);
1087 	OWRITE(sc, OHCI_PHYACCESS, fun);
1088 	for (i = 0; i < MAX_RETRY; i++) {
1089 		fun = OREAD(sc, OHCI_PHYACCESS);
1090 		if ((fun & PHYDEV_RDCMD) == 0 && (fun & PHYDEV_RDDONE) != 0)
1091 			break;
1092 		DELAY(100);
1093 	}
1094 	if (i >= MAX_RETRY) {
1095 		if (firewire_debug)
1096 			printf("phy read failed(1).\n");
1097 		if (++retry < MAX_RETRY) {
1098 			DELAY(100);
1099 			goto again;
1100 		}
1101 	}
1102 	/* Make sure that SCLK is started */
1103 	stat = OREAD(sc, FWOHCI_INTSTAT);
1104 	if ((stat & OHCI_INT_REG_FAIL) != 0 ||
1105 	    ((fun >> PHYDEV_REGADDR) & 0xf) != addr) {
1106 		if (firewire_debug)
1107 			printf("phy read failed(2).\n");
1108 		if (++retry < MAX_RETRY) {
1109 			DELAY(100);
1110 			goto again;
1111 		}
1112 	}
1113 	if (firewire_debug || retry >= MAX_RETRY)
1114 		aprint_error_dev(sc->fc.dev,
1115 		    "fwphy_rddata: 0x%x loop=%d, retry=%d\n",
1116 		    addr, i, retry);
1117 #undef MAX_RETRY
1118 	return (fun >> PHYDEV_RDDATA) & 0xff;
1119 }
1120 
1121 static uint32_t
1122 fwphy_wrdata(struct fwohci_softc *sc, uint32_t addr, uint32_t data)
1123 {
1124 	uint32_t fun;
1125 
1126 	addr &= 0xf;
1127 	data &= 0xff;
1128 
1129 	fun =
1130 	    (PHYDEV_WRCMD | (addr << PHYDEV_REGADDR) | (data << PHYDEV_WRDATA));
1131 	OWRITE(sc, OHCI_PHYACCESS, fun);
1132 	DELAY(100);
1133 
1134 	return fwphy_rddata(sc, addr);
1135 }
1136 
1137 static int
1138 fwohci_probe_phy(struct fwohci_softc *sc)
1139 {
1140 	uint32_t reg, reg2;
1141 	int e1394a = 1;
1142 
1143 /*
1144  * probe PHY parameters
1145  * 0. to prove PHY version, whether compliance of 1394a.
1146  * 1. to probe maximum speed supported by the PHY and
1147  *    number of port supported by core-logic.
1148  *    It is not actually available port on your PC .
1149  */
1150 	OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LPS);
1151 	DELAY(500);
1152 
1153 	reg = fwphy_rddata(sc, FW_PHY_SPD_REG);
1154 
1155 	if ((reg >> 5) != 7) {
1156 		sc->fc.mode &= ~FWPHYASYST;
1157 		sc->fc.nport = reg & FW_PHY_NP;
1158 		sc->fc.speed = reg & FW_PHY_SPD >> 6;
1159 		if (sc->fc.speed > MAX_SPEED) {
1160 			aprint_error_dev(sc->fc.dev,
1161 			    "invalid speed %d (fixed to %d).\n",
1162 			    sc->fc.speed, MAX_SPEED);
1163 			sc->fc.speed = MAX_SPEED;
1164 		}
1165 		aprint_normal_dev(sc->fc.dev, "Phy 1394 only %s, %d ports.\n",
1166 		    fw_linkspeed[sc->fc.speed], sc->fc.nport);
1167 	} else {
1168 		reg2 = fwphy_rddata(sc, FW_PHY_ESPD_REG);
1169 		sc->fc.mode |= FWPHYASYST;
1170 		sc->fc.nport = reg & FW_PHY_NP;
1171 		sc->fc.speed = (reg2 & FW_PHY_ESPD) >> 5;
1172 		if (sc->fc.speed > MAX_SPEED) {
1173 			aprint_error_dev(sc->fc.dev,
1174 			    "invalid speed %d (fixed to %d).\n",
1175 			    sc->fc.speed, MAX_SPEED);
1176 			sc->fc.speed = MAX_SPEED;
1177 		}
1178 		aprint_normal_dev(sc->fc.dev,
1179 		    "Phy 1394a available %s, %d ports.\n",
1180 		    fw_linkspeed[sc->fc.speed], sc->fc.nport);
1181 
1182 		/* check programPhyEnable */
1183 		reg2 = fwphy_rddata(sc, 5);
1184 #if 0
1185 		if (e1394a && (OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_PRPHY)) {
1186 #else	/* XXX force to enable 1394a */
1187 		if (e1394a) {
1188 #endif
1189 			if (firewire_debug)
1190 				printf("Enable 1394a Enhancements\n");
1191 			/* enable EAA EMC */
1192 			reg2 |= 0x03;
1193 			/* set aPhyEnhanceEnable */
1194 			OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_PHYEN);
1195 			OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_PRPHY);
1196 		}
1197 #if 0
1198 		else {
1199 			/* for safe */
1200 			reg2 &= ~0x83;
1201 		}
1202 #endif
1203 		reg2 = fwphy_wrdata(sc, 5, reg2);
1204 	}
1205 
1206 	reg = fwphy_rddata(sc, FW_PHY_SPD_REG);
1207 	if ((reg >> 5) == 7) {
1208 		reg = fwphy_rddata(sc, 4);
1209 		reg |= 1 << 6;
1210 		fwphy_wrdata(sc, 4, reg);
1211 		reg = fwphy_rddata(sc, 4);
1212 	}
1213 	return 0;
1214 }
1215 
1216 static void
1217 fwohci_reset(struct fwohci_softc *sc)
1218 {
1219 	struct fwohcidb_tr *db_tr;
1220 	uint32_t reg, reg2;
1221 	int i, max_rec, speed;
1222 
1223 	/* Disable interrupts */
1224 	OWRITE(sc, FWOHCI_INTMASKCLR, ~0);
1225 
1226 	/* Now stopping all DMA channels */
1227 	OWRITE(sc, OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN);
1228 	OWRITE(sc, OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN);
1229 	OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN);
1230 	OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
1231 
1232 	OWRITE(sc, OHCI_IR_MASKCLR, ~0);
1233 	for (i = 0; i < sc->fc.nisodma; i++) {
1234 		OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN);
1235 		OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN);
1236 	}
1237 
1238 	/* FLUSH FIFO and reset Transmitter/Reciever */
1239 	OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_RESET);
1240 	if (firewire_debug)
1241 		printf("resetting OHCI...");
1242 	i = 0;
1243 	while (OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_RESET) {
1244 		if (i++ > 100)
1245 			break;
1246 		DELAY(1000);
1247 	}
1248 	if (firewire_debug)
1249 		printf("done (loop=%d)\n", i);
1250 
1251 	/* Probe phy */
1252 	fwohci_probe_phy(sc);
1253 
1254 	/* Probe link */
1255 	reg = OREAD(sc, OHCI_BUS_OPT);
1256 	reg2 = reg | OHCI_BUSFNC;
1257 	max_rec = (reg & 0x0000f000) >> 12;
1258 	speed = (reg & 0x00000007);
1259 	aprint_normal_dev(sc->fc.dev, "Link %s, max_rec %d bytes.\n",
1260 	    fw_linkspeed[speed], MAXREC(max_rec));
1261 	/* XXX fix max_rec */
1262 	sc->fc.maxrec = sc->fc.speed + 8;
1263 	if (max_rec != sc->fc.maxrec) {
1264 		reg2 = (reg2 & 0xffff0fff) | (sc->fc.maxrec << 12);
1265 		aprint_normal_dev(sc->fc.dev, "max_rec %d -> %d\n",
1266 		    MAXREC(max_rec), MAXREC(sc->fc.maxrec));
1267 	}
1268 	if (firewire_debug)
1269 		printf("BUS_OPT 0x%x -> 0x%x\n", reg, reg2);
1270 	OWRITE(sc, OHCI_BUS_OPT, reg2);
1271 
1272 	/* Initialize registers */
1273 	OWRITE(sc, OHCI_CROMHDR, sc->fc.config_rom[0]);
1274 	OWRITE(sc, OHCI_CROMPTR, sc->crom_dma.bus_addr);
1275 	OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_BIGEND);
1276 	OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_POSTWR);
1277 	OWRITE(sc, OHCI_SID_BUF, sc->sid_dma.bus_addr);
1278 	OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_SID);
1279 
1280 	/* Enable link */
1281 	OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LINKEN);
1282 
1283 	/* Force to start async RX DMA */
1284 	sc->arrq.xferq.flag &= ~FWXFERQ_RUNNING;
1285 	sc->arrs.xferq.flag &= ~FWXFERQ_RUNNING;
1286 	fwohci_rx_enable(sc, &sc->arrq);
1287 	fwohci_rx_enable(sc, &sc->arrs);
1288 
1289 	/* Initialize async TX */
1290 	OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD);
1291 	OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD);
1292 
1293 	/* AT Retries */
1294 	OWRITE(sc, FWOHCI_RETRY,
1295 	    /* CycleLimit   PhyRespRetries ATRespRetries ATReqRetries */
1296 	    (0xffff << 16) | (0x0f << 8) | (0x0f << 4) | 0x0f);
1297 
1298 	sc->atrq.top = STAILQ_FIRST(&sc->atrq.db_trq);
1299 	sc->atrs.top = STAILQ_FIRST(&sc->atrs.db_trq);
1300 	sc->atrq.bottom = sc->atrq.top;
1301 	sc->atrs.bottom = sc->atrs.top;
1302 
1303 	for (i = 0, db_tr = sc->atrq.top; i < sc->atrq.ndb;
1304 	    i++, db_tr = STAILQ_NEXT(db_tr, link))
1305 		db_tr->xfer = NULL;
1306 	for (i = 0, db_tr = sc->atrs.top; i < sc->atrs.ndb;
1307 	    i++, db_tr = STAILQ_NEXT(db_tr, link))
1308 		db_tr->xfer = NULL;
1309 
1310 
1311 	/* Enable interrupts */
1312 	sc->intmask =  (OHCI_INT_ERR | OHCI_INT_PHY_SID
1313 			| OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS
1314 			| OHCI_INT_DMA_PRRQ | OHCI_INT_DMA_PRRS
1315 			| OHCI_INT_PHY_BUS_R | OHCI_INT_PW_ERR);
1316 	sc->intmask |= OHCI_INT_DMA_IR | OHCI_INT_DMA_IT;
1317 	sc->intmask |= OHCI_INT_CYC_LOST | OHCI_INT_PHY_INT;
1318 	OWRITE(sc, FWOHCI_INTMASK, sc->intmask);
1319 	fwohci_set_intr(&sc->fc, 1);
1320 }
1321 
1322 #define LAST_DB(dbtr) \
1323 	&dbtr->db[(dbtr->dbcnt > 2) ? (dbtr->dbcnt - 1) : 0];
1324 
1325 static void
1326 fwohci_execute_db(struct fwohcidb_tr *db_tr, bus_dmamap_t dmamap)
1327 {
1328 	struct fwohcidb *db;
1329 	bus_dma_segment_t *s;
1330 	int i;
1331 
1332 	db = &db_tr->db[db_tr->dbcnt];
1333 	for (i = 0; i < dmamap->dm_nsegs; i++) {
1334 		s = &dmamap->dm_segs[i];
1335 		FWOHCI_DMA_WRITE(db->db.desc.addr, s->ds_addr);
1336 		FWOHCI_DMA_WRITE(db->db.desc.cmd, s->ds_len);
1337  		FWOHCI_DMA_WRITE(db->db.desc.res, 0);
1338 		db++;
1339 		db_tr->dbcnt++;
1340 	}
1341 }
1342 
1343 static void
1344 fwohci_start(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1345 {
1346 	struct fw_xfer *xfer;
1347 	struct fw_pkt *fp;
1348 	struct fwohci_txpkthdr *ohcifp;
1349 	struct fwohcidb_tr *db_tr, *kick;
1350 	struct fwohcidb *db;
1351 	uint32_t *ld;
1352 	int tcode, hdr_len, pl_off, fsegment = -1, i;
1353 	const struct tcode_info *info;
1354 	static int maxdesc = 0;
1355 
1356 	KASSERT(mutex_owned(&dbch->xferq.q_mtx));
1357 
1358 #if DIAGNOSTIC
1359 	if (dbch->off != OHCI_ATQOFF &&
1360 	    dbch->off != OHCI_ATSOFF)
1361 		panic("not async tx");
1362 #endif
1363 
1364 	if (dbch->flags & FWOHCI_DBCH_FULL)
1365 		return;
1366 
1367 	db_tr = dbch->top;
1368 	kick = db_tr;
1369 	if (dbch->pdb_tr != NULL) {
1370 		kick = dbch->pdb_tr;
1371 		fwdma_sync_multiseg(dbch->am, kick->idx, kick->idx,
1372 		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1373 	}
1374 txloop:
1375 	xfer = STAILQ_FIRST(&dbch->xferq.q);
1376 	if (xfer == NULL)
1377 		goto kick;
1378 #if 0
1379 	if (dbch->xferq.queued == 0)
1380 		aprint_error_dev(sc->fc.dev, "TX queue empty\n");
1381 #endif
1382 	STAILQ_REMOVE_HEAD(&dbch->xferq.q, link);
1383 	db_tr->xfer = xfer;
1384 	xfer->flag = FWXF_START;
1385 
1386 	fp = &xfer->send.hdr;
1387 	tcode = fp->mode.common.tcode;
1388 
1389 	ohcifp = (struct fwohci_txpkthdr *) db_tr->db[1].db.immed;
1390 	info = &tinfo[tcode];
1391 	hdr_len = pl_off = info->hdr_len;
1392 
1393 	ld = ohcifp->mode.ld;
1394 	ld[0] = ld[1] = ld[2] = ld[3] = 0;
1395 	for (i = 0; i < pl_off / 4; i++)
1396 		ld[i] = fp->mode.ld[i];
1397 
1398 	ohcifp->mode.common.spd = xfer->send.spd & 0x7;
1399 	if (tcode == FWTCODE_STREAM) {
1400 		hdr_len = 8;
1401 		ohcifp->mode.stream.len = fp->mode.stream.len;
1402 	} else if (tcode == FWTCODE_PHY) {
1403 		hdr_len = 12;
1404 		ld[1] = fp->mode.ld[1];
1405 		ld[2] = fp->mode.ld[2];
1406 		ohcifp->mode.common.spd = 0;
1407 		ohcifp->mode.common.tcode = FWOHCITCODE_PHY;
1408 	} else {
1409 		ohcifp->mode.asycomm.dst = fp->mode.hdr.dst;
1410 		ohcifp->mode.asycomm.srcbus = OHCI_ASYSRCBUS;
1411 		ohcifp->mode.asycomm.tlrt |= FWRETRY_X;
1412 	}
1413 	db = db_tr->db;
1414  	FWOHCI_DMA_WRITE(db->db.desc.cmd,
1415 	    OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | hdr_len);
1416  	FWOHCI_DMA_WRITE(db->db.desc.addr, 0);
1417  	FWOHCI_DMA_WRITE(db->db.desc.res, 0);
1418 /* Specify bound timer of asy. responce */
1419 	if (dbch->off != OHCI_ATSOFF)
1420  		FWOHCI_DMA_WRITE(db->db.desc.res,
1421 		     (OREAD(sc, OHCI_CYCLETIMER) >> 12) + (1 << 13));
1422 #if BYTE_ORDER == BIG_ENDIAN
1423 	if (tcode == FWTCODE_WREQQ || tcode == FWTCODE_RRESQ)
1424 		hdr_len = 12;
1425 	for (i = 0; i < hdr_len / 4; i++)
1426 		FWOHCI_DMA_WRITE(ld[i], ld[i]);
1427 #endif
1428 
1429 again:
1430 	db_tr->dbcnt = 2;
1431 	db = &db_tr->db[db_tr->dbcnt];
1432 	if (xfer->send.pay_len > 0) {
1433 		int err;
1434 		/* handle payload */
1435 		if (xfer->mbuf == NULL)
1436 			err = bus_dmamap_load(sc->fc.dmat, db_tr->dma_map,
1437 			    xfer->send.payload, xfer->send.pay_len, NULL,
1438 			    BUS_DMA_WAITOK);
1439 		else {
1440 			/* XXX we can handle only 6 (=8-2) mbuf chains */
1441 			err = bus_dmamap_load_mbuf(sc->fc.dmat, db_tr->dma_map,
1442 			    xfer->mbuf, BUS_DMA_WAITOK);
1443 			if (err == EFBIG) {
1444 				struct mbuf *m0;
1445 
1446 				if (firewire_debug)
1447 					printf("EFBIG.\n");
1448 				m0 = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
1449 				if (m0 != NULL) {
1450 					m_copydata(xfer->mbuf, 0,
1451 					    xfer->mbuf->m_pkthdr.len,
1452 					    mtod(m0, void *));
1453 					m0->m_len = m0->m_pkthdr.len =
1454 					    xfer->mbuf->m_pkthdr.len;
1455 					m_freem(xfer->mbuf);
1456 					xfer->mbuf = m0;
1457 					goto again;
1458 				}
1459 				aprint_error_dev(sc->fc.dev,
1460 				    "m_getcl failed.\n");
1461 			}
1462 		}
1463 		if (!err)
1464 			fwohci_execute_db(db_tr, db_tr->dma_map);
1465 		else
1466 			aprint_error_dev(sc->fc.dev,
1467 			    "dmamap_load: err=%d\n", err);
1468 		bus_dmamap_sync(sc->fc.dmat, db_tr->dma_map,
1469 		    0, db_tr->dma_map->dm_mapsize, BUS_DMASYNC_PREWRITE);
1470 #if 0 /* OHCI_OUTPUT_MODE == 0 */
1471 		for (i = 2; i < db_tr->dbcnt; i++)
1472 			FWOHCI_DMA_SET(db_tr->db[i].db.desc.cmd,
1473 			    OHCI_OUTPUT_MORE);
1474 #endif
1475 	}
1476 	if (maxdesc < db_tr->dbcnt) {
1477 		maxdesc = db_tr->dbcnt;
1478 		if (firewire_debug)
1479 			printf("maxdesc: %d\n", maxdesc);
1480 	}
1481 	/* last db */
1482 	db = LAST_DB(db_tr);
1483  	FWOHCI_DMA_SET(db->db.desc.cmd,
1484 	    OHCI_OUTPUT_LAST | OHCI_INTERRUPT_ALWAYS | OHCI_BRANCH_ALWAYS);
1485  	FWOHCI_DMA_WRITE(db->db.desc.depend,
1486 	    STAILQ_NEXT(db_tr, link)->bus_addr);
1487 
1488 	if (fsegment == -1)
1489 		fsegment = db_tr->dbcnt;
1490 	if (dbch->pdb_tr != NULL) {
1491 		db = LAST_DB(dbch->pdb_tr);
1492  		FWOHCI_DMA_SET(db->db.desc.depend, db_tr->dbcnt);
1493 	}
1494 	dbch->xferq.queued++;
1495 	dbch->pdb_tr = db_tr;
1496 	db_tr = STAILQ_NEXT(db_tr, link);
1497 	if (db_tr != dbch->bottom)
1498 		goto txloop;
1499 	else {
1500 		aprint_error_dev(sc->fc.dev, "fwohci_start: lack of db_trq\n");
1501 		dbch->flags |= FWOHCI_DBCH_FULL;
1502 	}
1503 kick:
1504 	/* kick asy q */
1505 	fwdma_sync_multiseg(dbch->am, kick->idx, dbch->pdb_tr->idx,
1506 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1507 
1508 	if (dbch->xferq.flag & FWXFERQ_RUNNING)
1509 		OWRITE(sc, OHCI_DMACTL(dbch->off), OHCI_CNTL_DMA_WAKE);
1510 	else {
1511 		if (firewire_debug)
1512 			printf("start AT DMA status=%x\n",
1513 			    OREAD(sc, OHCI_DMACTL(dbch->off)));
1514 		OWRITE(sc, OHCI_DMACMD(dbch->off),
1515 		    dbch->top->bus_addr | fsegment);
1516 		OWRITE(sc, OHCI_DMACTL(dbch->off), OHCI_CNTL_DMA_RUN);
1517 		dbch->xferq.flag |= FWXFERQ_RUNNING;
1518 	}
1519 
1520 	dbch->top = db_tr;
1521 	return;
1522 }
1523 
1524 static void
1525 fwohci_start_atq(struct firewire_comm *fc)
1526 {
1527 	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1528 	struct fwohci_dbch *dbch = &sc->atrq;
1529 
1530 	mutex_enter(&dbch->xferq.q_mtx);
1531 	fwohci_start(sc, dbch);
1532 	mutex_exit(&dbch->xferq.q_mtx);
1533 	return;
1534 }
1535 
1536 static void
1537 fwohci_start_ats(struct firewire_comm *fc)
1538 {
1539 	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1540 	struct fwohci_dbch *dbch = &sc->atrs;
1541 
1542 	mutex_enter(&dbch->xferq.q_mtx);
1543 	fwohci_start(sc, dbch);
1544 	mutex_exit(&dbch->xferq.q_mtx);
1545 	return;
1546 }
1547 
1548 static void
1549 fwohci_txd(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1550 {
1551 	struct firewire_comm *fc = &sc->fc;
1552 	struct fwohcidb_tr *tr;
1553 	struct fwohcidb *db;
1554 	struct fw_xfer *xfer;
1555 	u_int stat, status;
1556 	int packets = 0, ch, err = 0;
1557 
1558 #if DIAGNOSTIC
1559 	if (dbch->off != OHCI_ATQOFF &&
1560 	    dbch->off != OHCI_ATSOFF)
1561 		panic("not async tx");
1562 #endif
1563 	if (dbch->off == OHCI_ATQOFF)
1564 		ch = ATRQ_CH;
1565 	else	/* OHCI_ATSOFF */
1566 		ch = ATRS_CH;
1567 
1568 	mutex_enter(&dbch->xferq.q_mtx);
1569 	tr = dbch->bottom;
1570 	while (dbch->xferq.queued > 0) {
1571 		fwdma_sync_multiseg(dbch->am, tr->idx, tr->idx,
1572 		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1573 		db = LAST_DB(tr);
1574 		status = FWOHCI_DMA_READ(db->db.desc.res) >> OHCI_STATUS_SHIFT;
1575 		if (!(status & OHCI_CNTL_DMA_ACTIVE))
1576 			if (fc->status != FWBUSINIT)
1577 				goto out;
1578 		if (tr->xfer->send.pay_len > 0) {
1579 			bus_dmamap_sync(fc->dmat, tr->dma_map,
1580 			    0, tr->dma_map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
1581 			bus_dmamap_unload(fc->dmat, tr->dma_map);
1582 		}
1583 #if 1
1584 		if (firewire_debug > 1)
1585 			dump_db(sc, ch);
1586 #endif
1587 		if (status & OHCI_CNTL_DMA_DEAD) {
1588 			/* Stop DMA */
1589 			OWRITE(sc, OHCI_DMACTLCLR(dbch->off),
1590 			    OHCI_CNTL_DMA_RUN);
1591 			aprint_error_dev(fc->dev, "force reset AT FIFO\n");
1592 			OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_LINKEN);
1593 			OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LPS | OHCI_HCC_LINKEN);
1594 			OWRITE(sc, OHCI_DMACTLCLR(dbch->off),
1595 			    OHCI_CNTL_DMA_RUN);
1596 		}
1597 		stat = status & FWOHCIEV_MASK;
1598 		switch(stat) {
1599 		case FWOHCIEV_ACKPEND:
1600 
1601 			/* FALLTHROUGH */
1602 
1603 		case FWOHCIEV_ACKCOMPL:
1604 			err = 0;
1605 			break;
1606 
1607 		case FWOHCIEV_ACKBSA:
1608 		case FWOHCIEV_ACKBSB:
1609 		case FWOHCIEV_ACKBSX:
1610 			aprint_error_dev(fc->dev, "txd err=%2x %s\n", stat,
1611 			    fwohcicode[stat]);
1612 			err = EBUSY;
1613 			break;
1614 
1615 		case FWOHCIEV_FLUSHED:
1616 		case FWOHCIEV_ACKTARD:
1617 			aprint_error_dev(fc->dev, "txd err=%2x %s\n", stat,
1618 			    fwohcicode[stat]);
1619 			err = EAGAIN;
1620 			break;
1621 
1622 		case FWOHCIEV_MISSACK:
1623 		case FWOHCIEV_UNDRRUN:
1624 		case FWOHCIEV_OVRRUN:
1625 		case FWOHCIEV_DESCERR:
1626 		case FWOHCIEV_DTRDERR:
1627 		case FWOHCIEV_TIMEOUT:
1628 		case FWOHCIEV_TCODERR:
1629 		case FWOHCIEV_UNKNOWN:
1630 		case FWOHCIEV_ACKDERR:
1631 		case FWOHCIEV_ACKTERR:
1632 		default:
1633 			aprint_error_dev(fc->dev, "txd err=%2x %s\n", stat,
1634 			    fwohcicode[stat]);
1635 			err = EINVAL;
1636 			break;
1637 		}
1638 		dbch->xferq.queued--;
1639 		dbch->bottom = STAILQ_NEXT(tr, link);
1640 		if (tr->xfer != NULL) {
1641 			xfer = tr->xfer;
1642 			tr->xfer = NULL;
1643 			mutex_exit(&dbch->xferq.q_mtx);
1644 			if (xfer->flag & FWXF_RCVD) {
1645 #if 0
1646 				if (firewire_debug)
1647 					printf("already rcvd\n");
1648 #endif
1649 				fw_xfer_done(xfer);
1650 			} else {
1651 				microtime(&xfer->tv);
1652 				xfer->flag = FWXF_SENT;
1653 				if (err == EBUSY) {
1654 					xfer->flag = FWXF_BUSY;
1655 					xfer->resp = err;
1656 					xfer->recv.pay_len = 0;
1657 					fw_xfer_done(xfer);
1658 				} else if (stat != FWOHCIEV_ACKPEND) {
1659 					if (stat != FWOHCIEV_ACKCOMPL)
1660 						xfer->flag = FWXF_SENTERR;
1661 					xfer->resp = err;
1662 					xfer->recv.pay_len = 0;
1663 					fw_xfer_done(xfer);
1664 				}
1665 			}
1666 			mutex_enter(&dbch->xferq.q_mtx);
1667 			/*
1668 			 * The watchdog timer takes care of split
1669 			 * transcation timeout for ACKPEND case.
1670 			 */
1671 		} else
1672 			aprint_error_dev(fc->dev, "this shouldn't happen\n");
1673 		packets++;
1674 		if (dbch->bottom == dbch->top) {
1675 			/* we reaches the end of context program */
1676 			if (firewire_debug && dbch->xferq.queued > 0)
1677 				printf("queued > 0\n");
1678 			break;
1679 		}
1680 		tr = dbch->bottom;
1681 	}
1682 out:
1683 	if (dbch->xferq.queued > 0 || packets > 0)
1684 		fwdma_sync_multiseg(dbch->am, tr->idx, tr->idx,
1685 		    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1686 	if ((dbch->flags & FWOHCI_DBCH_FULL) && packets > 0) {
1687 		aprint_normal_dev(fc->dev, "make free slot\n");
1688 		dbch->flags &= ~FWOHCI_DBCH_FULL;
1689 		fwohci_start(sc, dbch);
1690 	}
1691 	mutex_exit(&dbch->xferq.q_mtx);
1692 }
1693 
1694 static void
1695 fwohci_db_free(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1696 {
1697 	struct fwohcidb_tr *db_tr, *last;
1698 
1699 	if ((dbch->flags & FWOHCI_DBCH_INIT) == 0)
1700 		return;
1701 
1702 	for (last = db_tr = STAILQ_FIRST(&dbch->db_trq); db_tr != last;
1703 	    db_tr = STAILQ_NEXT(db_tr, link)) {
1704 		bus_dmamap_destroy(sc->fc.dmat, db_tr->dma_map);
1705 		if ((dbch->xferq.flag & FWXFERQ_EXTBUF) == 0 &&
1706 		    db_tr->buf != NULL) {
1707 			fwdma_free(sc->fc.dmat, db_tr->dma_map, db_tr->buf);
1708 			db_tr->buf = NULL;
1709 		}
1710 	}
1711 	dbch->ndb = 0;
1712 	db_tr = STAILQ_FIRST(&dbch->db_trq);
1713 	fwdma_free_multiseg(dbch->am);
1714 	free(db_tr, M_FW);
1715 	STAILQ_INIT(&dbch->db_trq);
1716 	dbch->flags &= ~FWOHCI_DBCH_INIT;
1717 	seldestroy(&dbch->xferq.rsel);
1718 }
1719 
1720 static void
1721 fwohci_db_init(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1722 {
1723 	struct firewire_comm *fc = &sc->fc;
1724 	struct fwohcidb_tr *db_tr, *lastq, *tmpq;
1725 	int idb;
1726 	const int db_tr_sz = sizeof(struct fwohcidb_tr) * dbch->ndb;
1727 
1728 	if ((dbch->flags & FWOHCI_DBCH_INIT) != 0)
1729 		goto out;
1730 
1731 	/* allocate DB entries and attach one to each DMA channels */
1732 	/* DB entry must start at 16 bytes bounary. */
1733 	STAILQ_INIT(&dbch->db_trq);
1734 	db_tr = (struct fwohcidb_tr *)malloc(db_tr_sz, M_FW, M_WAITOK | M_ZERO);
1735 	if (db_tr == NULL) {
1736 		aprint_error_dev(fc->dev, "malloc(1) failed\n");
1737 		return;
1738 	}
1739 
1740 #define DB_SIZE(x) (sizeof(struct fwohcidb) * (x)->ndesc)
1741 	dbch->am = fwdma_malloc_multiseg(fc, DB_SIZE(dbch), DB_SIZE(dbch),
1742 #if 0
1743 	    dbch->ndb, BUS_DMA_WAITOK);
1744 #else	/* Ooops, debugging now... */
1745 	    dbch->ndb, BUS_DMA_WAITOK |
1746 		(dbch->off == OHCI_ARQOFF || dbch->off == OHCI_ARSOFF) ?
1747 							BUS_DMA_COHERENT : 0);
1748 #endif
1749 	if (dbch->am == NULL) {
1750 		aprint_error_dev(fc->dev, "fwdma_malloc_multiseg failed\n");
1751 		free(db_tr, M_FW);
1752 		return;
1753 	}
1754 	/* Attach DB to DMA ch. */
1755 	for (idb = 0; idb < dbch->ndb; idb++) {
1756 		db_tr->idx = idb;
1757 		db_tr->dbcnt = 0;
1758 		db_tr->db = (struct fwohcidb *)fwdma_v_addr(dbch->am, idb);
1759 		db_tr->bus_addr = fwdma_bus_addr(dbch->am, idb);
1760 		/* create dmamap for buffers */
1761 #define MAX_REQCOUNT	0xffff
1762 		if (bus_dmamap_create(fc->dmat, dbch->xferq.psize,
1763 		    dbch->ndesc > 3 ? dbch->ndesc - 2 : 1, MAX_REQCOUNT, 0,
1764 		    0, &db_tr->dma_map) != 0) {
1765 			aprint_error_dev(fc->dev, "bus_dmamap_create failed\n");
1766 			dbch->flags = FWOHCI_DBCH_INIT; /* XXX fake */
1767 			fwohci_db_free(sc, dbch);
1768 			return;
1769 		}
1770 		if (dbch->off == OHCI_ARQOFF ||
1771 		    dbch->off == OHCI_ARSOFF) {
1772 			db_tr->buf = fwdma_malloc(fc->dev, fc->dmat,
1773 			    &db_tr->dma_map, dbch->xferq.psize, 1,
1774 			    BUS_DMA_NOWAIT);
1775 			if (db_tr->buf == NULL) {
1776 				aprint_error_dev(fc->dev,
1777 				    "fwdma_malloc failed\n");
1778 				dbch->flags = FWOHCI_DBCH_INIT; /* XXX fake */
1779 				fwohci_db_free(sc, dbch);
1780 				return;
1781 			}
1782 		}
1783 		STAILQ_INSERT_TAIL(&dbch->db_trq, db_tr, link);
1784 		if (dbch->xferq.flag & FWXFERQ_EXTBUF) {
1785 			struct fw_bulkxfer *bulkxfer =
1786 			    &dbch->xferq.bulkxfer[idb / dbch->xferq.bnpacket];
1787 
1788 			if (idb % dbch->xferq.bnpacket == 0)
1789 				bulkxfer->start = (void *)db_tr;
1790 			if ((idb + 1) % dbch->xferq.bnpacket == 0)
1791 				bulkxfer->end = (void *)db_tr;
1792 		}
1793 		db_tr++;
1794 	}
1795 	lastq = NULL;
1796 	STAILQ_FOREACH(tmpq, &dbch->db_trq, link)
1797 		lastq = tmpq;
1798 	lastq->link.stqe_next = STAILQ_FIRST(&dbch->db_trq);
1799 out:
1800 	dbch->xferq.queued = 0;
1801 	dbch->pdb_tr = NULL;
1802 	dbch->top = STAILQ_FIRST(&dbch->db_trq);
1803 	dbch->bottom = dbch->top;
1804 	dbch->flags = FWOHCI_DBCH_INIT;
1805 	selinit(&dbch->xferq.rsel);
1806 }
1807 
1808 static int
1809 fwohci_tx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1810 {
1811 	int err = 0;
1812 	int idb, z, i, dmach = 0, ldesc;
1813 	struct fwohcidb_tr *db_tr;
1814 	struct fwohcidb *db;
1815 
1816 	if (!(dbch->xferq.flag & FWXFERQ_EXTBUF)) {
1817 		err = EINVAL;
1818 		return err;
1819 	}
1820 	z = dbch->ndesc;
1821 	for (dmach = 0; dmach < sc->fc.nisodma; dmach++)
1822 		if (dbch->off == sc->it[dmach].off)
1823 			break;
1824 	if (dmach == sc->fc.nisodma) {
1825 		err = EINVAL;
1826 		return err;
1827 	}
1828 	if (dbch->xferq.flag & FWXFERQ_RUNNING)
1829 		return err;
1830 	dbch->xferq.flag |= FWXFERQ_RUNNING;
1831 	for (i = 0, dbch->bottom = dbch->top; i < dbch->ndb - 1; i++)
1832 		dbch->bottom = STAILQ_NEXT(dbch->bottom, link);
1833 	db_tr = dbch->top;
1834 	for (idb = 0; idb < dbch->ndb; idb++) {
1835 		fwohci_add_tx_buf(dbch, db_tr, idb);
1836 		if (STAILQ_NEXT(db_tr, link) == NULL)
1837 			break;
1838 		db = db_tr->db;
1839 		ldesc = db_tr->dbcnt - 1;
1840 		FWOHCI_DMA_WRITE(db[0].db.desc.depend,
1841 		    STAILQ_NEXT(db_tr, link)->bus_addr | z);
1842 		db[ldesc].db.desc.depend = db[0].db.desc.depend;
1843 		if (dbch->xferq.flag & FWXFERQ_EXTBUF) {
1844 			if (((idb + 1) % dbch->xferq.bnpacket) == 0) {
1845 				FWOHCI_DMA_SET(db[ldesc].db.desc.cmd,
1846 				    OHCI_INTERRUPT_ALWAYS);
1847 				/* OHCI 1.1 and above */
1848 				FWOHCI_DMA_SET(db[0].db.desc.cmd,
1849 				    OHCI_INTERRUPT_ALWAYS);
1850 			}
1851 		}
1852 		db_tr = STAILQ_NEXT(db_tr, link);
1853 	}
1854 	FWOHCI_DMA_CLEAR(
1855 	    dbch->bottom->db[dbch->bottom->dbcnt - 1].db.desc.depend, 0xf);
1856 	return err;
1857 }
1858 
1859 static int
1860 fwohci_rx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1861 {
1862 	struct fwohcidb_tr *db_tr;
1863 	struct fwohcidb *db;
1864 	int idb, z, i, ldesc, err = 0;
1865 
1866 	z = dbch->ndesc;
1867 	if (dbch->xferq.flag & FWXFERQ_STREAM) {
1868 		if (dbch->xferq.flag & FWXFERQ_RUNNING)
1869 			return err;
1870 	} else
1871 		if (dbch->xferq.flag & FWXFERQ_RUNNING) {
1872 			err = EBUSY;
1873 			return err;
1874 		}
1875 	dbch->xferq.flag |= FWXFERQ_RUNNING;
1876 	dbch->top = STAILQ_FIRST(&dbch->db_trq);
1877 	for (i = 0, dbch->bottom = dbch->top; i < dbch->ndb - 1; i++)
1878 		dbch->bottom = STAILQ_NEXT(dbch->bottom, link);
1879 	db_tr = dbch->top;
1880 	if (db_tr->dbcnt != 0)
1881 		goto run;
1882 	for (idb = 0; idb < dbch->ndb; idb++) {
1883 		if (dbch->off == OHCI_ARQOFF ||
1884 		    dbch->off == OHCI_ARSOFF)
1885 			bus_dmamap_sync(sc->fc.dmat, db_tr->dma_map,
1886 			    0, db_tr->dma_map->dm_mapsize, BUS_DMASYNC_PREREAD);
1887 		fwohci_add_rx_buf(dbch, db_tr, idb, &sc->dummy_dma);
1888 		if (STAILQ_NEXT(db_tr, link) == NULL)
1889 			break;
1890 		db = db_tr->db;
1891 		ldesc = db_tr->dbcnt - 1;
1892 		FWOHCI_DMA_WRITE(db[ldesc].db.desc.depend,
1893 		    STAILQ_NEXT(db_tr, link)->bus_addr | z);
1894 		if (dbch->xferq.flag & FWXFERQ_EXTBUF) {
1895 			if (((idb + 1) % dbch->xferq.bnpacket) == 0) {
1896 				FWOHCI_DMA_SET(db[ldesc].db.desc.cmd,
1897 				    OHCI_INTERRUPT_ALWAYS);
1898 				FWOHCI_DMA_CLEAR(db[ldesc].db.desc.depend, 0xf);
1899 			}
1900 		}
1901 		db_tr = STAILQ_NEXT(db_tr, link);
1902 	}
1903 	FWOHCI_DMA_CLEAR(dbch->bottom->db[db_tr->dbcnt - 1].db.desc.depend,
1904 	    0xf);
1905 	dbch->buf_offset = 0;
1906 run:
1907 	fwdma_sync_multiseg_all(dbch->am,
1908 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1909 	if (!(dbch->xferq.flag & FWXFERQ_STREAM)) {
1910 		OWRITE(sc, OHCI_DMACMD(dbch->off), dbch->top->bus_addr | z);
1911 		OWRITE(sc, OHCI_DMACTL(dbch->off), OHCI_CNTL_DMA_RUN);
1912 	}
1913 	return err;
1914 }
1915 
1916 static int
1917 fwohci_next_cycle(struct fwohci_softc *sc, int cycle_now)
1918 {
1919 	int sec, cycle, cycle_match;
1920 
1921 	cycle = cycle_now & 0x1fff;
1922 	sec = cycle_now >> 13;
1923 #define CYCLE_MOD	0x10
1924 #if 1
1925 #define CYCLE_DELAY	8	/* min delay to start DMA */
1926 #else
1927 #define CYCLE_DELAY	7000	/* min delay to start DMA */
1928 #endif
1929 	cycle = cycle + CYCLE_DELAY;
1930 	if (cycle >= 8000) {
1931 		sec++;
1932 		cycle -= 8000;
1933 	}
1934 	cycle = roundup2(cycle, CYCLE_MOD);
1935 	if (cycle >= 8000) {
1936 		sec++;
1937 		if (cycle == 8000)
1938 			cycle = 0;
1939 		else
1940 			cycle = CYCLE_MOD;
1941 	}
1942 	cycle_match = ((sec << 13) | cycle) & 0x7ffff;
1943 
1944 	return cycle_match;
1945 }
1946 
1947 #ifdef OHCI_DEBUG
1948 static void
1949 fwohci_dump_intr(struct fwohci_softc *sc, uint32_t stat)
1950 {
1951 
1952 	if (stat & OREAD(sc, FWOHCI_INTMASK))
1953 		print("%s: INTERRUPT"
1954 		    " < %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s>"
1955 		    " 0x%08x, 0x%08x\n",
1956 		    device_xname(fc->dev),
1957 		    stat & OHCI_INT_EN ? "DMA_EN ":"",
1958 		    stat & OHCI_INT_PHY_REG ? "PHY_REG ":"",
1959 		    stat & OHCI_INT_CYC_LONG ? "CYC_LONG ":"",
1960 		    stat & OHCI_INT_ERR ? "INT_ERR ":"",
1961 		    stat & OHCI_INT_CYC_ERR ? "CYC_ERR ":"",
1962 		    stat & OHCI_INT_CYC_LOST ? "CYC_LOST ":"",
1963 		    stat & OHCI_INT_CYC_64SECOND ? "CYC_64SECOND ":"",
1964 		    stat & OHCI_INT_CYC_START ? "CYC_START ":"",
1965 		    stat & OHCI_INT_PHY_INT ? "PHY_INT ":"",
1966 		    stat & OHCI_INT_PHY_BUS_R ? "BUS_RESET ":"",
1967 		    stat & OHCI_INT_PHY_SID ? "SID ":"",
1968 		    stat & OHCI_INT_LR_ERR ? "DMA_LR_ERR ":"",
1969 		    stat & OHCI_INT_PW_ERR ? "DMA_PW_ERR ":"",
1970 		    stat & OHCI_INT_DMA_IR ? "DMA_IR ":"",
1971 		    stat & OHCI_INT_DMA_IT ? "DMA_IT " :"",
1972 		    stat & OHCI_INT_DMA_PRRS ? "DMA_PRRS " :"",
1973 		    stat & OHCI_INT_DMA_PRRQ ? "DMA_PRRQ " :"",
1974 		    stat & OHCI_INT_DMA_ARRS ? "DMA_ARRS " :"",
1975 		    stat & OHCI_INT_DMA_ARRQ ? "DMA_ARRQ " :"",
1976 		    stat & OHCI_INT_DMA_ATRS ? "DMA_ATRS " :"",
1977 		    stat & OHCI_INT_DMA_ATRQ ? "DMA_ATRQ " :"",
1978 		    stat, OREAD(sc, FWOHCI_INTMASK)
1979 		);
1980 }
1981 #endif
1982 
1983 static void
1984 fwohci_intr_core(struct fwohci_softc *sc, uint32_t stat)
1985 {
1986 	struct firewire_comm *fc = &sc->fc;
1987 	uint32_t node_id, plen;
1988 
1989 	if ((stat & OHCI_INT_PHY_BUS_R) && (fc->status != FWBUSRESET)) {
1990 		fc->status = FWBUSRESET;
1991 		/* Disable bus reset interrupt until sid recv. */
1992 		OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_PHY_BUS_R);
1993 
1994 		aprint_normal_dev(fc->dev, "BUS reset\n");
1995 		OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST);
1996 		OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCSRC);
1997 
1998 		OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN);
1999 		sc->atrq.xferq.flag &= ~FWXFERQ_RUNNING;
2000 		OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
2001 		sc->atrs.xferq.flag &= ~FWXFERQ_RUNNING;
2002 
2003 		fw_busreset(&sc->fc, FWBUSRESET);
2004 		OWRITE(sc, OHCI_CROMHDR, ntohl(sc->fc.config_rom[0]));
2005 		OWRITE(sc, OHCI_BUS_OPT, ntohl(sc->fc.config_rom[2]));
2006 	}
2007 	if (stat & OHCI_INT_PHY_SID) {
2008 		/* Enable bus reset interrupt */
2009 		OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_BUS_R);
2010 		OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_PHY_BUS_R);
2011 
2012 		/* Allow async. request to us */
2013 		OWRITE(sc, OHCI_AREQHI, 1 << 31);
2014 		if (firewire_phydma_enable) {
2015 			/* allow from all nodes */
2016 			OWRITE(sc, OHCI_PREQHI, 0x7fffffff);
2017 			OWRITE(sc, OHCI_PREQLO, 0xffffffff);
2018 			/* 0 to 4GB region */
2019 			OWRITE(sc, OHCI_PREQUPPER, 0x10000);
2020 		}
2021 		/* Set ATRetries register */
2022 		OWRITE(sc, OHCI_ATRETRY, 1<<(13+16) | 0xfff);
2023 
2024 		/*
2025 		 * Checking whether the node is root or not. If root, turn on
2026 		 * cycle master.
2027 		 */
2028 		node_id = OREAD(sc, FWOHCI_NODEID);
2029 		plen = OREAD(sc, OHCI_SID_CNT);
2030 
2031 		fc->nodeid = node_id & 0x3f;
2032 		aprint_normal_dev(fc->dev, "node_id=0x%08x, gen=%d, ",
2033 		    node_id, (plen >> 16) & 0xff);
2034 		if (!(node_id & OHCI_NODE_VALID)) {
2035 			aprint_error_dev(fc->dev, "Bus reset failure\n");
2036 			goto sidout;
2037 		}
2038 
2039 		/* cycle timer */
2040 		sc->cycle_lost = 0;
2041 		OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_CYC_LOST);
2042 		if ((node_id & OHCI_NODE_ROOT) && !nocyclemaster) {
2043 			aprint_normal("CYCLEMASTER mode\n");
2044 			OWRITE(sc, OHCI_LNKCTL,
2045 			    OHCI_CNTL_CYCMTR | OHCI_CNTL_CYCTIMER);
2046 		} else {
2047 			aprint_normal("non CYCLEMASTER mode\n");
2048 			OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCMTR);
2049 			OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_CYCTIMER);
2050 		}
2051 
2052 		fc->status = FWBUSINIT;
2053 
2054 		fwohci_task_sid(sc);
2055 	}
2056 sidout:
2057 	if ((stat & ~(OHCI_INT_PHY_BUS_R | OHCI_INT_PHY_SID)))
2058 		fwohci_task_dma(sc);
2059 }
2060 
2061 static void
2062 fwohci_intr_dma(struct fwohci_softc *sc, uint32_t stat)
2063 {
2064 	struct firewire_comm *fc = &sc->fc;
2065 	uint32_t irstat, itstat;
2066 	u_int i;
2067 
2068 	if (stat & OHCI_INT_DMA_IR) {
2069 		irstat = atomic_swap_32(&sc->irstat, 0);
2070 		for (i = 0; i < fc->nisodma; i++)
2071 			if ((irstat & (1 << i)) != 0) {
2072 				struct fwohci_dbch *dbch = &sc->ir[i];
2073 
2074 				if ((dbch->xferq.flag & FWXFERQ_OPEN) == 0) {
2075 					aprint_error_dev(fc->dev,
2076 					    "dma(%d) not active\n", i);
2077 					continue;
2078 				}
2079 				fwohci_rbuf_update(sc, i);
2080 			}
2081 	}
2082 	if (stat & OHCI_INT_DMA_IT) {
2083 		itstat = atomic_swap_32(&sc->itstat, 0);
2084 		for (i = 0; i < fc->nisodma; i++)
2085 			if ((itstat & (1 << i)) != 0)
2086 				fwohci_tbuf_update(sc, i);
2087 	}
2088 	if (stat & OHCI_INT_DMA_PRRS) {
2089 #if 0
2090 		dump_dma(sc, ARRS_CH);
2091 		dump_db(sc, ARRS_CH);
2092 #endif
2093 		fwohci_arcv(sc, &sc->arrs);
2094 	}
2095 	if (stat & OHCI_INT_DMA_PRRQ) {
2096 #if 0
2097 		dump_dma(sc, ARRQ_CH);
2098 		dump_db(sc, ARRQ_CH);
2099 #endif
2100 		fwohci_arcv(sc, &sc->arrq);
2101 	}
2102 	if (stat & OHCI_INT_CYC_LOST) {
2103 		if (sc->cycle_lost >= 0)
2104 			sc->cycle_lost++;
2105 		if (sc->cycle_lost > 10) {
2106 			sc->cycle_lost = -1;
2107 #if 0
2108 			OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCTIMER);
2109 #endif
2110 			OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST);
2111 			aprint_error_dev(fc->dev, "too many cycle lost, "
2112 			    "no cycle master present?\n");
2113 		}
2114 	}
2115 	if (stat & OHCI_INT_DMA_ATRQ)
2116 		fwohci_txd(sc, &(sc->atrq));
2117 	if (stat & OHCI_INT_DMA_ATRS)
2118 		fwohci_txd(sc, &(sc->atrs));
2119 	if (stat & OHCI_INT_PW_ERR)
2120 		aprint_error_dev(fc->dev, "posted write error\n");
2121 	if (stat & OHCI_INT_ERR)
2122 		aprint_error_dev(fc->dev, "unrecoverable error\n");
2123 	if (stat & OHCI_INT_PHY_INT)
2124 		aprint_normal_dev(fc->dev, "phy int\n");
2125 
2126 	return;
2127 }
2128 
2129 static void
2130 fwohci_task_sid(struct fwohci_softc *sc)
2131 {
2132 	struct firewire_comm *fc = &sc->fc;
2133 	uint32_t *buf;
2134 	int i, plen;
2135 
2136 	plen = OREAD(sc, OHCI_SID_CNT);
2137 
2138 	if (plen & OHCI_SID_ERR) {
2139 		aprint_error_dev(fc->dev, "SID Error\n");
2140 		return;
2141 	}
2142 	plen &= OHCI_SID_CNT_MASK;
2143 	if (plen < 4 || plen > OHCI_SIDSIZE) {
2144 		aprint_error_dev(fc->dev, "invalid SID len = %d\n", plen);
2145 		return;
2146 	}
2147 	plen -= 4; /* chop control info */
2148 	buf = (uint32_t *)malloc(OHCI_SIDSIZE, M_FW, M_NOWAIT);
2149 	if (buf == NULL) {
2150 		aprint_error_dev(fc->dev, "malloc failed\n");
2151 		return;
2152 	}
2153 	for (i = 0; i < plen / 4; i++)
2154 		buf[i] = FWOHCI_DMA_READ(sc->sid_buf[i + 1]);
2155 #if 1 /* XXX needed?? */
2156 	/* pending all pre-bus_reset packets */
2157 	fwohci_txd(sc, &sc->atrq);
2158 	fwohci_txd(sc, &sc->atrs);
2159 	fwohci_arcv(sc, &sc->arrs);
2160 	fwohci_arcv(sc, &sc->arrq);
2161 	fw_drain_txq(fc);
2162 #endif
2163 	fw_sidrcv(fc, buf, plen);
2164 	free(buf, M_FW);
2165 }
2166 
2167 static void
2168 fwohci_task_dma(struct fwohci_softc *sc)
2169 {
2170 	uint32_t stat;
2171 
2172 again:
2173 	stat = atomic_swap_32(&sc->intstat, 0);
2174 	if (stat)
2175 		fwohci_intr_dma(sc, stat);
2176 	else
2177 		return;
2178 	goto again;
2179 }
2180 
2181 static void
2182 fwohci_tbuf_update(struct fwohci_softc *sc, int dmach)
2183 {
2184 	struct firewire_comm *fc = &sc->fc;
2185 	struct fwohcidb *db;
2186 	struct fw_bulkxfer *chunk;
2187 	struct fw_xferq *it;
2188 	uint32_t stat;
2189 #if 0
2190 	uint32_t count;
2191 #endif
2192 	int w = 0, ldesc;
2193 
2194 	it = fc->it[dmach];
2195 	ldesc = sc->it[dmach].ndesc - 1;
2196 	mutex_enter(&fc->fc_mtx);
2197 	fwdma_sync_multiseg_all(sc->it[dmach].am, BUS_DMASYNC_POSTREAD);
2198 	if (firewire_debug)
2199 		dump_db(sc, ITX_CH + dmach);
2200 	while ((chunk = STAILQ_FIRST(&it->stdma)) != NULL) {
2201 		db = ((struct fwohcidb_tr *)(chunk->end))->db;
2202 		stat =
2203 		    FWOHCI_DMA_READ(db[ldesc].db.desc.res) >> OHCI_STATUS_SHIFT;
2204 		db = ((struct fwohcidb_tr *)(chunk->start))->db;
2205 		/* timestamp */
2206 #if 0
2207 		count =
2208 		    FWOHCI_DMA_READ(db[ldesc].db.desc.res) & OHCI_COUNT_MASK;
2209 #else
2210 		(void)FWOHCI_DMA_READ(db[ldesc].db.desc.res);
2211 #endif
2212 		if (stat == 0)
2213 			break;
2214 		STAILQ_REMOVE_HEAD(&it->stdma, link);
2215 		switch (stat & FWOHCIEV_MASK) {
2216 		case FWOHCIEV_ACKCOMPL:
2217 #if 0
2218 			printf("0x%08x\n", count);
2219 #endif
2220 			break;
2221 		default:
2222 			aprint_error_dev(fc->dev,
2223 			    "Isochronous transmit err %02x(%s)\n",
2224 			    stat, fwohcicode[stat & 0x1f]);
2225 		}
2226 		STAILQ_INSERT_TAIL(&it->stfree, chunk, link);
2227 		w++;
2228 	}
2229 	mutex_exit(&fc->fc_mtx);
2230 	if (w)
2231 		wakeup(it);
2232 }
2233 
2234 static void
2235 fwohci_rbuf_update(struct fwohci_softc *sc, int dmach)
2236 {
2237 	struct firewire_comm *fc = &sc->fc;
2238 	struct fwohcidb_tr *db_tr;
2239 	struct fw_bulkxfer *chunk;
2240 	struct fw_xferq *ir;
2241 	uint32_t stat;
2242 	int w = 0, ldesc;
2243 
2244 	ir = fc->ir[dmach];
2245 	ldesc = sc->ir[dmach].ndesc - 1;
2246 
2247 #if 0
2248 	dump_db(sc, dmach);
2249 #endif
2250 	if ((ir->flag & FWXFERQ_HANDLER) == 0)
2251 		mutex_enter(&fc->fc_mtx);
2252 	fwdma_sync_multiseg_all(sc->ir[dmach].am, BUS_DMASYNC_POSTREAD);
2253 	while ((chunk = STAILQ_FIRST(&ir->stdma)) != NULL) {
2254 		db_tr = (struct fwohcidb_tr *)chunk->end;
2255 		stat = FWOHCI_DMA_READ(db_tr->db[ldesc].db.desc.res) >>
2256 		    OHCI_STATUS_SHIFT;
2257 		if (stat == 0)
2258 			break;
2259 
2260 		if (chunk->mbuf != NULL) {
2261 			bus_dmamap_sync(fc->dmat, db_tr->dma_map, 0,
2262 			    db_tr->dma_map->dm_mapsize, BUS_DMASYNC_POSTREAD);
2263 			bus_dmamap_unload(fc->dmat, db_tr->dma_map);
2264 		} else if (ir->buf != NULL)
2265 			fwdma_sync_multiseg(ir->buf, chunk->poffset,
2266 			    ir->bnpacket, BUS_DMASYNC_POSTREAD);
2267 		else
2268 			/* XXX */
2269 			aprint_error_dev(fc->dev,
2270 			    "fwohci_rbuf_update: this shouldn't happend\n");
2271 
2272 		STAILQ_REMOVE_HEAD(&ir->stdma, link);
2273 		STAILQ_INSERT_TAIL(&ir->stvalid, chunk, link);
2274 		switch (stat & FWOHCIEV_MASK) {
2275 		case FWOHCIEV_ACKCOMPL:
2276 			chunk->resp = 0;
2277 			break;
2278 		default:
2279 			chunk->resp = EINVAL;
2280 			aprint_error_dev(fc->dev,
2281 			    "Isochronous receive err %02x(%s)\n",
2282 			    stat, fwohcicode[stat & 0x1f]);
2283 		}
2284 		w++;
2285 	}
2286 	if ((ir->flag & FWXFERQ_HANDLER) == 0)
2287 		mutex_exit(&fc->fc_mtx);
2288 	if (w == 0)
2289 		return;
2290 	if (ir->flag & FWXFERQ_HANDLER)
2291 		ir->hand(ir);
2292 	else
2293 		wakeup(ir);
2294 }
2295 
2296 static void
2297 dump_dma(struct fwohci_softc *sc, uint32_t ch)
2298 {
2299 	struct fwohci_dbch *dbch;
2300 	uint32_t cntl, stat, cmd, match;
2301 
2302 	if (ch == ATRQ_CH)
2303 		dbch = &sc->atrq;
2304 	else if (ch == ATRS_CH)
2305 		dbch = &sc->atrs;
2306 	else if (ch == ARRQ_CH)
2307 		dbch = &sc->arrq;
2308 	else if (ch == ARRS_CH)
2309 		dbch = &sc->arrs;
2310 	else if (ch < IRX_CH)
2311 		dbch = &sc->it[ch - ITX_CH];
2312 	else
2313 		dbch = &sc->ir[ch - IRX_CH];
2314 	cntl = stat = OREAD(sc, dbch->off);
2315 	cmd = OREAD(sc, dbch->off + 0xc);
2316 	match = OREAD(sc, dbch->off + 0x10);
2317 
2318 	aprint_normal_dev(sc->fc.dev,
2319 	    "ch %1x cntl:0x%08x cmd:0x%08x match:0x%08x\n",
2320 	    ch,
2321 	    cntl,
2322 	    cmd,
2323 	    match);
2324 	stat &= 0xffff;
2325 	if (stat)
2326 		aprint_normal_dev(sc->fc.dev, "dma %d ch:%s%s%s%s%s%s %s(%x)\n",
2327 		    ch,
2328 		    stat & OHCI_CNTL_DMA_RUN ? "RUN," : "",
2329 		    stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "",
2330 		    stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "",
2331 		    stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "",
2332 		    stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "",
2333 		    stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "",
2334 		    fwohcicode[stat & 0x1f],
2335 		    stat & 0x1f
2336 		);
2337 	else
2338 		aprint_normal_dev(sc->fc.dev, "dma %d ch: Nostat\n", ch);
2339 }
2340 
2341 static void
2342 dump_db(struct fwohci_softc *sc, uint32_t ch)
2343 {
2344 	struct fwohci_dbch *dbch;
2345 	struct fwohcidb_tr *cp = NULL, *pp;
2346 	struct fwohcidb *curr = NULL;
2347 #if 0
2348 	struct fwohcidb_tr *np = NULL;
2349 	struct fwohcidb *prev, *next = NULL;
2350 #endif
2351 	int idb, jdb;
2352 	uint32_t cmd;
2353 
2354 	if (ch == ATRQ_CH)
2355 		dbch = &sc->atrq;
2356 	else if (ch == ATRS_CH)
2357 		dbch = &sc->atrs;
2358 	else if (ch == ARRQ_CH)
2359 		dbch = &sc->arrq;
2360 	else if (ch == ARRS_CH)
2361 		dbch = &sc->arrs;
2362 	else if (ch < IRX_CH)
2363 		dbch = &sc->it[ch - ITX_CH];
2364 	else
2365 		dbch = &sc->ir[ch - IRX_CH];
2366 	cmd = OREAD(sc, dbch->off + 0xc);
2367 
2368 	if (dbch->ndb == 0) {
2369 		aprint_error_dev(sc->fc.dev, "No DB is attached ch=%d\n", ch);
2370 		return;
2371 	}
2372 	pp = dbch->top;
2373 #if 0
2374 	prev = pp->db;
2375 #endif
2376 	for (idb = 0; idb < dbch->ndb; idb++) {
2377 		cp = STAILQ_NEXT(pp, link);
2378 		if (cp == NULL) {
2379 			curr = NULL;
2380 			goto outdb;
2381 		}
2382 #if 0
2383 		np = STAILQ_NEXT(cp, link);
2384 #endif
2385 		for (jdb = 0; jdb < dbch->ndesc; jdb++)
2386 			if ((cmd & 0xfffffff0) == cp->bus_addr) {
2387 				curr = cp->db;
2388 #if 0
2389 				if (np != NULL)
2390 					next = np->db;
2391 				else
2392 					next = NULL;
2393 #endif
2394 				goto outdb;
2395 			}
2396 		pp = STAILQ_NEXT(pp, link);
2397 		if (pp == NULL) {
2398 			curr = NULL;
2399 			goto outdb;
2400 		}
2401 #if 0
2402 		prev = pp->db;
2403 #endif
2404 	}
2405 outdb:
2406 	if (curr != NULL) {
2407 #if 0
2408 		aprint_normal("Prev DB %d\n", ch);
2409 		print_db(pp, prev, ch, dbch->ndesc);
2410 #endif
2411 		aprint_normal("Current DB %d\n", ch);
2412 		print_db(cp, curr, ch, dbch->ndesc);
2413 #if 0
2414 		aprint_normal("Next DB %d\n", ch);
2415 		print_db(np, next, ch, dbch->ndesc);
2416 #endif
2417 	} else
2418 		aprint_error("dbdump err ch = %d cmd = 0x%08x\n", ch, cmd);
2419 	return;
2420 }
2421 
2422 static void
2423 print_db(struct fwohcidb_tr *db_tr, struct fwohcidb *db, uint32_t ch,
2424 	 uint32_t hogemax)
2425 {
2426 	fwohcireg_t stat;
2427 	int i, key;
2428 	uint32_t cmd, res;
2429 
2430 	if (db == NULL) {
2431 		aprint_error("No Descriptor is found\n");
2432 		return;
2433 	}
2434 
2435 	aprint_normal("ch = %d\n%8s %s %s %s %s %4s %8s %8s %4s:%4s\n",
2436 	    ch,
2437 	    "Current",
2438 	    "OP  ",
2439 	    "KEY",
2440 	    "INT",
2441 	    "BR ",
2442 	    "len",
2443 	    "Addr",
2444 	    "Depend",
2445 	    "Stat",
2446 	    "Cnt");
2447 	for (i = 0; i <= hogemax; i++) {
2448 		cmd = FWOHCI_DMA_READ(db[i].db.desc.cmd);
2449 		res = FWOHCI_DMA_READ(db[i].db.desc.res);
2450 		key = cmd & OHCI_KEY_MASK;
2451 		stat = res >> OHCI_STATUS_SHIFT;
2452 		aprint_normal("%08jx %s %s %s %s %5d %08x %08x %04x:%04x",
2453 		    (uintmax_t)db_tr->bus_addr,
2454 		    dbcode[(cmd >> 28) & 0xf],
2455 		    dbkey[(cmd >> 24) & 0x7],
2456 		    dbcond[(cmd >> 20) & 0x3],
2457 		    dbcond[(cmd >> 18) & 0x3],
2458 		    cmd & OHCI_COUNT_MASK,
2459 		    FWOHCI_DMA_READ(db[i].db.desc.addr),
2460 		    FWOHCI_DMA_READ(db[i].db.desc.depend),
2461 		    stat,
2462 		    res & OHCI_COUNT_MASK);
2463 		if (stat & 0xff00)
2464 			aprint_normal(" %s%s%s%s%s%s %s(%x)\n",
2465 			    stat & OHCI_CNTL_DMA_RUN ? "RUN," : "",
2466 			    stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "",
2467 			    stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "",
2468 			    stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "",
2469 			    stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "",
2470 			    stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "",
2471 			    fwohcicode[stat & 0x1f],
2472 			    stat & 0x1f
2473 			);
2474 		else
2475 			aprint_normal(" Nostat\n");
2476 		if (key == OHCI_KEY_ST2)
2477 			aprint_normal("0x%08x 0x%08x 0x%08x 0x%08x\n",
2478 			    FWOHCI_DMA_READ(db[i+1].db.immed[0]),
2479 			    FWOHCI_DMA_READ(db[i+1].db.immed[1]),
2480 			    FWOHCI_DMA_READ(db[i+1].db.immed[2]),
2481 			    FWOHCI_DMA_READ(db[i+1].db.immed[3]));
2482 		if (key == OHCI_KEY_DEVICE)
2483 			return;
2484 		if ((cmd & OHCI_BRANCH_MASK) == OHCI_BRANCH_ALWAYS)
2485 			return;
2486 		if ((cmd & OHCI_CMD_MASK) == OHCI_OUTPUT_LAST)
2487 			return;
2488 		if ((cmd & OHCI_CMD_MASK) == OHCI_INPUT_LAST)
2489 			return;
2490 		if (key == OHCI_KEY_ST2)
2491 			i++;
2492 	}
2493 	return;
2494 }
2495 
2496 static void
2497 fwohci_txbufdb(struct fwohci_softc *sc, int dmach, struct fw_bulkxfer *bulkxfer)
2498 {
2499 	struct fwohcidb_tr *db_tr /*, *fdb_tr */;
2500 	struct fwohci_dbch *dbch;
2501 	struct fwohcidb *db;
2502 	struct fw_pkt *fp;
2503 	struct fwohci_txpkthdr *ohcifp;
2504 	unsigned short chtag;
2505 	int idb;
2506 
2507 	KASSERT(mutex_owner(&sc->fc.fc_mtx));
2508 
2509 	dbch = &sc->it[dmach];
2510 	chtag = sc->it[dmach].xferq.flag & 0xff;
2511 
2512 	db_tr = (struct fwohcidb_tr *)(bulkxfer->start);
2513 /*
2514 	fdb_tr = (struct fwohcidb_tr *)(bulkxfer->end);
2515 aprint_normal(sc->fc.dev, "DB %08x %08x %08x\n", bulkxfer, db_tr->bus_addr, fdb_tr->bus_addr);
2516 */
2517 	for (idb = 0; idb < dbch->xferq.bnpacket; idb++) {
2518 		db = db_tr->db;
2519 		fp = (struct fw_pkt *)db_tr->buf;
2520 		ohcifp = (struct fwohci_txpkthdr *) db[1].db.immed;
2521 		ohcifp->mode.ld[0] = fp->mode.ld[0];
2522 		ohcifp->mode.common.spd = 0 & 0x7;
2523 		ohcifp->mode.stream.len = fp->mode.stream.len;
2524 		ohcifp->mode.stream.chtag = chtag;
2525 		ohcifp->mode.stream.tcode = 0xa;
2526 #if BYTE_ORDER == BIG_ENDIAN
2527 		FWOHCI_DMA_WRITE(db[1].db.immed[0], db[1].db.immed[0]);
2528 		FWOHCI_DMA_WRITE(db[1].db.immed[1], db[1].db.immed[1]);
2529 #endif
2530 
2531 		FWOHCI_DMA_CLEAR(db[2].db.desc.cmd, OHCI_COUNT_MASK);
2532 		FWOHCI_DMA_SET(db[2].db.desc.cmd, fp->mode.stream.len);
2533 		FWOHCI_DMA_WRITE(db[2].db.desc.res, 0);
2534 #if 0 /* if bulkxfer->npackets changes */
2535 		db[2].db.desc.cmd =
2536 		    OHCI_OUTPUT_LAST | OHCI_UPDATE | OHCI_BRANCH_ALWAYS;
2537 		db[0].db.desc.depend = db[dbch->ndesc - 1].db.desc.depend =
2538 		    STAILQ_NEXT(db_tr, link)->bus_addr | dbch->ndesc;
2539 #else
2540 		FWOHCI_DMA_SET(db[0].db.desc.depend, dbch->ndesc);
2541 		FWOHCI_DMA_SET(db[dbch->ndesc - 1].db.desc.depend, dbch->ndesc);
2542 #endif
2543 		bulkxfer->end = (void *)db_tr;
2544 		db_tr = STAILQ_NEXT(db_tr, link);
2545 	}
2546 	db = ((struct fwohcidb_tr *)bulkxfer->end)->db;
2547 	FWOHCI_DMA_CLEAR(db[0].db.desc.depend, 0xf);
2548 	FWOHCI_DMA_CLEAR(db[dbch->ndesc - 1].db.desc.depend, 0xf);
2549 #if 0 /* if bulkxfer->npackets changes */
2550 	db[dbch->ndesc - 1].db.desc.control |= OHCI_INTERRUPT_ALWAYS;
2551 	/* OHCI 1.1 and above */
2552 	db[0].db.desc.control |= OHCI_INTERRUPT_ALWAYS;
2553 #endif
2554 /*
2555 	db_tr = (struct fwohcidb_tr *)bulkxfer->start;
2556 	fdb_tr = (struct fwohcidb_tr *)bulkxfer->end;
2557 aprint_normal(sc->fc.dev, "DB %08x %3d %08x %08x\n", bulkxfer, bulkxfer->npacket, db_tr->bus_addr, fdb_tr->bus_addr);
2558 */
2559 	return;
2560 }
2561 
2562 static int
2563 fwohci_add_tx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr,
2564 		  int poffset)
2565 {
2566 	struct fwohcidb *db = db_tr->db;
2567 	struct fw_xferq *it;
2568 	int err = 0;
2569 
2570 	it = &dbch->xferq;
2571 	if (it->buf == 0) {
2572 		err = EINVAL;
2573 		return err;
2574 	}
2575 	db_tr->buf = fwdma_v_addr(it->buf, poffset);
2576 	db_tr->dbcnt = 3;
2577 
2578 	FWOHCI_DMA_WRITE(db[0].db.desc.cmd,
2579 	    OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | 8);
2580 	FWOHCI_DMA_WRITE(db[0].db.desc.addr, 0);
2581 	memset((void *)db[1].db.immed, 0, sizeof(db[1].db.immed));
2582 	FWOHCI_DMA_WRITE(db[2].db.desc.addr,
2583 	    fwdma_bus_addr(it->buf, poffset) + sizeof(uint32_t));
2584 
2585 	FWOHCI_DMA_WRITE(db[2].db.desc.cmd,
2586 	    OHCI_OUTPUT_LAST | OHCI_UPDATE | OHCI_BRANCH_ALWAYS);
2587 #if 1
2588 	FWOHCI_DMA_WRITE(db[0].db.desc.res, 0);
2589 	FWOHCI_DMA_WRITE(db[2].db.desc.res, 0);
2590 #endif
2591 	return 0;
2592 }
2593 
2594 int
2595 fwohci_add_rx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr,
2596 		  int poffset, struct fwdma_alloc *dummy_dma)
2597 {
2598 	struct fwohcidb *db = db_tr->db;
2599 	struct fw_xferq *rq;
2600 	int i, ldesc;
2601 	bus_addr_t dbuf[2];
2602 	int dsiz[2];
2603 
2604 	rq = &dbch->xferq;
2605 	if (rq->buf == NULL && (dbch->xferq.flag & FWXFERQ_EXTBUF) == 0) {
2606 		/* async */
2607 		db_tr->dbcnt = 1;
2608 		dsiz[0] = rq->psize;
2609 		dbuf[0] = db_tr->dma_map->dm_segs[0].ds_addr;
2610 	} else {
2611 		/* isoc */
2612 		db_tr->dbcnt = 0;
2613 		dsiz[db_tr->dbcnt] = sizeof(uint32_t);
2614 		dbuf[db_tr->dbcnt++] = dummy_dma->bus_addr;
2615 		dsiz[db_tr->dbcnt] = rq->psize;
2616 		if (rq->buf != NULL) {
2617 			db_tr->buf = fwdma_v_addr(rq->buf, poffset);
2618 			dbuf[db_tr->dbcnt] = fwdma_bus_addr(rq->buf, poffset);
2619 		}
2620 		db_tr->dbcnt++;
2621 	}
2622 	for (i = 0; i < db_tr->dbcnt; i++) {
2623 		FWOHCI_DMA_WRITE(db[i].db.desc.addr, dbuf[i]);
2624 		FWOHCI_DMA_WRITE(db[i].db.desc.cmd, OHCI_INPUT_MORE | dsiz[i]);
2625 		if (rq->flag & FWXFERQ_STREAM)
2626 			FWOHCI_DMA_SET(db[i].db.desc.cmd, OHCI_UPDATE);
2627 		FWOHCI_DMA_WRITE(db[i].db.desc.res, dsiz[i]);
2628 	}
2629 	ldesc = db_tr->dbcnt - 1;
2630 	if (rq->flag & FWXFERQ_STREAM)
2631 		FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, OHCI_INPUT_LAST);
2632 	FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, OHCI_BRANCH_ALWAYS);
2633 	return 0;
2634 }
2635 
2636 
2637 static int
2638 fwohci_arcv_swap(struct fw_pkt *fp, int len)
2639 {
2640 	struct fw_pkt *fp0;
2641 	uint32_t ld0;
2642 	int hlen;
2643 #if BYTE_ORDER == BIG_ENDIAN
2644 	int slen, i;
2645 #endif
2646 
2647 	ld0 = FWOHCI_DMA_READ(fp->mode.ld[0]);
2648 #if 0
2649 	printf("ld0: x%08x\n", ld0);
2650 #endif
2651 	fp0 = (struct fw_pkt *)&ld0;
2652 	/* determine length to swap */
2653 	switch (fp0->mode.common.tcode) {
2654 	case FWTCODE_WRES:
2655 	case FWTCODE_RREQQ:
2656 	case FWTCODE_WREQQ:
2657 	case FWTCODE_RRESQ:
2658 	case FWOHCITCODE_PHY:
2659 #if BYTE_ORDER == BIG_ENDIAN
2660 		slen = 12;
2661 #endif
2662 		break;
2663 
2664 	case FWTCODE_RREQB:
2665 	case FWTCODE_WREQB:
2666 	case FWTCODE_LREQ:
2667 	case FWTCODE_RRESB:
2668 	case FWTCODE_LRES:
2669 #if BYTE_ORDER == BIG_ENDIAN
2670 		slen = 16;
2671 #endif
2672 		break;
2673 
2674 	default:
2675 		aprint_error("Unknown tcode %d\n", fp0->mode.common.tcode);
2676 		return 0;
2677 	}
2678 	hlen = tinfo[fp0->mode.common.tcode].hdr_len;
2679 	if (hlen > len) {
2680 		if (firewire_debug)
2681 			printf("splitted header\n");
2682 		return len - hlen;
2683 	}
2684 #if BYTE_ORDER == BIG_ENDIAN
2685 	for (i = 0; i < slen / 4; i++)
2686 		fp->mode.ld[i] = FWOHCI_DMA_READ(fp->mode.ld[i]);
2687 #endif
2688 	return hlen;
2689 }
2690 
2691 static int
2692 fwohci_get_plen(struct fwohci_softc *sc, struct fwohci_dbch *dbch,
2693 		struct fw_pkt *fp)
2694 {
2695 	const struct tcode_info *info;
2696 	int r;
2697 
2698 	info = &tinfo[fp->mode.common.tcode];
2699 	r = info->hdr_len + sizeof(uint32_t);
2700 	if (info->flag & FWTI_BLOCK_ASY)
2701 		r += roundup2(fp->mode.wreqb.len, sizeof(uint32_t));
2702 
2703 	if (r == sizeof(uint32_t)) {
2704 		/* XXX */
2705 		aprint_error_dev(sc->fc.dev, "Unknown tcode %d\n",
2706 		    fp->mode.common.tcode);
2707 		return -1;
2708 	}
2709 
2710 	if (r > dbch->xferq.psize) {
2711 		aprint_error_dev(sc->fc.dev, "Invalid packet length %d\n", r);
2712 		return -1;
2713 		/* panic ? */
2714 	}
2715 
2716 	return r;
2717 }
2718 
2719 static void
2720 fwohci_arcv_free_buf(struct fwohci_softc *sc, struct fwohci_dbch *dbch,
2721 		     struct fwohcidb_tr *db_tr, int wake)
2722 {
2723 	struct fwohcidb *db = db_tr->db;
2724 	struct fwohcidb_tr *bdb_tr = dbch->bottom;
2725 
2726 	FWOHCI_DMA_CLEAR(db->db.desc.depend, 0xf);
2727 	FWOHCI_DMA_WRITE(db->db.desc.res, dbch->xferq.psize);
2728 
2729 	fwdma_sync_multiseg(dbch->am, bdb_tr->idx, bdb_tr->idx,
2730 	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
2731 	FWOHCI_DMA_SET(bdb_tr->db[0].db.desc.depend, dbch->ndesc);
2732 
2733 	fwdma_sync_multiseg(dbch->am, bdb_tr->idx, db_tr->idx,
2734 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
2735 	dbch->bottom = db_tr;
2736 
2737 	if (wake)
2738 		OWRITE(sc, OHCI_DMACTL(dbch->off), OHCI_CNTL_DMA_WAKE);
2739 }
2740 
2741 static void
2742 fwohci_arcv(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
2743 {
2744 	struct fwohcidb_tr *db_tr;
2745 	struct fw_pkt pktbuf, *fp;
2746 	struct iovec vec[2];
2747 	bus_addr_t m;
2748 	bus_size_t n;
2749 	u_int spd;
2750 	uint32_t stat, status, event;
2751 	uint8_t *ld;
2752 	int nvec, resCount, len, plen, hlen, offset;
2753 	const int psize = dbch->xferq.psize;
2754 
2755 #if DIAGNOSTIC
2756 	if (dbch->off != OHCI_ARQOFF &&
2757 	    dbch->off != OHCI_ARSOFF)
2758 		panic("not async rx");
2759 #endif
2760 
2761 	mutex_enter(&dbch->xferq.q_mtx);
2762 	db_tr = dbch->top;
2763 	/* XXX we cannot handle a packet which lies in more than two buf */
2764 	fwdma_sync_multiseg(dbch->am, db_tr->idx, db_tr->idx,
2765 	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
2766 	status = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) >> OHCI_STATUS_SHIFT;
2767 	resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) & OHCI_COUNT_MASK;
2768 	while (status & OHCI_CNTL_DMA_ACTIVE) {
2769 #if 0
2770 		if (dbch->off == OHCI_ARQOFF)
2771 			aprint_normal_dev(sc->fc.dev,
2772 			    "buf 0x%08x, status 0x%04x, resCount 0x%04x\n",
2773 			    db_tr->bus_addr, status, resCount);
2774 #endif
2775 		n = 0;
2776 		len = psize - resCount;
2777 		ld = (uint8_t *)db_tr->buf;
2778 		if (dbch->pdb_tr == NULL) {
2779 			len -= dbch->buf_offset;
2780 			ld += dbch->buf_offset;
2781 			m = dbch->buf_offset;
2782 		} else
2783 			m = 0;
2784 		if (len > 0)
2785 			bus_dmamap_sync(sc->fc.dmat, db_tr->dma_map,
2786 			    m, len, BUS_DMASYNC_POSTREAD);
2787 		while (len > 0) {
2788 			if (dbch->pdb_tr != NULL) {
2789 				/* we have a fragment in previous buffer */
2790 				int rlen = 0;
2791 				void *buf;
2792 
2793 				if (dbch->buf_offset < 0) {
2794 					/* splitted in header, pull up */
2795 					char *p;
2796 
2797 					rlen -= dbch->buf_offset;
2798 					buf = (char *)dbch->pdb_tr->buf +
2799 					    psize - rlen;
2800 
2801 					KASSERT(rlen <= sizeof(pktbuf));
2802 
2803 					p = (char *)&pktbuf;
2804 					memcpy(p, buf, rlen);
2805 					p += rlen;
2806 					/* this must be too long but harmless */
2807 					rlen = sizeof(pktbuf) - rlen;
2808 					memcpy(p, db_tr->buf, rlen);
2809 					ld += rlen;
2810 					len -= rlen;
2811 					hlen = fwohci_arcv_swap(&pktbuf,
2812 					    sizeof(pktbuf));
2813 					if (hlen <= 0) {
2814 						aprint_error_dev(sc->fc.dev,
2815 						    "hlen should be positive.");
2816 						goto err;
2817 					}
2818 					offset = sizeof(pktbuf);
2819 					vec[0].iov_base = (char *)&pktbuf;
2820 					vec[0].iov_len = offset;
2821 				} else {
2822 					/* splitted in payload */
2823 					buf = (char *)dbch->pdb_tr->buf +
2824 					    dbch->buf_offset;
2825 					rlen = psize - dbch->buf_offset;
2826 					if (firewire_debug)
2827 						printf("rlen=%d, offset=%d\n",
2828 						    rlen, dbch->buf_offset);
2829 					offset = rlen;
2830 					vec[0].iov_base = buf;
2831 					vec[0].iov_len = rlen;
2832 				}
2833 				fp = (struct fw_pkt *)vec[0].iov_base;
2834 				nvec = 1;
2835 			} else {
2836 				/* no fragment in previous buffer */
2837 				fp = (struct fw_pkt *)ld;
2838 				hlen = fwohci_arcv_swap(fp, len);
2839 				if (hlen == 0)
2840 					goto err;
2841 				if (hlen < 0) {
2842 					dbch->pdb_tr = db_tr;
2843 					dbch->buf_offset -= psize;
2844 					/* sanity check */
2845 					if (resCount != 0)  {
2846 						aprint_error_dev(sc->fc.dev,
2847 						    "resCount=%d hlen=%d\n",
2848 						    resCount, hlen);
2849 						goto err;
2850 					}
2851 					goto out;
2852 				}
2853 				offset = 0;
2854 				nvec = 0;
2855 			}
2856 			plen = fwohci_get_plen(sc, dbch, fp) - offset;
2857 			if (plen < 0) {
2858 				/*
2859 				 * minimum header size + trailer =
2860 				 *     sizeof(fw_pkt) so this shouldn't happens
2861 				 */
2862 				aprint_error_dev(sc->fc.dev,
2863 				    "plen(%d) is negative! offset=%d\n",
2864 				    plen, offset);
2865 				goto err;
2866 			}
2867 			if (plen > 0) {
2868 				len -= plen;
2869 				if (len < 0) {
2870 					dbch->pdb_tr = db_tr;
2871 					if (firewire_debug)
2872 						printf("splitted payload\n");
2873 					/* sanity check */
2874 					if (resCount != 0) {
2875 						aprint_error_dev(sc->fc.dev,
2876 						    "resCount=%d plen=%d"
2877 						    " len=%d\n",
2878 						    resCount, plen, len);
2879 						goto err;
2880 					}
2881 					goto out;
2882 				}
2883 				vec[nvec].iov_base = ld;
2884 				vec[nvec].iov_len = plen;
2885 				nvec++;
2886 				ld += plen;
2887 			}
2888 			if (nvec == 0)
2889 				aprint_error_dev(sc->fc.dev, "nvec == 0\n");
2890 
2891 /* DMA result-code will be written at the tail of packet */
2892 			stat = FWOHCI_DMA_READ(*(uint32_t *)(ld -
2893 						sizeof(struct fwohci_trailer)));
2894 #if 0
2895 			aprint_normal("plen: %d, stat %x\n", plen, stat);
2896 #endif
2897 			spd = (stat >> 21) & 0x3;
2898 			event = (stat >> 16) & 0x1f;
2899 			switch (event) {
2900 			case FWOHCIEV_ACKPEND:
2901 #if 0
2902 				aprint_normal(sc->fc.dev,
2903 				    "ack pending tcode=0x%x..\n",
2904 				    fp->mode.common.tcode);
2905 #endif
2906 				/* fall through */
2907 			case FWOHCIEV_ACKCOMPL:
2908 			{
2909 				struct fw_rcv_buf rb;
2910 
2911 				vec[nvec - 1].iov_len -=
2912 				    sizeof(struct fwohci_trailer);
2913 				if (vec[nvec - 1].iov_len == 0)
2914 					nvec--;
2915 				rb.fc = &sc->fc;
2916 				rb.vec = vec;
2917 				rb.nvec = nvec;
2918 				rb.spd = spd;
2919 				fw_rcv(&rb);
2920 				break;
2921 			}
2922 			case FWOHCIEV_BUSRST:
2923 				if ((sc->fc.status != FWBUSRESET) &&
2924 				    (sc->fc.status != FWBUSINIT))
2925 					aprint_error_dev(sc->fc.dev,
2926 					    "got BUSRST packet!?\n");
2927 				break;
2928 			default:
2929 				aprint_error_dev(sc->fc.dev,
2930 				    "Async DMA Receive error err=%02x %s"
2931 				    " plen=%d offset=%d len=%d status=0x%08x"
2932 				    " tcode=0x%x, stat=0x%08x\n",
2933 				    event, fwohcicode[event], plen,
2934 				    (int)(ld - (uint8_t *)db_tr->buf - plen),
2935 				    len, OREAD(sc, OHCI_DMACTL(dbch->off)),
2936 				    fp->mode.common.tcode, stat);
2937 #if 1 /* XXX */
2938 				goto err;
2939 #endif
2940 				break;
2941 			}
2942 			if (dbch->pdb_tr != NULL) {
2943 				if (dbch->buf_offset < 0)
2944 					bus_dmamap_sync(sc->fc.dmat,
2945 					    dbch->pdb_tr->dma_map,
2946 					    psize + dbch->buf_offset,
2947 					    0 - dbch->buf_offset,
2948 					    BUS_DMASYNC_PREREAD);
2949 				else
2950 					bus_dmamap_sync(sc->fc.dmat,
2951 					    dbch->pdb_tr->dma_map,
2952 					    dbch->buf_offset,
2953 					    psize - dbch->buf_offset,
2954 					    BUS_DMASYNC_PREREAD);
2955 				fwohci_arcv_free_buf(sc, dbch, dbch->pdb_tr, 1);
2956 				dbch->pdb_tr = NULL;
2957 			}
2958 			dbch->buf_offset = ld - (uint8_t *)db_tr->buf;
2959 			n += (plen + offset);
2960 		}
2961 out:
2962 		if (n > 0)
2963 			bus_dmamap_sync(sc->fc.dmat, db_tr->dma_map, m, n,
2964 			    BUS_DMASYNC_PREREAD);
2965 
2966 		if (resCount != 0) {
2967 			dbch->buf_offset = psize - resCount;
2968 			break;
2969 		}
2970 
2971 		/* done on this buffer */
2972 
2973 		if (dbch->pdb_tr == NULL) {
2974 			fwohci_arcv_free_buf(sc, dbch, db_tr, 1);
2975 			dbch->buf_offset = 0;
2976 		} else
2977 			if (dbch->pdb_tr != db_tr)
2978 				aprint_error_dev(sc->fc.dev,
2979 				    "pdb_tr != db_tr\n");
2980 		dbch->top = STAILQ_NEXT(db_tr, link);
2981 
2982 		db_tr = dbch->top;
2983 		fwdma_sync_multiseg(dbch->am, db_tr->idx, db_tr->idx,
2984 		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
2985 		status = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) >>
2986 		    OHCI_STATUS_SHIFT;
2987 		resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res)
2988 		    & OHCI_COUNT_MASK;
2989 
2990 		/* XXX check buffer overrun */
2991 
2992 		/* XXX make sure DMA is not dead */
2993 	}
2994 	fwdma_sync_multiseg(dbch->am, db_tr->idx, db_tr->idx,
2995 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
2996 	mutex_exit(&dbch->xferq.q_mtx);
2997 	return;
2998 
2999 err:
3000 	aprint_error_dev(sc->fc.dev, "AR DMA status=%x, ",
3001 	    OREAD(sc, OHCI_DMACTL(dbch->off)));
3002 	if (dbch->pdb_tr != NULL) {
3003 		if (dbch->buf_offset < 0)
3004 			bus_dmamap_sync(sc->fc.dmat, dbch->pdb_tr->dma_map,
3005 			    psize + dbch->buf_offset, 0 - dbch->buf_offset,
3006 			    BUS_DMASYNC_PREREAD);
3007 		else
3008 			bus_dmamap_sync(sc->fc.dmat, dbch->pdb_tr->dma_map,
3009 			    dbch->buf_offset, psize - dbch->buf_offset,
3010 			    BUS_DMASYNC_PREREAD);
3011 		fwohci_arcv_free_buf(sc, dbch, dbch->pdb_tr, 1);
3012 		dbch->pdb_tr = NULL;
3013 	}
3014 	/* skip until resCount != 0 */
3015 	aprint_error(" skip buffer");
3016 	while (resCount == 0) {
3017 		aprint_error(" #");
3018 		fwohci_arcv_free_buf(sc, dbch, db_tr, 0);
3019 		db_tr = STAILQ_NEXT(db_tr, link);
3020 		resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res)
3021 		    & OHCI_COUNT_MASK;
3022 	}
3023 	aprint_error(" done\n");
3024 	dbch->top = db_tr;
3025 	dbch->buf_offset = psize - resCount;
3026 	OWRITE(sc, OHCI_DMACTL(dbch->off), OHCI_CNTL_DMA_WAKE);
3027 	fwdma_sync_multiseg(dbch->am, db_tr->idx, db_tr->idx,
3028 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
3029 	bus_dmamap_sync(sc->fc.dmat, db_tr->dma_map,
3030 	    0, db_tr->dma_map->dm_mapsize, BUS_DMASYNC_PREREAD);
3031 	mutex_exit(&dbch->xferq.q_mtx);
3032 }
3033