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