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