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