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