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