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