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