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