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