xref: /freebsd/sys/dev/firewire/fwohci.c (revision 3416500aef140042c64bc149cb1ec6620483bc44)
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/Receiver */
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 receive 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. response */
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 
1251 #define DB_SIZE(x) (sizeof(struct fwohcidb) * (x)->ndesc)
1252 	dbch->am = fwdma_malloc_multiseg(&sc->fc, sizeof(struct fwohcidb),
1253 		DB_SIZE(dbch), dbch->ndb, BUS_DMA_WAITOK);
1254 	if (dbch->am == NULL) {
1255 		printf("fwohci_db_init: fwdma_malloc_multiseg failed\n");
1256 		free(db_tr, M_FW);
1257 		return;
1258 	}
1259 	/* Attach DB to DMA ch. */
1260 	for (idb = 0; idb < dbch->ndb; idb++) {
1261 		db_tr->dbcnt = 0;
1262 		db_tr->db = (struct fwohcidb *)fwdma_v_addr(dbch->am, idb);
1263 		db_tr->bus_addr = fwdma_bus_addr(dbch->am, idb);
1264 		/* create dmamap for buffers */
1265 		/* XXX do we need 4bytes alignment tag? */
1266 		/* XXX don't alloc dma_map for AR */
1267 		if (bus_dmamap_create(dbch->dmat, 0, &db_tr->dma_map) != 0) {
1268 			printf("bus_dmamap_create failed\n");
1269 			dbch->flags = FWOHCI_DBCH_INIT; /* XXX fake */
1270 			fwohci_db_free(dbch);
1271 			return;
1272 		}
1273 		STAILQ_INSERT_TAIL(&dbch->db_trq, db_tr, link);
1274 		if (dbch->xferq.flag & FWXFERQ_EXTBUF) {
1275 			if (idb % dbch->xferq.bnpacket == 0)
1276 				dbch->xferq.bulkxfer[idb / dbch->xferq.bnpacket
1277 						].start = (caddr_t)db_tr;
1278 			if ((idb + 1) % dbch->xferq.bnpacket == 0)
1279 				dbch->xferq.bulkxfer[idb / dbch->xferq.bnpacket
1280 						].end = (caddr_t)db_tr;
1281 		}
1282 		db_tr++;
1283 	}
1284 	STAILQ_LAST(&dbch->db_trq, fwohcidb_tr,link)->link.stqe_next
1285 			= STAILQ_FIRST(&dbch->db_trq);
1286 out:
1287 	dbch->xferq.queued = 0;
1288 	dbch->pdb_tr = NULL;
1289 	dbch->top = STAILQ_FIRST(&dbch->db_trq);
1290 	dbch->bottom = dbch->top;
1291 	dbch->flags = FWOHCI_DBCH_INIT;
1292 }
1293 
1294 static int
1295 fwohci_itx_disable(struct firewire_comm *fc, int dmach)
1296 {
1297 	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1298 
1299 	OWRITE(sc, OHCI_ITCTLCLR(dmach),
1300 			OHCI_CNTL_DMA_RUN | OHCI_CNTL_CYCMATCH_S);
1301 	OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach);
1302 	OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach);
1303 	/* XXX we cannot free buffers until the DMA really stops */
1304 	pause("fwitxd", hz);
1305 	fwohci_db_free(&sc->it[dmach]);
1306 	sc->it[dmach].xferq.flag &= ~FWXFERQ_RUNNING;
1307 	return 0;
1308 }
1309 
1310 static int
1311 fwohci_irx_disable(struct firewire_comm *fc, int dmach)
1312 {
1313 	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1314 
1315 	OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
1316 	OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach);
1317 	OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach);
1318 	/* XXX we cannot free buffers until the DMA really stops */
1319 	pause("fwirxd", hz);
1320 	fwohci_db_free(&sc->ir[dmach]);
1321 	sc->ir[dmach].xferq.flag &= ~FWXFERQ_RUNNING;
1322 	return 0;
1323 }
1324 
1325 #if BYTE_ORDER == BIG_ENDIAN
1326 static void
1327 fwohci_irx_post (struct firewire_comm *fc , uint32_t *qld)
1328 {
1329 	qld[0] = FWOHCI_DMA_READ(qld[0]);
1330 	return;
1331 }
1332 #endif
1333 
1334 static int
1335 fwohci_tx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1336 {
1337 	int err = 0;
1338 	int idb, z, i, dmach = 0, ldesc;
1339 	uint32_t off = 0;
1340 	struct fwohcidb_tr *db_tr;
1341 	struct fwohcidb *db;
1342 
1343 	if (!(dbch->xferq.flag & FWXFERQ_EXTBUF)) {
1344 		err = EINVAL;
1345 		return err;
1346 	}
1347 	z = dbch->ndesc;
1348 	for (dmach = 0; dmach < sc->fc.nisodma; dmach++) {
1349 		if (&sc->it[dmach] == dbch) {
1350 			off = OHCI_ITOFF(dmach);
1351 			break;
1352 		}
1353 	}
1354 	if (off == 0) {
1355 		err = EINVAL;
1356 		return err;
1357 	}
1358 	if (dbch->xferq.flag & FWXFERQ_RUNNING)
1359 		return err;
1360 	dbch->xferq.flag |= FWXFERQ_RUNNING;
1361 	for (i = 0, dbch->bottom = dbch->top; i < (dbch->ndb - 1); i++) {
1362 		dbch->bottom = STAILQ_NEXT(dbch->bottom, link);
1363 	}
1364 	db_tr = dbch->top;
1365 	for (idb = 0; idb < dbch->ndb; idb++) {
1366 		fwohci_add_tx_buf(dbch, db_tr, idb);
1367 		if (STAILQ_NEXT(db_tr, link) == NULL) {
1368 			break;
1369 		}
1370 		db = db_tr->db;
1371 		ldesc = db_tr->dbcnt - 1;
1372 		FWOHCI_DMA_WRITE(db[0].db.desc.depend,
1373 				STAILQ_NEXT(db_tr, link)->bus_addr | z);
1374 		db[ldesc].db.desc.depend = db[0].db.desc.depend;
1375 		if (dbch->xferq.flag & FWXFERQ_EXTBUF) {
1376 			if (((idb + 1) % dbch->xferq.bnpacket) == 0) {
1377 				FWOHCI_DMA_SET(
1378 					db[ldesc].db.desc.cmd,
1379 					OHCI_INTERRUPT_ALWAYS);
1380 				/* OHCI 1.1 and above */
1381 				FWOHCI_DMA_SET(
1382 					db[0].db.desc.cmd,
1383 					OHCI_INTERRUPT_ALWAYS);
1384 			}
1385 		}
1386 		db_tr = STAILQ_NEXT(db_tr, link);
1387 	}
1388 	FWOHCI_DMA_CLEAR(
1389 		dbch->bottom->db[dbch->bottom->dbcnt - 1].db.desc.depend, 0xf);
1390 	return err;
1391 }
1392 
1393 static int
1394 fwohci_rx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1395 {
1396 	int err = 0;
1397 	int idb, z, i, dmach = 0, ldesc;
1398 	uint32_t off = 0;
1399 	struct fwohcidb_tr *db_tr;
1400 	struct fwohcidb *db;
1401 
1402 	z = dbch->ndesc;
1403 	if (&sc->arrq == dbch) {
1404 		off = OHCI_ARQOFF;
1405 	} else if (&sc->arrs == dbch) {
1406 		off = OHCI_ARSOFF;
1407 	} else {
1408 		for (dmach = 0; dmach < sc->fc.nisodma; dmach++) {
1409 			if (&sc->ir[dmach] == dbch) {
1410 				off = OHCI_IROFF(dmach);
1411 				break;
1412 			}
1413 		}
1414 	}
1415 	if (off == 0) {
1416 		err = EINVAL;
1417 		return err;
1418 	}
1419 	if (dbch->xferq.flag & FWXFERQ_STREAM) {
1420 		if (dbch->xferq.flag & FWXFERQ_RUNNING)
1421 			return err;
1422 	} else {
1423 		if (dbch->xferq.flag & FWXFERQ_RUNNING) {
1424 			err = EBUSY;
1425 			return err;
1426 		}
1427 	}
1428 	dbch->xferq.flag |= FWXFERQ_RUNNING;
1429 	dbch->top = STAILQ_FIRST(&dbch->db_trq);
1430 	for (i = 0, dbch->bottom = dbch->top; i < (dbch->ndb - 1); i++) {
1431 		dbch->bottom = STAILQ_NEXT(dbch->bottom, link);
1432 	}
1433 	db_tr = dbch->top;
1434 	for (idb = 0; idb < dbch->ndb; idb++) {
1435 		fwohci_add_rx_buf(dbch, db_tr, idb, &sc->dummy_dma);
1436 		if (STAILQ_NEXT(db_tr, link) == NULL)
1437 			break;
1438 		db = db_tr->db;
1439 		ldesc = db_tr->dbcnt - 1;
1440 		FWOHCI_DMA_WRITE(db[ldesc].db.desc.depend,
1441 			STAILQ_NEXT(db_tr, link)->bus_addr | z);
1442 		if (dbch->xferq.flag & FWXFERQ_EXTBUF) {
1443 			if (((idb + 1) % dbch->xferq.bnpacket) == 0) {
1444 				FWOHCI_DMA_SET(
1445 					db[ldesc].db.desc.cmd,
1446 					OHCI_INTERRUPT_ALWAYS);
1447 				FWOHCI_DMA_CLEAR(
1448 					db[ldesc].db.desc.depend,
1449 					0xf);
1450 			}
1451 		}
1452 		db_tr = STAILQ_NEXT(db_tr, link);
1453 	}
1454 	FWOHCI_DMA_CLEAR(
1455 		dbch->bottom->db[db_tr->dbcnt - 1].db.desc.depend, 0xf);
1456 	dbch->buf_offset = 0;
1457 	fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREREAD);
1458 	fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREWRITE);
1459 	if (dbch->xferq.flag & FWXFERQ_STREAM) {
1460 		return err;
1461 	} else {
1462 		OWRITE(sc, OHCI_DMACMD(off), dbch->top->bus_addr | z);
1463 	}
1464 	OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_RUN);
1465 	return err;
1466 }
1467 
1468 static int
1469 fwohci_next_cycle(struct firewire_comm *fc, int cycle_now)
1470 {
1471 	int sec, cycle, cycle_match;
1472 
1473 	cycle = cycle_now & 0x1fff;
1474 	sec = cycle_now >> 13;
1475 #define CYCLE_MOD	0x10
1476 #if 1
1477 #define CYCLE_DELAY	8	/* min delay to start DMA */
1478 #else
1479 #define CYCLE_DELAY	7000	/* min delay to start DMA */
1480 #endif
1481 	cycle = cycle + CYCLE_DELAY;
1482 	if (cycle >= 8000) {
1483 		sec++;
1484 		cycle -= 8000;
1485 	}
1486 	cycle = roundup2(cycle, CYCLE_MOD);
1487 	if (cycle >= 8000) {
1488 		sec++;
1489 		if (cycle == 8000)
1490 			cycle = 0;
1491 		else
1492 			cycle = CYCLE_MOD;
1493 	}
1494 	cycle_match = ((sec << 13) | cycle) & 0x7ffff;
1495 
1496 	return (cycle_match);
1497 }
1498 
1499 static int
1500 fwohci_itxbuf_enable(struct firewire_comm *fc, int dmach)
1501 {
1502 	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1503 	int err = 0;
1504 	unsigned short tag, ich;
1505 	struct fwohci_dbch *dbch;
1506 	int cycle_match, cycle_now, s, ldesc;
1507 	uint32_t stat;
1508 	struct fw_bulkxfer *first, *chunk, *prev;
1509 	struct fw_xferq *it;
1510 
1511 	dbch = &sc->it[dmach];
1512 	it = &dbch->xferq;
1513 
1514 	tag = (it->flag >> 6) & 3;
1515 	ich = it->flag & 0x3f;
1516 	if ((dbch->flags & FWOHCI_DBCH_INIT) == 0) {
1517 		dbch->ndb = it->bnpacket * it->bnchunk;
1518 		dbch->ndesc = 3;
1519 		fwohci_db_init(sc, dbch);
1520 		if ((dbch->flags & FWOHCI_DBCH_INIT) == 0)
1521 			return ENOMEM;
1522 
1523 		err = fwohci_tx_enable(sc, dbch);
1524 	}
1525 	if (err)
1526 		return err;
1527 
1528 	ldesc = dbch->ndesc - 1;
1529 	s = splfw();
1530 	FW_GLOCK(fc);
1531 	prev = STAILQ_LAST(&it->stdma, fw_bulkxfer, link);
1532 	while  ((chunk = STAILQ_FIRST(&it->stvalid)) != NULL) {
1533 		struct fwohcidb *db;
1534 
1535 		fwdma_sync_multiseg(it->buf, chunk->poffset, it->bnpacket,
1536 					BUS_DMASYNC_PREWRITE);
1537 		fwohci_txbufdb(sc, dmach, chunk);
1538 		if (prev != NULL) {
1539 			db = ((struct fwohcidb_tr *)(prev->end))->db;
1540 #if 0 /* XXX necessary? */
1541 			FWOHCI_DMA_SET(db[ldesc].db.desc.cmd,
1542 						OHCI_BRANCH_ALWAYS);
1543 #endif
1544 #if 0 /* if bulkxfer->npacket changes */
1545 			db[ldesc].db.desc.depend = db[0].db.desc.depend =
1546 				((struct fwohcidb_tr *)
1547 				(chunk->start))->bus_addr | dbch->ndesc;
1548 #else
1549 			FWOHCI_DMA_SET(db[0].db.desc.depend, dbch->ndesc);
1550 			FWOHCI_DMA_SET(db[ldesc].db.desc.depend, dbch->ndesc);
1551 #endif
1552 		}
1553 		STAILQ_REMOVE_HEAD(&it->stvalid, link);
1554 		STAILQ_INSERT_TAIL(&it->stdma, chunk, link);
1555 		prev = chunk;
1556 	}
1557 	FW_GUNLOCK(fc);
1558 	fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREWRITE);
1559 	fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREREAD);
1560 	splx(s);
1561 	stat = OREAD(sc, OHCI_ITCTL(dmach));
1562 	if (firewire_debug && (stat & OHCI_CNTL_CYCMATCH_S))
1563 		printf("stat 0x%x\n", stat);
1564 
1565 	if (stat & (OHCI_CNTL_DMA_ACTIVE | OHCI_CNTL_CYCMATCH_S))
1566 		return 0;
1567 
1568 #if 0
1569 	OWRITE(sc, OHCI_ITCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
1570 #endif
1571 	OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach);
1572 	OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach);
1573 	OWRITE(sc, OHCI_IT_MASK, 1 << dmach);
1574 	OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IT);
1575 
1576 	first = STAILQ_FIRST(&it->stdma);
1577 	OWRITE(sc, OHCI_ITCMD(dmach),
1578 		((struct fwohcidb_tr *)(first->start))->bus_addr | dbch->ndesc);
1579 	if (firewire_debug > 1) {
1580 		printf("fwohci_itxbuf_enable: kick 0x%08x\n", stat);
1581 #if 1
1582 		dump_dma(sc, ITX_CH + dmach);
1583 #endif
1584 	}
1585 	if ((stat & OHCI_CNTL_DMA_RUN) == 0) {
1586 #if 1
1587 		/* Don't start until all chunks are buffered */
1588 		if (STAILQ_FIRST(&it->stfree) != NULL)
1589 			goto out;
1590 #endif
1591 #if 1
1592 		/* Clear cycle match counter bits */
1593 		OWRITE(sc, OHCI_ITCTLCLR(dmach), 0xffff0000);
1594 
1595 		/* 2bit second + 13bit cycle */
1596 		cycle_now = (fc->cyctimer(fc) >> 12) & 0x7fff;
1597 		cycle_match = fwohci_next_cycle(fc, cycle_now);
1598 
1599 		OWRITE(sc, OHCI_ITCTL(dmach),
1600 				OHCI_CNTL_CYCMATCH_S | (cycle_match << 16)
1601 				| OHCI_CNTL_DMA_RUN);
1602 #else
1603 		OWRITE(sc, OHCI_ITCTL(dmach), OHCI_CNTL_DMA_RUN);
1604 #endif
1605 		if (firewire_debug > 1) {
1606 			printf("cycle_match: 0x%04x->0x%04x\n",
1607 						cycle_now, cycle_match);
1608 			dump_dma(sc, ITX_CH + dmach);
1609 			dump_db(sc, ITX_CH + dmach);
1610 		}
1611 	} else if ((stat & OHCI_CNTL_CYCMATCH_S) == 0) {
1612 		device_printf(sc->fc.dev,
1613 			"IT DMA underrun (0x%08x)\n", stat);
1614 		OWRITE(sc, OHCI_ITCTL(dmach), OHCI_CNTL_DMA_WAKE);
1615 	}
1616 out:
1617 	return err;
1618 }
1619 
1620 static int
1621 fwohci_irx_enable(struct firewire_comm *fc, int dmach)
1622 {
1623 	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1624 	int err = 0, s, ldesc;
1625 	unsigned short tag, ich;
1626 	uint32_t stat;
1627 	struct fwohci_dbch *dbch;
1628 	struct fwohcidb_tr *db_tr;
1629 	struct fw_bulkxfer *first, *prev, *chunk;
1630 	struct fw_xferq *ir;
1631 
1632 	dbch = &sc->ir[dmach];
1633 	ir = &dbch->xferq;
1634 
1635 	if ((ir->flag & FWXFERQ_RUNNING) == 0) {
1636 		tag = (ir->flag >> 6) & 3;
1637 		ich = ir->flag & 0x3f;
1638 		OWRITE(sc, OHCI_IRMATCH(dmach), tagbit[tag] | ich);
1639 
1640 		ir->queued = 0;
1641 		dbch->ndb = ir->bnpacket * ir->bnchunk;
1642 		dbch->ndesc = 2;
1643 		fwohci_db_init(sc, dbch);
1644 		if ((dbch->flags & FWOHCI_DBCH_INIT) == 0)
1645 			return ENOMEM;
1646 		err = fwohci_rx_enable(sc, dbch);
1647 	}
1648 	if (err)
1649 		return err;
1650 
1651 	first = STAILQ_FIRST(&ir->stfree);
1652 	if (first == NULL) {
1653 		device_printf(fc->dev, "IR DMA no free chunk\n");
1654 		return 0;
1655 	}
1656 
1657 	ldesc = dbch->ndesc - 1;
1658 	s = splfw();
1659 	if ((ir->flag & FWXFERQ_HANDLER) == 0)
1660 		FW_GLOCK(fc);
1661 	prev = STAILQ_LAST(&ir->stdma, fw_bulkxfer, link);
1662 	while  ((chunk = STAILQ_FIRST(&ir->stfree)) != NULL) {
1663 		struct fwohcidb *db;
1664 
1665 #if 1 /* XXX for if_fwe */
1666 		if (chunk->mbuf != NULL) {
1667 			db_tr = (struct fwohcidb_tr *)(chunk->start);
1668 			db_tr->dbcnt = 1;
1669 			err = bus_dmamap_load_mbuf(dbch->dmat, db_tr->dma_map,
1670 					chunk->mbuf, fwohci_execute_db2, db_tr,
1671 					/* flags */0);
1672  			FWOHCI_DMA_SET(db_tr->db[1].db.desc.cmd,
1673 				OHCI_UPDATE | OHCI_INPUT_LAST |
1674 				OHCI_INTERRUPT_ALWAYS | OHCI_BRANCH_ALWAYS);
1675 		}
1676 #endif
1677 		db = ((struct fwohcidb_tr *)(chunk->end))->db;
1678 		FWOHCI_DMA_WRITE(db[ldesc].db.desc.res, 0);
1679 		FWOHCI_DMA_CLEAR(db[ldesc].db.desc.depend, 0xf);
1680 		if (prev != NULL) {
1681 			db = ((struct fwohcidb_tr *)(prev->end))->db;
1682 			FWOHCI_DMA_SET(db[ldesc].db.desc.depend, dbch->ndesc);
1683 		}
1684 		STAILQ_REMOVE_HEAD(&ir->stfree, link);
1685 		STAILQ_INSERT_TAIL(&ir->stdma, chunk, link);
1686 		prev = chunk;
1687 	}
1688 	if ((ir->flag & FWXFERQ_HANDLER) == 0)
1689 		FW_GUNLOCK(fc);
1690 	fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREWRITE);
1691 	fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREREAD);
1692 	splx(s);
1693 	stat = OREAD(sc, OHCI_IRCTL(dmach));
1694 	if (stat & OHCI_CNTL_DMA_ACTIVE)
1695 		return 0;
1696 	if (stat & OHCI_CNTL_DMA_RUN) {
1697 		OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
1698 		device_printf(sc->fc.dev, "IR DMA overrun (0x%08x)\n", stat);
1699 	}
1700 
1701 	if (firewire_debug)
1702 		printf("start IR DMA 0x%x\n", stat);
1703 	OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach);
1704 	OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach);
1705 	OWRITE(sc, OHCI_IR_MASK, 1 << dmach);
1706 	OWRITE(sc, OHCI_IRCTLCLR(dmach), 0xf0000000);
1707 	OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_ISOHDR);
1708 	OWRITE(sc, OHCI_IRCMD(dmach),
1709 		((struct fwohcidb_tr *)(first->start))->bus_addr
1710 							| dbch->ndesc);
1711 	OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_DMA_RUN);
1712 	OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IR);
1713 #if 0
1714 	dump_db(sc, IRX_CH + dmach);
1715 #endif
1716 	return err;
1717 }
1718 
1719 int
1720 fwohci_stop(struct fwohci_softc *sc, device_t dev)
1721 {
1722 	u_int i;
1723 
1724 	fwohci_set_intr(&sc->fc, 0);
1725 
1726 /* Now stopping all DMA channel */
1727 	OWRITE(sc, OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN);
1728 	OWRITE(sc, OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN);
1729 	OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN);
1730 	OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
1731 
1732 	for (i = 0; i < sc->fc.nisodma; i++) {
1733 		OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN);
1734 		OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN);
1735 	}
1736 
1737 #if 0 /* Let dcons(4) be accessed */
1738 /* Stop interrupt */
1739 	OWRITE(sc, FWOHCI_INTMASKCLR,
1740 			OHCI_INT_EN | OHCI_INT_ERR | OHCI_INT_PHY_SID
1741 			| OHCI_INT_PHY_INT
1742 			| OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS
1743 			| OHCI_INT_DMA_PRRQ | OHCI_INT_DMA_PRRS
1744 			| OHCI_INT_DMA_ARRQ | OHCI_INT_DMA_ARRS
1745 			| OHCI_INT_PHY_BUS_R);
1746 
1747 /* FLUSH FIFO and reset Transmitter/Receiver */
1748 	OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_RESET);
1749 #endif
1750 
1751 /* XXX Link down?  Bus reset? */
1752 	return 0;
1753 }
1754 
1755 int
1756 fwohci_resume(struct fwohci_softc *sc, device_t dev)
1757 {
1758 	int i;
1759 	struct fw_xferq *ir;
1760 	struct fw_bulkxfer *chunk;
1761 
1762 	fwohci_reset(sc, dev);
1763 	/* XXX resume isochronous receive automatically. (how about TX?) */
1764 	for (i = 0; i < sc->fc.nisodma; i++) {
1765 		ir = &sc->ir[i].xferq;
1766 		if ((ir->flag & FWXFERQ_RUNNING) != 0) {
1767 			device_printf(sc->fc.dev,
1768 				"resume iso receive ch: %d\n", i);
1769 			ir->flag &= ~FWXFERQ_RUNNING;
1770 			/* requeue stdma to stfree */
1771 			while ((chunk = STAILQ_FIRST(&ir->stdma)) != NULL) {
1772 				STAILQ_REMOVE_HEAD(&ir->stdma, link);
1773 				STAILQ_INSERT_TAIL(&ir->stfree, chunk, link);
1774 			}
1775 			sc->fc.irx_enable(&sc->fc, i);
1776 		}
1777 	}
1778 
1779 	bus_generic_resume(dev);
1780 	sc->fc.ibr(&sc->fc);
1781 	return 0;
1782 }
1783 
1784 #ifdef OHCI_DEBUG
1785 static void
1786 fwohci_dump_intr(struct fwohci_softc *sc, uint32_t stat)
1787 {
1788 	if (stat & OREAD(sc, FWOHCI_INTMASK))
1789 		device_printf(fc->dev, "INTERRUPT < %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s> 0x%08x, 0x%08x\n",
1790 			stat & OHCI_INT_EN ? "DMA_EN ":"",
1791 			stat & OHCI_INT_PHY_REG ? "PHY_REG ":"",
1792 			stat & OHCI_INT_CYC_LONG ? "CYC_LONG ":"",
1793 			stat & OHCI_INT_ERR ? "INT_ERR ":"",
1794 			stat & OHCI_INT_CYC_ERR ? "CYC_ERR ":"",
1795 			stat & OHCI_INT_CYC_LOST ? "CYC_LOST ":"",
1796 			stat & OHCI_INT_CYC_64SECOND ? "CYC_64SECOND ":"",
1797 			stat & OHCI_INT_CYC_START ? "CYC_START ":"",
1798 			stat & OHCI_INT_PHY_INT ? "PHY_INT ":"",
1799 			stat & OHCI_INT_PHY_BUS_R ? "BUS_RESET ":"",
1800 			stat & OHCI_INT_PHY_SID ? "SID ":"",
1801 			stat & OHCI_INT_LR_ERR ? "DMA_LR_ERR ":"",
1802 			stat & OHCI_INT_PW_ERR ? "DMA_PW_ERR ":"",
1803 			stat & OHCI_INT_DMA_IR ? "DMA_IR ":"",
1804 			stat & OHCI_INT_DMA_IT  ? "DMA_IT " :"",
1805 			stat & OHCI_INT_DMA_PRRS  ? "DMA_PRRS " :"",
1806 			stat & OHCI_INT_DMA_PRRQ  ? "DMA_PRRQ " :"",
1807 			stat & OHCI_INT_DMA_ARRS  ? "DMA_ARRS " :"",
1808 			stat & OHCI_INT_DMA_ARRQ  ? "DMA_ARRQ " :"",
1809 			stat & OHCI_INT_DMA_ATRS  ? "DMA_ATRS " :"",
1810 			stat & OHCI_INT_DMA_ATRQ  ? "DMA_ATRQ " :"",
1811 			stat, OREAD(sc, FWOHCI_INTMASK)
1812 		);
1813 }
1814 #endif
1815 
1816 static void
1817 fwohci_intr_core(struct fwohci_softc *sc, uint32_t stat, int count)
1818 {
1819 	struct firewire_comm *fc = (struct firewire_comm *)sc;
1820 	uintmax_t prequpper;
1821 	uint32_t node_id, plen;
1822 
1823 	FW_GLOCK_ASSERT(fc);
1824 	if ((stat & OHCI_INT_PHY_BUS_R) && (fc->status != FWBUSRESET)) {
1825 		fc->status = FWBUSRESET;
1826 		/* Disable bus reset interrupt until sid recv. */
1827 		OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_PHY_BUS_R);
1828 
1829 		device_printf(fc->dev, "%s: BUS reset\n", __func__);
1830 		OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST);
1831 		OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCSRC);
1832 
1833 		OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN);
1834 		sc->atrq.xferq.flag &= ~FWXFERQ_RUNNING;
1835 		OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
1836 		sc->atrs.xferq.flag &= ~FWXFERQ_RUNNING;
1837 
1838 		if (!kdb_active)
1839 			taskqueue_enqueue(sc->fc.taskqueue, &sc->fwohci_task_busreset);
1840 	}
1841 	if (stat & OHCI_INT_PHY_SID) {
1842 		/* Enable bus reset interrupt */
1843 		OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_BUS_R);
1844 		OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_PHY_BUS_R);
1845 
1846 		/* Allow async. request to us */
1847 		OWRITE(sc, OHCI_AREQHI, 1 << 31);
1848 		if (firewire_phydma_enable) {
1849 			/* allow from all nodes */
1850 			OWRITE(sc, OHCI_PREQHI, 0x7fffffff);
1851 			OWRITE(sc, OHCI_PREQLO, 0xffffffff);
1852 			prequpper = ((uintmax_t)Maxmem << PAGE_SHIFT) >> 16;
1853 			if (prequpper > OHCI_PREQUPPER_MAX) {
1854 				device_printf(fc->dev,
1855 				    "Physical memory size of 0x%jx exceeds "
1856 				    "fire wire address space.  Limiting dma "
1857 				    "to memory below 0x%jx\n",
1858 				    (uintmax_t)Maxmem << PAGE_SHIFT,
1859 				    (uintmax_t)OHCI_PREQUPPER_MAX << 16);
1860 				prequpper = OHCI_PREQUPPER_MAX;
1861 			}
1862 			OWRITE(sc, OHCI_PREQUPPER, prequpper & 0xffffffff);
1863 			if (OREAD(sc, OHCI_PREQUPPER) !=
1864 			    (prequpper & 0xffffffff)) {
1865 				device_printf(fc->dev,
1866 				   "PhysicalUpperBound register is not "
1867 				   "implemented.  Physical memory access "
1868 				   "is limited to the first 4GB\n");
1869 				device_printf(fc->dev,
1870 				   "PhysicalUpperBound = 0x%08x\n",
1871 				    OREAD(sc, OHCI_PREQUPPER));
1872 			}
1873 		}
1874 		/* Set ATRetries register */
1875 		OWRITE(sc, OHCI_ATRETRY, 1<<(13 + 16) | 0xfff);
1876 
1877 		/*
1878 		 * Checking whether the node is root or not. If root, turn on
1879 		 * cycle master.
1880 		 */
1881 		node_id = OREAD(sc, FWOHCI_NODEID);
1882 		plen = OREAD(sc, OHCI_SID_CNT);
1883 
1884 		fc->nodeid = node_id & 0x3f;
1885 		device_printf(fc->dev, "%s: node_id=0x%08x, SelfID Count=%d, ",
1886 				__func__, fc->nodeid, (plen >> 16) & 0xff);
1887 		if (!(node_id & OHCI_NODE_VALID)) {
1888 			device_printf(fc->dev, "%s: Bus reset failure\n",
1889 				__func__);
1890 			goto sidout;
1891 		}
1892 
1893 		/* cycle timer */
1894 		sc->cycle_lost = 0;
1895 		OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_CYC_LOST);
1896 		if ((node_id & OHCI_NODE_ROOT) && !nocyclemaster) {
1897 			printf("CYCLEMASTER mode\n");
1898 			OWRITE(sc, OHCI_LNKCTL,
1899 				OHCI_CNTL_CYCMTR | OHCI_CNTL_CYCTIMER);
1900 		} else {
1901 			printf("non CYCLEMASTER mode\n");
1902 			OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCMTR);
1903 			OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_CYCTIMER);
1904 		}
1905 
1906 		fc->status = FWBUSINIT;
1907 
1908 		if (!kdb_active)
1909 			taskqueue_enqueue(sc->fc.taskqueue, &sc->fwohci_task_sid);
1910 	}
1911 sidout:
1912 	if ((stat & ~(OHCI_INT_PHY_BUS_R | OHCI_INT_PHY_SID)) && (!kdb_active))
1913 		taskqueue_enqueue(sc->fc.taskqueue, &sc->fwohci_task_dma);
1914 }
1915 
1916 static void
1917 fwohci_intr_dma(struct fwohci_softc *sc, uint32_t stat, int count)
1918 {
1919 	uint32_t irstat, itstat;
1920 	u_int i;
1921 	struct firewire_comm *fc = (struct firewire_comm *)sc;
1922 
1923 	if (stat & OHCI_INT_DMA_IR) {
1924 		irstat = atomic_readandclear_int(&sc->irstat);
1925 		for (i = 0; i < fc->nisodma; i++) {
1926 			struct fwohci_dbch *dbch;
1927 
1928 			if ((irstat & (1 << i)) != 0) {
1929 				dbch = &sc->ir[i];
1930 				if ((dbch->xferq.flag & FWXFERQ_OPEN) == 0) {
1931 					device_printf(sc->fc.dev,
1932 						"dma(%d) not active\n", i);
1933 					continue;
1934 				}
1935 				fwohci_rbuf_update(sc, i);
1936 			}
1937 		}
1938 	}
1939 	if (stat & OHCI_INT_DMA_IT) {
1940 		itstat = atomic_readandclear_int(&sc->itstat);
1941 		for (i = 0; i < fc->nisodma; i++) {
1942 			if ((itstat & (1 << i)) != 0) {
1943 				fwohci_tbuf_update(sc, i);
1944 			}
1945 		}
1946 	}
1947 	if (stat & OHCI_INT_DMA_PRRS) {
1948 #if 0
1949 		dump_dma(sc, ARRS_CH);
1950 		dump_db(sc, ARRS_CH);
1951 #endif
1952 		fwohci_arcv(sc, &sc->arrs, count);
1953 	}
1954 	if (stat & OHCI_INT_DMA_PRRQ) {
1955 #if 0
1956 		dump_dma(sc, ARRQ_CH);
1957 		dump_db(sc, ARRQ_CH);
1958 #endif
1959 		fwohci_arcv(sc, &sc->arrq, count);
1960 	}
1961 	if (stat & OHCI_INT_CYC_LOST) {
1962 		if (sc->cycle_lost >= 0)
1963 			sc->cycle_lost++;
1964 		if (sc->cycle_lost > 10) {
1965 			sc->cycle_lost = -1;
1966 #if 0
1967 			OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCTIMER);
1968 #endif
1969 			OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST);
1970 			device_printf(fc->dev, "too many cycles lost, "
1971 			 "no cycle master present?\n");
1972 		}
1973 	}
1974 	if (stat & OHCI_INT_DMA_ATRQ) {
1975 		fwohci_txd(sc, &(sc->atrq));
1976 	}
1977 	if (stat & OHCI_INT_DMA_ATRS) {
1978 		fwohci_txd(sc, &(sc->atrs));
1979 	}
1980 	if (stat & OHCI_INT_PW_ERR) {
1981 		device_printf(fc->dev, "posted write error\n");
1982 	}
1983 	if (stat & OHCI_INT_ERR) {
1984 		device_printf(fc->dev, "unrecoverable error\n");
1985 	}
1986 	if (stat & OHCI_INT_PHY_INT) {
1987 		device_printf(fc->dev, "phy int\n");
1988 	}
1989 }
1990 
1991 static void
1992 fwohci_task_busreset(void *arg, int pending)
1993 {
1994 	struct fwohci_softc *sc = (struct fwohci_softc *)arg;
1995 
1996 	FW_GLOCK(&sc->fc);
1997 	fw_busreset(&sc->fc, FWBUSRESET);
1998 	OWRITE(sc, OHCI_CROMHDR, ntohl(sc->fc.config_rom[0]));
1999 	OWRITE(sc, OHCI_BUS_OPT, ntohl(sc->fc.config_rom[2]));
2000 	FW_GUNLOCK(&sc->fc);
2001 }
2002 
2003 static void
2004 fwohci_task_sid(void *arg, int pending)
2005 {
2006 	struct fwohci_softc *sc = (struct fwohci_softc *)arg;
2007 	struct firewire_comm *fc = &sc->fc;
2008 	uint32_t *buf;
2009 	int i, plen;
2010 
2011 
2012 	/*
2013 	 * We really should have locking
2014 	 * here.  Not sure why it's not
2015 	 */
2016 	plen = OREAD(sc, OHCI_SID_CNT);
2017 
2018 	if (plen & OHCI_SID_ERR) {
2019 		device_printf(fc->dev, "SID Error\n");
2020 		return;
2021 	}
2022 	plen &= OHCI_SID_CNT_MASK;
2023 	if (plen < 4 || plen > OHCI_SIDSIZE) {
2024 		device_printf(fc->dev, "invalid SID len = %d\n", plen);
2025 		return;
2026 	}
2027 	plen -= 4; /* chop control info */
2028 	buf = (uint32_t *)malloc(OHCI_SIDSIZE, M_FW, M_NOWAIT);
2029 	if (buf == NULL) {
2030 		device_printf(fc->dev, "malloc failed\n");
2031 		return;
2032 	}
2033 	for (i = 0; i < plen / 4; i++)
2034 		buf[i] = FWOHCI_DMA_READ(sc->sid_buf[i + 1]);
2035 
2036 	/* pending all pre-bus_reset packets */
2037 	fwohci_txd(sc, &sc->atrq);
2038 	fwohci_txd(sc, &sc->atrs);
2039 	fwohci_arcv(sc, &sc->arrs, -1);
2040 	fwohci_arcv(sc, &sc->arrq, -1);
2041 	fw_drain_txq(fc);
2042 	fw_sidrcv(fc, buf, plen);
2043 	free(buf, M_FW);
2044 }
2045 
2046 static void
2047 fwohci_task_dma(void *arg, int pending)
2048 {
2049 	struct fwohci_softc *sc = (struct fwohci_softc *)arg;
2050 	uint32_t stat;
2051 
2052 again:
2053 	stat = atomic_readandclear_int(&sc->intstat);
2054 	if (stat)
2055 		fwohci_intr_dma(sc, stat, -1);
2056 	else
2057 		return;
2058 	goto again;
2059 }
2060 
2061 static int
2062 fwohci_check_stat(struct fwohci_softc *sc)
2063 {
2064 	uint32_t stat, irstat, itstat;
2065 
2066 	FW_GLOCK_ASSERT(&sc->fc);
2067 	stat = OREAD(sc, FWOHCI_INTSTAT);
2068 	if (stat == 0xffffffff) {
2069 		if (!bus_child_present(sc->fc.dev))
2070 			return (FILTER_HANDLED);
2071 		device_printf(sc->fc.dev, "device physically ejected?\n");
2072 		return (FILTER_STRAY);
2073 	}
2074 	if (stat)
2075 		OWRITE(sc, FWOHCI_INTSTATCLR, stat & ~OHCI_INT_PHY_BUS_R);
2076 
2077 	stat &= sc->intmask;
2078 	if (stat == 0)
2079 		return (FILTER_STRAY);
2080 
2081 	atomic_set_int(&sc->intstat, stat);
2082 	if (stat & OHCI_INT_DMA_IR) {
2083 		irstat = OREAD(sc, OHCI_IR_STAT);
2084 		OWRITE(sc, OHCI_IR_STATCLR, irstat);
2085 		atomic_set_int(&sc->irstat, irstat);
2086 	}
2087 	if (stat & OHCI_INT_DMA_IT) {
2088 		itstat = OREAD(sc, OHCI_IT_STAT);
2089 		OWRITE(sc, OHCI_IT_STATCLR, itstat);
2090 		atomic_set_int(&sc->itstat, itstat);
2091 	}
2092 
2093 	fwohci_intr_core(sc, stat, -1);
2094 	return (FILTER_HANDLED);
2095 }
2096 
2097 void
2098 fwohci_intr(void *arg)
2099 {
2100 	struct fwohci_softc *sc = (struct fwohci_softc *)arg;
2101 
2102 	FW_GLOCK(&sc->fc);
2103 	fwohci_check_stat(sc);
2104 	FW_GUNLOCK(&sc->fc);
2105 }
2106 
2107 void
2108 fwohci_poll(struct firewire_comm *fc, int quick, int count)
2109 {
2110 	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
2111 
2112 	FW_GLOCK(fc);
2113 	fwohci_check_stat(sc);
2114 	FW_GUNLOCK(fc);
2115 }
2116 
2117 static void
2118 fwohci_set_intr(struct firewire_comm *fc, int enable)
2119 {
2120 	struct fwohci_softc *sc;
2121 
2122 	sc = (struct fwohci_softc *)fc;
2123 	if (firewire_debug)
2124 		device_printf(sc->fc.dev, "fwohci_set_intr: %d\n", enable);
2125 	if (enable) {
2126 		sc->intmask |= OHCI_INT_EN;
2127 		OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_EN);
2128 	} else {
2129 		sc->intmask &= ~OHCI_INT_EN;
2130 		OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_EN);
2131 	}
2132 }
2133 
2134 static void
2135 fwohci_tbuf_update(struct fwohci_softc *sc, int dmach)
2136 {
2137 	struct firewire_comm *fc = &sc->fc;
2138 	struct fwohcidb *db;
2139 	struct fw_bulkxfer *chunk;
2140 	struct fw_xferq *it;
2141 	uint32_t stat, count;
2142 	int s, w=0, ldesc;
2143 
2144 	it = fc->it[dmach];
2145 	ldesc = sc->it[dmach].ndesc - 1;
2146 	s = splfw(); /* unnecessary ? */
2147 	FW_GLOCK(fc);
2148 	fwdma_sync_multiseg_all(sc->it[dmach].am, BUS_DMASYNC_POSTREAD);
2149 	if (firewire_debug)
2150 		dump_db(sc, ITX_CH + dmach);
2151 	while ((chunk = STAILQ_FIRST(&it->stdma)) != NULL) {
2152 		db = ((struct fwohcidb_tr *)(chunk->end))->db;
2153 		stat = FWOHCI_DMA_READ(db[ldesc].db.desc.res)
2154 				>> OHCI_STATUS_SHIFT;
2155 		db = ((struct fwohcidb_tr *)(chunk->start))->db;
2156 		/* timestamp */
2157 		count = FWOHCI_DMA_READ(db[ldesc].db.desc.res)
2158 				& OHCI_COUNT_MASK;
2159 		if (stat == 0)
2160 			break;
2161 		STAILQ_REMOVE_HEAD(&it->stdma, link);
2162 		switch (stat & FWOHCIEV_MASK) {
2163 		case FWOHCIEV_ACKCOMPL:
2164 #if 0
2165 			device_printf(fc->dev, "0x%08x\n", count);
2166 #endif
2167 			break;
2168 		default:
2169 			device_printf(fc->dev,
2170 				"Isochronous transmit err %02x(%s)\n",
2171 					stat, fwohcicode[stat & 0x1f]);
2172 		}
2173 		STAILQ_INSERT_TAIL(&it->stfree, chunk, link);
2174 		w++;
2175 	}
2176 	FW_GUNLOCK(fc);
2177 	splx(s);
2178 	if (w)
2179 		wakeup(it);
2180 }
2181 
2182 static void
2183 fwohci_rbuf_update(struct fwohci_softc *sc, int dmach)
2184 {
2185 	struct firewire_comm *fc = &sc->fc;
2186 	struct fwohcidb_tr *db_tr;
2187 	struct fw_bulkxfer *chunk;
2188 	struct fw_xferq *ir;
2189 	uint32_t stat;
2190 	int w = 0, ldesc;
2191 
2192 	ir = fc->ir[dmach];
2193 	ldesc = sc->ir[dmach].ndesc - 1;
2194 
2195 #if 0
2196 	dump_db(sc, dmach);
2197 #endif
2198 	if ((ir->flag & FWXFERQ_HANDLER) == 0)
2199 		FW_GLOCK(fc);
2200 	fwdma_sync_multiseg_all(sc->ir[dmach].am, BUS_DMASYNC_POSTREAD);
2201 	while ((chunk = STAILQ_FIRST(&ir->stdma)) != NULL) {
2202 		db_tr = (struct fwohcidb_tr *)chunk->end;
2203 		stat = FWOHCI_DMA_READ(db_tr->db[ldesc].db.desc.res)
2204 				>> OHCI_STATUS_SHIFT;
2205 		if (stat == 0)
2206 			break;
2207 
2208 		if (chunk->mbuf != NULL) {
2209 			bus_dmamap_sync(sc->ir[dmach].dmat, db_tr->dma_map,
2210 						BUS_DMASYNC_POSTREAD);
2211 			bus_dmamap_unload(sc->ir[dmach].dmat, db_tr->dma_map);
2212 		} else if (ir->buf != NULL) {
2213 			fwdma_sync_multiseg(ir->buf, chunk->poffset,
2214 				ir->bnpacket, BUS_DMASYNC_POSTREAD);
2215 		} else {
2216 			/* XXX */
2217 			printf("fwohci_rbuf_update: this shouldn't happened\n");
2218 		}
2219 
2220 		STAILQ_REMOVE_HEAD(&ir->stdma, link);
2221 		STAILQ_INSERT_TAIL(&ir->stvalid, chunk, link);
2222 		switch (stat & FWOHCIEV_MASK) {
2223 		case FWOHCIEV_ACKCOMPL:
2224 			chunk->resp = 0;
2225 			break;
2226 		default:
2227 			chunk->resp = EINVAL;
2228 			device_printf(fc->dev,
2229 				"Isochronous receive err %02x(%s)\n",
2230 					stat, fwohcicode[stat & 0x1f]);
2231 		}
2232 		w++;
2233 	}
2234 	if ((ir->flag & FWXFERQ_HANDLER) == 0)
2235 		FW_GUNLOCK(fc);
2236 	if (w == 0)
2237 		return;
2238 
2239 	if (ir->flag & FWXFERQ_HANDLER)
2240 		ir->hand(ir);
2241 	else
2242 		wakeup(ir);
2243 }
2244 
2245 void
2246 dump_dma(struct fwohci_softc *sc, uint32_t ch)
2247 {
2248 	uint32_t off, cntl, stat, cmd, match;
2249 
2250 	if (ch == 0) {
2251 		off = OHCI_ATQOFF;
2252 	} else if (ch == 1) {
2253 		off = OHCI_ATSOFF;
2254 	} else if (ch == 2) {
2255 		off = OHCI_ARQOFF;
2256 	} else if (ch == 3) {
2257 		off = OHCI_ARSOFF;
2258 	} else if (ch < IRX_CH) {
2259 		off = OHCI_ITCTL(ch - ITX_CH);
2260 	} else {
2261 		off = OHCI_IRCTL(ch - IRX_CH);
2262 	}
2263 	cntl = stat = OREAD(sc, off);
2264 	cmd = OREAD(sc, off + 0xc);
2265 	match = OREAD(sc, off + 0x10);
2266 
2267 	device_printf(sc->fc.dev, "ch %1x cntl:0x%08x cmd:0x%08x match:0x%08x\n",
2268 		ch,
2269 		cntl,
2270 		cmd,
2271 		match);
2272 	stat &= 0xffff;
2273 	if (stat) {
2274 		device_printf(sc->fc.dev, "dma %d ch:%s%s%s%s%s%s %s(%x)\n",
2275 			ch,
2276 			stat & OHCI_CNTL_DMA_RUN ? "RUN," : "",
2277 			stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "",
2278 			stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "",
2279 			stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "",
2280 			stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "",
2281 			stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "",
2282 			fwohcicode[stat & 0x1f],
2283 			stat & 0x1f
2284 		);
2285 	} else {
2286 		device_printf(sc->fc.dev, "dma %d ch: Nostat\n", ch);
2287 	}
2288 }
2289 
2290 void
2291 dump_db(struct fwohci_softc *sc, uint32_t ch)
2292 {
2293 	struct fwohci_dbch *dbch;
2294 	struct fwohcidb_tr *cp = NULL, *pp, *np = NULL;
2295 	struct fwohcidb *curr = NULL, *prev, *next = NULL;
2296 	int idb, jdb;
2297 	uint32_t cmd, off;
2298 
2299 	if (ch == 0) {
2300 		off = OHCI_ATQOFF;
2301 		dbch = &sc->atrq;
2302 	} else if (ch == 1) {
2303 		off = OHCI_ATSOFF;
2304 		dbch = &sc->atrs;
2305 	} else if (ch == 2) {
2306 		off = OHCI_ARQOFF;
2307 		dbch = &sc->arrq;
2308 	} else if (ch == 3) {
2309 		off = OHCI_ARSOFF;
2310 		dbch = &sc->arrs;
2311 	} else if (ch < IRX_CH) {
2312 		off = OHCI_ITCTL(ch - ITX_CH);
2313 		dbch = &sc->it[ch - ITX_CH];
2314 	} else {
2315 		off = OHCI_IRCTL(ch - IRX_CH);
2316 		dbch = &sc->ir[ch - IRX_CH];
2317 	}
2318 	cmd = OREAD(sc, off + 0xc);
2319 
2320 	if (dbch->ndb == 0) {
2321 		device_printf(sc->fc.dev, "No DB is attached ch=%d\n", ch);
2322 		return;
2323 	}
2324 	pp = dbch->top;
2325 	prev = pp->db;
2326 	for (idb = 0; idb < dbch->ndb; idb++) {
2327 		cp = STAILQ_NEXT(pp, link);
2328 		if (cp == NULL) {
2329 			curr = NULL;
2330 			goto outdb;
2331 		}
2332 		np = STAILQ_NEXT(cp, link);
2333 		for (jdb = 0; jdb < dbch->ndesc; jdb++) {
2334 			if ((cmd  & 0xfffffff0) == cp->bus_addr) {
2335 				curr = cp->db;
2336 				if (np != NULL) {
2337 					next = np->db;
2338 				} else {
2339 					next = NULL;
2340 				}
2341 				goto outdb;
2342 			}
2343 		}
2344 		pp = STAILQ_NEXT(pp, link);
2345 		if (pp == NULL) {
2346 			curr = NULL;
2347 			goto outdb;
2348 		}
2349 		prev = pp->db;
2350 	}
2351 outdb:
2352 	if (curr != NULL) {
2353 #if 0
2354 		printf("Prev DB %d\n", ch);
2355 		print_db(pp, prev, ch, dbch->ndesc);
2356 #endif
2357 		printf("Current DB %d\n", ch);
2358 		print_db(cp, curr, ch, dbch->ndesc);
2359 #if 0
2360 		printf("Next DB %d\n", ch);
2361 		print_db(np, next, ch, dbch->ndesc);
2362 #endif
2363 	} else {
2364 		printf("dbdump err ch = %d cmd = 0x%08x\n", ch, cmd);
2365 	}
2366 	return;
2367 }
2368 
2369 void
2370 print_db(struct fwohcidb_tr *db_tr, struct fwohcidb *db,
2371 		uint32_t ch, uint32_t max)
2372 {
2373 	fwohcireg_t stat;
2374 	int i, key;
2375 	uint32_t cmd, res;
2376 
2377 	if (db == NULL) {
2378 		printf("No Descriptor is found\n");
2379 		return;
2380 	}
2381 
2382 	printf("ch = %d\n%8s %s %s %s %s %4s %8s %8s %4s:%4s\n",
2383 		ch,
2384 		"Current",
2385 		"OP  ",
2386 		"KEY",
2387 		"INT",
2388 		"BR ",
2389 		"len",
2390 		"Addr",
2391 		"Depend",
2392 		"Stat",
2393 		"Cnt");
2394 	for (i = 0; i <= max; i++) {
2395 		cmd = FWOHCI_DMA_READ(db[i].db.desc.cmd);
2396 		res = FWOHCI_DMA_READ(db[i].db.desc.res);
2397 		key = cmd & OHCI_KEY_MASK;
2398 		stat = res >> OHCI_STATUS_SHIFT;
2399 		printf("%08jx %s %s %s %s %5d %08x %08x %04x:%04x",
2400 				(uintmax_t)db_tr->bus_addr,
2401 				dbcode[(cmd >> 28) & 0xf],
2402 				dbkey[(cmd >> 24) & 0x7],
2403 				dbcond[(cmd >> 20) & 0x3],
2404 				dbcond[(cmd >> 18) & 0x3],
2405 				cmd & OHCI_COUNT_MASK,
2406 				FWOHCI_DMA_READ(db[i].db.desc.addr),
2407 				FWOHCI_DMA_READ(db[i].db.desc.depend),
2408 				stat,
2409 				res & OHCI_COUNT_MASK);
2410 		if (stat & 0xff00) {
2411 			printf(" %s%s%s%s%s%s %s(%x)\n",
2412 				stat & OHCI_CNTL_DMA_RUN ? "RUN," : "",
2413 				stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "",
2414 				stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "",
2415 				stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "",
2416 				stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "",
2417 				stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "",
2418 				fwohcicode[stat & 0x1f],
2419 				stat & 0x1f
2420 			);
2421 		} else {
2422 			printf(" Nostat\n");
2423 		}
2424 		if (key == OHCI_KEY_ST2) {
2425 			printf("0x%08x 0x%08x 0x%08x 0x%08x\n",
2426 				FWOHCI_DMA_READ(db[i + 1].db.immed[0]),
2427 				FWOHCI_DMA_READ(db[i + 1].db.immed[1]),
2428 				FWOHCI_DMA_READ(db[i + 1].db.immed[2]),
2429 				FWOHCI_DMA_READ(db[i + 1].db.immed[3]));
2430 		}
2431 		if (key == OHCI_KEY_DEVICE) {
2432 			return;
2433 		}
2434 		if ((cmd & OHCI_BRANCH_MASK)
2435 				== OHCI_BRANCH_ALWAYS) {
2436 			return;
2437 		}
2438 		if ((cmd & OHCI_CMD_MASK)
2439 				== OHCI_OUTPUT_LAST) {
2440 			return;
2441 		}
2442 		if ((cmd & OHCI_CMD_MASK)
2443 				== OHCI_INPUT_LAST) {
2444 			return;
2445 		}
2446 		if (key == OHCI_KEY_ST2) {
2447 			i++;
2448 		}
2449 	}
2450 	return;
2451 }
2452 
2453 void
2454 fwohci_ibr(struct firewire_comm *fc)
2455 {
2456 	struct fwohci_softc *sc;
2457 	uint32_t fun;
2458 
2459 	device_printf(fc->dev, "Initiate bus reset\n");
2460 	sc = (struct fwohci_softc *)fc;
2461 
2462 	FW_GLOCK(fc);
2463 	/*
2464 	 * Make sure our cached values from the config rom are
2465 	 * initialised.
2466 	 */
2467 	OWRITE(sc, OHCI_CROMHDR, ntohl(sc->fc.config_rom[0]));
2468 	OWRITE(sc, OHCI_BUS_OPT, ntohl(sc->fc.config_rom[2]));
2469 
2470 	/*
2471 	 * Set root hold-off bit so that non cyclemaster capable node
2472 	 * shouldn't became the root node.
2473 	 */
2474 #if 1
2475 	fun = fwphy_rddata(sc, FW_PHY_IBR_REG);
2476 	fun |= FW_PHY_IBR | FW_PHY_RHB;
2477 	fun = fwphy_wrdata(sc, FW_PHY_IBR_REG, fun);
2478 #else	/* Short bus reset */
2479 	fun = fwphy_rddata(sc, FW_PHY_ISBR_REG);
2480 	fun |= FW_PHY_ISBR | FW_PHY_RHB;
2481 	fun = fwphy_wrdata(sc, FW_PHY_ISBR_REG, fun);
2482 #endif
2483 	FW_GUNLOCK(fc);
2484 }
2485 
2486 void
2487 fwohci_txbufdb(struct fwohci_softc *sc, int dmach, struct fw_bulkxfer *bulkxfer)
2488 {
2489 	struct fwohcidb_tr *db_tr, *fdb_tr;
2490 	struct fwohci_dbch *dbch;
2491 	struct fwohcidb *db;
2492 	struct fw_pkt *fp;
2493 	struct fwohci_txpkthdr *ohcifp;
2494 	unsigned short chtag;
2495 	int idb;
2496 
2497 	FW_GLOCK_ASSERT(&sc->fc);
2498 
2499 	dbch = &sc->it[dmach];
2500 	chtag = sc->it[dmach].xferq.flag & 0xff;
2501 
2502 	db_tr = (struct fwohcidb_tr *)(bulkxfer->start);
2503 	fdb_tr = (struct fwohcidb_tr *)(bulkxfer->end);
2504 /*
2505 device_printf(sc->fc.dev, "DB %08x %08x %08x\n", bulkxfer, db_tr->bus_addr, fdb_tr->bus_addr);
2506 */
2507 	for (idb = 0; idb < dbch->xferq.bnpacket; idb++) {
2508 		db = db_tr->db;
2509 		fp = (struct fw_pkt *)db_tr->buf;
2510 		ohcifp = (struct fwohci_txpkthdr *) db[1].db.immed;
2511 		ohcifp->mode.ld[0] = fp->mode.ld[0];
2512 		ohcifp->mode.common.spd = 0 & 0x7;
2513 		ohcifp->mode.stream.len = fp->mode.stream.len;
2514 		ohcifp->mode.stream.chtag = chtag;
2515 		ohcifp->mode.stream.tcode = 0xa;
2516 #if BYTE_ORDER == BIG_ENDIAN
2517 		FWOHCI_DMA_WRITE(db[1].db.immed[0], db[1].db.immed[0]);
2518 		FWOHCI_DMA_WRITE(db[1].db.immed[1], db[1].db.immed[1]);
2519 #endif
2520 
2521 		FWOHCI_DMA_CLEAR(db[2].db.desc.cmd, OHCI_COUNT_MASK);
2522 		FWOHCI_DMA_SET(db[2].db.desc.cmd, fp->mode.stream.len);
2523 		FWOHCI_DMA_WRITE(db[2].db.desc.res, 0);
2524 #if 0 /* if bulkxfer->npackets changes */
2525 		db[2].db.desc.cmd = OHCI_OUTPUT_LAST
2526 			| OHCI_UPDATE
2527 			| OHCI_BRANCH_ALWAYS;
2528 		db[0].db.desc.depend =
2529 			= db[dbch->ndesc - 1].db.desc.depend
2530 			= STAILQ_NEXT(db_tr, link)->bus_addr | dbch->ndesc;
2531 #else
2532 		FWOHCI_DMA_SET(db[0].db.desc.depend, dbch->ndesc);
2533 		FWOHCI_DMA_SET(db[dbch->ndesc - 1].db.desc.depend, dbch->ndesc);
2534 #endif
2535 		bulkxfer->end = (caddr_t)db_tr;
2536 		db_tr = STAILQ_NEXT(db_tr, link);
2537 	}
2538 	db = ((struct fwohcidb_tr *)bulkxfer->end)->db;
2539 	FWOHCI_DMA_CLEAR(db[0].db.desc.depend, 0xf);
2540 	FWOHCI_DMA_CLEAR(db[dbch->ndesc - 1].db.desc.depend, 0xf);
2541 #if 0 /* if bulkxfer->npackets changes */
2542 	db[dbch->ndesc - 1].db.desc.control |= OHCI_INTERRUPT_ALWAYS;
2543 	/* OHCI 1.1 and above */
2544 	db[0].db.desc.control |= OHCI_INTERRUPT_ALWAYS;
2545 #endif
2546 /*
2547 	db_tr = (struct fwohcidb_tr *)bulkxfer->start;
2548 	fdb_tr = (struct fwohcidb_tr *)bulkxfer->end;
2549 device_printf(sc->fc.dev, "DB %08x %3d %08x %08x\n", bulkxfer, bulkxfer->npacket, db_tr->bus_addr, fdb_tr->bus_addr);
2550 */
2551 	return;
2552 }
2553 
2554 static int
2555 fwohci_add_tx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr,
2556 								int poffset)
2557 {
2558 	struct fwohcidb *db = db_tr->db;
2559 	struct fw_xferq *it;
2560 	int err = 0;
2561 
2562 	it = &dbch->xferq;
2563 	if (it->buf == 0) {
2564 		err = EINVAL;
2565 		return err;
2566 	}
2567 	db_tr->buf = fwdma_v_addr(it->buf, poffset);
2568 	db_tr->dbcnt = 3;
2569 
2570 	FWOHCI_DMA_WRITE(db[0].db.desc.cmd,
2571 		OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | 8);
2572 	FWOHCI_DMA_WRITE(db[0].db.desc.addr, 0);
2573 	bzero((void *)&db[1].db.immed[0], sizeof(db[1].db.immed));
2574 	FWOHCI_DMA_WRITE(db[2].db.desc.addr,
2575 	fwdma_bus_addr(it->buf, poffset) + sizeof(uint32_t));
2576 
2577 	FWOHCI_DMA_WRITE(db[2].db.desc.cmd,
2578 		OHCI_OUTPUT_LAST | OHCI_UPDATE | OHCI_BRANCH_ALWAYS);
2579 #if 1
2580 	FWOHCI_DMA_WRITE(db[0].db.desc.res, 0);
2581 	FWOHCI_DMA_WRITE(db[2].db.desc.res, 0);
2582 #endif
2583 	return 0;
2584 }
2585 
2586 int
2587 fwohci_add_rx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr,
2588 		int poffset, struct fwdma_alloc *dummy_dma)
2589 {
2590 	struct fwohcidb *db = db_tr->db;
2591 	struct fw_xferq *ir;
2592 	int i, ldesc;
2593 	bus_addr_t dbuf[2];
2594 	int dsiz[2];
2595 
2596 	ir = &dbch->xferq;
2597 	if (ir->buf == NULL && (dbch->xferq.flag & FWXFERQ_EXTBUF) == 0) {
2598 		if (db_tr->buf == NULL) {
2599 			db_tr->buf = fwdma_malloc_size(dbch->dmat,
2600 			    &db_tr->dma_map, ir->psize, &dbuf[0],
2601 			    BUS_DMA_NOWAIT);
2602 			if (db_tr->buf == NULL)
2603 				return (ENOMEM);
2604 		}
2605 		db_tr->dbcnt = 1;
2606 		dsiz[0] = ir->psize;
2607 		bus_dmamap_sync(dbch->dmat, db_tr->dma_map,
2608 			BUS_DMASYNC_PREREAD);
2609 	} else {
2610 		db_tr->dbcnt = 0;
2611 		if (dummy_dma != NULL) {
2612 			dsiz[db_tr->dbcnt] = sizeof(uint32_t);
2613 			dbuf[db_tr->dbcnt++] = dummy_dma->bus_addr;
2614 		}
2615 		dsiz[db_tr->dbcnt] = ir->psize;
2616 		if (ir->buf != NULL) {
2617 			db_tr->buf = fwdma_v_addr(ir->buf, poffset);
2618 			dbuf[db_tr->dbcnt] = fwdma_bus_addr(ir->buf, poffset);
2619 		}
2620 		db_tr->dbcnt++;
2621 	}
2622 	for (i = 0; i < db_tr->dbcnt; i++) {
2623 		FWOHCI_DMA_WRITE(db[i].db.desc.addr, dbuf[i]);
2624 		FWOHCI_DMA_WRITE(db[i].db.desc.cmd, OHCI_INPUT_MORE | dsiz[i]);
2625 		if (ir->flag & FWXFERQ_STREAM) {
2626 			FWOHCI_DMA_SET(db[i].db.desc.cmd, OHCI_UPDATE);
2627 		}
2628 		FWOHCI_DMA_WRITE(db[i].db.desc.res, dsiz[i]);
2629 	}
2630 	ldesc = db_tr->dbcnt - 1;
2631 	if (ir->flag & FWXFERQ_STREAM) {
2632 		FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, OHCI_INPUT_LAST);
2633 	}
2634 	FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, OHCI_BRANCH_ALWAYS);
2635 	return 0;
2636 }
2637 
2638 
2639 static int
2640 fwohci_arcv_swap(struct fw_pkt *fp, int len)
2641 {
2642 	struct fw_pkt *fp0;
2643 	uint32_t ld0;
2644 	int slen, hlen;
2645 #if BYTE_ORDER == BIG_ENDIAN
2646 	int i;
2647 #endif
2648 
2649 	ld0 = FWOHCI_DMA_READ(fp->mode.ld[0]);
2650 #if 0
2651 	printf("ld0: x%08x\n", ld0);
2652 #endif
2653 	fp0 = (struct fw_pkt *)&ld0;
2654 	/* determine length to swap */
2655 	switch (fp0->mode.common.tcode) {
2656 	case FWTCODE_RREQQ:
2657 	case FWTCODE_WRES:
2658 	case FWTCODE_WREQQ:
2659 	case FWTCODE_RRESQ:
2660 	case FWOHCITCODE_PHY:
2661 		slen = 12;
2662 		break;
2663 	case FWTCODE_RREQB:
2664 	case FWTCODE_WREQB:
2665 	case FWTCODE_LREQ:
2666 	case FWTCODE_RRESB:
2667 	case FWTCODE_LRES:
2668 		slen = 16;
2669 		break;
2670 	default:
2671 		printf("Unknown tcode %d\n", fp0->mode.common.tcode);
2672 		return (0);
2673 	}
2674 	hlen = tinfo[fp0->mode.common.tcode].hdr_len;
2675 	if (hlen > len) {
2676 		if (firewire_debug)
2677 			printf("splitted header\n");
2678 		return (-hlen);
2679 	}
2680 #if BYTE_ORDER == BIG_ENDIAN
2681 	for (i = 0; i < slen/4; i++)
2682 		fp->mode.ld[i] = FWOHCI_DMA_READ(fp->mode.ld[i]);
2683 #endif
2684 	return (hlen);
2685 }
2686 
2687 static int
2688 fwohci_get_plen(struct fwohci_softc *sc, struct fwohci_dbch *dbch, struct fw_pkt *fp)
2689 {
2690 	struct tcode_info *info;
2691 	int r;
2692 
2693 	info = &tinfo[fp->mode.common.tcode];
2694 	r = info->hdr_len + sizeof(uint32_t);
2695 	if ((info->flag & FWTI_BLOCK_ASY) != 0)
2696 		r += roundup2(fp->mode.wreqb.len, sizeof(uint32_t));
2697 
2698 	if (r == sizeof(uint32_t)) {
2699 		/* XXX */
2700 		device_printf(sc->fc.dev, "Unknown tcode %d\n",
2701 						fp->mode.common.tcode);
2702 		return (-1);
2703 	}
2704 
2705 	if (r > dbch->xferq.psize) {
2706 		device_printf(sc->fc.dev, "Invalid packet length %d\n", r);
2707 		return (-1);
2708 		/* panic ? */
2709 	}
2710 
2711 	return r;
2712 }
2713 
2714 static void
2715 fwohci_arcv_free_buf(struct fwohci_softc *sc, struct fwohci_dbch *dbch,
2716     struct fwohcidb_tr *db_tr, uint32_t off, int wake)
2717 {
2718 	struct fwohcidb *db = &db_tr->db[0];
2719 
2720 	FWOHCI_DMA_CLEAR(db->db.desc.depend, 0xf);
2721 	FWOHCI_DMA_WRITE(db->db.desc.res, dbch->xferq.psize);
2722 	FWOHCI_DMA_SET(dbch->bottom->db[0].db.desc.depend, 1);
2723 	fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREWRITE);
2724 	dbch->bottom = db_tr;
2725 
2726 	if (wake)
2727 		OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_WAKE);
2728 }
2729 
2730 static void
2731 fwohci_arcv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count)
2732 {
2733 	struct fwohcidb_tr *db_tr;
2734 	struct iovec vec[2];
2735 	struct fw_pkt pktbuf;
2736 	int nvec;
2737 	struct fw_pkt *fp;
2738 	uint8_t *ld;
2739 	uint32_t stat, off, status, event;
2740 	u_int spd;
2741 	int len, plen, hlen, pcnt, offset;
2742 	int s;
2743 	caddr_t buf;
2744 	int resCount;
2745 
2746 	if (&sc->arrq == dbch) {
2747 		off = OHCI_ARQOFF;
2748 	} else if (&sc->arrs == dbch) {
2749 		off = OHCI_ARSOFF;
2750 	} else {
2751 		return;
2752 	}
2753 
2754 	s = splfw();
2755 	db_tr = dbch->top;
2756 	pcnt = 0;
2757 	/* XXX we cannot handle a packet which lies in more than two buf */
2758 	fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_POSTREAD);
2759 	fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_POSTWRITE);
2760 	status = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) >> OHCI_STATUS_SHIFT;
2761 	resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) & OHCI_COUNT_MASK;
2762 	while (status & OHCI_CNTL_DMA_ACTIVE) {
2763 #if 0
2764 
2765 		if (off == OHCI_ARQOFF)
2766 			printf("buf 0x%08x, status 0x%04x, resCount 0x%04x\n",
2767 			    db_tr->bus_addr, status, resCount);
2768 #endif
2769 		len = dbch->xferq.psize - resCount;
2770 		ld = (uint8_t *)db_tr->buf;
2771 		if (dbch->pdb_tr == NULL) {
2772 			len -= dbch->buf_offset;
2773 			ld += dbch->buf_offset;
2774 		}
2775 		if (len > 0)
2776 			bus_dmamap_sync(dbch->dmat, db_tr->dma_map,
2777 					BUS_DMASYNC_POSTREAD);
2778 		while (len > 0) {
2779 			if (count >= 0 && count-- == 0)
2780 				goto out;
2781 			if (dbch->pdb_tr != NULL) {
2782 				/* we have a fragment in previous buffer */
2783 				int rlen;
2784 
2785 				offset = dbch->buf_offset;
2786 				if (offset < 0)
2787 					offset = - offset;
2788 				buf = dbch->pdb_tr->buf + offset;
2789 				rlen = dbch->xferq.psize - offset;
2790 				if (firewire_debug)
2791 					printf("rlen=%d, offset=%d\n",
2792 						rlen, dbch->buf_offset);
2793 				if (dbch->buf_offset < 0) {
2794 					/* splitted in header, pull up */
2795 					char *p;
2796 
2797 					p = (char *)&pktbuf;
2798 					bcopy(buf, p, rlen);
2799 					p += rlen;
2800 					/* this must be too long but harmless */
2801 					rlen = sizeof(pktbuf) - rlen;
2802 					if (rlen < 0)
2803 						printf("why rlen < 0\n");
2804 					bcopy(db_tr->buf, p, rlen);
2805 					ld += rlen;
2806 					len -= rlen;
2807 					hlen = fwohci_arcv_swap(&pktbuf, sizeof(pktbuf));
2808 					if (hlen <= 0) {
2809 						printf("hlen should be positive.");
2810 						goto err;
2811 					}
2812 					offset = sizeof(pktbuf);
2813 					vec[0].iov_base = (char *)&pktbuf;
2814 					vec[0].iov_len = offset;
2815 				} else {
2816 					/* splitted in payload */
2817 					offset = rlen;
2818 					vec[0].iov_base = buf;
2819 					vec[0].iov_len = rlen;
2820 				}
2821 				fp=(struct fw_pkt *)vec[0].iov_base;
2822 				nvec = 1;
2823 			} else {
2824 				/* no fragment in previous buffer */
2825 				fp=(struct fw_pkt *)ld;
2826 				hlen = fwohci_arcv_swap(fp, len);
2827 				if (hlen == 0)
2828 					goto err;
2829 				if (hlen < 0) {
2830 					dbch->pdb_tr = db_tr;
2831 					dbch->buf_offset = - dbch->buf_offset;
2832 					/* sanity check */
2833 					if (resCount != 0) {
2834 						printf("resCount=%d hlen=%d\n",
2835 						    resCount, hlen);
2836 						    goto err;
2837 					}
2838 					goto out;
2839 				}
2840 				offset = 0;
2841 				nvec = 0;
2842 			}
2843 			plen = fwohci_get_plen(sc, dbch, fp) - offset;
2844 			if (plen < 0) {
2845 				/* minimum header size + trailer
2846 				= sizeof(fw_pkt) so this shouldn't happens */
2847 				printf("plen(%d) is negative! offset=%d\n",
2848 				    plen, offset);
2849 				goto err;
2850 			}
2851 			if (plen > 0) {
2852 				len -= plen;
2853 				if (len < 0) {
2854 					dbch->pdb_tr = db_tr;
2855 					if (firewire_debug)
2856 						printf("splitted payload\n");
2857 					/* sanity check */
2858 					if (resCount != 0) {
2859 						printf("resCount=%d plen=%d"
2860 						    " len=%d\n",
2861 						    resCount, plen, len);
2862 						goto err;
2863 					}
2864 					goto out;
2865 				}
2866 				vec[nvec].iov_base = ld;
2867 				vec[nvec].iov_len = plen;
2868 				nvec++;
2869 				ld += plen;
2870 			}
2871 			dbch->buf_offset = ld - (uint8_t *)db_tr->buf;
2872 			if (nvec == 0)
2873 				printf("nvec == 0\n");
2874 
2875 /* DMA result-code will be written at the tail of packet */
2876 			stat = FWOHCI_DMA_READ(*(uint32_t *)(ld - sizeof(struct fwohci_trailer)));
2877 #if 0
2878 			printf("plen: %d, stat %x\n",
2879 			    plen ,stat);
2880 #endif
2881 			spd = (stat >> 21) & 0x3;
2882 			event = (stat >> 16) & 0x1f;
2883 			switch (event) {
2884 			case FWOHCIEV_ACKPEND:
2885 #if 0
2886 				printf("fwohci_arcv: ack pending tcode=0x%x..\n", fp->mode.common.tcode);
2887 #endif
2888 				/* fall through */
2889 			case FWOHCIEV_ACKCOMPL:
2890 			{
2891 				struct fw_rcv_buf rb;
2892 
2893 				if ((vec[nvec-1].iov_len -=
2894 					sizeof(struct fwohci_trailer)) == 0)
2895 					nvec--;
2896 				rb.fc = &sc->fc;
2897 				rb.vec = vec;
2898 				rb.nvec = nvec;
2899 				rb.spd = spd;
2900 				fw_rcv(&rb);
2901 				break;
2902 			}
2903 			case FWOHCIEV_BUSRST:
2904 				if ((sc->fc.status != FWBUSRESET) &&
2905 				    (sc->fc.status != FWBUSINIT))
2906 					printf("got BUSRST packet!?\n");
2907 				break;
2908 			default:
2909 				device_printf(sc->fc.dev,
2910 				    "Async DMA Receive error err=%02x %s"
2911 				    " plen=%d offset=%d len=%d status=0x%08x"
2912 				    " tcode=0x%x, stat=0x%08x\n",
2913 				    event, fwohcicode[event], plen,
2914 				    dbch->buf_offset, len,
2915 				    OREAD(sc, OHCI_DMACTL(off)),
2916 				    fp->mode.common.tcode, stat);
2917 #if 1 /* XXX */
2918 				goto err;
2919 #endif
2920 				break;
2921 			}
2922 			pcnt++;
2923 			if (dbch->pdb_tr != NULL) {
2924 				fwohci_arcv_free_buf(sc, dbch, dbch->pdb_tr,
2925 				    off, 1);
2926 				dbch->pdb_tr = NULL;
2927 			}
2928 
2929 		}
2930 out:
2931 		if (resCount == 0) {
2932 			/* done on this buffer */
2933 			if (dbch->pdb_tr == NULL) {
2934 				fwohci_arcv_free_buf(sc, dbch, db_tr, off, 1);
2935 				dbch->buf_offset = 0;
2936 			} else
2937 				if (dbch->pdb_tr != db_tr)
2938 					printf("pdb_tr != db_tr\n");
2939 			db_tr = STAILQ_NEXT(db_tr, link);
2940 			status = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res)
2941 						>> OHCI_STATUS_SHIFT;
2942 			resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res)
2943 						& OHCI_COUNT_MASK;
2944 			/* XXX check buffer overrun */
2945 			dbch->top = db_tr;
2946 		} else {
2947 			dbch->buf_offset = dbch->xferq.psize - resCount;
2948 			break;
2949 		}
2950 		/* XXX make sure DMA is not dead */
2951 	}
2952 #if 0
2953 	if (pcnt < 1)
2954 		printf("fwohci_arcv: no packets\n");
2955 #endif
2956 	splx(s);
2957 	return;
2958 
2959 err:
2960 	device_printf(sc->fc.dev, "AR DMA status=%x, ",
2961 					OREAD(sc, OHCI_DMACTL(off)));
2962 	dbch->pdb_tr = NULL;
2963 	/* skip until resCount != 0 */
2964 	printf(" skip buffer");
2965 	while (resCount == 0) {
2966 		printf(" #");
2967 		fwohci_arcv_free_buf(sc, dbch, db_tr, off, 0);
2968 		db_tr = STAILQ_NEXT(db_tr, link);
2969 		resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res)
2970 						& OHCI_COUNT_MASK;
2971 	}
2972 	printf(" done\n");
2973 	dbch->top = db_tr;
2974 	dbch->buf_offset = dbch->xferq.psize - resCount;
2975 	OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_WAKE);
2976 	splx(s);
2977 }
2978