fwohci.c revision 109814
1104349Sphk/*
2104349Sphk * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa
3104349Sphk * All rights reserved.
4104349Sphk *
5104349Sphk * Redistribution and use in source and binary forms, with or without
6104349Sphk * modification, are permitted provided that the following conditions
7178848Scokane * are met:
8247296Sdelphij * 1. Redistributions of source code must retain the above copyright
9247296Sdelphij *    notice, this list of conditions and the following disclaimer.
10104349Sphk * 2. Redistributions in binary form must reproduce the above copyright
11178848Scokane *    notice, this list of conditions and the following disclaimer in the
12178848Scokane *    documentation and/or other materials provided with the distribution.
13104349Sphk * 3. All advertising materials mentioning features or use of this software
14104349Sphk *    must display the acknowledgement as bellow:
15104349Sphk *
16104349Sphk *    This product includes software developed by K. Kobayashi and H. Shimokawa
17247296Sdelphij *
18178848Scokane * 4. The name of the author may not be used to endorse or promote products
19178848Scokane *    derived from this software without specific prior written permission.
20178848Scokane *
21178848Scokane * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22104349Sphk * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23178848Scokane * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24104349Sphk * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25178848Scokane * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26104349Sphk * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27104349Sphk * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28104349Sphk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29104349Sphk * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30104349Sphk * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31104349Sphk * POSSIBILITY OF SUCH DAMAGE.
32104349Sphk *
33104349Sphk * $FreeBSD: head/sys/dev/firewire/fwohci.c 109814 2003-01-25 14:47:33Z simokawa $
34178848Scokane *
35178848Scokane */
36104349Sphk
37104349Sphk#define ATRQ_CH 0
38104349Sphk#define ATRS_CH 1
39104349Sphk#define ARRQ_CH 2
40104349Sphk#define ARRS_CH 3
41104349Sphk#define ITX_CH 4
42104349Sphk#define IRX_CH 0x24
43104349Sphk
44104349Sphk#include <sys/param.h>
45104349Sphk#include <sys/systm.h>
46104349Sphk#include <sys/types.h>
47104349Sphk#include <sys/mbuf.h>
48104349Sphk#include <sys/mman.h>
49104349Sphk#include <sys/socket.h>
50104349Sphk#include <sys/socketvar.h>
51104349Sphk#include <sys/signalvar.h>
52104349Sphk#include <sys/malloc.h>
53104349Sphk#include <sys/uio.h>
54104349Sphk#include <sys/sockio.h>
55104349Sphk#include <sys/bus.h>
56104349Sphk#include <sys/kernel.h>
57104349Sphk#include <sys/conf.h>
58104349Sphk
59104349Sphk#include <machine/bus.h>
60104349Sphk#include <machine/resource.h>
61104349Sphk#include <sys/rman.h>
62104349Sphk
63104349Sphk#include <machine/cpufunc.h>            /* for rdtsc proto for clock.h below */
64104349Sphk#include <machine/clock.h>
65104349Sphk#include <pci/pcivar.h>
66104349Sphk#include <pci/pcireg.h>
67104349Sphk#include <vm/vm.h>
68104349Sphk#include <vm/vm_extern.h>
69104349Sphk#include <vm/pmap.h>            /* for vtophys proto */
70104349Sphk
71104349Sphk#include <dev/firewire/firewire.h>
72104349Sphk#include <dev/firewire/firewirereg.h>
73104349Sphk#include <dev/firewire/fwohcireg.h>
74104349Sphk#include <dev/firewire/fwohcivar.h>
75104349Sphk#include <dev/firewire/firewire_phy.h>
76104349Sphk
77104349Sphk#include <dev/firewire/iec68113.h>
78104349Sphk
79104349Sphk#undef OHCI_DEBUG
80104349Sphk
81104349Sphkstatic char dbcode[16][0x10]={"OUTM", "OUTL","INPM","INPL",
82104349Sphk		"STOR","LOAD","NOP ","STOP",};
83104349Sphkstatic char dbkey[8][0x10]={"ST0", "ST1","ST2","ST3",
84104349Sphk		"UNDEF","REG","SYS","DEV"};
85104349Sphkchar fwohcicode[32][0x20]={
86104349Sphk	"No stat","Undef","long","miss Ack err",
87104349Sphk	"underrun","overrun","desc err", "data read err",
88104349Sphk	"data write err","bus reset","timeout","tcode err",
89104349Sphk	"Undef","Undef","unknown event","flushed",
90104349Sphk	"Undef","ack complete","ack pend","Undef",
91104349Sphk	"ack busy_X","ack busy_A","ack busy_B","Undef",
92104349Sphk	"Undef","Undef","Undef","ack tardy",
93104349Sphk	"Undef","ack data_err","ack type_err",""};
94104349Sphk#define MAX_SPEED 2
95104349Sphkextern char linkspeed[MAX_SPEED+1][0x10];
96104349Sphkstatic char dbcond[4][0x10]={"NEV","C=1", "C=0", "ALL"};
97104349Sphku_int32_t tagbit[4] = { 1 << 28, 1 << 29, 1 << 30, 1 << 31};
98104349Sphk
99178848Scokanestatic struct tcode_info tinfo[] = {
100104349Sphk/*		hdr_len block 	flag*/
101104349Sphk/* 0 WREQQ  */ {16,	FWTI_REQ | FWTI_TLABEL},
102178848Scokane/* 1 WREQB  */ {16,	FWTI_REQ | FWTI_TLABEL | FWTI_BLOCK_ASY},
103104349Sphk/* 2 WRES   */ {12,	FWTI_RES},
104104349Sphk/* 3 XXX    */ { 0,	0},
105178848Scokane/* 4 RREQQ  */ {12,	FWTI_REQ | FWTI_TLABEL},
106178848Scokane/* 5 RREQB  */ {16,	FWTI_REQ | FWTI_TLABEL},
107178848Scokane/* 6 RRESQ  */ {16,	FWTI_RES},
108178848Scokane/* 7 RRESB  */ {16,	FWTI_RES | FWTI_BLOCK_ASY},
109178848Scokane/* 8 CYCS   */ { 0,	0},
110178848Scokane/* 9 LREQ   */ {16,	FWTI_REQ | FWTI_TLABEL | FWTI_BLOCK_ASY},
111178848Scokane/* a STREAM */ { 4,	FWTI_REQ | FWTI_BLOCK_STR},
112178848Scokane/* b LRES   */ {16,	FWTI_RES | FWTI_BLOCK_ASY},
113178848Scokane/* c XXX    */ { 0,	0},
114178848Scokane/* d XXX    */ { 0, 	0},
115178848Scokane/* e PHY    */ {12,	FWTI_REQ},
116178848Scokane/* f XXX    */ { 0,	0}
117178848Scokane};
118178848Scokane
119178848Scokane#define OHCI_WRITE_SIGMASK 0xffff0000
120178848Scokane#define OHCI_READ_SIGMASK 0xffff0000
121178848Scokane
122178848Scokane#define OWRITE(sc, r, x) bus_space_write_4((sc)->bst, (sc)->bsh, (r), (x))
123178848Scokane#define OREAD(sc, r) bus_space_read_4((sc)->bst, (sc)->bsh, (r))
124178848Scokane
125178848Scokanestatic void fwohci_ibr __P((struct firewire_comm *));
126178848Scokanestatic void fwohci_db_init __P((struct fwohci_dbch *));
127178848Scokanestatic void fwohci_db_free __P((struct fwohci_dbch *));
128178848Scokanestatic void fwohci_arcv __P((struct fwohci_softc *, struct fwohci_dbch *, int));
129178848Scokanestatic void fwohci_ircv __P((struct fwohci_softc *, struct fwohci_dbch *, int));
130104349Sphkstatic void fwohci_txd __P((struct fwohci_softc *, struct fwohci_dbch *));
131104349Sphkstatic void fwohci_start_atq __P((struct firewire_comm *));
132104349Sphkstatic void fwohci_start_ats __P((struct firewire_comm *));
133104349Sphkstatic void fwohci_start __P((struct fwohci_softc *, struct fwohci_dbch *));
134104349Sphkstatic void fwohci_drain_atq __P((struct firewire_comm *, struct fw_xfer *));
135104349Sphkstatic void fwohci_drain_ats __P((struct firewire_comm *, struct fw_xfer *));
136104349Sphkstatic void fwohci_drain __P((struct firewire_comm *, struct fw_xfer *, struct fwohci_dbch *));
137104349Sphkstatic u_int32_t fwphy_wrdata __P(( struct fwohci_softc *, u_int32_t, u_int32_t));
138178848Scokanestatic u_int32_t fwphy_rddata __P(( struct fwohci_softc *, u_int32_t));
139104349Sphkstatic int fwohci_rx_enable __P((struct fwohci_softc *, struct fwohci_dbch *));
140104349Sphkstatic int fwohci_tx_enable __P((struct fwohci_softc *, struct fwohci_dbch *));
141104349Sphkstatic int fwohci_irx_enable __P((struct firewire_comm *, int));
142104349Sphkstatic int fwohci_irxpp_enable __P((struct firewire_comm *, int));
143104349Sphkstatic int fwohci_irxbuf_enable __P((struct firewire_comm *, int));
144104349Sphkstatic int fwohci_irx_disable __P((struct firewire_comm *, int));
145104349Sphkstatic void fwohci_irx_post __P((struct firewire_comm *, u_int32_t *));
146104349Sphkstatic int fwohci_itxbuf_enable __P((struct firewire_comm *, int));
147104349Sphkstatic int fwohci_itx_disable __P((struct firewire_comm *, int));
148104349Sphkstatic void fwohci_timeout __P((void *));
149104349Sphkstatic void fwohci_poll __P((struct firewire_comm *, int, int));
150104349Sphkstatic void fwohci_set_intr __P((struct firewire_comm *, int));
151104349Sphkstatic int fwohci_add_rx_buf __P((struct fwohcidb_tr *, unsigned short, int, void *, void *));
152104349Sphkstatic int fwohci_add_tx_buf __P((struct fwohcidb_tr *, unsigned short, int, void *));
153104349Sphkstatic void	dump_db __P((struct fwohci_softc *, u_int32_t));
154104349Sphkstatic void 	print_db __P((volatile struct fwohcidb *, u_int32_t , u_int32_t));
155104349Sphkstatic void	dump_dma __P((struct fwohci_softc *, u_int32_t));
156104349Sphkstatic u_int32_t fwohci_cyctimer __P((struct firewire_comm *));
157104349Sphkstatic void fwohci_rbuf_update __P((struct fwohci_softc *, int));
158104349Sphkstatic void fwohci_tbuf_update __P((struct fwohci_softc *, int));
159104349Sphkvoid fwohci_txbufdb __P((struct fwohci_softc *, int , struct fw_bulkxfer *));
160104349Sphk
161104349Sphk/*
162104349Sphk * memory allocated for DMA programs
163104349Sphk */
164104349Sphk#define DMA_PROG_ALLOC		(8 * PAGE_SIZE)
165104349Sphk
166104349Sphk/* #define NDB 1024 */
167104349Sphk#define NDB FWMAXQUEUE
168104349Sphk#define NDVDB (DVBUF * NDB)
169104349Sphk
170104349Sphk#define	OHCI_VERSION		0x00
171104349Sphk#define	OHCI_CROMHDR		0x18
172104349Sphk#define	OHCI_BUS_OPT		0x20
173104349Sphk#define	OHCI_BUSIRMC		(1 << 31)
174104349Sphk#define	OHCI_BUSCMC		(1 << 30)
175104349Sphk#define	OHCI_BUSISC		(1 << 29)
176104349Sphk#define	OHCI_BUSBMC		(1 << 28)
177104349Sphk#define	OHCI_BUSPMC		(1 << 27)
178104349Sphk#define OHCI_BUSFNC		OHCI_BUSIRMC | OHCI_BUSCMC | OHCI_BUSISC |\
179104349Sphk				OHCI_BUSBMC | OHCI_BUSPMC
180104349Sphk
181104349Sphk#define	OHCI_EUID_HI		0x24
182104349Sphk#define	OHCI_EUID_LO		0x28
183104349Sphk
184104349Sphk#define	OHCI_CROMPTR		0x34
185104349Sphk#define	OHCI_HCCCTL		0x50
186104349Sphk#define	OHCI_HCCCTLCLR		0x54
187104349Sphk#define	OHCI_AREQHI		0x100
188104349Sphk#define	OHCI_AREQHICLR		0x104
189104349Sphk#define	OHCI_AREQLO		0x108
190104349Sphk#define	OHCI_AREQLOCLR		0x10c
191104349Sphk#define	OHCI_PREQHI		0x110
192104349Sphk#define	OHCI_PREQHICLR		0x114
193104349Sphk#define	OHCI_PREQLO		0x118
194178848Scokane#define	OHCI_PREQLOCLR		0x11c
195178848Scokane#define	OHCI_PREQUPPER		0x120
196104349Sphk
197104349Sphk#define	OHCI_SID_BUF		0x64
198104349Sphk#define	OHCI_SID_CNT		0x68
199104349Sphk#define OHCI_SID_CNT_MASK	0xffc
200104349Sphk
201104349Sphk#define	OHCI_IT_STAT		0x90
202104349Sphk#define	OHCI_IT_STATCLR		0x94
203104349Sphk#define	OHCI_IT_MASK		0x98
204104349Sphk#define	OHCI_IT_MASKCLR		0x9c
205104349Sphk
206104349Sphk#define	OHCI_IR_STAT		0xa0
207104349Sphk#define	OHCI_IR_STATCLR		0xa4
208104349Sphk#define	OHCI_IR_MASK		0xa8
209104349Sphk#define	OHCI_IR_MASKCLR		0xac
210104349Sphk
211104349Sphk#define	OHCI_LNKCTL		0xe0
212104349Sphk#define	OHCI_LNKCTLCLR		0xe4
213104349Sphk
214104349Sphk#define	OHCI_PHYACCESS		0xec
215104349Sphk#define	OHCI_CYCLETIMER		0xf0
216104349Sphk
217104349Sphk#define	OHCI_DMACTL(off)	(off)
218104349Sphk#define	OHCI_DMACTLCLR(off)	(off + 4)
219104349Sphk#define	OHCI_DMACMD(off)	(off + 0xc)
220104349Sphk#define	OHCI_DMAMATCH(off)	(off + 0x10)
221104349Sphk
222104349Sphk#define OHCI_ATQOFF		0x180
223104349Sphk#define OHCI_ATQCTL		OHCI_ATQOFF
224104349Sphk#define OHCI_ATQCTLCLR		(OHCI_ATQOFF + 4)
225104349Sphk#define OHCI_ATQCMD		(OHCI_ATQOFF + 0xc)
226104349Sphk#define OHCI_ATQMATCH		(OHCI_ATQOFF + 0x10)
227104349Sphk
228104349Sphk#define OHCI_ATSOFF		0x1a0
229178848Scokane#define OHCI_ATSCTL		OHCI_ATSOFF
230104349Sphk#define OHCI_ATSCTLCLR		(OHCI_ATSOFF + 4)
231104349Sphk#define OHCI_ATSCMD		(OHCI_ATSOFF + 0xc)
232104349Sphk#define OHCI_ATSMATCH		(OHCI_ATSOFF + 0x10)
233104349Sphk
234104349Sphk#define OHCI_ARQOFF		0x1c0
235104349Sphk#define OHCI_ARQCTL		OHCI_ARQOFF
236104349Sphk#define OHCI_ARQCTLCLR		(OHCI_ARQOFF + 4)
237104349Sphk#define OHCI_ARQCMD		(OHCI_ARQOFF + 0xc)
238104349Sphk#define OHCI_ARQMATCH		(OHCI_ARQOFF + 0x10)
239104349Sphk
240104349Sphk#define OHCI_ARSOFF		0x1e0
241104349Sphk#define OHCI_ARSCTL		OHCI_ARSOFF
242104349Sphk#define OHCI_ARSCTLCLR		(OHCI_ARSOFF + 4)
243104349Sphk#define OHCI_ARSCMD		(OHCI_ARSOFF + 0xc)
244104349Sphk#define OHCI_ARSMATCH		(OHCI_ARSOFF + 0x10)
245104349Sphk
246104349Sphk#define OHCI_ITOFF(CH)		(0x200 + 0x10 * (CH))
247104349Sphk#define OHCI_ITCTL(CH)		(OHCI_ITOFF(CH))
248178848Scokane#define OHCI_ITCTLCLR(CH)	(OHCI_ITOFF(CH) + 4)
249178848Scokane#define OHCI_ITCMD(CH)		(OHCI_ITOFF(CH) + 0xc)
250178848Scokane
251178848Scokane#define OHCI_IROFF(CH)		(0x400 + 0x20 * (CH))
252178848Scokane#define OHCI_IRCTL(CH)		(OHCI_IROFF(CH))
253178848Scokane#define OHCI_IRCTLCLR(CH)	(OHCI_IROFF(CH) + 4)
254104349Sphk#define OHCI_IRCMD(CH)		(OHCI_IROFF(CH) + 0xc)
255104349Sphk#define OHCI_IRMATCH(CH)	(OHCI_IROFF(CH) + 0x10)
256104349Sphk
257104349Sphkd_ioctl_t fwohci_ioctl;
258104349Sphk
259104349Sphk/*
260104349Sphk * Communication with PHY device
261104349Sphk */
262104349Sphkstatic u_int32_t
263104349Sphkfwphy_wrdata( struct fwohci_softc *sc, u_int32_t addr, u_int32_t data)
264104349Sphk{
265104349Sphk	u_int32_t fun;
266104349Sphk
267104349Sphk	addr &= 0xf;
268104349Sphk	data &= 0xff;
269104349Sphk
270104349Sphk	fun = (PHYDEV_WRCMD | (addr << PHYDEV_REGADDR) | (data << PHYDEV_WRDATA));
271104349Sphk	OWRITE(sc, OHCI_PHYACCESS, fun);
272178848Scokane	DELAY(100);
273104349Sphk
274104349Sphk	return(fwphy_rddata( sc, addr));
275104349Sphk}
276104349Sphk
277104349Sphkstatic u_int32_t
278104349Sphkfwohci_set_bus_manager(struct firewire_comm *fc, u_int node)
279104349Sphk{
280104349Sphk	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
281104349Sphk	int i;
282104349Sphk	u_int32_t bm;
283104349Sphk
284104349Sphk#define OHCI_CSR_DATA	0x0c
285104349Sphk#define OHCI_CSR_COMP	0x10
286104349Sphk#define OHCI_CSR_CONT	0x14
287104349Sphk#define OHCI_BUS_MANAGER_ID	0
288104349Sphk
289104349Sphk	OWRITE(sc, OHCI_CSR_DATA, node);
290104349Sphk	OWRITE(sc, OHCI_CSR_COMP, 0x3f);
291104349Sphk	OWRITE(sc, OHCI_CSR_CONT, OHCI_BUS_MANAGER_ID);
292104349Sphk 	for (i = 0; !(OREAD(sc, OHCI_CSR_CONT) & (1<<31)) && (i < 1000); i++)
293104349Sphk		DELAY(10);
294104349Sphk	bm = OREAD(sc, OHCI_CSR_DATA);
295104349Sphk	if((bm & 0x3f) == 0x3f)
296178848Scokane		bm = node;
297178848Scokane	if (bootverbose)
298104349Sphk		device_printf(sc->fc.dev,
299104349Sphk			"fw_set_bus_manager: %d->%d (loop=%d)\n", bm, node, i);
300178848Scokane
301178848Scokane	return(bm);
302178848Scokane}
303178848Scokane
304104349Sphkstatic u_int32_t
305104349Sphkfwphy_rddata(struct fwohci_softc *sc,  u_int addr)
306104349Sphk{
307104349Sphk	u_int32_t fun, stat;
308104349Sphk	u_int i, retry = 0;
309104349Sphk
310104349Sphk	addr &= 0xf;
311104349Sphk#define MAX_RETRY 100
312104349Sphkagain:
313104349Sphk	OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_REG_FAIL);
314104349Sphk	fun = PHYDEV_RDCMD | (addr << PHYDEV_REGADDR);
315104349Sphk	OWRITE(sc, OHCI_PHYACCESS, fun);
316104349Sphk	for ( i = 0 ; i < MAX_RETRY ; i ++ ){
317104349Sphk		fun = OREAD(sc, OHCI_PHYACCESS);
318104349Sphk		if ((fun & PHYDEV_RDCMD) == 0 && (fun & PHYDEV_RDDONE) != 0)
319104349Sphk			break;
320104349Sphk		DELAY(100);
321104349Sphk	}
322178848Scokane	if(i >= MAX_RETRY) {
323104349Sphk		if (bootverbose)
324178848Scokane			device_printf(sc->fc.dev, "phy read failed(1).\n");
325104349Sphk		if (++retry < MAX_RETRY) {
326178848Scokane			DELAY(100);
327104349Sphk			goto again;
328178848Scokane		}
329178848Scokane	}
330104349Sphk	/* Make sure that SCLK is started */
331178848Scokane	stat = OREAD(sc, FWOHCI_INTSTAT);
332247296Sdelphij	if ((stat & OHCI_INT_REG_FAIL) != 0 ||
333247296Sdelphij			((fun >> PHYDEV_REGADDR) & 0xf) != addr) {
334178848Scokane		if (bootverbose)
335178848Scokane			device_printf(sc->fc.dev, "phy read failed(2).\n");
336247296Sdelphij		if (++retry < MAX_RETRY) {
337178848Scokane			DELAY(100);
338178848Scokane			goto again;
339104349Sphk		}
340247296Sdelphij	}
341178848Scokane	if (bootverbose || retry >= MAX_RETRY)
342178848Scokane		device_printf(sc->fc.dev,
343104349Sphk			"fwphy_rddata: loop=%d, retry=%d\n", i, retry);
344178848Scokane#undef MAX_RETRY
345104349Sphk	return((fun >> PHYDEV_RDDATA )& 0xff);
346178848Scokane}
347104349Sphk/* Device specific ioctl. */
348178848Scokaneint
349104349Sphkfwohci_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td)
350178848Scokane{
351178848Scokane	struct firewire_softc *sc;
352178848Scokane	struct fwohci_softc *fc;
353178848Scokane	int unit = DEV2UNIT(dev);
354178848Scokane	int err = 0;
355104349Sphk	struct fw_reg_req_t *reg  = (struct fw_reg_req_t *) data;
356104349Sphk	u_int32_t *dmach = (u_int32_t *) data;
357178848Scokane
358247296Sdelphij	sc = devclass_get_softc(firewire_devclass, unit);
359178848Scokane	if(sc == NULL){
360178848Scokane		return(EINVAL);
361104349Sphk	}
362104349Sphk	fc = (struct fwohci_softc *)sc->fc;
363178848Scokane
364104349Sphk	if (!data)
365104349Sphk		return(EINVAL);
366178848Scokane
367104349Sphk	switch (cmd) {
368104349Sphk	case FWOHCI_WRREG:
369178848Scokane#define OHCI_MAX_REG 0x800
370104349Sphk		if(reg->addr <= OHCI_MAX_REG){
371178848Scokane			OWRITE(fc, reg->addr, reg->data);
372104349Sphk			reg->data = OREAD(fc, reg->addr);
373104349Sphk		}else{
374178848Scokane			err = EINVAL;
375104349Sphk		}
376104349Sphk		break;
377178848Scokane	case FWOHCI_RDREG:
378104349Sphk		if(reg->addr <= OHCI_MAX_REG){
379104349Sphk			reg->data = OREAD(fc, reg->addr);
380178848Scokane		}else{
381104349Sphk			err = EINVAL;
382104349Sphk		}
383104349Sphk		break;
384178848Scokane/* Read DMA descriptors for debug  */
385178848Scokane	case DUMPDMA:
386104349Sphk		if(*dmach <= OHCI_MAX_DMA_CH ){
387178848Scokane			dump_dma(fc, *dmach);
388104349Sphk			dump_db(fc, *dmach);
389104349Sphk		}else{
390178848Scokane			err = EINVAL;
391104349Sphk		}
392178848Scokane		break;
393178848Scokane	default:
394178848Scokane		break;
395178848Scokane	}
396247296Sdelphij	return err;
397247296Sdelphij}
398178848Scokane
399247296Sdelphijstatic int
400247296Sdelphijfwohci_probe_phy(struct fwohci_softc *sc, device_t dev)
401178848Scokane{
402247296Sdelphij	u_int32_t reg, reg2;
403104349Sphk	int e1394a = 1;
404178848Scokane/*
405104349Sphk * probe PHY parameters
406104349Sphk * 0. to prove PHY version, whether compliance of 1394a.
407178848Scokane * 1. to probe maximum speed supported by the PHY and
408178848Scokane *    number of port supported by core-logic.
409104349Sphk *    It is not actually available port on your PC .
410178848Scokane */
411178848Scokane	OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LPS);
412178848Scokane#if 0
413104349Sphk	/* XXX wait for SCLK. */
414104349Sphk	DELAY(100000);
415178848Scokane#endif
416104349Sphk	reg = fwphy_rddata(sc, FW_PHY_SPD_REG);
417104349Sphk
418178848Scokane	if((reg >> 5) != 7 ){
419104349Sphk		sc->fc.mode &= ~FWPHYASYST;
420104349Sphk		sc->fc.nport = reg & FW_PHY_NP;
421104349Sphk		sc->fc.speed = reg & FW_PHY_SPD >> 6;
422104349Sphk		if (sc->fc.speed > MAX_SPEED) {
423104349Sphk			device_printf(dev, "invalid speed %d (fixed to %d).\n",
424178848Scokane				sc->fc.speed, MAX_SPEED);
425104349Sphk			sc->fc.speed = MAX_SPEED;
426104349Sphk		}
427104349Sphk		device_printf(dev,
428178848Scokane			"Phy 1394 only %s, %d ports.\n",
429178848Scokane			linkspeed[sc->fc.speed], sc->fc.nport);
430178848Scokane	}else{
431178848Scokane		reg2 = fwphy_rddata(sc, FW_PHY_ESPD_REG);
432178848Scokane		sc->fc.mode |= FWPHYASYST;
433104349Sphk		sc->fc.nport = reg & FW_PHY_NP;
434104349Sphk		sc->fc.speed = (reg2 & FW_PHY_ESPD) >> 5;
435247296Sdelphij		if (sc->fc.speed > MAX_SPEED) {
436247296Sdelphij			device_printf(dev, "invalid speed %d (fixed to %d).\n",
437247296Sdelphij				sc->fc.speed, MAX_SPEED);
438178848Scokane			sc->fc.speed = MAX_SPEED;
439178848Scokane		}
440178848Scokane		device_printf(dev,
441178848Scokane			"Phy 1394a available %s, %d ports.\n",
442178848Scokane			linkspeed[sc->fc.speed], sc->fc.nport);
443247296Sdelphij
444178848Scokane		/* check programPhyEnable */
445104349Sphk		reg2 = fwphy_rddata(sc, 5);
446104349Sphk#if 0
447104349Sphk		if (e1394a && (OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_PRPHY)) {
448104349Sphk#else	/* XXX force to enable 1394a */
449104349Sphk		if (e1394a) {
450104349Sphk#endif
451104349Sphk			if (bootverbose)
452104349Sphk				device_printf(dev,
453104349Sphk					"Enable 1394a Enhancements\n");
454104349Sphk			/* enable EAA EMC */
455104349Sphk			reg2 |= 0x03;
456104349Sphk			/* set aPhyEnhanceEnable */
457104349Sphk			OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_PHYEN);
458104349Sphk			OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_PRPHY);
459104349Sphk		} else {
460104349Sphk			/* for safe */
461104349Sphk			reg2 &= ~0x83;
462104349Sphk		}
463104349Sphk		reg2 = fwphy_wrdata(sc, 5, reg2);
464104349Sphk	}
465178848Scokane
466104349Sphk	reg = fwphy_rddata(sc, FW_PHY_SPD_REG);
467104349Sphk	if((reg >> 5) == 7 ){
468104349Sphk		reg = fwphy_rddata(sc, 4);
469104349Sphk		reg |= 1 << 6;
470104349Sphk		fwphy_wrdata(sc, 4, reg);
471104349Sphk		reg = fwphy_rddata(sc, 4);
472178848Scokane	}
473104349Sphk	return 0;
474104349Sphk}
475104349Sphk
476104349Sphk
477104349Sphkvoid
478104349Sphkfwohci_reset(struct fwohci_softc *sc, device_t dev)
479104349Sphk{
480104349Sphk	int i, max_rec, speed;
481104349Sphk	u_int32_t reg, reg2;
482104349Sphk	struct fwohcidb_tr *db_tr;
483104349Sphk
484104349Sphk	/* Disable interrupt */
485104349Sphk	OWRITE(sc, FWOHCI_INTMASKCLR, ~0);
486104349Sphk
487104349Sphk	/* Now stopping all DMA channel */
488104349Sphk	OWRITE(sc,  OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN);
489104349Sphk	OWRITE(sc,  OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN);
490104349Sphk	OWRITE(sc,  OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN);
491104349Sphk	OWRITE(sc,  OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
492178848Scokane
493104349Sphk	OWRITE(sc,  OHCI_IR_MASKCLR, ~0);
494104349Sphk	for( i = 0 ; i < sc->fc.nisodma ; i ++ ){
495104349Sphk		OWRITE(sc,  OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN);
496104349Sphk		OWRITE(sc,  OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN);
497104349Sphk	}
498104349Sphk
499104349Sphk	/* FLUSH FIFO and reset Transmitter/Reciever */
500104349Sphk	OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_RESET);
501104349Sphk	if (bootverbose)
502104349Sphk		device_printf(dev, "resetting OHCI...");
503104349Sphk	i = 0;
504104349Sphk	while(OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_RESET) {
505104349Sphk		if (i++ > 100) break;
506104349Sphk		DELAY(1000);
507104349Sphk	}
508178848Scokane	if (bootverbose)
509104349Sphk		printf("done (loop=%d)\n", i);
510104349Sphk
511104349Sphk	/* Probe phy */
512104349Sphk	fwohci_probe_phy(sc, dev);
513104349Sphk
514104349Sphk	/* Probe link */
515104349Sphk	reg = OREAD(sc,  OHCI_BUS_OPT);
516178848Scokane	reg2 = reg | OHCI_BUSFNC;
517104349Sphk	max_rec = (reg & 0x0000f000) >> 12;
518104349Sphk	speed = (reg & 0x00000007);
519104349Sphk	device_printf(dev, "Link %s, max_rec %d bytes.\n",
520104349Sphk			linkspeed[speed], MAXREC(max_rec));
521104349Sphk	/* XXX fix max_rec */
522104349Sphk	sc->fc.maxrec = sc->fc.speed + 8;
523104349Sphk	if (max_rec != sc->fc.maxrec) {
524104349Sphk		reg2 = (reg2 & 0xffff0fff) | (sc->fc.maxrec << 12);
525104349Sphk		device_printf(dev, "max_rec %d -> %d\n",
526104349Sphk				MAXREC(max_rec), MAXREC(sc->fc.maxrec));
527104349Sphk	}
528104349Sphk	if (bootverbose)
529104349Sphk		device_printf(dev, "BUS_OPT 0x%x -> 0x%x\n", reg, reg2);
530178848Scokane	OWRITE(sc,  OHCI_BUS_OPT, reg2);
531104349Sphk
532104349Sphk	/* Initialize registers */
533104349Sphk	OWRITE(sc, OHCI_CROMHDR, sc->fc.config_rom[0]);
534104349Sphk	OWRITE(sc, OHCI_CROMPTR, vtophys(&sc->fc.config_rom[0]));
535104349Sphk	OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_BIGEND);
536104349Sphk	OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_POSTWR);
537104349Sphk	OWRITE(sc, OHCI_SID_BUF, vtophys(sc->fc.sid_buf));
538104349Sphk	OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_SID);
539104349Sphk	fw_busreset(&sc->fc);
540178848Scokane
541178848Scokane	/* Enable link */
542178848Scokane	OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LINKEN);
543247296Sdelphij
544247296Sdelphij	/* Force to start async RX DMA */
545247296Sdelphij	sc->arrq.xferq.flag &= ~FWXFERQ_RUNNING;
546104349Sphk	sc->arrs.xferq.flag &= ~FWXFERQ_RUNNING;
547104349Sphk	fwohci_rx_enable(sc, &sc->arrq);
548104349Sphk	fwohci_rx_enable(sc, &sc->arrs);
549104349Sphk
550178848Scokane	/* Initialize async TX */
551104349Sphk	OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD);
552104349Sphk	OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD);
553178848Scokane	/* AT Retries */
554104349Sphk	OWRITE(sc, FWOHCI_RETRY,
555104349Sphk		/* CycleLimit   PhyRespRetries ATRespRetries ATReqRetries */
556104349Sphk		(0xffff << 16 ) | (0x0f << 8) | (0x0f << 4) | 0x0f) ;
557104349Sphk	for( i = 0, db_tr = sc->atrq.top; i < sc->atrq.ndb ;
558104349Sphk				i ++, db_tr = STAILQ_NEXT(db_tr, link)){
559247296Sdelphij		db_tr->xfer = NULL;
560104349Sphk	}
561104349Sphk	for( i = 0, db_tr = sc->atrs.top; i < sc->atrs.ndb ;
562178848Scokane				i ++, db_tr = STAILQ_NEXT(db_tr, link)){
563178848Scokane		db_tr->xfer = NULL;
564178848Scokane	}
565104349Sphk
566104349Sphk
567104349Sphk	/* Enable interrupt */
568104349Sphk	OWRITE(sc, FWOHCI_INTMASK,
569104349Sphk			OHCI_INT_ERR  | OHCI_INT_PHY_SID
570104349Sphk			| OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS
571104349Sphk			| OHCI_INT_DMA_PRRQ | OHCI_INT_DMA_PRRS
572104349Sphk			| OHCI_INT_PHY_BUS_R | OHCI_INT_PW_ERR);
573104349Sphk	fwohci_set_intr(&sc->fc, 1);
574104349Sphk
575104349Sphk}
576104349Sphk
577104349Sphkint
578104349Sphkfwohci_init(struct fwohci_softc *sc, device_t dev)
579104349Sphk{
580104349Sphk	int i;
581104349Sphk	u_int32_t reg;
582104349Sphk	u_int8_t ui[8];
583104349Sphk
584104349Sphk	reg = OREAD(sc, OHCI_VERSION);
585104349Sphk	device_printf(dev, "OHCI version %x.%x (ROM=%d)\n",
586104349Sphk			(reg>>16) & 0xff, reg & 0xff, (reg>>24) & 1);
587104349Sphk
588104349Sphk/* XXX: Available Isochrounous DMA channel probe */
589104349Sphk	for( i = 0 ; i < 0x20 ; i ++ ){
590104349Sphk		OWRITE(sc,  OHCI_IRCTL(i), OHCI_CNTL_DMA_RUN);
591104349Sphk		reg = OREAD(sc, OHCI_IRCTL(i));
592104349Sphk		if(!(reg & OHCI_CNTL_DMA_RUN)) break;
593104349Sphk		OWRITE(sc,  OHCI_ITCTL(i), OHCI_CNTL_DMA_RUN);
594104349Sphk		reg = OREAD(sc, OHCI_ITCTL(i));
595104349Sphk		if(!(reg & OHCI_CNTL_DMA_RUN)) break;
596104349Sphk	}
597104349Sphk	sc->fc.nisodma = i;
598104349Sphk	device_printf(dev, "No. of Isochronous channel is %d.\n", i);
599104349Sphk
600104349Sphk	sc->fc.arq = &sc->arrq.xferq;
601104349Sphk	sc->fc.ars = &sc->arrs.xferq;
602104349Sphk	sc->fc.atq = &sc->atrq.xferq;
603104349Sphk	sc->fc.ats = &sc->atrs.xferq;
604104349Sphk
605104349Sphk	sc->arrq.xferq.start = NULL;
606104349Sphk	sc->arrs.xferq.start = NULL;
607104349Sphk	sc->atrq.xferq.start = fwohci_start_atq;
608104349Sphk	sc->atrs.xferq.start = fwohci_start_ats;
609104349Sphk
610104349Sphk	sc->arrq.xferq.drain = NULL;
611104349Sphk	sc->arrs.xferq.drain = NULL;
612104349Sphk	sc->atrq.xferq.drain = fwohci_drain_atq;
613104349Sphk	sc->atrs.xferq.drain = fwohci_drain_ats;
614104349Sphk
615104349Sphk	sc->arrq.ndesc = 1;
616104349Sphk	sc->arrs.ndesc = 1;
617104349Sphk	sc->atrq.ndesc = 6;	/* equal to maximum of mbuf chains */
618178848Scokane	sc->atrs.ndesc = 6 / 2;
619104349Sphk
620104349Sphk	sc->arrq.ndb = NDB;
621104349Sphk	sc->arrs.ndb = NDB / 2;
622104349Sphk	sc->atrq.ndb = NDB;
623104349Sphk	sc->atrs.ndb = NDB / 2;
624104349Sphk
625104349Sphk	sc->arrq.dummy = NULL;
626104349Sphk	sc->arrs.dummy = NULL;
627104349Sphk	sc->atrq.dummy = NULL;
628104349Sphk	sc->atrs.dummy = NULL;
629104349Sphk	for( i = 0 ; i < sc->fc.nisodma ; i ++ ){
630178848Scokane		sc->fc.it[i] = &sc->it[i].xferq;
631104349Sphk		sc->fc.ir[i] = &sc->ir[i].xferq;
632104349Sphk		sc->it[i].ndb = 0;
633104349Sphk		sc->ir[i].ndb = 0;
634104349Sphk	}
635104349Sphk
636104349Sphk	sc->fc.tcode = tinfo;
637104349Sphk
638104349Sphk	sc->cromptr = (u_int32_t *) malloc(CROMSIZE * 2, M_DEVBUF, M_NOWAIT);
639104349Sphk
640104349Sphk	if(sc->cromptr == NULL){
641104349Sphk		device_printf(dev, "cromptr alloc failed.");
642104349Sphk		return ENOMEM;
643104349Sphk	}
644104349Sphk	sc->fc.dev = dev;
645104349Sphk	sc->fc.config_rom = &(sc->cromptr[CROMSIZE/4]);
646104349Sphk
647104349Sphk	sc->fc.config_rom[1] = 0x31333934;
648104349Sphk	sc->fc.config_rom[2] = 0xf000a002;
649104349Sphk	sc->fc.config_rom[3] = OREAD(sc, OHCI_EUID_HI);
650104349Sphk	sc->fc.config_rom[4] = OREAD(sc, OHCI_EUID_LO);
651178848Scokane	sc->fc.config_rom[5] = 0;
652178848Scokane	sc->fc.config_rom[0] = (4 << 24) | (5 << 16);
653178848Scokane
654247296Sdelphij	sc->fc.config_rom[0] |= fw_crc16(&sc->fc.config_rom[1], 5*4);
655104349Sphk
656104349Sphk
657104349Sphk/* SID recieve buffer must allign 2^11 */
658104349Sphk#define	OHCI_SIDSIZE	(1 << 11)
659104349Sphk	sc->fc.sid_buf = (u_int32_t *) malloc(OHCI_SIDSIZE, M_DEVBUF, M_NOWAIT);
660104349Sphk	if (sc->fc.sid_buf == NULL) {
661178848Scokane		device_printf(dev, "sid_buf alloc failed.\n");
662178848Scokane		return ENOMEM;
663104349Sphk	}
664104349Sphk	if (((u_int32_t) sc->fc.sid_buf & (OHCI_SIDSIZE - 1)) != 0) {
665104349Sphk		device_printf(dev, "sid_buf(%p) not aligned.\n",
666104349Sphk							sc->fc.sid_buf);
667104349Sphk		return ENOMEM;
668247296Sdelphij	}
669104349Sphk
670178848Scokane	fwohci_db_init(&sc->arrq);
671104349Sphk	if ((sc->arrq.flags & FWOHCI_DBCH_INIT) == 0)
672104349Sphk		return ENOMEM;
673104349Sphk
674104349Sphk	fwohci_db_init(&sc->arrs);
675104349Sphk	if ((sc->arrs.flags & FWOHCI_DBCH_INIT) == 0)
676178848Scokane		return ENOMEM;
677104349Sphk
678104349Sphk	fwohci_db_init(&sc->atrq);
679104349Sphk	if ((sc->atrq.flags & FWOHCI_DBCH_INIT) == 0)
680104349Sphk		return ENOMEM;
681104349Sphk
682104349Sphk	fwohci_db_init(&sc->atrs);
683104349Sphk	if ((sc->atrs.flags & FWOHCI_DBCH_INIT) == 0)
684178848Scokane		return ENOMEM;
685178848Scokane
686247296Sdelphij	sc->fc.eui.hi = OREAD(sc, FWOHCIGUID_H);
687178848Scokane	sc->fc.eui.lo = OREAD(sc, FWOHCIGUID_L);
688178848Scokane	for( i = 0 ; i < 8 ; i ++)
689178848Scokane		ui[i] = FW_EUI64_BYTE(&sc->fc.eui,i);
690178848Scokane	device_printf(dev, "EUI64 %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
691178848Scokane		ui[0], ui[1], ui[2], ui[3], ui[4], ui[5], ui[6], ui[7]);
692178848Scokane
693247296Sdelphij	sc->fc.ioctl = fwohci_ioctl;
694247296Sdelphij	sc->fc.cyctimer = fwohci_cyctimer;
695247296Sdelphij	sc->fc.set_bmr = fwohci_set_bus_manager;
696247296Sdelphij	sc->fc.ibr = fwohci_ibr;
697247296Sdelphij	sc->fc.irx_enable = fwohci_irx_enable;
698247296Sdelphij	sc->fc.irx_disable = fwohci_irx_disable;
699247296Sdelphij
700247296Sdelphij	sc->fc.itx_enable = fwohci_itxbuf_enable;
701247296Sdelphij	sc->fc.itx_disable = fwohci_itx_disable;
702247296Sdelphij	sc->fc.irx_post = fwohci_irx_post;
703247296Sdelphij	sc->fc.itx_post = NULL;
704247296Sdelphij	sc->fc.timeout = fwohci_timeout;
705247296Sdelphij	sc->fc.poll = fwohci_poll;
706247296Sdelphij	sc->fc.set_intr = fwohci_set_intr;
707247296Sdelphij
708247296Sdelphij	fw_init(&sc->fc);
709247296Sdelphij	fwohci_reset(sc, dev);
710247296Sdelphij
711247296Sdelphij	return 0;
712247296Sdelphij}
713247296Sdelphij
714247296Sdelphijvoid
715247296Sdelphijfwohci_timeout(void *arg)
716178848Scokane{
717104349Sphk	struct fwohci_softc *sc;
718104349Sphk
719178848Scokane	sc = (struct fwohci_softc *)arg;
720178848Scokane	sc->fc.timeouthandle = timeout(fwohci_timeout,
721247296Sdelphij				(void *)sc, FW_XFERTIMEOUT * hz * 10);
722178848Scokane}
723178848Scokane
724178848Scokaneu_int32_t
725178848Scokanefwohci_cyctimer(struct firewire_comm *fc)
726178848Scokane{
727178848Scokane	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
728178848Scokane	return(OREAD(sc, OHCI_CYCLETIMER));
729178848Scokane}
730104349Sphk
731104349Sphkint
732104349Sphkfwohci_detach(struct fwohci_softc *sc, device_t dev)
733104349Sphk{
734178848Scokane	int i;
735178848Scokane
736104349Sphk	if (sc->fc.sid_buf != NULL)
737178848Scokane		free((void *)(uintptr_t)sc->fc.sid_buf, M_DEVBUF);
738104349Sphk	if (sc->cromptr != NULL)
739104349Sphk		free((void *)sc->cromptr, M_DEVBUF);
740104349Sphk
741104349Sphk	fwohci_db_free(&sc->arrq);
742104349Sphk	fwohci_db_free(&sc->arrs);
743104349Sphk
744104349Sphk	fwohci_db_free(&sc->atrq);
745178848Scokane	fwohci_db_free(&sc->atrs);
746104349Sphk
747178848Scokane	for( i = 0 ; i < sc->fc.nisodma ; i ++ ){
748104349Sphk		fwohci_db_free(&sc->it[i]);
749104349Sphk		fwohci_db_free(&sc->ir[i]);
750104349Sphk	}
751104349Sphk
752104349Sphk	return 0;
753104349Sphk}
754104349Sphk
755104349Sphk#define LAST_DB(dbtr, db) do {						\
756104349Sphk	struct fwohcidb_tr *_dbtr = (dbtr);				\
757104349Sphk	int _cnt = _dbtr->dbcnt;					\
758104349Sphk	db = &_dbtr->db[ (_cnt > 2) ? (_cnt -1) : 0];			\
759104349Sphk} while (0)
760104349Sphk
761178848Scokanestatic void
762104349Sphkfwohci_start(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
763104349Sphk{
764104349Sphk	int i, s;
765104349Sphk	int tcode, hdr_len, hdr_off, len;
766247296Sdelphij	int fsegment = -1;
767247296Sdelphij	u_int32_t off;
768247296Sdelphij	struct fw_xfer *xfer;
769247296Sdelphij	struct fw_pkt *fp;
770247296Sdelphij	volatile struct fwohci_txpkthdr *ohcifp;
771247296Sdelphij	struct fwohcidb_tr *db_tr;
772247296Sdelphij	volatile struct fwohcidb *db;
773247296Sdelphij	struct mbuf *m;
774178848Scokane	struct tcode_info *info;
775104349Sphk	static int maxdesc=0;
776104349Sphk
777247296Sdelphij	if(&sc->atrq == dbch){
778247296Sdelphij		off = OHCI_ATQOFF;
779247296Sdelphij	}else if(&sc->atrs == dbch){
780104349Sphk		off = OHCI_ATSOFF;
781104349Sphk	}else{
782104349Sphk		return;
783104349Sphk	}
784104349Sphk
785178848Scokane	if (dbch->flags & FWOHCI_DBCH_FULL)
786178848Scokane		return;
787178848Scokane
788178848Scokane	s = splfw();
789178848Scokane	db_tr = dbch->top;
790178848Scokanetxloop:
791178848Scokane	xfer = STAILQ_FIRST(&dbch->xferq.q);
792247296Sdelphij	if(xfer == NULL){
793247296Sdelphij		goto kick;
794247296Sdelphij	}
795178848Scokane	if(dbch->xferq.queued == 0 ){
796178848Scokane		device_printf(sc->fc.dev, "TX queue empty\n");
797178848Scokane	}
798178848Scokane	STAILQ_REMOVE_HEAD(&dbch->xferq.q, link);
799178848Scokane	db_tr->xfer = xfer;
800104349Sphk	xfer->state = FWXF_START;
801104349Sphk	dbch->xferq.packets++;
802178848Scokane
803104349Sphk	fp = (struct fw_pkt *)(xfer->send.buf + xfer->send.off);
804104349Sphk	tcode = fp->mode.common.tcode;
805104349Sphk
806104349Sphk	ohcifp = (volatile struct fwohci_txpkthdr *) db_tr->db[1].db.immed;
807104349Sphk	info = &tinfo[tcode];
808104349Sphk	hdr_len = hdr_off = info->hdr_len;
809104349Sphk	/* fw_asyreq must pass valid send.len */
810178848Scokane	len = xfer->send.len;
811104349Sphk	for( i = 0 ; i < hdr_off ; i+= 4){
812104349Sphk		ohcifp->mode.ld[i/4] = ntohl(fp->mode.ld[i/4]);
813104349Sphk	}
814178848Scokane	ohcifp->mode.common.spd = xfer->spd;
815178848Scokane	if (tcode == FWTCODE_STREAM ){
816178848Scokane		hdr_len = 8;
817178848Scokane		ohcifp->mode.stream.len = ntohs(fp->mode.stream.len);
818104349Sphk	} else if (tcode == FWTCODE_PHY) {
819104349Sphk		hdr_len = 12;
820104349Sphk		ohcifp->mode.ld[1] = ntohl(fp->mode.ld[1]);
821104349Sphk		ohcifp->mode.ld[2] = ntohl(fp->mode.ld[2]);
822178848Scokane		ohcifp->mode.common.spd = 0;
823104349Sphk		ohcifp->mode.common.tcode = FWOHCITCODE_PHY;
824104349Sphk	} else {
825104349Sphk		ohcifp->mode.asycomm.dst = ntohs(fp->mode.hdr.dst);
826104349Sphk		ohcifp->mode.asycomm.srcbus = OHCI_ASYSRCBUS;
827104349Sphk		ohcifp->mode.asycomm.tlrt |= FWRETRY_X;
828104349Sphk	}
829104349Sphk	db = &db_tr->db[0];
830104349Sphk 	db->db.desc.cmd = OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | hdr_len;
831104349Sphk 	db->db.desc.status = 0;
832104349Sphk/* Specify bound timer of asy. responce */
833104349Sphk	if(&sc->atrs == dbch){
834104349Sphk 		db->db.desc.count
835104349Sphk			 = (OREAD(sc, OHCI_CYCLETIMER) >> 12) + (1 << 13);
836104349Sphk	}
837104349Sphk
838104349Sphk	db_tr->dbcnt = 2;
839178848Scokane	db = &db_tr->db[db_tr->dbcnt];
840104349Sphk	if(len > hdr_off){
841104349Sphk		if (xfer->mbuf == NULL) {
842104349Sphk			db->db.desc.addr
843104349Sphk				= vtophys(xfer->send.buf + xfer->send.off) + hdr_off;
844104349Sphk			db->db.desc.cmd
845104349Sphk				= OHCI_OUTPUT_MORE | ((len - hdr_off) & 0xffff);
846104349Sphk 			db->db.desc.status = 0;
847104349Sphk
848104349Sphk			db_tr->dbcnt++;
849104349Sphk		} else {
850104349Sphk			/* XXX we assume mbuf chain is shorter than ndesc */
851104349Sphk			for (m = xfer->mbuf; m != NULL; m = m->m_next) {
852104349Sphk				if (m->m_len == 0)
853104349Sphk					/* unrecoverable error could ocurre. */
854104349Sphk					continue;
855104349Sphk				if (db_tr->dbcnt >= dbch->ndesc) {
856104349Sphk					device_printf(sc->fc.dev,
857104349Sphk						"dbch->ndesc is too small"
858104349Sphk						", trancated.\n");
859104349Sphk					break;
860104349Sphk				}
861104349Sphk				db->db.desc.addr
862104349Sphk					= vtophys(mtod(m, caddr_t));
863104349Sphk				db->db.desc.cmd = OHCI_OUTPUT_MORE | m->m_len;
864104349Sphk 				db->db.desc.status = 0;
865104349Sphk				db++;
866104349Sphk				db_tr->dbcnt++;
867104349Sphk			}
868104349Sphk		}
869104349Sphk	}
870104349Sphk	if (maxdesc < db_tr->dbcnt) {
871104349Sphk		maxdesc = db_tr->dbcnt;
872104349Sphk		if (bootverbose)
873104349Sphk			device_printf(sc->fc.dev, "maxdesc: %d\n", maxdesc);
874104349Sphk	}
875104349Sphk	/* last db */
876104349Sphk	LAST_DB(db_tr, db);
877104349Sphk 	db->db.desc.cmd |= OHCI_OUTPUT_LAST
878104349Sphk			| OHCI_INTERRUPT_ALWAYS
879104349Sphk			| OHCI_BRANCH_ALWAYS;
880104349Sphk 	db->db.desc.depend = vtophys(STAILQ_NEXT(db_tr, link)->db);
881104349Sphk
882104349Sphk	if(fsegment == -1 )
883104349Sphk		fsegment = db_tr->dbcnt;
884104349Sphk	if (dbch->pdb_tr != NULL) {
885104349Sphk		LAST_DB(dbch->pdb_tr, db);
886104349Sphk 		db->db.desc.depend |= db_tr->dbcnt;
887104349Sphk	}
888104349Sphk	dbch->pdb_tr = db_tr;
889104349Sphk	db_tr = STAILQ_NEXT(db_tr, link);
890104349Sphk	if(db_tr != dbch->bottom){
891104349Sphk		goto txloop;
892104349Sphk	} else {
893178848Scokane		device_printf(sc->fc.dev, "fwohci_start: lack of db_trq\n");
894104349Sphk		dbch->flags |= FWOHCI_DBCH_FULL;
895104349Sphk	}
896104349Sphkkick:
897104349Sphk	if (firewire_debug) printf("kick\n");
898104349Sphk	/* kick asy q */
899104349Sphk
900104349Sphk	if(dbch->xferq.flag & FWXFERQ_RUNNING) {
901104349Sphk		OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_WAKE);
902104349Sphk	} else {
903178848Scokane		if (bootverbose)
904104349Sphk			device_printf(sc->fc.dev, "start AT DMA status=%x\n",
905104349Sphk					OREAD(sc, OHCI_DMACTL(off)));
906104349Sphk		OWRITE(sc, OHCI_DMACMD(off), vtophys(dbch->top->db) | fsegment);
907104349Sphk		OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_RUN);
908104349Sphk		dbch->xferq.flag |= FWXFERQ_RUNNING;
909247296Sdelphij	}
910104349Sphk
911104349Sphk	dbch->top = db_tr;
912104349Sphk	splx(s);
913104349Sphk	return;
914104349Sphk}
915104349Sphk
916104349Sphkstatic void
917104349Sphkfwohci_drain_atq(struct firewire_comm *fc, struct fw_xfer *xfer)
918104349Sphk{
919104349Sphk	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
920104349Sphk	fwohci_drain(&sc->fc, xfer, &(sc->atrq));
921104349Sphk	return;
922104349Sphk}
923104349Sphk
924178848Scokanestatic void
925104349Sphkfwohci_drain_ats(struct firewire_comm *fc, struct fw_xfer *xfer)
926104349Sphk{
927104349Sphk	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
928178848Scokane	fwohci_drain(&sc->fc, xfer, &(sc->atrs));
929178848Scokane	return;
930104349Sphk}
931104349Sphk
932104349Sphkstatic void
933104349Sphkfwohci_start_atq(struct firewire_comm *fc)
934104349Sphk{
935104349Sphk	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
936104349Sphk	fwohci_start( sc, &(sc->atrq));
937104349Sphk	return;
938104349Sphk}
939104349Sphk
940104349Sphkstatic void
941178848Scokanefwohci_start_ats(struct firewire_comm *fc)
942178848Scokane{
943178848Scokane	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
944178848Scokane	fwohci_start( sc, &(sc->atrs));
945178848Scokane	return;
946178848Scokane}
947178848Scokane
948178848Scokanevoid
949104349Sphkfwohci_txd(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
950178848Scokane{
951104349Sphk	int s, err = 0;
952104349Sphk	struct fwohcidb_tr *tr;
953104349Sphk	volatile struct fwohcidb *db;
954104349Sphk	struct fw_xfer *xfer;
955104349Sphk	u_int32_t off;
956178848Scokane	u_int stat;
957247296Sdelphij	int	packets;
958104349Sphk	struct firewire_comm *fc = (struct firewire_comm *)sc;
959104349Sphk	if(&sc->atrq == dbch){
960178848Scokane		off = OHCI_ATQOFF;
961104349Sphk	}else if(&sc->atrs == dbch){
962104349Sphk		off = OHCI_ATSOFF;
963178848Scokane	}else{
964178848Scokane		return;
965178848Scokane	}
966178848Scokane	s = splfw();
967178848Scokane	tr = dbch->bottom;
968178848Scokane	packets = 0;
969104349Sphk	while(dbch->xferq.queued > 0){
970104349Sphk		LAST_DB(tr, db);
971104349Sphk		if(!(db->db.desc.status & OHCI_CNTL_DMA_ACTIVE)){
972104349Sphk			if (fc->status != FWBUSRESET)
973104349Sphk				/* maybe out of order?? */
974178848Scokane				goto out;
975104349Sphk		}
976178848Scokane		if(db->db.desc.status & OHCI_CNTL_DMA_DEAD) {
977104349Sphk#ifdef OHCI_DEBUG
978104349Sphk			dump_dma(sc, ch);
979178848Scokane			dump_db(sc, ch);
980104349Sphk#endif
981104349Sphk/* Stop DMA */
982104349Sphk			OWRITE(sc, OHCI_DMACTLCLR(off), OHCI_CNTL_DMA_RUN);
983104349Sphk			device_printf(sc->fc.dev, "force reset AT FIFO\n");
984104349Sphk			OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_LINKEN);
985178848Scokane			OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LPS | OHCI_HCC_LINKEN);
986178848Scokane			OWRITE(sc, OHCI_DMACTLCLR(off), OHCI_CNTL_DMA_RUN);
987104349Sphk		}
988104349Sphk		stat = db->db.desc.status & FWOHCIEV_MASK;
989104349Sphk		switch(stat){
990104349Sphk		case FWOHCIEV_ACKCOMPL:
991104349Sphk		case FWOHCIEV_ACKPEND:
992104349Sphk			err = 0;
993104349Sphk			break;
994104349Sphk		case FWOHCIEV_ACKBSA:
995104349Sphk		case FWOHCIEV_ACKBSB:
996104349Sphk			device_printf(sc->fc.dev, "txd err=%2x %s\n", stat, fwohcicode[stat]);
997104349Sphk		case FWOHCIEV_ACKBSX:
998104349Sphk			err = EBUSY;
999104349Sphk			break;
1000104349Sphk		case FWOHCIEV_FLUSHED:
1001104349Sphk		case FWOHCIEV_ACKTARD:
1002104349Sphk			device_printf(sc->fc.dev, "txd err=%2x %s\n", stat, fwohcicode[stat]);
1003104349Sphk			err = EAGAIN;
1004104349Sphk			break;
1005104349Sphk		case FWOHCIEV_MISSACK:
1006104349Sphk		case FWOHCIEV_UNDRRUN:
1007104349Sphk		case FWOHCIEV_OVRRUN:
1008104349Sphk		case FWOHCIEV_DESCERR:
1009104349Sphk		case FWOHCIEV_DTRDERR:
1010104349Sphk		case FWOHCIEV_TIMEOUT:
1011104349Sphk		case FWOHCIEV_TCODERR:
1012104349Sphk		case FWOHCIEV_UNKNOWN:
1013104349Sphk		case FWOHCIEV_ACKDERR:
1014104349Sphk		case FWOHCIEV_ACKTERR:
1015104349Sphk		default:
1016104349Sphk			device_printf(sc->fc.dev, "txd err=%2x %s\n",
1017104349Sphk							stat, fwohcicode[stat]);
1018104349Sphk			err = EINVAL;
1019104349Sphk			break;
1020178848Scokane		}
1021104349Sphk		if(tr->xfer != NULL){
1022178848Scokane			xfer = tr->xfer;
1023104349Sphk			xfer->state = FWXF_SENT;
1024104349Sphk			if(err == EBUSY && fc->status != FWBUSRESET){
1025104349Sphk				xfer->state = FWXF_BUSY;
1026247296Sdelphij				switch(xfer->act_type){
1027247296Sdelphij				case FWACT_XFER:
1028247296Sdelphij					xfer->resp = err;
1029247296Sdelphij					if(xfer->retry_req != NULL){
1030247296Sdelphij						xfer->retry_req(xfer);
1031247296Sdelphij					}
1032104349Sphk					break;
1033178848Scokane				default:
1034178848Scokane					break;
1035178848Scokane				}
1036178848Scokane			} else if( stat != FWOHCIEV_ACKPEND){
1037178848Scokane				if (stat != FWOHCIEV_ACKCOMPL)
1038104349Sphk					xfer->state = FWXF_SENTERR;
1039104349Sphk				xfer->resp = err;
1040104349Sphk				switch(xfer->act_type){
1041104349Sphk				case FWACT_XFER:
1042104349Sphk					fw_xfer_done(xfer);
1043104349Sphk					break;
1044104349Sphk				default:
1045104349Sphk					break;
1046178848Scokane				}
1047104349Sphk			}
1048104349Sphk			dbch->xferq.queued --;
1049178848Scokane		}
1050104349Sphk		tr->xfer = NULL;
1051104349Sphk
1052104349Sphk		packets ++;
1053104349Sphk		tr = STAILQ_NEXT(tr, link);
1054104349Sphk		dbch->bottom = tr;
1055104349Sphk	}
1056104349Sphkout:
1057104349Sphk	if ((dbch->flags & FWOHCI_DBCH_FULL) && packets > 0) {
1058104349Sphk		printf("make free slot\n");
1059104349Sphk		dbch->flags &= ~FWOHCI_DBCH_FULL;
1060104349Sphk		fwohci_start(sc, dbch);
1061104349Sphk	}
1062104349Sphk	splx(s);
1063104349Sphk}
1064104349Sphk
1065104349Sphkstatic void
1066104349Sphkfwohci_drain(struct firewire_comm *fc, struct fw_xfer *xfer, struct fwohci_dbch *dbch)
1067104349Sphk{
1068104349Sphk	int i, s;
1069104349Sphk	struct fwohcidb_tr *tr;
1070104349Sphk
1071104349Sphk	if(xfer->state != FWXF_START) return;
1072104349Sphk
1073104349Sphk	s = splfw();
1074104349Sphk	tr = dbch->bottom;
1075104349Sphk	for( i = 0 ; i <= dbch->xferq.queued  ; i ++){
1076104349Sphk		if(tr->xfer == xfer){
1077104349Sphk			s = splfw();
1078104349Sphk			tr->xfer = NULL;
1079104349Sphk			dbch->xferq.queued --;
1080104349Sphk#if 1
1081104349Sphk			/* XXX */
1082104349Sphk			if (tr == dbch->bottom)
1083104349Sphk				dbch->bottom = STAILQ_NEXT(tr, link);
1084104349Sphk#endif
1085247296Sdelphij			if (dbch->flags & FWOHCI_DBCH_FULL) {
1086104349Sphk				printf("fwohci_drain: make slot\n");
1087104349Sphk				dbch->flags &= ~FWOHCI_DBCH_FULL;
1088104349Sphk				fwohci_start((struct fwohci_softc *)fc, dbch);
1089104349Sphk			}
1090104349Sphk
1091104349Sphk			splx(s);
1092247296Sdelphij			break;
1093178848Scokane		}
1094104349Sphk		tr = STAILQ_NEXT(tr, link);
1095104349Sphk	}
1096104349Sphk	splx(s);
1097104349Sphk	return;
1098104349Sphk}
1099104349Sphk
1100104349Sphkstatic void
1101178848Scokanefwohci_db_free(struct fwohci_dbch *dbch)
1102178848Scokane{
1103178848Scokane	struct fwohcidb_tr *db_tr;
1104178848Scokane	int idb, i;
1105178848Scokane
1106178848Scokane	if ((dbch->flags & FWOHCI_DBCH_INIT) == 0)
1107178848Scokane		return;
1108104349Sphk
1109104349Sphk	if(!(dbch->xferq.flag & FWXFERQ_EXTBUF)){
1110104349Sphk		for(db_tr = STAILQ_FIRST(&dbch->db_trq), idb = 0;
1111104349Sphk			idb < dbch->ndb;
1112104349Sphk			db_tr = STAILQ_NEXT(db_tr, link), idb++){
1113104349Sphk			if (db_tr->buf != NULL) {
1114104349Sphk				free(db_tr->buf, M_DEVBUF);
1115104349Sphk				db_tr->buf = NULL;
1116104349Sphk			}
1117104349Sphk		}
1118104349Sphk	}
1119104349Sphk	dbch->ndb = 0;
1120104349Sphk	db_tr = STAILQ_FIRST(&dbch->db_trq);
1121104349Sphk	for (i = 0; i < dbch->npages; i++)
1122104349Sphk		free(dbch->pages[i], M_DEVBUF);
1123104349Sphk	free(db_tr, M_DEVBUF);
1124104349Sphk	STAILQ_INIT(&dbch->db_trq);
1125104349Sphk	dbch->flags &= ~FWOHCI_DBCH_INIT;
1126104349Sphk}
1127104349Sphk
1128104349Sphkstatic void
1129178848Scokanefwohci_db_init(struct fwohci_dbch *dbch)
1130104349Sphk{
1131104349Sphk	int	idb;
1132178848Scokane	struct fwohcidb_tr *db_tr;
1133178848Scokane	int	ndbpp, i, j;
1134178848Scokane
1135178848Scokane	if ((dbch->flags & FWOHCI_DBCH_INIT) != 0)
1136178848Scokane		goto out;
1137178848Scokane
1138104349Sphk	/* allocate DB entries and attach one to each DMA channels */
1139104349Sphk	/* DB entry must start at 16 bytes bounary. */
1140178848Scokane	STAILQ_INIT(&dbch->db_trq);
1141104349Sphk	db_tr = (struct fwohcidb_tr *)
1142104349Sphk		malloc(sizeof(struct fwohcidb_tr) * dbch->ndb,
1143178848Scokane		M_DEVBUF, M_NOWAIT | M_ZERO);
1144104349Sphk	if(db_tr == NULL){
1145104349Sphk		printf("fwohci_db_init: malloc(1) failed\n");
1146178848Scokane		return;
1147178848Scokane	}
1148104349Sphk
1149104349Sphk	ndbpp = PAGE_SIZE / (sizeof(struct fwohcidb) * dbch->ndesc);
1150104349Sphk	dbch->npages = (dbch->ndb + ndbpp - 1)/ ndbpp;
1151104349Sphk	if (firewire_debug)
1152178848Scokane		printf("ndesc: %d, ndbpp: %d, ndb: %d, npages: %d\n",
1153178848Scokane			dbch->ndesc, ndbpp, dbch->ndb, dbch->npages);
1154178848Scokane	if (dbch->npages > FWOHCI_DBCH_MAX_PAGES) {
1155178848Scokane		printf("npages(%d) > DBCH_MAX_PAGES(%d)\n",
1156178848Scokane				dbch->npages, FWOHCI_DBCH_MAX_PAGES);
1157178848Scokane		return;
1158178848Scokane	}
1159178848Scokane	for (i = 0; i < dbch->npages; i++) {
1160178848Scokane		dbch->pages[i] = malloc(PAGE_SIZE, M_DEVBUF,
1161178848Scokane						M_NOWAIT | M_ZERO);
1162178848Scokane		if (dbch->pages[i] == NULL) {
1163178848Scokane			printf("fwohci_db_init: malloc(2) failed\n");
1164178848Scokane			for (j = 0; j < i; j ++)
1165178848Scokane				free(dbch->pages[j], M_DEVBUF);
1166178848Scokane			free(db_tr, M_DEVBUF);
1167104349Sphk			return;
1168104349Sphk		}
1169104349Sphk	}
1170104349Sphk	/* Attach DB to DMA ch. */
1171104349Sphk	for(idb = 0 ; idb < dbch->ndb ; idb++){
1172178848Scokane		db_tr->dbcnt = 0;
1173178848Scokane		db_tr->db = (struct fwohcidb *)dbch->pages[idb/ndbpp]
1174178848Scokane					+ dbch->ndesc * (idb % ndbpp);
1175178848Scokane		STAILQ_INSERT_TAIL(&dbch->db_trq, db_tr, link);
1176178848Scokane		if (!(dbch->xferq.flag & FWXFERQ_PACKET) &&
1177178848Scokane					dbch->xferq.bnpacket != 0) {
1178104349Sphk			if (idb % dbch->xferq.bnpacket == 0)
1179178848Scokane				dbch->xferq.bulkxfer[idb / dbch->xferq.bnpacket
1180104349Sphk						].start = (caddr_t)db_tr;
1181247296Sdelphij			if ((idb + 1) % dbch->xferq.bnpacket == 0)
1182247296Sdelphij				dbch->xferq.bulkxfer[idb / dbch->xferq.bnpacket
1183247296Sdelphij						].end = (caddr_t)db_tr;
1184178848Scokane		}
1185178848Scokane		db_tr++;
1186104349Sphk	}
1187178848Scokane	STAILQ_LAST(&dbch->db_trq, fwohcidb_tr,link)->link.stqe_next
1188178848Scokane			= STAILQ_FIRST(&dbch->db_trq);
1189104349Sphkout:
1190104349Sphk	dbch->frag.buf = NULL;
1191104349Sphk	dbch->frag.len = 0;
1192104349Sphk	dbch->frag.plen = 0;
1193104349Sphk	dbch->xferq.queued = 0;
1194178848Scokane	dbch->pdb_tr = NULL;
1195104349Sphk	dbch->top = STAILQ_FIRST(&dbch->db_trq);
1196104349Sphk	dbch->bottom = dbch->top;
1197104349Sphk	dbch->flags = FWOHCI_DBCH_INIT;
1198104349Sphk}
1199104349Sphk
1200178848Scokanestatic int
1201104349Sphkfwohci_itx_disable(struct firewire_comm *fc, int dmach)
1202104349Sphk{
1203104349Sphk	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1204104349Sphk	OWRITE(sc, OHCI_ITCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
1205178848Scokane	OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach);
1206104349Sphk	OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach);
1207104349Sphk	fwohci_db_free(&sc->it[dmach]);
1208104349Sphk	sc->it[dmach].xferq.flag &= ~FWXFERQ_RUNNING;
1209104349Sphk	return 0;
1210104349Sphk}
1211104349Sphk
1212104349Sphkstatic int
1213104349Sphkfwohci_irx_disable(struct firewire_comm *fc, int dmach)
1214178848Scokane{
1215104349Sphk	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1216104349Sphk
1217104349Sphk	OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
1218178848Scokane	OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach);
1219104349Sphk	OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach);
1220104349Sphk	if(sc->ir[dmach].dummy != NULL){
1221104349Sphk		free(sc->ir[dmach].dummy, M_DEVBUF);
1222104349Sphk	}
1223178848Scokane	sc->ir[dmach].dummy = NULL;
1224104349Sphk	fwohci_db_free(&sc->ir[dmach]);
1225104349Sphk	sc->ir[dmach].xferq.flag &= ~FWXFERQ_RUNNING;
1226104349Sphk	return 0;
1227104349Sphk}
1228104349Sphk
1229104349Sphkstatic void
1230104349Sphkfwohci_irx_post (struct firewire_comm *fc , u_int32_t *qld)
1231104349Sphk{
1232178848Scokane	qld[0] = ntohl(qld[0]);
1233104349Sphk	return;
1234104349Sphk}
1235104349Sphk
1236178848Scokanestatic int
1237104349Sphkfwohci_irxpp_enable(struct firewire_comm *fc, int dmach)
1238178848Scokane{
1239104349Sphk	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1240104349Sphk	int err = 0;
1241104349Sphk	unsigned short tag, ich;
1242104349Sphk
1243178848Scokane	tag = (sc->ir[dmach].xferq.flag >> 6) & 3;
1244104349Sphk	ich = sc->ir[dmach].xferq.flag & 0x3f;
1245104349Sphk
1246178848Scokane#if 0
1247104349Sphk	if(STAILQ_FIRST(&fc->ir[dmach]->q) != NULL){
1248104349Sphk		wakeup(fc->ir[dmach]);
1249104349Sphk		return err;
1250104349Sphk	}
1251104349Sphk#endif
1252178848Scokane
1253104349Sphk	OWRITE(sc, OHCI_IRMATCH(dmach), tagbit[tag] | ich);
1254104349Sphk	if(!(sc->ir[dmach].xferq.flag & FWXFERQ_RUNNING)){
1255104349Sphk		sc->ir[dmach].xferq.queued = 0;
1256104349Sphk		sc->ir[dmach].ndb = NDB;
1257104349Sphk		sc->ir[dmach].xferq.psize = PAGE_SIZE;
1258178848Scokane		sc->ir[dmach].ndesc = 1;
1259104349Sphk		fwohci_db_init(&sc->ir[dmach]);
1260104349Sphk		if ((sc->ir[dmach].flags & FWOHCI_DBCH_INIT) == 0)
1261104349Sphk			return ENOMEM;
1262104349Sphk		err = fwohci_rx_enable(sc, &sc->ir[dmach]);
1263104349Sphk	}
1264247296Sdelphij	if(err){
1265247296Sdelphij		device_printf(sc->fc.dev, "err in IRX setting\n");
1266247296Sdelphij		return err;
1267247296Sdelphij	}
1268247296Sdelphij	if(!(OREAD(sc, OHCI_IRCTL(dmach)) & OHCI_CNTL_DMA_ACTIVE)){
1269247296Sdelphij		OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
1270247296Sdelphij		OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach);
1271247296Sdelphij		OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach);
1272178848Scokane		OWRITE(sc, OHCI_IR_MASK, 1 << dmach);
1273104349Sphk		OWRITE(sc, OHCI_IRCTLCLR(dmach), 0xf8000000);
1274104349Sphk		OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_ISOHDR);
1275104349Sphk		OWRITE(sc, OHCI_IRCMD(dmach),
1276104349Sphk			vtophys(sc->ir[dmach].top->db) | 1);
1277104349Sphk		OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_DMA_RUN);
1278104349Sphk		OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IR);
1279104349Sphk	}
1280104349Sphk	return err;
1281178848Scokane}
1282104349Sphk
1283104349Sphkstatic int
1284104349Sphkfwohci_tx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1285104349Sphk{
1286104349Sphk	int err = 0;
1287178848Scokane	int idb, z, i, dmach = 0;
1288104349Sphk	u_int32_t off = NULL;
1289104349Sphk	struct fwohcidb_tr *db_tr;
1290104349Sphk
1291104349Sphk	if(!(dbch->xferq.flag & FWXFERQ_EXTBUF)){
1292104349Sphk		err = EINVAL;
1293178848Scokane		return err;
1294104349Sphk	}
1295104349Sphk	z = dbch->ndesc;
1296104349Sphk	for(dmach = 0 ; dmach < sc->fc.nisodma ; dmach++){
1297104349Sphk		if( &sc->it[dmach] == dbch){
1298104349Sphk			off = OHCI_ITOFF(dmach);
1299104349Sphk			break;
1300178848Scokane		}
1301104349Sphk	}
1302104349Sphk	if(off == NULL){
1303104349Sphk		err = EINVAL;
1304104349Sphk		return err;
1305104349Sphk	}
1306104349Sphk	if(dbch->xferq.flag & FWXFERQ_RUNNING)
1307178848Scokane		return err;
1308104349Sphk	dbch->xferq.flag |= FWXFERQ_RUNNING;
1309104349Sphk	for( i = 0, dbch->bottom = dbch->top; i < (dbch->ndb - 1); i++){
1310104349Sphk		dbch->bottom = STAILQ_NEXT(dbch->bottom, link);
1311104349Sphk	}
1312104349Sphk	db_tr = dbch->top;
1313104349Sphk	for( idb = 0 ; idb < dbch->ndb ; idb ++){
1314178848Scokane		fwohci_add_tx_buf(db_tr,
1315104349Sphk			dbch->xferq.psize, dbch->xferq.flag,
1316104349Sphk			dbch->xferq.buf + dbch->xferq.psize * idb);
1317104349Sphk		if(STAILQ_NEXT(db_tr, link) == NULL){
1318104349Sphk			break;
1319104349Sphk		}
1320104349Sphk		db_tr->db[0].db.desc.depend
1321104349Sphk			= vtophys(STAILQ_NEXT(db_tr, link)->db) | z;
1322104349Sphk		db_tr->db[db_tr->dbcnt - 1].db.desc.depend
1323178848Scokane			= vtophys(STAILQ_NEXT(db_tr, link)->db) | z;
1324104349Sphk		if(dbch->xferq.flag & FWXFERQ_EXTBUF){
1325104349Sphk			if(((idb + 1 ) % dbch->xferq.bnpacket) == 0){
1326104349Sphk				db_tr->db[db_tr->dbcnt - 1].db.desc.cmd
1327104349Sphk					|= OHCI_INTERRUPT_ALWAYS;
1328104349Sphk				db_tr->db[0].db.desc.depend &= ~0xf;
1329178848Scokane				db_tr->db[db_tr->dbcnt - 1].db.desc.depend &=
1330104349Sphk						~0xf;
1331104349Sphk				/* OHCI 1.1 and above */
1332104349Sphk				db_tr->db[0].db.desc.cmd
1333104349Sphk					|= OHCI_INTERRUPT_ALWAYS;
1334104349Sphk			}
1335178848Scokane		}
1336104349Sphk		db_tr = STAILQ_NEXT(db_tr, link);
1337104349Sphk	}
1338104349Sphk	dbch->bottom->db[db_tr->dbcnt - 1].db.desc.depend &= 0xfffffff0;
1339104349Sphk	return err;
1340104349Sphk}
1341104349Sphk
1342104349Sphkstatic int
1343178848Scokanefwohci_rx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1344104349Sphk{
1345104349Sphk	int err = 0;
1346104349Sphk	int idb, z, i, dmach = 0;
1347104349Sphk	u_int32_t off = NULL;
1348104349Sphk	struct fwohcidb_tr *db_tr;
1349104349Sphk
1350104349Sphk	z = dbch->ndesc;
1351178848Scokane	if(&sc->arrq == dbch){
1352104349Sphk		off = OHCI_ARQOFF;
1353104349Sphk	}else if(&sc->arrs == dbch){
1354104349Sphk		off = OHCI_ARSOFF;
1355104349Sphk	}else{
1356104349Sphk		for(dmach = 0 ; dmach < sc->fc.nisodma ; dmach++){
1357104349Sphk			if( &sc->ir[dmach] == dbch){
1358104349Sphk				off = OHCI_IROFF(dmach);
1359104349Sphk				break;
1360178848Scokane			}
1361104349Sphk		}
1362104349Sphk	}
1363104349Sphk	if(off == NULL){
1364104349Sphk		err = EINVAL;
1365104349Sphk		return err;
1366178848Scokane	}
1367104349Sphk	if(dbch->xferq.flag & FWXFERQ_STREAM){
1368104349Sphk		if(dbch->xferq.flag & FWXFERQ_RUNNING)
1369104349Sphk			return err;
1370104349Sphk	}else{
1371104349Sphk		if(dbch->xferq.flag & FWXFERQ_RUNNING){
1372178848Scokane			err = EBUSY;
1373104349Sphk			return err;
1374104349Sphk		}
1375104349Sphk	}
1376104349Sphk	dbch->xferq.flag |= FWXFERQ_RUNNING;
1377104349Sphk	dbch->top = STAILQ_FIRST(&dbch->db_trq);
1378104349Sphk	for( i = 0, dbch->bottom = dbch->top; i < (dbch->ndb - 1); i++){
1379178848Scokane		dbch->bottom = STAILQ_NEXT(dbch->bottom, link);
1380104349Sphk	}
1381104349Sphk	db_tr = dbch->top;
1382104349Sphk	for( idb = 0 ; idb < dbch->ndb ; idb ++){
1383104349Sphk		if(!(dbch->xferq.flag & FWXFERQ_EXTBUF)){
1384104349Sphk			fwohci_add_rx_buf(db_tr,
1385104349Sphk				dbch->xferq.psize, dbch->xferq.flag, 0, NULL);
1386178848Scokane		}else{
1387104349Sphk			fwohci_add_rx_buf(db_tr,
1388104349Sphk				dbch->xferq.psize, dbch->xferq.flag,
1389104349Sphk				dbch->xferq.buf + dbch->xferq.psize * idb,
1390104349Sphk				dbch->dummy + sizeof(u_int32_t) * idb);
1391104349Sphk		}
1392104349Sphk		if(STAILQ_NEXT(db_tr, link) == NULL){
1393104349Sphk			break;
1394104349Sphk		}
1395178848Scokane		db_tr->db[db_tr->dbcnt - 1].db.desc.depend
1396104349Sphk			= vtophys(STAILQ_NEXT(db_tr, link)->db) | z;
1397104349Sphk		if(dbch->xferq.flag & FWXFERQ_EXTBUF){
1398104349Sphk			if(((idb + 1 ) % dbch->xferq.bnpacket) == 0){
1399104349Sphk				db_tr->db[db_tr->dbcnt - 1].db.desc.cmd
1400104349Sphk					|= OHCI_INTERRUPT_ALWAYS;
1401178848Scokane				db_tr->db[db_tr->dbcnt - 1].db.desc.depend &=
1402104349Sphk						~0xf;
1403104349Sphk			}
1404104349Sphk		}
1405104349Sphk		db_tr = STAILQ_NEXT(db_tr, link);
1406104349Sphk	}
1407178848Scokane	dbch->bottom->db[db_tr->dbcnt - 1].db.desc.depend &= 0xfffffff0;
1408104349Sphk	dbch->buf_offset = 0;
1409104349Sphk	if(dbch->xferq.flag & FWXFERQ_STREAM){
1410104349Sphk		return err;
1411104349Sphk	}else{
1412104349Sphk		OWRITE(sc, OHCI_DMACMD(off), vtophys(dbch->top->db) | z);
1413104349Sphk	}
1414178848Scokane	OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_RUN);
1415104349Sphk	return err;
1416104349Sphk}
1417104349Sphk
1418104349Sphkstatic int
1419104349Sphkfwohci_itxbuf_enable(struct firewire_comm *fc, int dmach)
1420104349Sphk{
1421178848Scokane	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1422104349Sphk	int err = 0;
1423104349Sphk	unsigned short tag, ich;
1424104349Sphk	struct fwohci_dbch *dbch;
1425178848Scokane	int cycle_now, sec, cycle, cycle_match;
1426104349Sphk	u_int32_t stat;
1427104349Sphk
1428104349Sphk	tag = (sc->it[dmach].xferq.flag >> 6) & 3;
1429104349Sphk	ich = sc->it[dmach].xferq.flag & 0x3f;
1430178848Scokane	dbch = &sc->it[dmach];
1431104349Sphk	if ((dbch->flags & FWOHCI_DBCH_INIT) == 0) {
1432104349Sphk		dbch->xferq.queued = 0;
1433104349Sphk		dbch->ndb = dbch->xferq.bnpacket * dbch->xferq.bnchunk;
1434104349Sphk		dbch->ndesc = 3;
1435104349Sphk		fwohci_db_init(dbch);
1436104349Sphk		if ((dbch->flags & FWOHCI_DBCH_INIT) == 0)
1437178848Scokane			return ENOMEM;
1438104349Sphk		err = fwohci_tx_enable(sc, dbch);
1439104349Sphk	}
1440104349Sphk	if(err)
1441104349Sphk		return err;
1442104349Sphk	stat = OREAD(sc, OHCI_ITCTL(dmach));
1443104349Sphk	if (stat & OHCI_CNTL_DMA_ACTIVE) {
1444104349Sphk		if(dbch->xferq.stdma2 != NULL){
1445104349Sphk			fwohci_txbufdb(sc, dmach, dbch->xferq.stdma2);
1446178848Scokane			((struct fwohcidb_tr *)
1447104349Sphk		(dbch->xferq.stdma->end))->db[dbch->ndesc - 1].db.desc.cmd
1448104349Sphk			|= OHCI_BRANCH_ALWAYS;
1449104349Sphk			((struct fwohcidb_tr *)
1450104349Sphk		(dbch->xferq.stdma->end))->db[dbch->ndesc - 1].db.desc.depend =
1451104349Sphk	    vtophys(((struct fwohcidb_tr *)(dbch->xferq.stdma2->start))->db) | dbch->ndesc;
1452104349Sphk			((struct fwohcidb_tr *)(dbch->xferq.stdma->end))->db[0].db.desc.depend =
1453178848Scokane	    vtophys(((struct fwohcidb_tr *)(dbch->xferq.stdma2->start))->db) | dbch->ndesc;
1454104349Sphk			((struct fwohcidb_tr *)(dbch->xferq.stdma2->end))->db[dbch->ndesc - 1].db.desc.depend &= ~0xf;
1455104349Sphk			((struct fwohcidb_tr *)(dbch->xferq.stdma2->end))->db[0].db.desc.depend &= ~0xf;
1456104349Sphk		} else {
1457104349Sphk			device_printf(fc->dev,
1458104349Sphk				"fwohci_itxbuf_enable: queue underrun\n");
1459104349Sphk		}
1460178848Scokane		return err;
1461104349Sphk	}
1462104349Sphk	if (firewire_debug)
1463104349Sphk		printf("fwohci_itxbuf_enable: kick 0x%08x\n", stat);
1464104349Sphk	fw_tbuf_update(&sc->fc, dmach, 0);
1465104349Sphk	if(dbch->xferq.stdma == NULL){
1466104349Sphk		return err;
1467178848Scokane	}
1468104349Sphk	if(dbch->xferq.stdma2 == NULL){
1469104349Sphk		/* wait until 2 chunks buffered */
1470104349Sphk		return err;
1471104349Sphk	}
1472104349Sphk	OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach);
1473178848Scokane	OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach);
1474104349Sphk	OWRITE(sc, OHCI_IT_MASK, 1 << dmach);
1475104349Sphk	fwohci_txbufdb(sc, dmach, dbch->xferq.stdma);
1476104349Sphk	fwohci_txbufdb(sc, dmach, dbch->xferq.stdma2);
1477104349Sphk	((struct fwohcidb_tr *)
1478178848Scokane		(dbch->xferq.stdma->end))->db[dbch->ndesc - 1].db.desc.cmd
1479104349Sphk			|= OHCI_BRANCH_ALWAYS;
1480104349Sphk	((struct fwohcidb_tr *)(dbch->xferq.stdma->end))->db[dbch->ndesc - 1].db.desc.depend =
1481104349Sphk		    vtophys(((struct fwohcidb_tr *)(dbch->xferq.stdma2->start))->db) | dbch->ndesc;
1482104349Sphk	((struct fwohcidb_tr *)(dbch->xferq.stdma->end))->db[0].db.desc.depend =
1483104349Sphk		    vtophys(((struct fwohcidb_tr *)(dbch->xferq.stdma2->start))->db) | dbch->ndesc;
1484104349Sphk	((struct fwohcidb_tr *)(dbch->xferq.stdma2->end))->db[dbch->ndesc - 1].db.desc.depend &= ~0xf;
1485104349Sphk	((struct fwohcidb_tr *) (dbch->xferq.stdma2->end))->db[0].db.desc.depend &= ~0xf;
1486104349Sphk	OWRITE(sc, OHCI_ITCMD(dmach),
1487104349Sphk		vtophys(((struct fwohcidb_tr *)
1488247296Sdelphij			(dbch->xferq.stdma->start))->db) | dbch->ndesc);
1489247296Sdelphij#define CYCLE_OFFSET	1
1490247296Sdelphij	if ((stat & OHCI_CNTL_DMA_RUN) == 0) {
1491247296Sdelphij#ifdef FWXFERQ_DV
1492247296Sdelphij		if(dbch->xferq.flag & FWXFERQ_DV){
1493247296Sdelphij			struct fw_pkt *fp;
1494247296Sdelphij			struct fwohcidb_tr *db_tr;
1495247296Sdelphij
1496247296Sdelphij			db_tr = (struct fwohcidb_tr *)dbch->xferq.stdma->start;
1497247296Sdelphij			fp = (struct fw_pkt *)db_tr->buf;
1498247296Sdelphij			dbch->xferq.dvoffset = CYCLE_OFFSET;
1499178848Scokane			fp->mode.ld[2] |= htonl(dbch->xferq.dvoffset << 12);
1500104349Sphk		}
1501104349Sphk#endif
1502178848Scokane		/* 2bit second + 13bit cycle */
1503178848Scokane		cycle_now = (fc->cyctimer(fc) >> 12) & 0x7fff;
1504178848Scokane		cycle = cycle_now & 0x1fff;
1505178848Scokane		sec = cycle_now >> 13;
1506178848Scokane#define CYCLE_MOD	0x10
1507178848Scokane#define CYCLE_DELAY	8	/* min delay to start DMA */
1508178848Scokane		cycle = cycle + CYCLE_DELAY;
1509247296Sdelphij		if (cycle >= 8000) {
1510247296Sdelphij			sec ++;
1511247296Sdelphij			cycle -= 8000;
1512247296Sdelphij		}
1513247296Sdelphij		cycle = ((cycle + CYCLE_MOD - 1) / CYCLE_MOD) * CYCLE_MOD;
1514178848Scokane		if (cycle >= 8000) {
1515178848Scokane			sec ++;
1516178848Scokane			if (cycle == 8000)
1517178848Scokane				cycle = 0;
1518104349Sphk			else
1519178848Scokane				cycle = CYCLE_MOD;
1520104349Sphk		}
1521104349Sphk		cycle_match = ((sec << 13) | cycle) & 0x7ffff;
1522104349Sphk		/* Clear cycle match counter bits */
1523178848Scokane		OWRITE(sc, OHCI_ITCTLCLR(dmach), 0xffff0000);
1524178848Scokane		OWRITE(sc, OHCI_ITCTL(dmach),
1525178848Scokane				OHCI_CNTL_CYCMATCH_S | (cycle_match << 16)
1526178848Scokane				| OHCI_CNTL_DMA_RUN);
1527178848Scokane		OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IT);
1528178848Scokane		if (firewire_debug)
1529178848Scokane			printf("cycle_match: 0x%04x->0x%04x\n",
1530178848Scokane						cycle_now, cycle_match);
1531178848Scokane	} else if ((stat & OHCI_CNTL_CYCMATCH_S) == 0) {
1532178848Scokane		if (firewire_debug)
1533178848Scokane			printf("fwohci_itxbuf_enable: restart 0x%08x\n", stat);
1534178848Scokane		OWRITE(sc, OHCI_ITCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
1535178848Scokane		OWRITE(sc, OHCI_ITCTL(dmach), OHCI_CNTL_DMA_RUN);
1536178848Scokane	}
1537247296Sdelphij	return err;
1538178848Scokane}
1539178848Scokane
1540178848Scokanestatic int
1541178848Scokanefwohci_irxbuf_enable(struct firewire_comm *fc, int dmach)
1542178848Scokane{
1543178848Scokane	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1544178848Scokane	int err = 0;
1545104349Sphk	unsigned short tag, ich;
1546104349Sphk	u_int32_t stat;
1547104349Sphk
1548104349Sphk	if(!(sc->ir[dmach].xferq.flag & FWXFERQ_RUNNING)){
1549104349Sphk		tag = (sc->ir[dmach].xferq.flag >> 6) & 3;
1550104349Sphk		ich = sc->ir[dmach].xferq.flag & 0x3f;
1551104349Sphk		OWRITE(sc, OHCI_IRMATCH(dmach), tagbit[tag] | ich);
1552104349Sphk
1553178848Scokane		sc->ir[dmach].xferq.queued = 0;
1554104349Sphk		sc->ir[dmach].ndb = sc->ir[dmach].xferq.bnpacket *
1555104349Sphk				sc->ir[dmach].xferq.bnchunk;
1556178848Scokane		sc->ir[dmach].dummy =
1557178848Scokane			malloc(sizeof(u_int32_t) * sc->ir[dmach].ndb,
1558104349Sphk			   M_DEVBUF, M_NOWAIT);
1559178848Scokane		if(sc->ir[dmach].dummy == NULL){
1560104349Sphk			err = ENOMEM;
1561104349Sphk			return err;
1562104349Sphk		}
1563104349Sphk		sc->ir[dmach].ndesc = 2;
1564104349Sphk		fwohci_db_init(&sc->ir[dmach]);
1565178848Scokane		if ((sc->ir[dmach].flags & FWOHCI_DBCH_INIT) == 0)
1566178848Scokane			return ENOMEM;
1567178848Scokane		err = fwohci_rx_enable(sc, &sc->ir[dmach]);
1568178848Scokane	}
1569178848Scokane	if(err)
1570178848Scokane		return err;
1571178848Scokane
1572178848Scokane	stat = OREAD(sc, OHCI_IRCTL(dmach));
1573178848Scokane	if (stat & OHCI_CNTL_DMA_ACTIVE) {
1574247296Sdelphij		if(sc->ir[dmach].xferq.stdma2 != NULL){
1575178848Scokane			((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[sc->ir[dmach].ndesc - 1].db.desc.depend =
1576247296Sdelphij	    vtophys(((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->start))->db) | sc->ir[dmach].ndesc;
1577247296Sdelphij			((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[0].db.desc.depend =
1578247296Sdelphij	    vtophys(((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->start))->db);
1579178848Scokane			((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->end))->db[sc->ir[dmach].ndesc - 1].db.desc.depend &= ~0xf;
1580178848Scokane			((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->end))->db[0].db.desc.depend &= ~0xf;
1581178848Scokane		}
1582104349Sphk	} else if (!(stat & OHCI_CNTL_DMA_ACTIVE)
1583104349Sphk		&& !(sc->ir[dmach].xferq.flag & FWXFERQ_PACKET)) {
1584104349Sphk		if (firewire_debug)
1585104349Sphk			device_printf(sc->fc.dev, "IR DMA stat %x\n", stat);
1586104349Sphk		fw_rbuf_update(&sc->fc, dmach, 0);
1587104349Sphk
1588178848Scokane		OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
1589178848Scokane		OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach);
1590178848Scokane		OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach);
1591104349Sphk		OWRITE(sc, OHCI_IR_MASK, 1 << dmach);
1592104349Sphk		OWRITE(sc, OHCI_IRCTLCLR(dmach), 0xf0000000);
1593104349Sphk		OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_ISOHDR);
1594104349Sphk		if(sc->ir[dmach].xferq.stdma2 != NULL){
1595104349Sphk			((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[sc->ir[dmach].ndesc - 1].db.desc.depend =
1596104349Sphk		    vtophys(((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->start))->db) | sc->ir[dmach].ndesc;
1597247296Sdelphij			((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[0].db.desc.depend =
1598104349Sphk		    vtophys(((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->start))->db);
1599104349Sphk			((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->end))->db[sc->ir[dmach].ndesc - 1].db.desc.depend &= ~0xf;
1600104349Sphk		}else{
1601104349Sphk			((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[sc->ir[dmach].ndesc - 1].db.desc.depend &= ~0xf;
1602178848Scokane			((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[0].db.desc.depend &= ~0xf;
1603178848Scokane		}
1604178848Scokane		OWRITE(sc, OHCI_IRCMD(dmach),
1605178848Scokane			vtophys(((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->start))->db) | sc->ir[dmach].ndesc);
1606178848Scokane		OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_DMA_RUN);
1607178848Scokane		OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IR);
1608178848Scokane	}
1609104349Sphk	return err;
1610104349Sphk}
1611104349Sphk
1612104349Sphkstatic int
1613104349Sphkfwohci_irx_enable(struct firewire_comm *fc, int dmach)
1614104349Sphk{
1615104349Sphk	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1616104349Sphk	int err = 0;
1617104349Sphk
1618104349Sphk	if(sc->ir[dmach].xferq.flag & FWXFERQ_PACKET){
1619104349Sphk		err = fwohci_irxpp_enable(fc, dmach);
1620104349Sphk		return err;
1621104349Sphk	}else{
1622178848Scokane		err = fwohci_irxbuf_enable(fc, dmach);
1623104349Sphk		return err;
1624104349Sphk	}
1625178848Scokane}
1626178848Scokane
1627178848Scokaneint
1628178848Scokanefwohci_shutdown(struct fwohci_softc *sc, device_t dev)
1629178848Scokane{
1630178848Scokane	u_int i;
1631178848Scokane
1632178848Scokane/* Now stopping all DMA channel */
1633178848Scokane	OWRITE(sc,  OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN);
1634178848Scokane	OWRITE(sc,  OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN);
1635247296Sdelphij	OWRITE(sc,  OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN);
1636247296Sdelphij	OWRITE(sc,  OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
1637247296Sdelphij
1638247296Sdelphij	for( i = 0 ; i < sc->fc.nisodma ; i ++ ){
1639247296Sdelphij		OWRITE(sc,  OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN);
1640178848Scokane		OWRITE(sc,  OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN);
1641178848Scokane	}
1642178848Scokane
1643178848Scokane/* FLUSH FIFO and reset Transmitter/Reciever */
1644178848Scokane	OWRITE(sc,  OHCI_HCCCTL, OHCI_HCC_RESET);
1645104349Sphk
1646104349Sphk/* Stop interrupt */
1647178848Scokane	OWRITE(sc, FWOHCI_INTMASKCLR,
1648104349Sphk			OHCI_INT_EN | OHCI_INT_ERR | OHCI_INT_PHY_SID
1649178848Scokane			| OHCI_INT_PHY_INT
1650178848Scokane			| OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS
1651178848Scokane			| OHCI_INT_DMA_PRRQ | OHCI_INT_DMA_PRRS
1652178848Scokane			| OHCI_INT_DMA_ARRQ | OHCI_INT_DMA_ARRS
1653178848Scokane			| OHCI_INT_PHY_BUS_R);
1654104349Sphk/* XXX Link down?  Bus reset? */
1655104349Sphk	return 0;
1656104349Sphk}
1657104349Sphk
1658178848Scokaneint
1659178848Scokanefwohci_resume(struct fwohci_softc *sc, device_t dev)
1660178848Scokane{
1661178848Scokane	int i;
1662178848Scokane
1663247296Sdelphij	fwohci_reset(sc, dev);
1664178848Scokane	/* XXX resume isochronus receive automatically. (how about TX?) */
1665178848Scokane	for(i = 0; i < sc->fc.nisodma; i ++) {
1666178848Scokane		if((sc->ir[i].xferq.flag & FWXFERQ_RUNNING) != 0) {
1667178848Scokane			device_printf(sc->fc.dev,
1668178848Scokane				"resume iso receive ch: %d\n", i);
1669178848Scokane			sc->ir[i].xferq.flag &= ~FWXFERQ_RUNNING;
1670178848Scokane			sc->fc.irx_enable(&sc->fc, i);
1671178848Scokane		}
1672178848Scokane	}
1673178848Scokane
1674178848Scokane	bus_generic_resume(dev);
1675178848Scokane	sc->fc.ibr(&sc->fc);
1676104349Sphk	return 0;
1677104349Sphk}
1678178848Scokane
1679104349Sphk#define ACK_ALL
1680104349Sphkstatic void
1681286901Sdelphijfwohci_intr_body(struct fwohci_softc *sc, u_int32_t stat, int count)
1682286901Sdelphij{
1683286901Sdelphij	u_int32_t irstat, itstat;
1684286901Sdelphij	u_int i;
1685286901Sdelphij	struct firewire_comm *fc = (struct firewire_comm *)sc;
1686286901Sdelphij
1687178848Scokane#ifdef OHCI_DEBUG
1688178848Scokane	if(stat & OREAD(sc, FWOHCI_INTMASK))
1689178848Scokane		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",
1690178848Scokane			stat & OHCI_INT_EN ? "DMA_EN ":"",
1691178848Scokane			stat & OHCI_INT_PHY_REG ? "PHY_REG ":"",
1692178848Scokane			stat & OHCI_INT_CYC_LONG ? "CYC_LONG ":"",
1693178848Scokane			stat & OHCI_INT_ERR ? "INT_ERR ":"",
1694178848Scokane			stat & OHCI_INT_CYC_ERR ? "CYC_ERR ":"",
1695178848Scokane			stat & OHCI_INT_CYC_LOST ? "CYC_LOST ":"",
1696178848Scokane			stat & OHCI_INT_CYC_64SECOND ? "CYC_64SECOND ":"",
1697104349Sphk			stat & OHCI_INT_CYC_START ? "CYC_START ":"",
1698178848Scokane			stat & OHCI_INT_PHY_INT ? "PHY_INT ":"",
1699286901Sdelphij			stat & OHCI_INT_PHY_BUS_R ? "BUS_RESET ":"",
1700286901Sdelphij			stat & OHCI_INT_PHY_SID ? "SID ":"",
1701286901Sdelphij			stat & OHCI_INT_LR_ERR ? "DMA_LR_ERR ":"",
1702286901Sdelphij			stat & OHCI_INT_PW_ERR ? "DMA_PW_ERR ":"",
1703286901Sdelphij			stat & OHCI_INT_DMA_IR ? "DMA_IR ":"",
1704286901Sdelphij			stat & OHCI_INT_DMA_IT  ? "DMA_IT " :"",
1705104349Sphk			stat & OHCI_INT_DMA_PRRS  ? "DMA_PRRS " :"",
1706178848Scokane			stat & OHCI_INT_DMA_PRRQ  ? "DMA_PRRQ " :"",
1707104349Sphk			stat & OHCI_INT_DMA_ARRS  ? "DMA_ARRS " :"",
1708104349Sphk			stat & OHCI_INT_DMA_ARRQ  ? "DMA_ARRQ " :"",
1709104349Sphk			stat & OHCI_INT_DMA_ATRS  ? "DMA_ATRS " :"",
1710104349Sphk			stat & OHCI_INT_DMA_ATRQ  ? "DMA_ATRQ " :"",
1711104349Sphk			stat, OREAD(sc, FWOHCI_INTMASK)
1712104349Sphk		);
1713104349Sphk#endif
1714104349Sphk/* Bus reset */
1715178848Scokane	if(stat & OHCI_INT_PHY_BUS_R ){
1716104349Sphk		device_printf(fc->dev, "BUS reset\n");
1717104349Sphk		OWRITE(sc, FWOHCI_INTMASKCLR,  OHCI_INT_CYC_LOST);
1718104349Sphk		OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCSRC);
1719104349Sphk
1720104349Sphk		OWRITE(sc,  OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN);
1721104349Sphk		sc->atrq.xferq.flag &= ~FWXFERQ_RUNNING;
1722104349Sphk		OWRITE(sc,  OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
1723104349Sphk		sc->atrs.xferq.flag &= ~FWXFERQ_RUNNING;
1724104349Sphk
1725104349Sphk#if 0
1726104349Sphk		for( i = 0 ; i < fc->nisodma ; i ++ ){
1727104349Sphk			OWRITE(sc,  OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN);
1728178848Scokane			OWRITE(sc,  OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN);
1729104349Sphk		}
1730104349Sphk
1731104349Sphk#endif
1732104349Sphk		fw_busreset(fc);
1733286901Sdelphij
1734286901Sdelphij		/* XXX need to wait DMA to stop */
1735286901Sdelphij#ifndef ACK_ALL
1736286901Sdelphij		OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_BUS_R);
1737286901Sdelphij#endif
1738286901Sdelphij#if 1
1739286901Sdelphij		/* pending all pre-bus_reset packets */
1740286901Sdelphij		fwohci_txd(sc, &sc->atrq);
1741286901Sdelphij		fwohci_txd(sc, &sc->atrs);
1742178848Scokane		fwohci_arcv(sc, &sc->arrs, -1);
1743104349Sphk		fwohci_arcv(sc, &sc->arrq, -1);
1744104349Sphk#endif
1745104349Sphk
1746104349Sphk
1747104349Sphk		OWRITE(sc, OHCI_AREQHI, 1 << 31);
1748104349Sphk		/* XXX insecure ?? */
1749104349Sphk		OWRITE(sc, OHCI_PREQHI, 0x7fffffff);
1750178848Scokane		OWRITE(sc, OHCI_PREQLO, 0xffffffff);
1751104349Sphk		OWRITE(sc, OHCI_PREQUPPER, 0x10000);
1752104349Sphk
1753104349Sphk	}
1754104349Sphk	if((stat & OHCI_INT_DMA_IR )){
1755104349Sphk#ifndef ACK_ALL
1756104349Sphk		OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_IR);
1757104349Sphk#endif
1758104349Sphk		irstat = OREAD(sc, OHCI_IR_STAT);
1759104349Sphk		OWRITE(sc, OHCI_IR_STATCLR, irstat);
1760104349Sphk		for(i = 0; i < fc->nisodma ; i++){
1761104349Sphk			struct fwohci_dbch *dbch;
1762104349Sphk
1763104349Sphk			if((irstat & (1 << i)) != 0){
1764104349Sphk				dbch = &sc->ir[i];
1765104349Sphk				if ((dbch->xferq.flag & FWXFERQ_OPEN) == 0) {
1766104349Sphk					device_printf(sc->fc.dev,
1767104349Sphk						"dma(%d) not active\n", i);
1768104349Sphk					continue;
1769104349Sphk				}
1770104349Sphk				if (dbch->xferq.flag & FWXFERQ_PACKET) {
1771104349Sphk					fwohci_ircv(sc, dbch, count);
1772247296Sdelphij				} else {
1773247296Sdelphij					fwohci_rbuf_update(sc, i);
1774104349Sphk				}
1775104349Sphk			}
1776104349Sphk		}
1777104349Sphk	}
1778178848Scokane	if((stat & OHCI_INT_DMA_IT )){
1779178848Scokane#ifndef ACK_ALL
1780178848Scokane		OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_IT);
1781178848Scokane#endif
1782178848Scokane		itstat = OREAD(sc, OHCI_IT_STAT);
1783178848Scokane		OWRITE(sc, OHCI_IT_STATCLR, itstat);
1784178848Scokane		for(i = 0; i < fc->nisodma ; i++){
1785178848Scokane			if((itstat & (1 << i)) != 0){
1786178848Scokane				fwohci_tbuf_update(sc, i);
1787178848Scokane			}
1788178848Scokane		}
1789178848Scokane	}
1790178848Scokane	if((stat & OHCI_INT_DMA_PRRS )){
1791178848Scokane#ifndef ACK_ALL
1792178848Scokane		OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_PRRS);
1793178848Scokane#endif
1794178848Scokane#if 0
1795178848Scokane		dump_dma(sc, ARRS_CH);
1796178848Scokane		dump_db(sc, ARRS_CH);
1797178848Scokane#endif
1798178848Scokane		fwohci_arcv(sc, &sc->arrs, count);
1799178848Scokane	}
1800178848Scokane	if((stat & OHCI_INT_DMA_PRRQ )){
1801178848Scokane#ifndef ACK_ALL
1802178848Scokane		OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_PRRQ);
1803178848Scokane#endif
1804178848Scokane#if 0
1805178848Scokane		dump_dma(sc, ARRQ_CH);
1806178848Scokane		dump_db(sc, ARRQ_CH);
1807178848Scokane#endif
1808178848Scokane		fwohci_arcv(sc, &sc->arrq, count);
1809178848Scokane	}
1810178848Scokane	if(stat & OHCI_INT_PHY_SID){
1811178848Scokane		caddr_t buf;
1812178848Scokane		int plen;
1813178848Scokane
1814178848Scokane#ifndef ACK_ALL
1815178848Scokane		OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_SID);
1816178848Scokane#endif
1817178848Scokane/*
1818178848Scokane** Checking whether the node is root or not. If root, turn on
1819178848Scokane** cycle master.
1820178848Scokane*/
1821178848Scokane		device_printf(fc->dev, "node_id = 0x%08x, ", OREAD(sc, FWOHCI_NODEID));
1822178848Scokane		if(!(OREAD(sc, FWOHCI_NODEID) & OHCI_NODE_VALID)){
1823178848Scokane			printf("Bus reset failure\n");
1824178848Scokane			goto sidout;
1825178848Scokane		}
1826178848Scokane		if( OREAD(sc, FWOHCI_NODEID) & OHCI_NODE_ROOT ){
1827178848Scokane			printf("CYCLEMASTER mode\n");
1828178848Scokane			OWRITE(sc, OHCI_LNKCTL,
1829178848Scokane				OHCI_CNTL_CYCMTR | OHCI_CNTL_CYCTIMER);
1830178848Scokane		}else{
1831247296Sdelphij			printf("non CYCLEMASTER mode\n");
1832178848Scokane			OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCMTR);
1833178848Scokane			OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_CYCTIMER);
1834178848Scokane		}
1835178848Scokane		fc->nodeid = OREAD(sc, FWOHCI_NODEID) & 0x3f;
1836178848Scokane
1837178848Scokane		plen = OREAD(sc, OHCI_SID_CNT) & OHCI_SID_CNT_MASK;
1838178848Scokane		if (plen < 4 || plen > OHCI_SIDSIZE) {
1839178848Scokane			device_printf(fc->dev, "invalid SID len = %d\n", plen);
1840178848Scokane			goto sidout;
1841178848Scokane		}
1842178848Scokane		plen -= 4; /* chop control info */
1843178848Scokane		buf = malloc(OHCI_SIDSIZE, M_DEVBUF, M_NOWAIT);
1844178848Scokane		if(buf == NULL) goto sidout;
1845178848Scokane		bcopy((void *)(uintptr_t)(volatile void *)(fc->sid_buf + 1),
1846178848Scokane								buf, plen);
1847178848Scokane		fw_sidrcv(fc, buf, plen, 0);
1848178848Scokane	}
1849178848Scokanesidout:
1850178848Scokane	if((stat & OHCI_INT_DMA_ATRQ )){
1851178848Scokane#ifndef ACK_ALL
1852178848Scokane		OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_ATRQ);
1853178848Scokane#endif
1854104349Sphk		fwohci_txd(sc, &(sc->atrq));
1855104349Sphk	}
1856104349Sphk	if((stat & OHCI_INT_DMA_ATRS )){
1857104349Sphk#ifndef ACK_ALL
1858104349Sphk		OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_ATRS);
1859178848Scokane#endif
1860104349Sphk		fwohci_txd(sc, &(sc->atrs));
1861104349Sphk	}
1862104349Sphk	if((stat & OHCI_INT_PW_ERR )){
1863104349Sphk#ifndef ACK_ALL
1864104349Sphk		OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PW_ERR);
1865104349Sphk#endif
1866104349Sphk		device_printf(fc->dev, "posted write error\n");
1867178848Scokane	}
1868104349Sphk	if((stat & OHCI_INT_ERR )){
1869104349Sphk#ifndef ACK_ALL
1870104349Sphk		OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_ERR);
1871178848Scokane#endif
1872104349Sphk		device_printf(fc->dev, "unrecoverable error\n");
1873104349Sphk	}
1874104349Sphk	if((stat & OHCI_INT_PHY_INT)) {
1875178848Scokane#ifndef ACK_ALL
1876104349Sphk		OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_INT);
1877104349Sphk#endif
1878104349Sphk		device_printf(fc->dev, "phy int\n");
1879104349Sphk	}
1880178848Scokane
1881178848Scokane	return;
1882104349Sphk}
1883104349Sphk
1884104349Sphkvoid
1885104349Sphkfwohci_intr(void *arg)
1886104349Sphk{
1887104349Sphk	struct fwohci_softc *sc = (struct fwohci_softc *)arg;
1888178848Scokane	u_int32_t stat;
1889104349Sphk
1890104349Sphk	if (!(sc->intmask & OHCI_INT_EN)) {
1891178848Scokane		/* polling mode */
1892104349Sphk		return;
1893104349Sphk	}
1894104349Sphk
1895104349Sphk	while ((stat = OREAD(sc, FWOHCI_INTSTAT)) != 0) {
1896104349Sphk		if (stat == 0xffffffff) {
1897104349Sphk			device_printf(sc->fc.dev,
1898178848Scokane				"device physically ejected?\n");
1899104349Sphk			return;
1900104349Sphk		}
1901178848Scokane#ifdef ACK_ALL
1902104349Sphk		OWRITE(sc, FWOHCI_INTSTATCLR, stat);
1903104349Sphk#endif
1904104349Sphk		fwohci_intr_body(sc, stat, -1);
1905104349Sphk	}
1906104349Sphk}
1907104349Sphk
1908178848Scokanestatic void
1909178848Scokanefwohci_poll(struct firewire_comm *fc, int quick, int count)
1910178848Scokane{
1911178848Scokane	int s;
1912178848Scokane	u_int32_t stat;
1913178848Scokane	struct fwohci_softc *sc;
1914178848Scokane
1915178848Scokane
1916178848Scokane	sc = (struct fwohci_softc *)fc;
1917178848Scokane	stat = OHCI_INT_DMA_IR | OHCI_INT_DMA_IT |
1918178848Scokane		OHCI_INT_DMA_PRRS | OHCI_INT_DMA_PRRQ |
1919178848Scokane		OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS;
1920178848Scokane#if 0
1921178848Scokane	if (!quick) {
1922178848Scokane#else
1923178848Scokane	if (1) {
1924178848Scokane#endif
1925178848Scokane		stat = OREAD(sc, FWOHCI_INTSTAT);
1926178848Scokane		if (stat == 0)
1927178848Scokane			return;
1928178848Scokane		if (stat == 0xffffffff) {
1929178848Scokane			device_printf(sc->fc.dev,
1930178848Scokane				"device physically ejected?\n");
1931178848Scokane			return;
1932178848Scokane		}
1933104349Sphk#ifdef ACK_ALL
1934104349Sphk		OWRITE(sc, FWOHCI_INTSTATCLR, stat);
1935104349Sphk#endif
1936104349Sphk	}
1937104349Sphk	s = splfw();
1938104349Sphk	fwohci_intr_body(sc, stat, count);
1939104349Sphk	splx(s);
1940104349Sphk}
1941104349Sphk
1942104349Sphkstatic void
1943104349Sphkfwohci_set_intr(struct firewire_comm *fc, int enable)
1944104349Sphk{
1945104349Sphk	struct fwohci_softc *sc;
1946178848Scokane
1947104349Sphk	sc = (struct fwohci_softc *)fc;
1948104349Sphk	if (bootverbose)
1949178848Scokane		device_printf(sc->fc.dev, "fwohci_set_intr: %d\n", enable);
1950104349Sphk	if (enable) {
1951104349Sphk		sc->intmask |= OHCI_INT_EN;
1952104349Sphk		OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_EN);
1953104349Sphk	} else {
1954104349Sphk		sc->intmask &= ~OHCI_INT_EN;
1955104349Sphk		OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_EN);
1956104349Sphk	}
1957104349Sphk}
1958104349Sphk
1959104349Sphkstatic void
1960104349Sphkfwohci_tbuf_update(struct fwohci_softc *sc, int dmach)
1961104349Sphk{
1962104349Sphk	int stat;
1963104349Sphk	struct firewire_comm *fc = &sc->fc;
1964104349Sphk	struct fwohci_dbch *dbch;
1965104349Sphk	struct fwohcidb_tr *db_tr;
1966104349Sphk
1967178848Scokane	dbch = &sc->it[dmach];
1968104349Sphk#if 0	/* XXX OHCI interrupt before the last packet is really on the wire */
1969104349Sphk	if((dbch->xferq.flag & FWXFERQ_DV) && (dbch->xferq.stdma2 != NULL)){
1970104349Sphk		db_tr = (struct fwohcidb_tr *)dbch->xferq.stdma2->start;
1971104349Sphk/*
1972104349Sphk * Overwrite highest significant 4 bits timestamp information
1973104349Sphk */
1974104349Sphk		fp = (struct fw_pkt *)db_tr->buf;
1975104349Sphk		fp->mode.ld[2] &= htonl(0xffff0fff);
1976178848Scokane		fp->mode.ld[2] |= htonl((fc->cyctimer(fc) + 0x4000) & 0xf000);
1977178848Scokane	}
1978178848Scokane#endif
1979178848Scokane	/*
1980178848Scokane	 * XXX interrupt could be missed.
1981178848Scokane	 * We have to check more than one buffer/chunk
1982178848Scokane	 */
1983178848Scokane	if (firewire_debug && dbch->xferq.stdma2 != NULL) {
1984178848Scokane		db_tr = (struct fwohcidb_tr *)dbch->xferq.stdma2->end;
1985178848Scokane		stat = db_tr->db[2].db.desc.status;
1986178848Scokane		if (stat)
1987178848Scokane			device_printf(fc->dev,
1988178848Scokane				"stdma2 already done stat:0x%x\n", stat);
1989178848Scokane	}
1990178848Scokane
1991104349Sphk	stat = OREAD(sc, OHCI_ITCTL(dmach)) & 0x1f;
1992104349Sphk	switch(stat){
1993104349Sphk	case FWOHCIEV_ACKCOMPL:
1994104349Sphk#ifdef FWXFERQ_DV
1995104349Sphk	if (dbch->xferq.flag & FWXFERQ_DV) {
1996104349Sphk		struct ciphdr *ciph;
1997178848Scokane		int timer, timestamp, cycl, diff;
1998104349Sphk		static int last_timer=0;
1999104349Sphk		struct fw_pkt *fp;
2000104349Sphk
2001104349Sphk		timer = (fc->cyctimer(fc) >> 12) & 0xffff;
2002104349Sphk		db_tr = (struct fwohcidb_tr *)dbch->xferq.stdma->start;
2003104349Sphk		fp = (struct fw_pkt *)db_tr->buf;
2004104349Sphk		ciph = (struct ciphdr *) &fp->mode.ld[1];
2005104349Sphk		timestamp = db_tr->db[2].db.desc.count & 0xffff;
2006104349Sphk		cycl = ntohs(ciph->fdf.dv.cyc) >> 12;
2007104349Sphk		diff = cycl - (timestamp & 0xf) - CYCLE_OFFSET;
2008104349Sphk		if (diff < 0)
2009104349Sphk			diff += 16;
2010104349Sphk		if (diff > 8)
2011104349Sphk			diff -= 16;
2012104349Sphk		if (firewire_debug || diff != 0)
2013104349Sphk			printf("dbc: %3d timer: 0x%04x packet: 0x%04x"
2014104349Sphk				" cyc: 0x%x diff: %+1d\n",
2015104349Sphk				ciph->dbc, last_timer, timestamp, cycl, diff);
2016104349Sphk		last_timer = timer;
2017178848Scokane		/* XXX adjust dbch->xferq.dvoffset if diff != 0 or 1 */
2018104349Sphk	}
2019104349Sphk#endif
2020104349Sphk		fw_tbuf_update(fc, dmach, 1);
2021104349Sphk		break;
2022104349Sphk	default:
2023104349Sphk		device_printf(fc->dev, "Isochronous transmit err %02x\n", stat);
2024104349Sphk		fw_tbuf_update(fc, dmach, 0);
2025104349Sphk		break;
2026104349Sphk	}
2027104349Sphk	fwohci_itxbuf_enable(fc, dmach);
2028104349Sphk}
2029178848Scokane
2030104349Sphkstatic void
2031104349Sphkfwohci_rbuf_update(struct fwohci_softc *sc, int dmach)
2032178848Scokane{
2033178848Scokane	struct firewire_comm *fc = &sc->fc;
2034178848Scokane	int stat;
2035178848Scokane
2036178848Scokane	stat = OREAD(sc, OHCI_IRCTL(dmach)) & 0x1f;
2037104349Sphk	switch(stat){
2038178848Scokane	case FWOHCIEV_ACKCOMPL:
2039104349Sphk		fw_rbuf_update(fc, dmach, 1);
2040104349Sphk		wakeup(fc->ir[dmach]);
2041178848Scokane		fwohci_irx_enable(fc, dmach);
2042104349Sphk		break;
2043104349Sphk	default:
2044178848Scokane		device_printf(fc->dev, "Isochronous receive err %02x\n",
2045104349Sphk									stat);
2046104349Sphk		break;
2047104349Sphk	}
2048104349Sphk}
2049104349Sphk
2050104349Sphkvoid
2051178848Scokanedump_dma(struct fwohci_softc *sc, u_int32_t ch)
2052104349Sphk{
2053178848Scokane	u_int32_t off, cntl, stat, cmd, match;
2054178848Scokane
2055178848Scokane	if(ch == 0){
2056178848Scokane		off = OHCI_ATQOFF;
2057178848Scokane	}else if(ch == 1){
2058247296Sdelphij		off = OHCI_ATSOFF;
2059247296Sdelphij	}else if(ch == 2){
2060247296Sdelphij		off = OHCI_ARQOFF;
2061247296Sdelphij	}else if(ch == 3){
2062178848Scokane		off = OHCI_ARSOFF;
2063104349Sphk	}else if(ch < IRX_CH){
2064104349Sphk		off = OHCI_ITCTL(ch - ITX_CH);
2065104349Sphk	}else{
2066104349Sphk		off = OHCI_IRCTL(ch - IRX_CH);
2067104349Sphk	}
2068104349Sphk	cntl = stat = OREAD(sc, off);
2069104349Sphk	cmd = OREAD(sc, off + 0xc);
2070104349Sphk	match = OREAD(sc, off + 0x10);
2071104349Sphk
2072104349Sphk	device_printf(sc->fc.dev, "dma ch %1x:dma regs 0x%08x 0x%08x 0x%08x 0x%08x \n",
2073178848Scokane		ch,
2074104349Sphk		cntl,
2075104349Sphk		stat,
2076104349Sphk		cmd,
2077104349Sphk		match);
2078104349Sphk	stat &= 0xffff ;
2079104349Sphk	if(stat & 0xff00){
2080104349Sphk		device_printf(sc->fc.dev, "dma %d ch:%s%s%s%s%s%s %s(%x)\n",
2081104349Sphk			ch,
2082104349Sphk			stat & OHCI_CNTL_DMA_RUN ? "RUN," : "",
2083104349Sphk			stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "",
2084104349Sphk			stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "",
2085104349Sphk			stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "",
2086178848Scokane			stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "",
2087104349Sphk			stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "",
2088104349Sphk			fwohcicode[stat & 0x1f],
2089104349Sphk			stat & 0x1f
2090104349Sphk		);
2091104349Sphk	}else{
2092104349Sphk		device_printf(sc->fc.dev, "dma %d ch: Nostat\n", ch);
2093178848Scokane	}
2094104349Sphk}
2095104349Sphk
2096178848Scokanevoid
2097178848Scokanedump_db(struct fwohci_softc *sc, u_int32_t ch)
2098178848Scokane{
2099178848Scokane	struct fwohci_dbch *dbch;
2100178848Scokane	struct fwohcidb_tr *cp = NULL, *pp, *np;
2101178848Scokane	volatile struct fwohcidb *curr = NULL, *prev, *next = NULL;
2102178848Scokane	int idb, jdb;
2103178848Scokane	u_int32_t cmd, off;
2104178848Scokane	if(ch == 0){
2105178848Scokane		off = OHCI_ATQOFF;
2106178848Scokane		dbch = &sc->atrq;
2107104349Sphk	}else if(ch == 1){
2108104349Sphk		off = OHCI_ATSOFF;
2109104349Sphk		dbch = &sc->atrs;
2110104349Sphk	}else if(ch == 2){
2111104349Sphk		off = OHCI_ARQOFF;
2112104349Sphk		dbch = &sc->arrq;
2113104349Sphk	}else if(ch == 3){
2114104349Sphk		off = OHCI_ARSOFF;
2115104349Sphk		dbch = &sc->arrs;
2116104349Sphk	}else if(ch < IRX_CH){
2117104349Sphk		off = OHCI_ITCTL(ch - ITX_CH);
2118178848Scokane		dbch = &sc->it[ch - ITX_CH];
2119104349Sphk	}else {
2120104349Sphk		off = OHCI_IRCTL(ch - IRX_CH);
2121104349Sphk		dbch = &sc->ir[ch - IRX_CH];
2122104349Sphk	}
2123104349Sphk	cmd = OREAD(sc, off + 0xc);
2124247296Sdelphij
2125178848Scokane	if( dbch->ndb == 0 ){
2126178848Scokane		device_printf(sc->fc.dev, "No DB is attached ch=%d\n", ch);
2127178848Scokane		return;
2128178848Scokane	}
2129178848Scokane	pp = dbch->top;
2130104349Sphk	prev = pp->db;
2131104349Sphk	for(idb = 0 ; idb < dbch->ndb ; idb ++ ){
2132104349Sphk		if(pp == NULL){
2133178848Scokane			curr = NULL;
2134104349Sphk			goto outdb;
2135104349Sphk		}
2136104349Sphk		cp = STAILQ_NEXT(pp, link);
2137104349Sphk		if(cp == NULL){
2138104349Sphk			curr = NULL;
2139104349Sphk			goto outdb;
2140104349Sphk		}
2141104349Sphk		np = STAILQ_NEXT(cp, link);
2142104349Sphk		if(cp == NULL) break;
2143104349Sphk		for(jdb = 0 ; jdb < dbch->ndesc ; jdb ++ ){
2144104349Sphk			if((cmd  & 0xfffffff0)
2145104349Sphk				== vtophys(&(cp->db[jdb]))){
2146178848Scokane				curr = cp->db;
2147104349Sphk				if(np != NULL){
2148104349Sphk					next = np->db;
2149104349Sphk				}else{
2150104349Sphk					next = NULL;
2151104349Sphk				}
2152104349Sphk				goto outdb;
2153104349Sphk			}
2154104349Sphk		}
2155104349Sphk		pp = STAILQ_NEXT(pp, link);
2156104349Sphk		prev = pp->db;
2157104349Sphk	}
2158104349Sphkoutdb:
2159104349Sphk	if( curr != NULL){
2160104349Sphk		printf("Prev DB %d\n", ch);
2161178848Scokane		print_db(prev, ch, dbch->ndesc);
2162104349Sphk		printf("Current DB %d\n", ch);
2163104349Sphk		print_db(curr, ch, dbch->ndesc);
2164104349Sphk		printf("Next DB %d\n", ch);
2165104349Sphk		print_db(next, ch, dbch->ndesc);
2166104349Sphk	}else{
2167104349Sphk		printf("dbdump err ch = %d cmd = 0x%08x\n", ch, cmd);
2168178848Scokane	}
2169104349Sphk	return;
2170104349Sphk}
2171104349Sphk
2172104349Sphkvoid
2173104349Sphkprint_db(volatile struct fwohcidb *db, u_int32_t ch, u_int32_t max)
2174104349Sphk{
2175178848Scokane	fwohcireg_t stat;
2176104349Sphk	int i, key;
2177104349Sphk
2178104349Sphk	if(db == NULL){
2179104349Sphk		printf("No Descriptor is found\n");
2180104349Sphk		return;
2181104349Sphk	}
2182104349Sphk
2183104349Sphk	printf("ch = %d\n%8s %s %s %s %s %4s %8s %8s %4s:%4s\n",
2184104349Sphk		ch,
2185104349Sphk		"Current",
2186178848Scokane		"OP  ",
2187104349Sphk		"KEY",
2188104349Sphk		"INT",
2189104349Sphk		"BR ",
2190104349Sphk		"len",
2191104349Sphk		"Addr",
2192178848Scokane		"Depend",
2193104349Sphk		"Stat",
2194178848Scokane		"Cnt");
2195178848Scokane	for( i = 0 ; i <= max ; i ++){
2196178848Scokane		key = db[i].db.desc.cmd & OHCI_KEY_MASK;
2197178848Scokane#if __FreeBSD_version >= 500000
2198104349Sphk		printf("%08tx %s %s %s %s %5d %08x %08x %04x:%04x",
2199104349Sphk#else
2200104349Sphk		printf("%08x %s %s %s %s %5d %08x %08x %04x:%04x",
2201178848Scokane#endif
2202178848Scokane				vtophys(&db[i]),
2203104349Sphk				dbcode[(db[i].db.desc.cmd >> 28) & 0xf],
2204104349Sphk				dbkey[(db[i].db.desc.cmd >> 24) & 0x7],
2205178848Scokane				dbcond[(db[i].db.desc.cmd >> 20) & 0x3],
2206247296Sdelphij				dbcond[(db[i].db.desc.cmd >> 18) & 0x3],
2207178848Scokane				db[i].db.desc.cmd & 0xffff,
2208178848Scokane				db[i].db.desc.addr,
2209178848Scokane				db[i].db.desc.depend,
2210178848Scokane				db[i].db.desc.status,
2211178848Scokane				db[i].db.desc.count);
2212178848Scokane		stat = db[i].db.desc.status;
2213178848Scokane		if(stat & 0xff00){
2214104349Sphk			printf(" %s%s%s%s%s%s %s(%x)\n",
2215104349Sphk				stat & OHCI_CNTL_DMA_RUN ? "RUN," : "",
2216104349Sphk				stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "",
2217178848Scokane				stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "",
2218104349Sphk				stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "",
2219104349Sphk				stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "",
2220104349Sphk				stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "",
2221104349Sphk				fwohcicode[stat & 0x1f],
2222104349Sphk				stat & 0x1f
2223178848Scokane			);
2224104349Sphk		}else{
2225104349Sphk			printf(" Nostat\n");
2226104349Sphk		}
2227104349Sphk		if(key == OHCI_KEY_ST2 ){
2228104349Sphk			printf("0x%08x 0x%08x 0x%08x 0x%08x\n",
2229104349Sphk				db[i+1].db.immed[0],
2230104349Sphk				db[i+1].db.immed[1],
2231104349Sphk				db[i+1].db.immed[2],
2232104349Sphk				db[i+1].db.immed[3]);
2233104349Sphk		}
2234178848Scokane		if(key == OHCI_KEY_DEVICE){
2235104349Sphk			return;
2236104349Sphk		}
2237104349Sphk		if((db[i].db.desc.cmd & OHCI_BRANCH_MASK)
2238104349Sphk				== OHCI_BRANCH_ALWAYS){
2239104349Sphk			return;
2240247296Sdelphij		}
2241178848Scokane		if((db[i].db.desc.cmd & OHCI_CMD_MASK)
2242178848Scokane				== OHCI_OUTPUT_LAST){
2243178848Scokane			return;
2244178848Scokane		}
2245178848Scokane		if((db[i].db.desc.cmd & OHCI_CMD_MASK)
2246104349Sphk				== OHCI_INPUT_LAST){
2247104349Sphk			return;
2248104349Sphk		}
2249178848Scokane		if(key == OHCI_KEY_ST2 ){
2250104349Sphk			i++;
2251104349Sphk		}
2252104349Sphk	}
2253104349Sphk	return;
2254104349Sphk}
2255178848Scokane
2256178848Scokanevoid
2257104349Sphkfwohci_ibr(struct firewire_comm *fc)
2258178848Scokane{
2259247296Sdelphij	struct fwohci_softc *sc;
2260178848Scokane	u_int32_t fun;
2261104349Sphk
2262104349Sphk	sc = (struct fwohci_softc *)fc;
2263104349Sphk
2264104349Sphk	/*
2265104349Sphk	 * Set root hold-off bit so that non cyclemaster capable node
2266104349Sphk	 * shouldn't became the root node.
2267104349Sphk	 */
2268104349Sphk#if 1
2269104349Sphk	fun = fwphy_rddata(sc, FW_PHY_IBR_REG);
2270104349Sphk	fun |= FW_PHY_IBR | FW_PHY_RHB;
2271104349Sphk	fun = fwphy_wrdata(sc, FW_PHY_IBR_REG, fun);
2272178848Scokane#else	/* Short bus reset */
2273104349Sphk	fun = fwphy_rddata(sc, FW_PHY_ISBR_REG);
2274104349Sphk	fun |= FW_PHY_ISBR | FW_PHY_RHB;
2275104349Sphk	fun = fwphy_wrdata(sc, FW_PHY_ISBR_REG, fun);
2276104349Sphk#endif
2277104349Sphk}
2278104349Sphk
2279178848Scokanevoid
2280104349Sphkfwohci_txbufdb(struct fwohci_softc *sc, int dmach, struct fw_bulkxfer *bulkxfer)
2281104349Sphk{
2282104349Sphk	struct fwohcidb_tr *db_tr, *fdb_tr;
2283104349Sphk	struct fwohci_dbch *dbch;
2284104349Sphk	struct fw_pkt *fp;
2285104349Sphk	volatile struct fwohci_txpkthdr *ohcifp;
2286104349Sphk	unsigned short chtag;
2287104349Sphk	int idb;
2288104349Sphk
2289104349Sphk	dbch = &sc->it[dmach];
2290247296Sdelphij	chtag = sc->it[dmach].xferq.flag & 0xff;
2291247296Sdelphij
2292178848Scokane	db_tr = (struct fwohcidb_tr *)(bulkxfer->start);
2293104349Sphk	fdb_tr = (struct fwohcidb_tr *)(bulkxfer->end);
2294104349Sphk/*
2295104349Sphkdevice_printf(sc->fc.dev, "DB %08x %08x %08x\n", bulkxfer, vtophys(db_tr->db), vtophys(fdb_tr->db));
2296104349Sphk*/
2297178848Scokane	if(bulkxfer->flag != 0){
2298104349Sphk		return;
2299104349Sphk	}
2300178848Scokane	bulkxfer->flag = 1;
2301104349Sphk	for( idb = 0 ; idb < bulkxfer->npacket ; idb ++){
2302104349Sphk		db_tr->db[0].db.desc.cmd
2303104349Sphk			= OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | 8;
2304104349Sphk		fp = (struct fw_pkt *)db_tr->buf;
2305104349Sphk		ohcifp = (volatile struct fwohci_txpkthdr *)
2306104349Sphk						db_tr->db[1].db.immed;
2307178848Scokane		ohcifp->mode.ld[0] = ntohl(fp->mode.ld[0]);
2308104349Sphk		ohcifp->mode.stream.len = ntohs(fp->mode.stream.len);
2309104349Sphk		ohcifp->mode.stream.chtag = chtag;
2310104349Sphk		ohcifp->mode.stream.tcode = 0xa;
2311104349Sphk		ohcifp->mode.stream.spd = 4;
2312104349Sphk		ohcifp->mode.ld[2] = ntohl(fp->mode.ld[1]);
2313104349Sphk		ohcifp->mode.ld[3] = ntohl(fp->mode.ld[2]);
2314104349Sphk
2315178848Scokane		db_tr->db[2].db.desc.cmd
2316104349Sphk			= OHCI_OUTPUT_LAST
2317104349Sphk			| OHCI_UPDATE
2318104349Sphk			| OHCI_BRANCH_ALWAYS
2319104349Sphk			| ((ntohs(fp->mode.stream.len) ) & 0xffff);
2320104349Sphk		db_tr->db[2].db.desc.status = 0;
2321178848Scokane		db_tr->db[2].db.desc.count = 0;
2322104349Sphk		db_tr->db[0].db.desc.depend
2323104349Sphk			= vtophys(STAILQ_NEXT(db_tr, link)->db) | dbch->ndesc;
2324104349Sphk		db_tr->db[dbch->ndesc - 1].db.desc.depend
2325104349Sphk			= vtophys(STAILQ_NEXT(db_tr, link)->db) | dbch->ndesc;
2326104349Sphk		bulkxfer->end = (caddr_t)db_tr;
2327104349Sphk		db_tr = STAILQ_NEXT(db_tr, link);
2328104349Sphk	}
2329104349Sphk	db_tr = (struct fwohcidb_tr *)bulkxfer->end;
2330104349Sphk	db_tr->db[0].db.desc.depend &= ~0xf;
2331104349Sphk	db_tr->db[dbch->ndesc - 1].db.desc.depend &= ~0xf;
2332104349Sphk#if 0
2333104349Sphk/**/
2334104349Sphk	db_tr->db[dbch->ndesc - 1].db.desc.cmd &= ~OHCI_BRANCH_ALWAYS;
2335104349Sphk	db_tr->db[dbch->ndesc - 1].db.desc.cmd |= OHCI_BRANCH_NEVER;
2336104349Sphk/**/
2337104349Sphk#endif
2338104349Sphk	db_tr->db[dbch->ndesc - 1].db.desc.cmd |= OHCI_INTERRUPT_ALWAYS;
2339104349Sphk	/* OHCI 1.1 and above */
2340178848Scokane	db_tr->db[0].db.desc.cmd |= OHCI_INTERRUPT_ALWAYS;
2341104349Sphk
2342104349Sphk	db_tr = (struct fwohcidb_tr *)bulkxfer->start;
2343104349Sphk	fdb_tr = (struct fwohcidb_tr *)bulkxfer->end;
2344104349Sphk/*
2345247296Sdelphijdevice_printf(sc->fc.dev, "DB %08x %3d %08x %08x\n", bulkxfer, bulkxfer->npacket, vtophys(db_tr->db), vtophys(fdb_tr->db));
2346178848Scokane*/
2347104349Sphk	return;
2348104349Sphk}
2349104349Sphk
2350104349Sphkstatic int
2351178848Scokanefwohci_add_tx_buf(struct fwohcidb_tr *db_tr, unsigned short size,
2352104349Sphk	int mode, void *buf)
2353104349Sphk{
2354104349Sphk	volatile struct fwohcidb *db = db_tr->db;
2355104349Sphk	int err = 0;
2356104349Sphk	if(buf == 0){
2357104349Sphk		err = EINVAL;
2358104349Sphk		return err;
2359104349Sphk	}
2360104349Sphk	db_tr->buf = buf;
2361104349Sphk	db_tr->dbcnt = 3;
2362104349Sphk	db_tr->dummy = NULL;
2363104349Sphk
2364104349Sphk	db[0].db.desc.cmd = OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | 8;
2365104349Sphk
2366104349Sphk	db[2].db.desc.depend = 0;
2367104349Sphk	db[2].db.desc.addr = vtophys(buf) + sizeof(u_int32_t);
2368104349Sphk	db[2].db.desc.cmd = OHCI_OUTPUT_MORE;
2369104349Sphk
2370104349Sphk	db[0].db.desc.status = 0;
2371104349Sphk	db[0].db.desc.count = 0;
2372104349Sphk
2373104349Sphk	db[2].db.desc.status = 0;
2374104349Sphk	db[2].db.desc.count = 0;
2375104349Sphk	if( mode & FWXFERQ_STREAM ){
2376104349Sphk		db[2].db.desc.cmd |= OHCI_OUTPUT_LAST;
2377178848Scokane		if(mode & FWXFERQ_PACKET ){
2378178848Scokane			db[2].db.desc.cmd
2379104349Sphk					|= OHCI_INTERRUPT_ALWAYS;
2380104349Sphk		}
2381104349Sphk	}
2382104349Sphk	db[2].db.desc.cmd |= OHCI_BRANCH_ALWAYS;
2383104349Sphk	return 1;
2384104349Sphk}
2385104349Sphk
2386104349Sphkint
2387104349Sphkfwohci_add_rx_buf(struct fwohcidb_tr *db_tr, unsigned short size, int mode,
2388104349Sphk	void *buf, void *dummy)
2389104349Sphk{
2390104349Sphk	volatile struct fwohcidb *db = db_tr->db;
2391104349Sphk	int i;
2392104349Sphk	void *dbuf[2];
2393104349Sphk	int dsiz[2];
2394104349Sphk
2395104349Sphk	if(buf == 0){
2396104349Sphk		buf = malloc(size, M_DEVBUF, M_NOWAIT);
2397104349Sphk		if(buf == NULL) return 0;
2398104349Sphk		db_tr->buf = buf;
2399104349Sphk		db_tr->dbcnt = 1;
2400178848Scokane		db_tr->dummy = NULL;
2401178848Scokane		dsiz[0] = size;
2402104349Sphk		dbuf[0] = buf;
2403104349Sphk	}else if(dummy == NULL){
2404104349Sphk		db_tr->buf = buf;
2405104349Sphk		db_tr->dbcnt = 1;
2406104349Sphk		db_tr->dummy = NULL;
2407104349Sphk		dsiz[0] = size;
2408104349Sphk		dbuf[0] = buf;
2409104349Sphk	}else{
2410104349Sphk		db_tr->buf = buf;
2411104349Sphk		db_tr->dbcnt = 2;
2412178848Scokane		db_tr->dummy = dummy;
2413104349Sphk		dsiz[0] = sizeof(u_int32_t);
2414104349Sphk		dsiz[1] = size;
2415178848Scokane		dbuf[0] = dummy;
2416104349Sphk		dbuf[1] = buf;
2417104349Sphk	}
2418104349Sphk	for(i = 0 ; i < db_tr->dbcnt ; i++){
2419104349Sphk		db[i].db.desc.addr = vtophys(dbuf[i]) ;
2420104349Sphk		db[i].db.desc.cmd = OHCI_INPUT_MORE | dsiz[i];
2421104349Sphk		if( mode & FWXFERQ_STREAM ){
2422104349Sphk			db[i].db.desc.cmd |= OHCI_UPDATE;
2423104349Sphk		}
2424104349Sphk		db[i].db.desc.status = 0;
2425104349Sphk		db[i].db.desc.count = dsiz[i];
2426104349Sphk	}
2427104349Sphk	if( mode & FWXFERQ_STREAM ){
2428104349Sphk		db[db_tr->dbcnt - 1].db.desc.cmd |= OHCI_INPUT_LAST;
2429104349Sphk		if(mode & FWXFERQ_PACKET ){
2430104349Sphk			db[db_tr->dbcnt - 1].db.desc.cmd
2431104349Sphk					|= OHCI_INTERRUPT_ALWAYS;
2432104349Sphk		}
2433104349Sphk	}
2434104349Sphk	db[db_tr->dbcnt - 1].db.desc.cmd |= OHCI_BRANCH_ALWAYS;
2435104349Sphk	return 1;
2436104349Sphk}
2437104349Sphk
2438104349Sphkstatic void
2439104349Sphkfwohci_ircv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count)
2440178848Scokane{
2441104349Sphk	struct fwohcidb_tr *db_tr = dbch->top, *odb_tr;
2442104349Sphk	struct firewire_comm *fc = (struct firewire_comm *)sc;
2443104349Sphk	int z = 1;
2444104349Sphk	struct fw_pkt *fp;
2445178848Scokane	u_int8_t *ld;
2446104349Sphk	u_int32_t off = NULL;
2447178848Scokane	u_int32_t stat;
2448104349Sphk	u_int32_t *qld;
2449104349Sphk	u_int32_t reg;
2450104349Sphk	u_int spd;
2451104349Sphk	u_int dmach;
2452104349Sphk	int len, i, plen;
2453104349Sphk	caddr_t buf;
2454104349Sphk
2455104349Sphk	for(dmach = 0 ; dmach < sc->fc.nisodma ; dmach++){
2456104349Sphk		if( &sc->ir[dmach] == dbch){
2457104349Sphk			off = OHCI_IROFF(dmach);
2458178848Scokane			break;
2459178848Scokane		}
2460178848Scokane	}
2461178848Scokane	if(off == NULL){
2462104349Sphk		return;
2463104349Sphk	}
2464104349Sphk	if(!(dbch->xferq.flag & FWXFERQ_RUNNING)){
2465104349Sphk		fwohci_irx_disable(&sc->fc, dmach);
2466104349Sphk		return;
2467104349Sphk	}
2468104349Sphk
2469178848Scokane	odb_tr = NULL;
2470178848Scokane	db_tr = dbch->top;
2471104349Sphk	i = 0;
2472178848Scokane	while ((reg = db_tr->db[0].db.desc.status) & 0x1f) {
2473104349Sphk		if (count >= 0 && count-- == 0)
2474104349Sphk			break;
2475104349Sphk		ld = (u_int8_t *)db_tr->buf;
2476178848Scokane		if (dbch->xferq.flag & FWXFERQ_PACKET) {
2477104349Sphk			/* skip timeStamp */
2478104349Sphk			ld += sizeof(struct fwohci_trailer);
2479104349Sphk		}
2480104349Sphk		qld = (u_int32_t *)ld;
2481104349Sphk		len = dbch->xferq.psize - (db_tr->db[0].db.desc.count);
2482104349Sphk/*
2483104349Sphk{
2484104349Sphkdevice_printf(sc->fc.dev, "%04x %2x 0x%08x 0x%08x 0x%08x 0x%08x\n", len,
2485104349Sphk		db_tr->db[0].db.desc.status & 0x1f, qld[0],qld[1],qld[2],qld[3]);
2486104349Sphk}
2487178848Scokane*/
2488104349Sphk		fp=(struct fw_pkt *)ld;
2489178848Scokane		qld[0] = htonl(qld[0]);
2490178848Scokane		plen = sizeof(struct fw_isohdr)
2491104349Sphk			+ ntohs(fp->mode.stream.len) + sizeof(u_int32_t);
2492104349Sphk		ld += plen;
2493104349Sphk		len -= plen;
2494104349Sphk		buf = db_tr->buf;
2495178848Scokane		db_tr->buf = NULL;
2496104349Sphk		stat = reg & 0x1f;
2497178848Scokane		spd =  reg & 0x3;
2498178848Scokane		switch(stat){
2499104349Sphk			case FWOHCIEV_ACKCOMPL:
2500104349Sphk			case FWOHCIEV_ACKPEND:
2501104349Sphk				fw_rcv(&sc->fc, buf, plen - sizeof(u_int32_t), dmach, sizeof(u_int32_t), spd);
2502104349Sphk				break;
2503104349Sphk			default:
2504104349Sphk				free(buf, M_DEVBUF);
2505104349Sphk				device_printf(sc->fc.dev, "Isochronous receive err %02x\n", stat);
2506104349Sphk				break;
2507104349Sphk		}
2508104349Sphk		i++;
2509104349Sphk		fwohci_add_rx_buf(db_tr, dbch->xferq.psize,
2510104349Sphk					dbch->xferq.flag, 0, NULL);
2511104349Sphk		db_tr->db[0].db.desc.depend &= ~0xf;
2512104349Sphk		if(dbch->pdb_tr != NULL){
2513104349Sphk			dbch->pdb_tr->db[0].db.desc.depend |= z;
2514104349Sphk		} else {
2515104349Sphk			/* XXX should be rewritten in better way */
2516104349Sphk			dbch->bottom->db[0].db.desc.depend |= z;
2517104349Sphk		}
2518104349Sphk		dbch->pdb_tr = db_tr;
2519104349Sphk		db_tr = STAILQ_NEXT(db_tr, link);
2520104349Sphk	}
2521104349Sphk	dbch->top = db_tr;
2522104349Sphk	reg = OREAD(sc, OHCI_DMACTL(off));
2523104349Sphk	if (reg & OHCI_CNTL_DMA_ACTIVE)
2524104349Sphk		return;
2525104349Sphk	device_printf(sc->fc.dev, "IR DMA %d stopped at %x status=%x (%d)\n",
2526104349Sphk			dmach, OREAD(sc, OHCI_DMACMD(off)), reg, i);
2527104349Sphk	dbch->top = db_tr;
2528104349Sphk	fwohci_irx_enable(fc, dmach);
2529104349Sphk}
2530104349Sphk
2531104349Sphk#define PLEN(x)	(((ntohs(x))+0x3) & ~0x3)
2532104349Sphkstatic int
2533104349Sphkfwohci_get_plen(struct fwohci_softc *sc, struct fw_pkt *fp, int hlen)
2534104349Sphk{
2535104349Sphk	int i;
2536104349Sphk
2537104349Sphk	for( i = 4; i < hlen ; i+=4){
2538104349Sphk		fp->mode.ld[i/4] = htonl(fp->mode.ld[i/4]);
2539104349Sphk	}
2540104349Sphk
2541104349Sphk	switch(fp->mode.common.tcode){
2542104349Sphk	case FWTCODE_RREQQ:
2543104349Sphk		return sizeof(fp->mode.rreqq) + sizeof(u_int32_t);
2544104349Sphk	case FWTCODE_WRES:
2545104349Sphk		return sizeof(fp->mode.wres) + sizeof(u_int32_t);
2546104349Sphk	case FWTCODE_WREQQ:
2547104349Sphk		return sizeof(fp->mode.wreqq) + sizeof(u_int32_t);
2548104349Sphk	case FWTCODE_RREQB:
2549104349Sphk		return sizeof(fp->mode.rreqb) + sizeof(u_int32_t);
2550104349Sphk	case FWTCODE_RRESQ:
2551104349Sphk		return sizeof(fp->mode.rresq) + sizeof(u_int32_t);
2552104349Sphk	case FWTCODE_WREQB:
2553104349Sphk		return sizeof(struct fw_asyhdr) + PLEN(fp->mode.wreqb.len)
2554104349Sphk						+ sizeof(u_int32_t);
2555104349Sphk	case FWTCODE_LREQ:
2556104349Sphk		return sizeof(struct fw_asyhdr) + PLEN(fp->mode.lreq.len)
2557104349Sphk						+ sizeof(u_int32_t);
2558104349Sphk	case FWTCODE_RRESB:
2559104349Sphk		return sizeof(struct fw_asyhdr) + PLEN(fp->mode.rresb.len)
2560104349Sphk						+ sizeof(u_int32_t);
2561104349Sphk	case FWTCODE_LRES:
2562104349Sphk		return sizeof(struct fw_asyhdr) + PLEN(fp->mode.lres.len)
2563104349Sphk						+ sizeof(u_int32_t);
2564104349Sphk	case FWOHCITCODE_PHY:
2565104349Sphk		return 16;
2566104349Sphk	}
2567104349Sphk	device_printf(sc->fc.dev, "Unknown tcode %d\n", fp->mode.common.tcode);
2568104349Sphk	return 0;
2569104349Sphk}
2570104349Sphk
2571104349Sphkstatic void
2572104349Sphkfwohci_arcv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count)
2573104349Sphk{
2574104349Sphk	struct fwohcidb_tr *db_tr;
2575104349Sphk	int z = 1;
2576104349Sphk	struct fw_pkt *fp;
2577104349Sphk	u_int8_t *ld;
2578104349Sphk	u_int32_t stat, off;
2579104349Sphk	u_int spd;
2580104349Sphk	int len, plen, hlen, pcnt, poff = 0, rlen;
2581104349Sphk	int s;
2582104349Sphk	caddr_t buf;
2583104349Sphk	int resCount;
2584104349Sphk
2585104349Sphk	if(&sc->arrq == dbch){
2586104349Sphk		off = OHCI_ARQOFF;
2587104349Sphk	}else if(&sc->arrs == dbch){
2588104349Sphk		off = OHCI_ARSOFF;
2589104349Sphk	}else{
2590104349Sphk		return;
2591104349Sphk	}
2592104349Sphk
2593104349Sphk	s = splfw();
2594104349Sphk	db_tr = dbch->top;
2595104349Sphk	pcnt = 0;
2596104349Sphk	/* XXX we cannot handle a packet which lies in more than two buf */
2597104349Sphk	while (db_tr->db[0].db.desc.status & OHCI_CNTL_DMA_ACTIVE) {
2598104349Sphk		ld = (u_int8_t *)db_tr->buf + dbch->buf_offset;
2599104349Sphk		resCount = db_tr->db[0].db.desc.count;
2600104349Sphk		len = dbch->xferq.psize - resCount
2601104349Sphk					- dbch->buf_offset;
2602104349Sphk		while (len > 0 ) {
2603104349Sphk			if (count >= 0 && count-- == 0)
2604104349Sphk				goto out;
2605104349Sphk			if(dbch->frag.buf != NULL){
2606104349Sphk				buf = dbch->frag.buf;
2607104349Sphk				if (dbch->frag.plen < 0) {
2608104349Sphk					/* incomplete header */
2609104349Sphk					int hlen;
2610104349Sphk
2611104349Sphk					hlen = - dbch->frag.plen;
2612104349Sphk					rlen = hlen - dbch->frag.len;
2613104349Sphk					bcopy(ld, dbch->frag.buf + dbch->frag.len, rlen);
2614178848Scokane					ld += rlen;
2615178848Scokane					len -= rlen;
2616178848Scokane					dbch->frag.len += rlen;
2617178848Scokane#if 0
2618104349Sphk					printf("(1)frag.plen=%d frag.len=%d rlen=%d len=%d\n", dbch->frag.plen, dbch->frag.len, rlen, len);
2619104349Sphk#endif
2620104349Sphk					fp=(struct fw_pkt *)dbch->frag.buf;
2621104349Sphk					dbch->frag.plen
2622104349Sphk						= fwohci_get_plen(sc, fp, hlen);
2623104349Sphk					if (dbch->frag.plen == 0)
2624178848Scokane						goto out;
2625104349Sphk				}
2626104349Sphk				rlen = dbch->frag.plen - dbch->frag.len;
2627104349Sphk#if 0
2628104349Sphk				printf("(2)frag.plen=%d frag.len=%d rlen=%d len=%d\n", dbch->frag.plen, dbch->frag.len, rlen, len);
2629104349Sphk#endif
2630104349Sphk				bcopy(ld, dbch->frag.buf + dbch->frag.len,
2631104349Sphk						rlen);
2632104349Sphk				ld += rlen;
2633178848Scokane				len -= rlen;
2634104349Sphk				plen = dbch->frag.plen;
2635104349Sphk				dbch->frag.buf = NULL;
2636104349Sphk				dbch->frag.plen = 0;
2637104349Sphk				dbch->frag.len = 0;
2638178848Scokane				poff = 0;
2639104349Sphk			}else{
2640104349Sphk				fp=(struct fw_pkt *)ld;
2641104349Sphk				fp->mode.ld[0] = htonl(fp->mode.ld[0]);
2642247296Sdelphij				switch(fp->mode.common.tcode){
2643247296Sdelphij				case FWTCODE_RREQQ:
2644178848Scokane				case FWTCODE_WRES:
2645104349Sphk				case FWTCODE_WREQQ:
2646104349Sphk				case FWTCODE_RRESQ:
2647104349Sphk				case FWOHCITCODE_PHY:
2648104349Sphk					hlen = 12;
2649104349Sphk					break;
2650104349Sphk				case FWTCODE_RREQB:
2651104349Sphk				case FWTCODE_WREQB:
2652104349Sphk				case FWTCODE_LREQ:
2653178848Scokane				case FWTCODE_RRESB:
2654104349Sphk				case FWTCODE_LRES:
2655247296Sdelphij					hlen = 16;
2656178848Scokane					break;
2657178848Scokane				default:
2658178848Scokane					device_printf(sc->fc.dev, "Unknown tcode %d\n", fp->mode.common.tcode);
2659178848Scokane					goto out;
2660178848Scokane				}
2661178848Scokane				if (len >= hlen) {
2662178848Scokane					plen = fwohci_get_plen(sc, fp, hlen);
2663178848Scokane					if (plen == 0)
2664178848Scokane						goto out;
2665178848Scokane					plen = (plen + 3) & ~3;
2666178848Scokane					len -= plen;
2667178848Scokane				} else {
2668178848Scokane					plen = -hlen;
2669178848Scokane					len -= hlen;
2670104349Sphk				}
2671178848Scokane				if(resCount > 0 || len > 0){
2672178848Scokane					buf = malloc( dbch->xferq.psize,
2673178848Scokane							M_DEVBUF, M_NOWAIT);
2674178848Scokane					if(buf == NULL){
2675104349Sphk						printf("cannot malloc!\n");
2676178848Scokane						free(db_tr->buf, M_DEVBUF);
2677178848Scokane						goto out;
2678104349Sphk					}
2679104349Sphk					bcopy(ld, buf, plen);
2680104349Sphk					poff = 0;
2681104349Sphk					dbch->frag.buf = NULL;
2682104349Sphk					dbch->frag.plen = 0;
2683104349Sphk					dbch->frag.len = 0;
2684104349Sphk				}else if(len < 0){
2685104349Sphk					dbch->frag.buf = db_tr->buf;
2686104349Sphk					if (plen < 0) {
2687104349Sphk#if 0
2688104349Sphk						printf("plen < 0:"
2689104349Sphk						"hlen: %d  len: %d\n",
2690104349Sphk						hlen, len);
2691104349Sphk#endif
2692104349Sphk						dbch->frag.len = hlen + len;
2693104349Sphk						dbch->frag.plen = -hlen;
2694178848Scokane					} else {
2695247296Sdelphij						dbch->frag.len = plen + len;
2696178848Scokane						dbch->frag.plen = plen;
2697178848Scokane					}
2698178848Scokane					bcopy(ld, db_tr->buf, dbch->frag.len);
2699178848Scokane					buf = NULL;
2700178848Scokane				}else{
2701178848Scokane					buf = db_tr->buf;
2702104349Sphk					poff = ld - (u_int8_t *)buf;
2703104349Sphk					dbch->frag.buf = NULL;
2704104349Sphk					dbch->frag.plen = 0;
2705104349Sphk					dbch->frag.len = 0;
2706178848Scokane				}
2707178848Scokane				ld += plen;
2708178848Scokane			}
2709178848Scokane			if( buf != NULL){
2710178848Scokane/* DMA result-code will be written at the tail of packet */
2711178848Scokane				stat = ((struct fwohci_trailer *)(ld - sizeof(struct fwohci_trailer)))->stat;
2712178848Scokane				spd = (stat >> 5) & 0x3;
2713178848Scokane				stat &= 0x1f;
2714178848Scokane				switch(stat){
2715104349Sphk				case FWOHCIEV_ACKPEND:
2716178848Scokane#if 0
2717104349Sphk					printf("fwohci_arcv: ack pending..\n");
2718104349Sphk#endif
2719104349Sphk					/* fall through */
2720104349Sphk				case FWOHCIEV_ACKCOMPL:
2721178848Scokane					if( poff != 0 )
2722178848Scokane						bcopy(buf+poff, buf, plen - 4);
2723178848Scokane					fw_rcv(&sc->fc, buf, plen - sizeof(struct fwohci_trailer), 0, 0, spd);
2724104349Sphk					break;
2725104349Sphk				case FWOHCIEV_BUSRST:
2726104349Sphk					free(buf, M_DEVBUF);
2727104349Sphk					if (sc->fc.status != FWBUSRESET)
2728104349Sphk						printf("got BUSRST packet!?\n");
2729104349Sphk					break;
2730104349Sphk				default:
2731104349Sphk					device_printf(sc->fc.dev, "Async DMA Receive error err = %02x %s\n", stat, fwohcicode[stat]);
2732104349Sphk#if 0 /* XXX */
2733104349Sphk					goto out;
2734104349Sphk#endif
2735247296Sdelphij					break;
2736178848Scokane				}
2737178848Scokane			}
2738178848Scokane			pcnt ++;
2739178848Scokane		};
2740247296Sdelphijout:
2741178848Scokane		if (resCount == 0) {
2742178848Scokane			/* done on this buffer */
2743178848Scokane			fwohci_add_rx_buf(db_tr, dbch->xferq.psize,
2744178848Scokane						dbch->xferq.flag, 0, NULL);
2745178848Scokane			dbch->bottom->db[0].db.desc.depend |= z;
2746104349Sphk			dbch->bottom = db_tr;
2747178848Scokane			db_tr = STAILQ_NEXT(db_tr, link);
2748178848Scokane			dbch->top = db_tr;
2749104349Sphk			dbch->buf_offset = 0;
2750104349Sphk		} else {
2751104349Sphk			dbch->buf_offset = dbch->xferq.psize - resCount;
2752104349Sphk			break;
2753104349Sphk		}
2754247296Sdelphij		/* XXX make sure DMA is not dead */
2755247296Sdelphij	}
2756247296Sdelphij#if 0
2757104349Sphk	if (pcnt < 1)
2758178848Scokane		printf("fwohci_arcv: no packets\n");
2759104349Sphk#endif
2760104349Sphk	splx(s);
2761104349Sphk}
2762247296Sdelphij