fwohci.c revision 302408
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 299351 2016-05-10 10:21:03Z trasz $
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		}
1864		/* Set ATRetries register */
1865		OWRITE(sc, OHCI_ATRETRY, 1<<(13 + 16) | 0xfff);
1866
1867		/*
1868		 * Checking whether the node is root or not. If root, turn on
1869		 * cycle master.
1870		 */
1871		node_id = OREAD(sc, FWOHCI_NODEID);
1872		plen = OREAD(sc, OHCI_SID_CNT);
1873
1874		fc->nodeid = node_id & 0x3f;
1875		device_printf(fc->dev, "%s: node_id=0x%08x, SelfID Count=%d, ",
1876				__func__, fc->nodeid, (plen >> 16) & 0xff);
1877		if (!(node_id & OHCI_NODE_VALID)) {
1878			device_printf(fc->dev, "%s: Bus reset failure\n",
1879				__func__);
1880			goto sidout;
1881		}
1882
1883		/* cycle timer */
1884		sc->cycle_lost = 0;
1885		OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_CYC_LOST);
1886		if ((node_id & OHCI_NODE_ROOT) && !nocyclemaster) {
1887			printf("CYCLEMASTER mode\n");
1888			OWRITE(sc, OHCI_LNKCTL,
1889				OHCI_CNTL_CYCMTR | OHCI_CNTL_CYCTIMER);
1890		} else {
1891			printf("non CYCLEMASTER mode\n");
1892			OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCMTR);
1893			OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_CYCTIMER);
1894		}
1895
1896		fc->status = FWBUSINIT;
1897
1898		if (!kdb_active)
1899			taskqueue_enqueue(sc->fc.taskqueue, &sc->fwohci_task_sid);
1900	}
1901sidout:
1902	if ((stat & ~(OHCI_INT_PHY_BUS_R | OHCI_INT_PHY_SID)) && (!kdb_active))
1903		taskqueue_enqueue(sc->fc.taskqueue, &sc->fwohci_task_dma);
1904}
1905
1906static void
1907fwohci_intr_dma(struct fwohci_softc *sc, uint32_t stat, int count)
1908{
1909	uint32_t irstat, itstat;
1910	u_int i;
1911	struct firewire_comm *fc = (struct firewire_comm *)sc;
1912
1913	if (stat & OHCI_INT_DMA_IR) {
1914		irstat = atomic_readandclear_int(&sc->irstat);
1915		for (i = 0; i < fc->nisodma; i++) {
1916			struct fwohci_dbch *dbch;
1917
1918			if ((irstat & (1 << i)) != 0) {
1919				dbch = &sc->ir[i];
1920				if ((dbch->xferq.flag & FWXFERQ_OPEN) == 0) {
1921					device_printf(sc->fc.dev,
1922						"dma(%d) not active\n", i);
1923					continue;
1924				}
1925				fwohci_rbuf_update(sc, i);
1926			}
1927		}
1928	}
1929	if (stat & OHCI_INT_DMA_IT) {
1930		itstat = atomic_readandclear_int(&sc->itstat);
1931		for (i = 0; i < fc->nisodma; i++) {
1932			if ((itstat & (1 << i)) != 0) {
1933				fwohci_tbuf_update(sc, i);
1934			}
1935		}
1936	}
1937	if (stat & OHCI_INT_DMA_PRRS) {
1938#if 0
1939		dump_dma(sc, ARRS_CH);
1940		dump_db(sc, ARRS_CH);
1941#endif
1942		fwohci_arcv(sc, &sc->arrs, count);
1943	}
1944	if (stat & OHCI_INT_DMA_PRRQ) {
1945#if 0
1946		dump_dma(sc, ARRQ_CH);
1947		dump_db(sc, ARRQ_CH);
1948#endif
1949		fwohci_arcv(sc, &sc->arrq, count);
1950	}
1951	if (stat & OHCI_INT_CYC_LOST) {
1952		if (sc->cycle_lost >= 0)
1953			sc->cycle_lost++;
1954		if (sc->cycle_lost > 10) {
1955			sc->cycle_lost = -1;
1956#if 0
1957			OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCTIMER);
1958#endif
1959			OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST);
1960			device_printf(fc->dev, "too many cycles lost, "
1961			 "no cycle master present?\n");
1962		}
1963	}
1964	if (stat & OHCI_INT_DMA_ATRQ) {
1965		fwohci_txd(sc, &(sc->atrq));
1966	}
1967	if (stat & OHCI_INT_DMA_ATRS) {
1968		fwohci_txd(sc, &(sc->atrs));
1969	}
1970	if (stat & OHCI_INT_PW_ERR) {
1971		device_printf(fc->dev, "posted write error\n");
1972	}
1973	if (stat & OHCI_INT_ERR) {
1974		device_printf(fc->dev, "unrecoverable error\n");
1975	}
1976	if (stat & OHCI_INT_PHY_INT) {
1977		device_printf(fc->dev, "phy int\n");
1978	}
1979}
1980
1981static void
1982fwohci_task_busreset(void *arg, int pending)
1983{
1984	struct fwohci_softc *sc = (struct fwohci_softc *)arg;
1985
1986	FW_GLOCK(&sc->fc);
1987	fw_busreset(&sc->fc, FWBUSRESET);
1988	OWRITE(sc, OHCI_CROMHDR, ntohl(sc->fc.config_rom[0]));
1989	OWRITE(sc, OHCI_BUS_OPT, ntohl(sc->fc.config_rom[2]));
1990	FW_GUNLOCK(&sc->fc);
1991}
1992
1993static void
1994fwohci_task_sid(void *arg, int pending)
1995{
1996	struct fwohci_softc *sc = (struct fwohci_softc *)arg;
1997	struct firewire_comm *fc = &sc->fc;
1998	uint32_t *buf;
1999	int i, plen;
2000
2001
2002	/*
2003	 * We really should have locking
2004	 * here.  Not sure why it's not
2005	 */
2006	plen = OREAD(sc, OHCI_SID_CNT);
2007
2008	if (plen & OHCI_SID_ERR) {
2009		device_printf(fc->dev, "SID Error\n");
2010		return;
2011	}
2012	plen &= OHCI_SID_CNT_MASK;
2013	if (plen < 4 || plen > OHCI_SIDSIZE) {
2014		device_printf(fc->dev, "invalid SID len = %d\n", plen);
2015		return;
2016	}
2017	plen -= 4; /* chop control info */
2018	buf = (uint32_t *)malloc(OHCI_SIDSIZE, M_FW, M_NOWAIT);
2019	if (buf == NULL) {
2020		device_printf(fc->dev, "malloc failed\n");
2021		return;
2022	}
2023	for (i = 0; i < plen / 4; i++)
2024		buf[i] = FWOHCI_DMA_READ(sc->sid_buf[i + 1]);
2025
2026	/* pending all pre-bus_reset packets */
2027	fwohci_txd(sc, &sc->atrq);
2028	fwohci_txd(sc, &sc->atrs);
2029	fwohci_arcv(sc, &sc->arrs, -1);
2030	fwohci_arcv(sc, &sc->arrq, -1);
2031	fw_drain_txq(fc);
2032	fw_sidrcv(fc, buf, plen);
2033	free(buf, M_FW);
2034}
2035
2036static void
2037fwohci_task_dma(void *arg, int pending)
2038{
2039	struct fwohci_softc *sc = (struct fwohci_softc *)arg;
2040	uint32_t stat;
2041
2042again:
2043	stat = atomic_readandclear_int(&sc->intstat);
2044	if (stat)
2045		fwohci_intr_dma(sc, stat, -1);
2046	else
2047		return;
2048	goto again;
2049}
2050
2051static int
2052fwohci_check_stat(struct fwohci_softc *sc)
2053{
2054	uint32_t stat, irstat, itstat;
2055
2056	FW_GLOCK_ASSERT(&sc->fc);
2057	stat = OREAD(sc, FWOHCI_INTSTAT);
2058	if (stat == 0xffffffff) {
2059		if (!bus_child_present(sc->fc.dev))
2060			return (FILTER_HANDLED);
2061		device_printf(sc->fc.dev, "device physically ejected?\n");
2062		return (FILTER_STRAY);
2063	}
2064	if (stat)
2065		OWRITE(sc, FWOHCI_INTSTATCLR, stat & ~OHCI_INT_PHY_BUS_R);
2066
2067	stat &= sc->intmask;
2068	if (stat == 0)
2069		return (FILTER_STRAY);
2070
2071	atomic_set_int(&sc->intstat, stat);
2072	if (stat & OHCI_INT_DMA_IR) {
2073		irstat = OREAD(sc, OHCI_IR_STAT);
2074		OWRITE(sc, OHCI_IR_STATCLR, irstat);
2075		atomic_set_int(&sc->irstat, irstat);
2076	}
2077	if (stat & OHCI_INT_DMA_IT) {
2078		itstat = OREAD(sc, OHCI_IT_STAT);
2079		OWRITE(sc, OHCI_IT_STATCLR, itstat);
2080		atomic_set_int(&sc->itstat, itstat);
2081	}
2082
2083	fwohci_intr_core(sc, stat, -1);
2084	return (FILTER_HANDLED);
2085}
2086
2087void
2088fwohci_intr(void *arg)
2089{
2090	struct fwohci_softc *sc = (struct fwohci_softc *)arg;
2091
2092	FW_GLOCK(&sc->fc);
2093	fwohci_check_stat(sc);
2094	FW_GUNLOCK(&sc->fc);
2095}
2096
2097void
2098fwohci_poll(struct firewire_comm *fc, int quick, int count)
2099{
2100	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
2101
2102	FW_GLOCK(fc);
2103	fwohci_check_stat(sc);
2104	FW_GUNLOCK(fc);
2105}
2106
2107static void
2108fwohci_set_intr(struct firewire_comm *fc, int enable)
2109{
2110	struct fwohci_softc *sc;
2111
2112	sc = (struct fwohci_softc *)fc;
2113	if (firewire_debug)
2114		device_printf(sc->fc.dev, "fwohci_set_intr: %d\n", enable);
2115	if (enable) {
2116		sc->intmask |= OHCI_INT_EN;
2117		OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_EN);
2118	} else {
2119		sc->intmask &= ~OHCI_INT_EN;
2120		OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_EN);
2121	}
2122}
2123
2124static void
2125fwohci_tbuf_update(struct fwohci_softc *sc, int dmach)
2126{
2127	struct firewire_comm *fc = &sc->fc;
2128	struct fwohcidb *db;
2129	struct fw_bulkxfer *chunk;
2130	struct fw_xferq *it;
2131	uint32_t stat, count;
2132	int s, w=0, ldesc;
2133
2134	it = fc->it[dmach];
2135	ldesc = sc->it[dmach].ndesc - 1;
2136	s = splfw(); /* unnecessary ? */
2137	FW_GLOCK(fc);
2138	fwdma_sync_multiseg_all(sc->it[dmach].am, BUS_DMASYNC_POSTREAD);
2139	if (firewire_debug)
2140		dump_db(sc, ITX_CH + dmach);
2141	while ((chunk = STAILQ_FIRST(&it->stdma)) != NULL) {
2142		db = ((struct fwohcidb_tr *)(chunk->end))->db;
2143		stat = FWOHCI_DMA_READ(db[ldesc].db.desc.res)
2144				>> OHCI_STATUS_SHIFT;
2145		db = ((struct fwohcidb_tr *)(chunk->start))->db;
2146		/* timestamp */
2147		count = FWOHCI_DMA_READ(db[ldesc].db.desc.res)
2148				& OHCI_COUNT_MASK;
2149		if (stat == 0)
2150			break;
2151		STAILQ_REMOVE_HEAD(&it->stdma, link);
2152		switch (stat & FWOHCIEV_MASK) {
2153		case FWOHCIEV_ACKCOMPL:
2154#if 0
2155			device_printf(fc->dev, "0x%08x\n", count);
2156#endif
2157			break;
2158		default:
2159			device_printf(fc->dev,
2160				"Isochronous transmit err %02x(%s)\n",
2161					stat, fwohcicode[stat & 0x1f]);
2162		}
2163		STAILQ_INSERT_TAIL(&it->stfree, chunk, link);
2164		w++;
2165	}
2166	FW_GUNLOCK(fc);
2167	splx(s);
2168	if (w)
2169		wakeup(it);
2170}
2171
2172static void
2173fwohci_rbuf_update(struct fwohci_softc *sc, int dmach)
2174{
2175	struct firewire_comm *fc = &sc->fc;
2176	struct fwohcidb_tr *db_tr;
2177	struct fw_bulkxfer *chunk;
2178	struct fw_xferq *ir;
2179	uint32_t stat;
2180	int w = 0, ldesc;
2181
2182	ir = fc->ir[dmach];
2183	ldesc = sc->ir[dmach].ndesc - 1;
2184
2185#if 0
2186	dump_db(sc, dmach);
2187#endif
2188	if ((ir->flag & FWXFERQ_HANDLER) == 0)
2189		FW_GLOCK(fc);
2190	fwdma_sync_multiseg_all(sc->ir[dmach].am, BUS_DMASYNC_POSTREAD);
2191	while ((chunk = STAILQ_FIRST(&ir->stdma)) != NULL) {
2192		db_tr = (struct fwohcidb_tr *)chunk->end;
2193		stat = FWOHCI_DMA_READ(db_tr->db[ldesc].db.desc.res)
2194				>> OHCI_STATUS_SHIFT;
2195		if (stat == 0)
2196			break;
2197
2198		if (chunk->mbuf != NULL) {
2199			bus_dmamap_sync(sc->ir[dmach].dmat, db_tr->dma_map,
2200						BUS_DMASYNC_POSTREAD);
2201			bus_dmamap_unload(sc->ir[dmach].dmat, db_tr->dma_map);
2202		} else if (ir->buf != NULL) {
2203			fwdma_sync_multiseg(ir->buf, chunk->poffset,
2204				ir->bnpacket, BUS_DMASYNC_POSTREAD);
2205		} else {
2206			/* XXX */
2207			printf("fwohci_rbuf_update: this shouldn't happened\n");
2208		}
2209
2210		STAILQ_REMOVE_HEAD(&ir->stdma, link);
2211		STAILQ_INSERT_TAIL(&ir->stvalid, chunk, link);
2212		switch (stat & FWOHCIEV_MASK) {
2213		case FWOHCIEV_ACKCOMPL:
2214			chunk->resp = 0;
2215			break;
2216		default:
2217			chunk->resp = EINVAL;
2218			device_printf(fc->dev,
2219				"Isochronous receive err %02x(%s)\n",
2220					stat, fwohcicode[stat & 0x1f]);
2221		}
2222		w++;
2223	}
2224	if ((ir->flag & FWXFERQ_HANDLER) == 0)
2225		FW_GUNLOCK(fc);
2226	if (w == 0)
2227		return;
2228
2229	if (ir->flag & FWXFERQ_HANDLER)
2230		ir->hand(ir);
2231	else
2232		wakeup(ir);
2233}
2234
2235void
2236dump_dma(struct fwohci_softc *sc, uint32_t ch)
2237{
2238	uint32_t off, cntl, stat, cmd, match;
2239
2240	if (ch == 0) {
2241		off = OHCI_ATQOFF;
2242	} else if (ch == 1) {
2243		off = OHCI_ATSOFF;
2244	} else if (ch == 2) {
2245		off = OHCI_ARQOFF;
2246	} else if (ch == 3) {
2247		off = OHCI_ARSOFF;
2248	} else if (ch < IRX_CH) {
2249		off = OHCI_ITCTL(ch - ITX_CH);
2250	} else {
2251		off = OHCI_IRCTL(ch - IRX_CH);
2252	}
2253	cntl = stat = OREAD(sc, off);
2254	cmd = OREAD(sc, off + 0xc);
2255	match = OREAD(sc, off + 0x10);
2256
2257	device_printf(sc->fc.dev, "ch %1x cntl:0x%08x cmd:0x%08x match:0x%08x\n",
2258		ch,
2259		cntl,
2260		cmd,
2261		match);
2262	stat &= 0xffff;
2263	if (stat) {
2264		device_printf(sc->fc.dev, "dma %d ch:%s%s%s%s%s%s %s(%x)\n",
2265			ch,
2266			stat & OHCI_CNTL_DMA_RUN ? "RUN," : "",
2267			stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "",
2268			stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "",
2269			stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "",
2270			stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "",
2271			stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "",
2272			fwohcicode[stat & 0x1f],
2273			stat & 0x1f
2274		);
2275	} else {
2276		device_printf(sc->fc.dev, "dma %d ch: Nostat\n", ch);
2277	}
2278}
2279
2280void
2281dump_db(struct fwohci_softc *sc, uint32_t ch)
2282{
2283	struct fwohci_dbch *dbch;
2284	struct fwohcidb_tr *cp = NULL, *pp, *np = NULL;
2285	struct fwohcidb *curr = NULL, *prev, *next = NULL;
2286	int idb, jdb;
2287	uint32_t cmd, off;
2288
2289	if (ch == 0) {
2290		off = OHCI_ATQOFF;
2291		dbch = &sc->atrq;
2292	} else if (ch == 1) {
2293		off = OHCI_ATSOFF;
2294		dbch = &sc->atrs;
2295	} else if (ch == 2) {
2296		off = OHCI_ARQOFF;
2297		dbch = &sc->arrq;
2298	} else if (ch == 3) {
2299		off = OHCI_ARSOFF;
2300		dbch = &sc->arrs;
2301	} else if (ch < IRX_CH) {
2302		off = OHCI_ITCTL(ch - ITX_CH);
2303		dbch = &sc->it[ch - ITX_CH];
2304	} else {
2305		off = OHCI_IRCTL(ch - IRX_CH);
2306		dbch = &sc->ir[ch - IRX_CH];
2307	}
2308	cmd = OREAD(sc, off + 0xc);
2309
2310	if (dbch->ndb == 0) {
2311		device_printf(sc->fc.dev, "No DB is attached ch=%d\n", ch);
2312		return;
2313	}
2314	pp = dbch->top;
2315	prev = pp->db;
2316	for (idb = 0; idb < dbch->ndb; idb++) {
2317		cp = STAILQ_NEXT(pp, link);
2318		if (cp == NULL) {
2319			curr = NULL;
2320			goto outdb;
2321		}
2322		np = STAILQ_NEXT(cp, link);
2323		for (jdb = 0; jdb < dbch->ndesc; jdb++) {
2324			if ((cmd  & 0xfffffff0) == cp->bus_addr) {
2325				curr = cp->db;
2326				if (np != NULL) {
2327					next = np->db;
2328				} else {
2329					next = NULL;
2330				}
2331				goto outdb;
2332			}
2333		}
2334		pp = STAILQ_NEXT(pp, link);
2335		if (pp == NULL) {
2336			curr = NULL;
2337			goto outdb;
2338		}
2339		prev = pp->db;
2340	}
2341outdb:
2342	if (curr != NULL) {
2343#if 0
2344		printf("Prev DB %d\n", ch);
2345		print_db(pp, prev, ch, dbch->ndesc);
2346#endif
2347		printf("Current DB %d\n", ch);
2348		print_db(cp, curr, ch, dbch->ndesc);
2349#if 0
2350		printf("Next DB %d\n", ch);
2351		print_db(np, next, ch, dbch->ndesc);
2352#endif
2353	} else {
2354		printf("dbdump err ch = %d cmd = 0x%08x\n", ch, cmd);
2355	}
2356	return;
2357}
2358
2359void
2360print_db(struct fwohcidb_tr *db_tr, struct fwohcidb *db,
2361		uint32_t ch, uint32_t max)
2362{
2363	fwohcireg_t stat;
2364	int i, key;
2365	uint32_t cmd, res;
2366
2367	if (db == NULL) {
2368		printf("No Descriptor is found\n");
2369		return;
2370	}
2371
2372	printf("ch = %d\n%8s %s %s %s %s %4s %8s %8s %4s:%4s\n",
2373		ch,
2374		"Current",
2375		"OP  ",
2376		"KEY",
2377		"INT",
2378		"BR ",
2379		"len",
2380		"Addr",
2381		"Depend",
2382		"Stat",
2383		"Cnt");
2384	for (i = 0; i <= max; i++) {
2385		cmd = FWOHCI_DMA_READ(db[i].db.desc.cmd);
2386		res = FWOHCI_DMA_READ(db[i].db.desc.res);
2387		key = cmd & OHCI_KEY_MASK;
2388		stat = res >> OHCI_STATUS_SHIFT;
2389		printf("%08jx %s %s %s %s %5d %08x %08x %04x:%04x",
2390				(uintmax_t)db_tr->bus_addr,
2391				dbcode[(cmd >> 28) & 0xf],
2392				dbkey[(cmd >> 24) & 0x7],
2393				dbcond[(cmd >> 20) & 0x3],
2394				dbcond[(cmd >> 18) & 0x3],
2395				cmd & OHCI_COUNT_MASK,
2396				FWOHCI_DMA_READ(db[i].db.desc.addr),
2397				FWOHCI_DMA_READ(db[i].db.desc.depend),
2398				stat,
2399				res & OHCI_COUNT_MASK);
2400		if (stat & 0xff00) {
2401			printf(" %s%s%s%s%s%s %s(%x)\n",
2402				stat & OHCI_CNTL_DMA_RUN ? "RUN," : "",
2403				stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "",
2404				stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "",
2405				stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "",
2406				stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "",
2407				stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "",
2408				fwohcicode[stat & 0x1f],
2409				stat & 0x1f
2410			);
2411		} else {
2412			printf(" Nostat\n");
2413		}
2414		if (key == OHCI_KEY_ST2) {
2415			printf("0x%08x 0x%08x 0x%08x 0x%08x\n",
2416				FWOHCI_DMA_READ(db[i + 1].db.immed[0]),
2417				FWOHCI_DMA_READ(db[i + 1].db.immed[1]),
2418				FWOHCI_DMA_READ(db[i + 1].db.immed[2]),
2419				FWOHCI_DMA_READ(db[i + 1].db.immed[3]));
2420		}
2421		if (key == OHCI_KEY_DEVICE) {
2422			return;
2423		}
2424		if ((cmd & OHCI_BRANCH_MASK)
2425				== OHCI_BRANCH_ALWAYS) {
2426			return;
2427		}
2428		if ((cmd & OHCI_CMD_MASK)
2429				== OHCI_OUTPUT_LAST) {
2430			return;
2431		}
2432		if ((cmd & OHCI_CMD_MASK)
2433				== OHCI_INPUT_LAST) {
2434			return;
2435		}
2436		if (key == OHCI_KEY_ST2) {
2437			i++;
2438		}
2439	}
2440	return;
2441}
2442
2443void
2444fwohci_ibr(struct firewire_comm *fc)
2445{
2446	struct fwohci_softc *sc;
2447	uint32_t fun;
2448
2449	device_printf(fc->dev, "Initiate bus reset\n");
2450	sc = (struct fwohci_softc *)fc;
2451
2452	FW_GLOCK(fc);
2453	/*
2454	 * Make sure our cached values from the config rom are
2455	 * initialised.
2456	 */
2457	OWRITE(sc, OHCI_CROMHDR, ntohl(sc->fc.config_rom[0]));
2458	OWRITE(sc, OHCI_BUS_OPT, ntohl(sc->fc.config_rom[2]));
2459
2460	/*
2461	 * Set root hold-off bit so that non cyclemaster capable node
2462	 * shouldn't became the root node.
2463	 */
2464#if 1
2465	fun = fwphy_rddata(sc, FW_PHY_IBR_REG);
2466	fun |= FW_PHY_IBR | FW_PHY_RHB;
2467	fun = fwphy_wrdata(sc, FW_PHY_IBR_REG, fun);
2468#else	/* Short bus reset */
2469	fun = fwphy_rddata(sc, FW_PHY_ISBR_REG);
2470	fun |= FW_PHY_ISBR | FW_PHY_RHB;
2471	fun = fwphy_wrdata(sc, FW_PHY_ISBR_REG, fun);
2472#endif
2473	FW_GUNLOCK(fc);
2474}
2475
2476void
2477fwohci_txbufdb(struct fwohci_softc *sc, int dmach, struct fw_bulkxfer *bulkxfer)
2478{
2479	struct fwohcidb_tr *db_tr, *fdb_tr;
2480	struct fwohci_dbch *dbch;
2481	struct fwohcidb *db;
2482	struct fw_pkt *fp;
2483	struct fwohci_txpkthdr *ohcifp;
2484	unsigned short chtag;
2485	int idb;
2486
2487	FW_GLOCK_ASSERT(&sc->fc);
2488
2489	dbch = &sc->it[dmach];
2490	chtag = sc->it[dmach].xferq.flag & 0xff;
2491
2492	db_tr = (struct fwohcidb_tr *)(bulkxfer->start);
2493	fdb_tr = (struct fwohcidb_tr *)(bulkxfer->end);
2494/*
2495device_printf(sc->fc.dev, "DB %08x %08x %08x\n", bulkxfer, db_tr->bus_addr, fdb_tr->bus_addr);
2496*/
2497	for (idb = 0; idb < dbch->xferq.bnpacket; idb++) {
2498		db = db_tr->db;
2499		fp = (struct fw_pkt *)db_tr->buf;
2500		ohcifp = (struct fwohci_txpkthdr *) db[1].db.immed;
2501		ohcifp->mode.ld[0] = fp->mode.ld[0];
2502		ohcifp->mode.common.spd = 0 & 0x7;
2503		ohcifp->mode.stream.len = fp->mode.stream.len;
2504		ohcifp->mode.stream.chtag = chtag;
2505		ohcifp->mode.stream.tcode = 0xa;
2506#if BYTE_ORDER == BIG_ENDIAN
2507		FWOHCI_DMA_WRITE(db[1].db.immed[0], db[1].db.immed[0]);
2508		FWOHCI_DMA_WRITE(db[1].db.immed[1], db[1].db.immed[1]);
2509#endif
2510
2511		FWOHCI_DMA_CLEAR(db[2].db.desc.cmd, OHCI_COUNT_MASK);
2512		FWOHCI_DMA_SET(db[2].db.desc.cmd, fp->mode.stream.len);
2513		FWOHCI_DMA_WRITE(db[2].db.desc.res, 0);
2514#if 0 /* if bulkxfer->npackets changes */
2515		db[2].db.desc.cmd = OHCI_OUTPUT_LAST
2516			| OHCI_UPDATE
2517			| OHCI_BRANCH_ALWAYS;
2518		db[0].db.desc.depend =
2519			= db[dbch->ndesc - 1].db.desc.depend
2520			= STAILQ_NEXT(db_tr, link)->bus_addr | dbch->ndesc;
2521#else
2522		FWOHCI_DMA_SET(db[0].db.desc.depend, dbch->ndesc);
2523		FWOHCI_DMA_SET(db[dbch->ndesc - 1].db.desc.depend, dbch->ndesc);
2524#endif
2525		bulkxfer->end = (caddr_t)db_tr;
2526		db_tr = STAILQ_NEXT(db_tr, link);
2527	}
2528	db = ((struct fwohcidb_tr *)bulkxfer->end)->db;
2529	FWOHCI_DMA_CLEAR(db[0].db.desc.depend, 0xf);
2530	FWOHCI_DMA_CLEAR(db[dbch->ndesc - 1].db.desc.depend, 0xf);
2531#if 0 /* if bulkxfer->npackets changes */
2532	db[dbch->ndesc - 1].db.desc.control |= OHCI_INTERRUPT_ALWAYS;
2533	/* OHCI 1.1 and above */
2534	db[0].db.desc.control |= OHCI_INTERRUPT_ALWAYS;
2535#endif
2536/*
2537	db_tr = (struct fwohcidb_tr *)bulkxfer->start;
2538	fdb_tr = (struct fwohcidb_tr *)bulkxfer->end;
2539device_printf(sc->fc.dev, "DB %08x %3d %08x %08x\n", bulkxfer, bulkxfer->npacket, db_tr->bus_addr, fdb_tr->bus_addr);
2540*/
2541	return;
2542}
2543
2544static int
2545fwohci_add_tx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr,
2546								int poffset)
2547{
2548	struct fwohcidb *db = db_tr->db;
2549	struct fw_xferq *it;
2550	int err = 0;
2551
2552	it = &dbch->xferq;
2553	if (it->buf == 0) {
2554		err = EINVAL;
2555		return err;
2556	}
2557	db_tr->buf = fwdma_v_addr(it->buf, poffset);
2558	db_tr->dbcnt = 3;
2559
2560	FWOHCI_DMA_WRITE(db[0].db.desc.cmd,
2561		OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | 8);
2562	FWOHCI_DMA_WRITE(db[0].db.desc.addr, 0);
2563	bzero((void *)&db[1].db.immed[0], sizeof(db[1].db.immed));
2564	FWOHCI_DMA_WRITE(db[2].db.desc.addr,
2565	fwdma_bus_addr(it->buf, poffset) + sizeof(uint32_t));
2566
2567	FWOHCI_DMA_WRITE(db[2].db.desc.cmd,
2568		OHCI_OUTPUT_LAST | OHCI_UPDATE | OHCI_BRANCH_ALWAYS);
2569#if 1
2570	FWOHCI_DMA_WRITE(db[0].db.desc.res, 0);
2571	FWOHCI_DMA_WRITE(db[2].db.desc.res, 0);
2572#endif
2573	return 0;
2574}
2575
2576int
2577fwohci_add_rx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr,
2578		int poffset, struct fwdma_alloc *dummy_dma)
2579{
2580	struct fwohcidb *db = db_tr->db;
2581	struct fw_xferq *ir;
2582	int i, ldesc;
2583	bus_addr_t dbuf[2];
2584	int dsiz[2];
2585
2586	ir = &dbch->xferq;
2587	if (ir->buf == NULL && (dbch->xferq.flag & FWXFERQ_EXTBUF) == 0) {
2588		if (db_tr->buf == NULL) {
2589			db_tr->buf = fwdma_malloc_size(dbch->dmat,
2590			    &db_tr->dma_map, ir->psize, &dbuf[0],
2591			    BUS_DMA_NOWAIT);
2592			if (db_tr->buf == NULL)
2593				return (ENOMEM);
2594		}
2595		db_tr->dbcnt = 1;
2596		dsiz[0] = ir->psize;
2597		bus_dmamap_sync(dbch->dmat, db_tr->dma_map,
2598			BUS_DMASYNC_PREREAD);
2599	} else {
2600		db_tr->dbcnt = 0;
2601		if (dummy_dma != NULL) {
2602			dsiz[db_tr->dbcnt] = sizeof(uint32_t);
2603			dbuf[db_tr->dbcnt++] = dummy_dma->bus_addr;
2604		}
2605		dsiz[db_tr->dbcnt] = ir->psize;
2606		if (ir->buf != NULL) {
2607			db_tr->buf = fwdma_v_addr(ir->buf, poffset);
2608			dbuf[db_tr->dbcnt] = fwdma_bus_addr(ir->buf, poffset);
2609		}
2610		db_tr->dbcnt++;
2611	}
2612	for (i = 0; i < db_tr->dbcnt; i++) {
2613		FWOHCI_DMA_WRITE(db[i].db.desc.addr, dbuf[i]);
2614		FWOHCI_DMA_WRITE(db[i].db.desc.cmd, OHCI_INPUT_MORE | dsiz[i]);
2615		if (ir->flag & FWXFERQ_STREAM) {
2616			FWOHCI_DMA_SET(db[i].db.desc.cmd, OHCI_UPDATE);
2617		}
2618		FWOHCI_DMA_WRITE(db[i].db.desc.res, dsiz[i]);
2619	}
2620	ldesc = db_tr->dbcnt - 1;
2621	if (ir->flag & FWXFERQ_STREAM) {
2622		FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, OHCI_INPUT_LAST);
2623	}
2624	FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, OHCI_BRANCH_ALWAYS);
2625	return 0;
2626}
2627
2628
2629static int
2630fwohci_arcv_swap(struct fw_pkt *fp, int len)
2631{
2632	struct fw_pkt *fp0;
2633	uint32_t ld0;
2634	int slen, hlen;
2635#if BYTE_ORDER == BIG_ENDIAN
2636	int i;
2637#endif
2638
2639	ld0 = FWOHCI_DMA_READ(fp->mode.ld[0]);
2640#if 0
2641	printf("ld0: x%08x\n", ld0);
2642#endif
2643	fp0 = (struct fw_pkt *)&ld0;
2644	/* determine length to swap */
2645	switch (fp0->mode.common.tcode) {
2646	case FWTCODE_RREQQ:
2647	case FWTCODE_WRES:
2648	case FWTCODE_WREQQ:
2649	case FWTCODE_RRESQ:
2650	case FWOHCITCODE_PHY:
2651		slen = 12;
2652		break;
2653	case FWTCODE_RREQB:
2654	case FWTCODE_WREQB:
2655	case FWTCODE_LREQ:
2656	case FWTCODE_RRESB:
2657	case FWTCODE_LRES:
2658		slen = 16;
2659		break;
2660	default:
2661		printf("Unknown tcode %d\n", fp0->mode.common.tcode);
2662		return (0);
2663	}
2664	hlen = tinfo[fp0->mode.common.tcode].hdr_len;
2665	if (hlen > len) {
2666		if (firewire_debug)
2667			printf("splitted header\n");
2668		return (-hlen);
2669	}
2670#if BYTE_ORDER == BIG_ENDIAN
2671	for (i = 0; i < slen/4; i++)
2672		fp->mode.ld[i] = FWOHCI_DMA_READ(fp->mode.ld[i]);
2673#endif
2674	return (hlen);
2675}
2676
2677static int
2678fwohci_get_plen(struct fwohci_softc *sc, struct fwohci_dbch *dbch, struct fw_pkt *fp)
2679{
2680	struct tcode_info *info;
2681	int r;
2682
2683	info = &tinfo[fp->mode.common.tcode];
2684	r = info->hdr_len + sizeof(uint32_t);
2685	if ((info->flag & FWTI_BLOCK_ASY) != 0)
2686		r += roundup2(fp->mode.wreqb.len, sizeof(uint32_t));
2687
2688	if (r == sizeof(uint32_t)) {
2689		/* XXX */
2690		device_printf(sc->fc.dev, "Unknown tcode %d\n",
2691						fp->mode.common.tcode);
2692		return (-1);
2693	}
2694
2695	if (r > dbch->xferq.psize) {
2696		device_printf(sc->fc.dev, "Invalid packet length %d\n", r);
2697		return (-1);
2698		/* panic ? */
2699	}
2700
2701	return r;
2702}
2703
2704static void
2705fwohci_arcv_free_buf(struct fwohci_softc *sc, struct fwohci_dbch *dbch,
2706    struct fwohcidb_tr *db_tr, uint32_t off, int wake)
2707{
2708	struct fwohcidb *db = &db_tr->db[0];
2709
2710	FWOHCI_DMA_CLEAR(db->db.desc.depend, 0xf);
2711	FWOHCI_DMA_WRITE(db->db.desc.res, dbch->xferq.psize);
2712	FWOHCI_DMA_SET(dbch->bottom->db[0].db.desc.depend, 1);
2713	fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREWRITE);
2714	dbch->bottom = db_tr;
2715
2716	if (wake)
2717		OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_WAKE);
2718}
2719
2720static void
2721fwohci_arcv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count)
2722{
2723	struct fwohcidb_tr *db_tr;
2724	struct iovec vec[2];
2725	struct fw_pkt pktbuf;
2726	int nvec;
2727	struct fw_pkt *fp;
2728	uint8_t *ld;
2729	uint32_t stat, off, status, event;
2730	u_int spd;
2731	int len, plen, hlen, pcnt, offset;
2732	int s;
2733	caddr_t buf;
2734	int resCount;
2735
2736	if (&sc->arrq == dbch) {
2737		off = OHCI_ARQOFF;
2738	} else if (&sc->arrs == dbch) {
2739		off = OHCI_ARSOFF;
2740	} else {
2741		return;
2742	}
2743
2744	s = splfw();
2745	db_tr = dbch->top;
2746	pcnt = 0;
2747	/* XXX we cannot handle a packet which lies in more than two buf */
2748	fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_POSTREAD);
2749	fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_POSTWRITE);
2750	status = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) >> OHCI_STATUS_SHIFT;
2751	resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) & OHCI_COUNT_MASK;
2752	while (status & OHCI_CNTL_DMA_ACTIVE) {
2753#if 0
2754
2755		if (off == OHCI_ARQOFF)
2756			printf("buf 0x%08x, status 0x%04x, resCount 0x%04x\n",
2757			    db_tr->bus_addr, status, resCount);
2758#endif
2759		len = dbch->xferq.psize - resCount;
2760		ld = (uint8_t *)db_tr->buf;
2761		if (dbch->pdb_tr == NULL) {
2762			len -= dbch->buf_offset;
2763			ld += dbch->buf_offset;
2764		}
2765		if (len > 0)
2766			bus_dmamap_sync(dbch->dmat, db_tr->dma_map,
2767					BUS_DMASYNC_POSTREAD);
2768		while (len > 0) {
2769			if (count >= 0 && count-- == 0)
2770				goto out;
2771			if (dbch->pdb_tr != NULL) {
2772				/* we have a fragment in previous buffer */
2773				int rlen;
2774
2775				offset = dbch->buf_offset;
2776				if (offset < 0)
2777					offset = - offset;
2778				buf = dbch->pdb_tr->buf + offset;
2779				rlen = dbch->xferq.psize - offset;
2780				if (firewire_debug)
2781					printf("rlen=%d, offset=%d\n",
2782						rlen, dbch->buf_offset);
2783				if (dbch->buf_offset < 0) {
2784					/* splitted in header, pull up */
2785					char *p;
2786
2787					p = (char *)&pktbuf;
2788					bcopy(buf, p, rlen);
2789					p += rlen;
2790					/* this must be too long but harmless */
2791					rlen = sizeof(pktbuf) - rlen;
2792					if (rlen < 0)
2793						printf("why rlen < 0\n");
2794					bcopy(db_tr->buf, p, rlen);
2795					ld += rlen;
2796					len -= rlen;
2797					hlen = fwohci_arcv_swap(&pktbuf, sizeof(pktbuf));
2798					if (hlen <= 0) {
2799						printf("hlen should be positive.");
2800						goto err;
2801					}
2802					offset = sizeof(pktbuf);
2803					vec[0].iov_base = (char *)&pktbuf;
2804					vec[0].iov_len = offset;
2805				} else {
2806					/* splitted in payload */
2807					offset = rlen;
2808					vec[0].iov_base = buf;
2809					vec[0].iov_len = rlen;
2810				}
2811				fp=(struct fw_pkt *)vec[0].iov_base;
2812				nvec = 1;
2813			} else {
2814				/* no fragment in previous buffer */
2815				fp=(struct fw_pkt *)ld;
2816				hlen = fwohci_arcv_swap(fp, len);
2817				if (hlen == 0)
2818					goto err;
2819				if (hlen < 0) {
2820					dbch->pdb_tr = db_tr;
2821					dbch->buf_offset = - dbch->buf_offset;
2822					/* sanity check */
2823					if (resCount != 0) {
2824						printf("resCount=%d hlen=%d\n",
2825						    resCount, hlen);
2826						    goto err;
2827					}
2828					goto out;
2829				}
2830				offset = 0;
2831				nvec = 0;
2832			}
2833			plen = fwohci_get_plen(sc, dbch, fp) - offset;
2834			if (plen < 0) {
2835				/* minimum header size + trailer
2836				= sizeof(fw_pkt) so this shouldn't happens */
2837				printf("plen(%d) is negative! offset=%d\n",
2838				    plen, offset);
2839				goto err;
2840			}
2841			if (plen > 0) {
2842				len -= plen;
2843				if (len < 0) {
2844					dbch->pdb_tr = db_tr;
2845					if (firewire_debug)
2846						printf("splitted payload\n");
2847					/* sanity check */
2848					if (resCount != 0) {
2849						printf("resCount=%d plen=%d"
2850						    " len=%d\n",
2851						    resCount, plen, len);
2852						goto err;
2853					}
2854					goto out;
2855				}
2856				vec[nvec].iov_base = ld;
2857				vec[nvec].iov_len = plen;
2858				nvec++;
2859				ld += plen;
2860			}
2861			dbch->buf_offset = ld - (uint8_t *)db_tr->buf;
2862			if (nvec == 0)
2863				printf("nvec == 0\n");
2864
2865/* DMA result-code will be written at the tail of packet */
2866			stat = FWOHCI_DMA_READ(*(uint32_t *)(ld - sizeof(struct fwohci_trailer)));
2867#if 0
2868			printf("plen: %d, stat %x\n",
2869			    plen ,stat);
2870#endif
2871			spd = (stat >> 21) & 0x3;
2872			event = (stat >> 16) & 0x1f;
2873			switch (event) {
2874			case FWOHCIEV_ACKPEND:
2875#if 0
2876				printf("fwohci_arcv: ack pending tcode=0x%x..\n", fp->mode.common.tcode);
2877#endif
2878				/* fall through */
2879			case FWOHCIEV_ACKCOMPL:
2880			{
2881				struct fw_rcv_buf rb;
2882
2883				if ((vec[nvec-1].iov_len -=
2884					sizeof(struct fwohci_trailer)) == 0)
2885					nvec--;
2886				rb.fc = &sc->fc;
2887				rb.vec = vec;
2888				rb.nvec = nvec;
2889				rb.spd = spd;
2890				fw_rcv(&rb);
2891				break;
2892			}
2893			case FWOHCIEV_BUSRST:
2894				if ((sc->fc.status != FWBUSRESET) &&
2895				    (sc->fc.status != FWBUSINIT))
2896					printf("got BUSRST packet!?\n");
2897				break;
2898			default:
2899				device_printf(sc->fc.dev,
2900				    "Async DMA Receive error err=%02x %s"
2901				    " plen=%d offset=%d len=%d status=0x%08x"
2902				    " tcode=0x%x, stat=0x%08x\n",
2903				    event, fwohcicode[event], plen,
2904				    dbch->buf_offset, len,
2905				    OREAD(sc, OHCI_DMACTL(off)),
2906				    fp->mode.common.tcode, stat);
2907#if 1 /* XXX */
2908				goto err;
2909#endif
2910				break;
2911			}
2912			pcnt++;
2913			if (dbch->pdb_tr != NULL) {
2914				fwohci_arcv_free_buf(sc, dbch, dbch->pdb_tr,
2915				    off, 1);
2916				dbch->pdb_tr = NULL;
2917			}
2918
2919		}
2920out:
2921		if (resCount == 0) {
2922			/* done on this buffer */
2923			if (dbch->pdb_tr == NULL) {
2924				fwohci_arcv_free_buf(sc, dbch, db_tr, off, 1);
2925				dbch->buf_offset = 0;
2926			} else
2927				if (dbch->pdb_tr != db_tr)
2928					printf("pdb_tr != db_tr\n");
2929			db_tr = STAILQ_NEXT(db_tr, link);
2930			status = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res)
2931						>> OHCI_STATUS_SHIFT;
2932			resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res)
2933						& OHCI_COUNT_MASK;
2934			/* XXX check buffer overrun */
2935			dbch->top = db_tr;
2936		} else {
2937			dbch->buf_offset = dbch->xferq.psize - resCount;
2938			break;
2939		}
2940		/* XXX make sure DMA is not dead */
2941	}
2942#if 0
2943	if (pcnt < 1)
2944		printf("fwohci_arcv: no packets\n");
2945#endif
2946	splx(s);
2947	return;
2948
2949err:
2950	device_printf(sc->fc.dev, "AR DMA status=%x, ",
2951					OREAD(sc, OHCI_DMACTL(off)));
2952	dbch->pdb_tr = NULL;
2953	/* skip until resCount != 0 */
2954	printf(" skip buffer");
2955	while (resCount == 0) {
2956		printf(" #");
2957		fwohci_arcv_free_buf(sc, dbch, db_tr, off, 0);
2958		db_tr = STAILQ_NEXT(db_tr, link);
2959		resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res)
2960						& OHCI_COUNT_MASK;
2961	}
2962	printf(" done\n");
2963	dbch->top = db_tr;
2964	dbch->buf_offset = dbch->xferq.psize - resCount;
2965	OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_WAKE);
2966	splx(s);
2967}
2968