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