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