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