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