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