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