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