fwohci.c revision 298955
1/*-
2 * Copyright (c) 2003 Hidetoshi Shimokawa
3 * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 *    must display the acknowledgement as bellow:
16 *
17 *    This product includes software developed by K. Kobayashi and H. Shimokawa
18 *
19 * 4. The name of the author may not be used to endorse or promote products
20 *    derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
26 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
30 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *
34 * $FreeBSD: head/sys/dev/firewire/fwohci.c 298955 2016-05-03 03:41:25Z pfg $
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	if (db_tr == NULL) {
1251		printf("fwohci_db_init: malloc(1) failed\n");
1252		return;
1253	}
1254
1255#define DB_SIZE(x) (sizeof(struct fwohcidb) * (x)->ndesc)
1256	dbch->am = fwdma_malloc_multiseg(&sc->fc, sizeof(struct fwohcidb),
1257		DB_SIZE(dbch), dbch->ndb, BUS_DMA_WAITOK);
1258	if (dbch->am == NULL) {
1259		printf("fwohci_db_init: fwdma_malloc_multiseg failed\n");
1260		free(db_tr, M_FW);
1261		return;
1262	}
1263	/* Attach DB to DMA ch. */
1264	for (idb = 0; idb < dbch->ndb; idb++) {
1265		db_tr->dbcnt = 0;
1266		db_tr->db = (struct fwohcidb *)fwdma_v_addr(dbch->am, idb);
1267		db_tr->bus_addr = fwdma_bus_addr(dbch->am, idb);
1268		/* create dmamap for buffers */
1269		/* XXX do we need 4bytes alignment tag? */
1270		/* XXX don't alloc dma_map for AR */
1271		if (bus_dmamap_create(dbch->dmat, 0, &db_tr->dma_map) != 0) {
1272			printf("bus_dmamap_create failed\n");
1273			dbch->flags = FWOHCI_DBCH_INIT; /* XXX fake */
1274			fwohci_db_free(dbch);
1275			return;
1276		}
1277		STAILQ_INSERT_TAIL(&dbch->db_trq, db_tr, link);
1278		if (dbch->xferq.flag & FWXFERQ_EXTBUF) {
1279			if (idb % dbch->xferq.bnpacket == 0)
1280				dbch->xferq.bulkxfer[idb / dbch->xferq.bnpacket
1281						].start = (caddr_t)db_tr;
1282			if ((idb + 1) % dbch->xferq.bnpacket == 0)
1283				dbch->xferq.bulkxfer[idb / dbch->xferq.bnpacket
1284						].end = (caddr_t)db_tr;
1285		}
1286		db_tr++;
1287	}
1288	STAILQ_LAST(&dbch->db_trq, fwohcidb_tr,link)->link.stqe_next
1289			= STAILQ_FIRST(&dbch->db_trq);
1290out:
1291	dbch->xferq.queued = 0;
1292	dbch->pdb_tr = NULL;
1293	dbch->top = STAILQ_FIRST(&dbch->db_trq);
1294	dbch->bottom = dbch->top;
1295	dbch->flags = FWOHCI_DBCH_INIT;
1296}
1297
1298static int
1299fwohci_itx_disable(struct firewire_comm *fc, int dmach)
1300{
1301	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1302
1303	OWRITE(sc, OHCI_ITCTLCLR(dmach),
1304			OHCI_CNTL_DMA_RUN | OHCI_CNTL_CYCMATCH_S);
1305	OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach);
1306	OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach);
1307	/* XXX we cannot free buffers until the DMA really stops */
1308	pause("fwitxd", hz);
1309	fwohci_db_free(&sc->it[dmach]);
1310	sc->it[dmach].xferq.flag &= ~FWXFERQ_RUNNING;
1311	return 0;
1312}
1313
1314static int
1315fwohci_irx_disable(struct firewire_comm *fc, int dmach)
1316{
1317	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1318
1319	OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
1320	OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach);
1321	OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach);
1322	/* XXX we cannot free buffers until the DMA really stops */
1323	pause("fwirxd", hz);
1324	fwohci_db_free(&sc->ir[dmach]);
1325	sc->ir[dmach].xferq.flag &= ~FWXFERQ_RUNNING;
1326	return 0;
1327}
1328
1329#if BYTE_ORDER == BIG_ENDIAN
1330static void
1331fwohci_irx_post (struct firewire_comm *fc , uint32_t *qld)
1332{
1333	qld[0] = FWOHCI_DMA_READ(qld[0]);
1334	return;
1335}
1336#endif
1337
1338static int
1339fwohci_tx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1340{
1341	int err = 0;
1342	int idb, z, i, dmach = 0, ldesc;
1343	uint32_t off = 0;
1344	struct fwohcidb_tr *db_tr;
1345	struct fwohcidb *db;
1346
1347	if (!(dbch->xferq.flag & FWXFERQ_EXTBUF)) {
1348		err = EINVAL;
1349		return err;
1350	}
1351	z = dbch->ndesc;
1352	for (dmach = 0; dmach < sc->fc.nisodma; dmach++) {
1353		if (&sc->it[dmach] == dbch) {
1354			off = OHCI_ITOFF(dmach);
1355			break;
1356		}
1357	}
1358	if (off == 0) {
1359		err = EINVAL;
1360		return err;
1361	}
1362	if (dbch->xferq.flag & FWXFERQ_RUNNING)
1363		return err;
1364	dbch->xferq.flag |= FWXFERQ_RUNNING;
1365	for (i = 0, dbch->bottom = dbch->top; i < (dbch->ndb - 1); i++) {
1366		dbch->bottom = STAILQ_NEXT(dbch->bottom, link);
1367	}
1368	db_tr = dbch->top;
1369	for (idb = 0; idb < dbch->ndb; idb++) {
1370		fwohci_add_tx_buf(dbch, db_tr, idb);
1371		if (STAILQ_NEXT(db_tr, link) == NULL) {
1372			break;
1373		}
1374		db = db_tr->db;
1375		ldesc = db_tr->dbcnt - 1;
1376		FWOHCI_DMA_WRITE(db[0].db.desc.depend,
1377				STAILQ_NEXT(db_tr, link)->bus_addr | z);
1378		db[ldesc].db.desc.depend = db[0].db.desc.depend;
1379		if (dbch->xferq.flag & FWXFERQ_EXTBUF) {
1380			if (((idb + 1) % dbch->xferq.bnpacket) == 0) {
1381				FWOHCI_DMA_SET(
1382					db[ldesc].db.desc.cmd,
1383					OHCI_INTERRUPT_ALWAYS);
1384				/* OHCI 1.1 and above */
1385				FWOHCI_DMA_SET(
1386					db[0].db.desc.cmd,
1387					OHCI_INTERRUPT_ALWAYS);
1388			}
1389		}
1390		db_tr = STAILQ_NEXT(db_tr, link);
1391	}
1392	FWOHCI_DMA_CLEAR(
1393		dbch->bottom->db[dbch->bottom->dbcnt - 1].db.desc.depend, 0xf);
1394	return err;
1395}
1396
1397static int
1398fwohci_rx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1399{
1400	int err = 0;
1401	int idb, z, i, dmach = 0, ldesc;
1402	uint32_t off = 0;
1403	struct fwohcidb_tr *db_tr;
1404	struct fwohcidb *db;
1405
1406	z = dbch->ndesc;
1407	if (&sc->arrq == dbch) {
1408		off = OHCI_ARQOFF;
1409	} else if (&sc->arrs == dbch) {
1410		off = OHCI_ARSOFF;
1411	} else {
1412		for (dmach = 0; dmach < sc->fc.nisodma; dmach++) {
1413			if (&sc->ir[dmach] == dbch) {
1414				off = OHCI_IROFF(dmach);
1415				break;
1416			}
1417		}
1418	}
1419	if (off == 0) {
1420		err = EINVAL;
1421		return err;
1422	}
1423	if (dbch->xferq.flag & FWXFERQ_STREAM) {
1424		if (dbch->xferq.flag & FWXFERQ_RUNNING)
1425			return err;
1426	} else {
1427		if (dbch->xferq.flag & FWXFERQ_RUNNING) {
1428			err = EBUSY;
1429			return err;
1430		}
1431	}
1432	dbch->xferq.flag |= FWXFERQ_RUNNING;
1433	dbch->top = STAILQ_FIRST(&dbch->db_trq);
1434	for (i = 0, dbch->bottom = dbch->top; i < (dbch->ndb - 1); i++) {
1435		dbch->bottom = STAILQ_NEXT(dbch->bottom, link);
1436	}
1437	db_tr = dbch->top;
1438	for (idb = 0; idb < dbch->ndb; idb++) {
1439		fwohci_add_rx_buf(dbch, db_tr, idb, &sc->dummy_dma);
1440		if (STAILQ_NEXT(db_tr, link) == NULL)
1441			break;
1442		db = db_tr->db;
1443		ldesc = db_tr->dbcnt - 1;
1444		FWOHCI_DMA_WRITE(db[ldesc].db.desc.depend,
1445			STAILQ_NEXT(db_tr, link)->bus_addr | z);
1446		if (dbch->xferq.flag & FWXFERQ_EXTBUF) {
1447			if (((idb + 1) % dbch->xferq.bnpacket) == 0) {
1448				FWOHCI_DMA_SET(
1449					db[ldesc].db.desc.cmd,
1450					OHCI_INTERRUPT_ALWAYS);
1451				FWOHCI_DMA_CLEAR(
1452					db[ldesc].db.desc.depend,
1453					0xf);
1454			}
1455		}
1456		db_tr = STAILQ_NEXT(db_tr, link);
1457	}
1458	FWOHCI_DMA_CLEAR(
1459		dbch->bottom->db[db_tr->dbcnt - 1].db.desc.depend, 0xf);
1460	dbch->buf_offset = 0;
1461	fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREREAD);
1462	fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREWRITE);
1463	if (dbch->xferq.flag & FWXFERQ_STREAM) {
1464		return err;
1465	} else {
1466		OWRITE(sc, OHCI_DMACMD(off), dbch->top->bus_addr | z);
1467	}
1468	OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_RUN);
1469	return err;
1470}
1471
1472static int
1473fwohci_next_cycle(struct firewire_comm *fc, int cycle_now)
1474{
1475	int sec, cycle, cycle_match;
1476
1477	cycle = cycle_now & 0x1fff;
1478	sec = cycle_now >> 13;
1479#define CYCLE_MOD	0x10
1480#if 1
1481#define CYCLE_DELAY	8	/* min delay to start DMA */
1482#else
1483#define CYCLE_DELAY	7000	/* min delay to start DMA */
1484#endif
1485	cycle = cycle + CYCLE_DELAY;
1486	if (cycle >= 8000) {
1487		sec++;
1488		cycle -= 8000;
1489	}
1490	cycle = roundup2(cycle, CYCLE_MOD);
1491	if (cycle >= 8000) {
1492		sec++;
1493		if (cycle == 8000)
1494			cycle = 0;
1495		else
1496			cycle = CYCLE_MOD;
1497	}
1498	cycle_match = ((sec << 13) | cycle) & 0x7ffff;
1499
1500	return (cycle_match);
1501}
1502
1503static int
1504fwohci_itxbuf_enable(struct firewire_comm *fc, int dmach)
1505{
1506	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1507	int err = 0;
1508	unsigned short tag, ich;
1509	struct fwohci_dbch *dbch;
1510	int cycle_match, cycle_now, s, ldesc;
1511	uint32_t stat;
1512	struct fw_bulkxfer *first, *chunk, *prev;
1513	struct fw_xferq *it;
1514
1515	dbch = &sc->it[dmach];
1516	it = &dbch->xferq;
1517
1518	tag = (it->flag >> 6) & 3;
1519	ich = it->flag & 0x3f;
1520	if ((dbch->flags & FWOHCI_DBCH_INIT) == 0) {
1521		dbch->ndb = it->bnpacket * it->bnchunk;
1522		dbch->ndesc = 3;
1523		fwohci_db_init(sc, dbch);
1524		if ((dbch->flags & FWOHCI_DBCH_INIT) == 0)
1525			return ENOMEM;
1526
1527		err = fwohci_tx_enable(sc, dbch);
1528	}
1529	if (err)
1530		return err;
1531
1532	ldesc = dbch->ndesc - 1;
1533	s = splfw();
1534	FW_GLOCK(fc);
1535	prev = STAILQ_LAST(&it->stdma, fw_bulkxfer, link);
1536	while  ((chunk = STAILQ_FIRST(&it->stvalid)) != NULL) {
1537		struct fwohcidb *db;
1538
1539		fwdma_sync_multiseg(it->buf, chunk->poffset, it->bnpacket,
1540					BUS_DMASYNC_PREWRITE);
1541		fwohci_txbufdb(sc, dmach, chunk);
1542		if (prev != NULL) {
1543			db = ((struct fwohcidb_tr *)(prev->end))->db;
1544#if 0 /* XXX necessary? */
1545			FWOHCI_DMA_SET(db[ldesc].db.desc.cmd,
1546						OHCI_BRANCH_ALWAYS);
1547#endif
1548#if 0 /* if bulkxfer->npacket changes */
1549			db[ldesc].db.desc.depend = db[0].db.desc.depend =
1550				((struct fwohcidb_tr *)
1551				(chunk->start))->bus_addr | dbch->ndesc;
1552#else
1553			FWOHCI_DMA_SET(db[0].db.desc.depend, dbch->ndesc);
1554			FWOHCI_DMA_SET(db[ldesc].db.desc.depend, dbch->ndesc);
1555#endif
1556		}
1557		STAILQ_REMOVE_HEAD(&it->stvalid, link);
1558		STAILQ_INSERT_TAIL(&it->stdma, chunk, link);
1559		prev = chunk;
1560	}
1561	FW_GUNLOCK(fc);
1562	fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREWRITE);
1563	fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREREAD);
1564	splx(s);
1565	stat = OREAD(sc, OHCI_ITCTL(dmach));
1566	if (firewire_debug && (stat & OHCI_CNTL_CYCMATCH_S))
1567		printf("stat 0x%x\n", stat);
1568
1569	if (stat & (OHCI_CNTL_DMA_ACTIVE | OHCI_CNTL_CYCMATCH_S))
1570		return 0;
1571
1572#if 0
1573	OWRITE(sc, OHCI_ITCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
1574#endif
1575	OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach);
1576	OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach);
1577	OWRITE(sc, OHCI_IT_MASK, 1 << dmach);
1578	OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IT);
1579
1580	first = STAILQ_FIRST(&it->stdma);
1581	OWRITE(sc, OHCI_ITCMD(dmach),
1582		((struct fwohcidb_tr *)(first->start))->bus_addr | dbch->ndesc);
1583	if (firewire_debug > 1) {
1584		printf("fwohci_itxbuf_enable: kick 0x%08x\n", stat);
1585#if 1
1586		dump_dma(sc, ITX_CH + dmach);
1587#endif
1588	}
1589	if ((stat & OHCI_CNTL_DMA_RUN) == 0) {
1590#if 1
1591		/* Don't start until all chunks are buffered */
1592		if (STAILQ_FIRST(&it->stfree) != NULL)
1593			goto out;
1594#endif
1595#if 1
1596		/* Clear cycle match counter bits */
1597		OWRITE(sc, OHCI_ITCTLCLR(dmach), 0xffff0000);
1598
1599		/* 2bit second + 13bit cycle */
1600		cycle_now = (fc->cyctimer(fc) >> 12) & 0x7fff;
1601		cycle_match = fwohci_next_cycle(fc, cycle_now);
1602
1603		OWRITE(sc, OHCI_ITCTL(dmach),
1604				OHCI_CNTL_CYCMATCH_S | (cycle_match << 16)
1605				| OHCI_CNTL_DMA_RUN);
1606#else
1607		OWRITE(sc, OHCI_ITCTL(dmach), OHCI_CNTL_DMA_RUN);
1608#endif
1609		if (firewire_debug > 1) {
1610			printf("cycle_match: 0x%04x->0x%04x\n",
1611						cycle_now, cycle_match);
1612			dump_dma(sc, ITX_CH + dmach);
1613			dump_db(sc, ITX_CH + dmach);
1614		}
1615	} else if ((stat & OHCI_CNTL_CYCMATCH_S) == 0) {
1616		device_printf(sc->fc.dev,
1617			"IT DMA underrun (0x%08x)\n", stat);
1618		OWRITE(sc, OHCI_ITCTL(dmach), OHCI_CNTL_DMA_WAKE);
1619	}
1620out:
1621	return err;
1622}
1623
1624static int
1625fwohci_irx_enable(struct firewire_comm *fc, int dmach)
1626{
1627	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1628	int err = 0, s, ldesc;
1629	unsigned short tag, ich;
1630	uint32_t stat;
1631	struct fwohci_dbch *dbch;
1632	struct fwohcidb_tr *db_tr;
1633	struct fw_bulkxfer *first, *prev, *chunk;
1634	struct fw_xferq *ir;
1635
1636	dbch = &sc->ir[dmach];
1637	ir = &dbch->xferq;
1638
1639	if ((ir->flag & FWXFERQ_RUNNING) == 0) {
1640		tag = (ir->flag >> 6) & 3;
1641		ich = ir->flag & 0x3f;
1642		OWRITE(sc, OHCI_IRMATCH(dmach), tagbit[tag] | ich);
1643
1644		ir->queued = 0;
1645		dbch->ndb = ir->bnpacket * ir->bnchunk;
1646		dbch->ndesc = 2;
1647		fwohci_db_init(sc, dbch);
1648		if ((dbch->flags & FWOHCI_DBCH_INIT) == 0)
1649			return ENOMEM;
1650		err = fwohci_rx_enable(sc, dbch);
1651	}
1652	if (err)
1653		return err;
1654
1655	first = STAILQ_FIRST(&ir->stfree);
1656	if (first == NULL) {
1657		device_printf(fc->dev, "IR DMA no free chunk\n");
1658		return 0;
1659	}
1660
1661	ldesc = dbch->ndesc - 1;
1662	s = splfw();
1663	if ((ir->flag & FWXFERQ_HANDLER) == 0)
1664		FW_GLOCK(fc);
1665	prev = STAILQ_LAST(&ir->stdma, fw_bulkxfer, link);
1666	while  ((chunk = STAILQ_FIRST(&ir->stfree)) != NULL) {
1667		struct fwohcidb *db;
1668
1669#if 1 /* XXX for if_fwe */
1670		if (chunk->mbuf != NULL) {
1671			db_tr = (struct fwohcidb_tr *)(chunk->start);
1672			db_tr->dbcnt = 1;
1673			err = bus_dmamap_load_mbuf(dbch->dmat, db_tr->dma_map,
1674					chunk->mbuf, fwohci_execute_db2, db_tr,
1675					/* flags */0);
1676 			FWOHCI_DMA_SET(db_tr->db[1].db.desc.cmd,
1677				OHCI_UPDATE | OHCI_INPUT_LAST |
1678				OHCI_INTERRUPT_ALWAYS | OHCI_BRANCH_ALWAYS);
1679		}
1680#endif
1681		db = ((struct fwohcidb_tr *)(chunk->end))->db;
1682		FWOHCI_DMA_WRITE(db[ldesc].db.desc.res, 0);
1683		FWOHCI_DMA_CLEAR(db[ldesc].db.desc.depend, 0xf);
1684		if (prev != NULL) {
1685			db = ((struct fwohcidb_tr *)(prev->end))->db;
1686			FWOHCI_DMA_SET(db[ldesc].db.desc.depend, dbch->ndesc);
1687		}
1688		STAILQ_REMOVE_HEAD(&ir->stfree, link);
1689		STAILQ_INSERT_TAIL(&ir->stdma, chunk, link);
1690		prev = chunk;
1691	}
1692	if ((ir->flag & FWXFERQ_HANDLER) == 0)
1693		FW_GUNLOCK(fc);
1694	fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREWRITE);
1695	fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREREAD);
1696	splx(s);
1697	stat = OREAD(sc, OHCI_IRCTL(dmach));
1698	if (stat & OHCI_CNTL_DMA_ACTIVE)
1699		return 0;
1700	if (stat & OHCI_CNTL_DMA_RUN) {
1701		OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
1702		device_printf(sc->fc.dev, "IR DMA overrun (0x%08x)\n", stat);
1703	}
1704
1705	if (firewire_debug)
1706		printf("start IR DMA 0x%x\n", stat);
1707	OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach);
1708	OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach);
1709	OWRITE(sc, OHCI_IR_MASK, 1 << dmach);
1710	OWRITE(sc, OHCI_IRCTLCLR(dmach), 0xf0000000);
1711	OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_ISOHDR);
1712	OWRITE(sc, OHCI_IRCMD(dmach),
1713		((struct fwohcidb_tr *)(first->start))->bus_addr
1714							| dbch->ndesc);
1715	OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_DMA_RUN);
1716	OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IR);
1717#if 0
1718	dump_db(sc, IRX_CH + dmach);
1719#endif
1720	return err;
1721}
1722
1723int
1724fwohci_stop(struct fwohci_softc *sc, device_t dev)
1725{
1726	u_int i;
1727
1728	fwohci_set_intr(&sc->fc, 0);
1729
1730/* Now stopping all DMA channel */
1731	OWRITE(sc, OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN);
1732	OWRITE(sc, OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN);
1733	OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN);
1734	OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
1735
1736	for (i = 0; i < sc->fc.nisodma; i++) {
1737		OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN);
1738		OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN);
1739	}
1740
1741#if 0 /* Let dcons(4) be accessed */
1742/* Stop interrupt */
1743	OWRITE(sc, FWOHCI_INTMASKCLR,
1744			OHCI_INT_EN | OHCI_INT_ERR | OHCI_INT_PHY_SID
1745			| OHCI_INT_PHY_INT
1746			| OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS
1747			| OHCI_INT_DMA_PRRQ | OHCI_INT_DMA_PRRS
1748			| OHCI_INT_DMA_ARRQ | OHCI_INT_DMA_ARRS
1749			| OHCI_INT_PHY_BUS_R);
1750
1751/* FLUSH FIFO and reset Transmitter/Receiver */
1752	OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_RESET);
1753#endif
1754
1755/* XXX Link down?  Bus reset? */
1756	return 0;
1757}
1758
1759int
1760fwohci_resume(struct fwohci_softc *sc, device_t dev)
1761{
1762	int i;
1763	struct fw_xferq *ir;
1764	struct fw_bulkxfer *chunk;
1765
1766	fwohci_reset(sc, dev);
1767	/* XXX resume isochronous receive automatically. (how about TX?) */
1768	for (i = 0; i < sc->fc.nisodma; i++) {
1769		ir = &sc->ir[i].xferq;
1770		if ((ir->flag & FWXFERQ_RUNNING) != 0) {
1771			device_printf(sc->fc.dev,
1772				"resume iso receive ch: %d\n", i);
1773			ir->flag &= ~FWXFERQ_RUNNING;
1774			/* requeue stdma to stfree */
1775			while ((chunk = STAILQ_FIRST(&ir->stdma)) != NULL) {
1776				STAILQ_REMOVE_HEAD(&ir->stdma, link);
1777				STAILQ_INSERT_TAIL(&ir->stfree, chunk, link);
1778			}
1779			sc->fc.irx_enable(&sc->fc, i);
1780		}
1781	}
1782
1783	bus_generic_resume(dev);
1784	sc->fc.ibr(&sc->fc);
1785	return 0;
1786}
1787
1788#ifdef OHCI_DEBUG
1789static void
1790fwohci_dump_intr(struct fwohci_softc *sc, uint32_t stat)
1791{
1792	if (stat & OREAD(sc, FWOHCI_INTMASK))
1793		device_printf(fc->dev, "INTERRUPT < %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s> 0x%08x, 0x%08x\n",
1794			stat & OHCI_INT_EN ? "DMA_EN ":"",
1795			stat & OHCI_INT_PHY_REG ? "PHY_REG ":"",
1796			stat & OHCI_INT_CYC_LONG ? "CYC_LONG ":"",
1797			stat & OHCI_INT_ERR ? "INT_ERR ":"",
1798			stat & OHCI_INT_CYC_ERR ? "CYC_ERR ":"",
1799			stat & OHCI_INT_CYC_LOST ? "CYC_LOST ":"",
1800			stat & OHCI_INT_CYC_64SECOND ? "CYC_64SECOND ":"",
1801			stat & OHCI_INT_CYC_START ? "CYC_START ":"",
1802			stat & OHCI_INT_PHY_INT ? "PHY_INT ":"",
1803			stat & OHCI_INT_PHY_BUS_R ? "BUS_RESET ":"",
1804			stat & OHCI_INT_PHY_SID ? "SID ":"",
1805			stat & OHCI_INT_LR_ERR ? "DMA_LR_ERR ":"",
1806			stat & OHCI_INT_PW_ERR ? "DMA_PW_ERR ":"",
1807			stat & OHCI_INT_DMA_IR ? "DMA_IR ":"",
1808			stat & OHCI_INT_DMA_IT  ? "DMA_IT " :"",
1809			stat & OHCI_INT_DMA_PRRS  ? "DMA_PRRS " :"",
1810			stat & OHCI_INT_DMA_PRRQ  ? "DMA_PRRQ " :"",
1811			stat & OHCI_INT_DMA_ARRS  ? "DMA_ARRS " :"",
1812			stat & OHCI_INT_DMA_ARRQ  ? "DMA_ARRQ " :"",
1813			stat & OHCI_INT_DMA_ATRS  ? "DMA_ATRS " :"",
1814			stat & OHCI_INT_DMA_ATRQ  ? "DMA_ATRQ " :"",
1815			stat, OREAD(sc, FWOHCI_INTMASK)
1816		);
1817}
1818#endif
1819
1820static void
1821fwohci_intr_core(struct fwohci_softc *sc, uint32_t stat, int count)
1822{
1823	struct firewire_comm *fc = (struct firewire_comm *)sc;
1824	uintmax_t prequpper;
1825	uint32_t node_id, plen;
1826
1827	FW_GLOCK_ASSERT(fc);
1828	if ((stat & OHCI_INT_PHY_BUS_R) && (fc->status != FWBUSRESET)) {
1829		fc->status = FWBUSRESET;
1830		/* Disable bus reset interrupt until sid recv. */
1831		OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_PHY_BUS_R);
1832
1833		device_printf(fc->dev, "%s: BUS reset\n", __func__);
1834		OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST);
1835		OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCSRC);
1836
1837		OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN);
1838		sc->atrq.xferq.flag &= ~FWXFERQ_RUNNING;
1839		OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
1840		sc->atrs.xferq.flag &= ~FWXFERQ_RUNNING;
1841
1842		if (!kdb_active)
1843			taskqueue_enqueue(sc->fc.taskqueue, &sc->fwohci_task_busreset);
1844	}
1845	if (stat & OHCI_INT_PHY_SID) {
1846		/* Enable bus reset interrupt */
1847		OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_BUS_R);
1848		OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_PHY_BUS_R);
1849
1850		/* Allow async. request to us */
1851		OWRITE(sc, OHCI_AREQHI, 1 << 31);
1852		if (firewire_phydma_enable) {
1853			/* allow from all nodes */
1854			OWRITE(sc, OHCI_PREQHI, 0x7fffffff);
1855			OWRITE(sc, OHCI_PREQLO, 0xffffffff);
1856			prequpper = ((uintmax_t)Maxmem << PAGE_SHIFT) >> 16;
1857			if (prequpper > OHCI_PREQUPPER_MAX) {
1858				device_printf(fc->dev,
1859				    "Physical memory size of 0x%jx exceeds "
1860				    "fire wire address space.  Limiting dma "
1861				    "to memory below 0x%jx\n",
1862				    (uintmax_t)Maxmem << PAGE_SHIFT,
1863				    (uintmax_t)OHCI_PREQUPPER_MAX << 16);
1864				prequpper = OHCI_PREQUPPER_MAX;
1865			}
1866			OWRITE(sc, OHCI_PREQUPPER, prequpper & 0xffffffff);
1867		}
1868		/* Set ATRetries register */
1869		OWRITE(sc, OHCI_ATRETRY, 1<<(13 + 16) | 0xfff);
1870
1871		/*
1872		 * Checking whether the node is root or not. If root, turn on
1873		 * cycle master.
1874		 */
1875		node_id = OREAD(sc, FWOHCI_NODEID);
1876		plen = OREAD(sc, OHCI_SID_CNT);
1877
1878		fc->nodeid = node_id & 0x3f;
1879		device_printf(fc->dev, "%s: node_id=0x%08x, SelfID Count=%d, ",
1880				__func__, fc->nodeid, (plen >> 16) & 0xff);
1881		if (!(node_id & OHCI_NODE_VALID)) {
1882			device_printf(fc->dev, "%s: Bus reset failure\n",
1883				__func__);
1884			goto sidout;
1885		}
1886
1887		/* cycle timer */
1888		sc->cycle_lost = 0;
1889		OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_CYC_LOST);
1890		if ((node_id & OHCI_NODE_ROOT) && !nocyclemaster) {
1891			printf("CYCLEMASTER mode\n");
1892			OWRITE(sc, OHCI_LNKCTL,
1893				OHCI_CNTL_CYCMTR | OHCI_CNTL_CYCTIMER);
1894		} else {
1895			printf("non CYCLEMASTER mode\n");
1896			OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCMTR);
1897			OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_CYCTIMER);
1898		}
1899
1900		fc->status = FWBUSINIT;
1901
1902		if (!kdb_active)
1903			taskqueue_enqueue(sc->fc.taskqueue, &sc->fwohci_task_sid);
1904	}
1905sidout:
1906	if ((stat & ~(OHCI_INT_PHY_BUS_R | OHCI_INT_PHY_SID)) && (!kdb_active))
1907		taskqueue_enqueue(sc->fc.taskqueue, &sc->fwohci_task_dma);
1908}
1909
1910static void
1911fwohci_intr_dma(struct fwohci_softc *sc, uint32_t stat, int count)
1912{
1913	uint32_t irstat, itstat;
1914	u_int i;
1915	struct firewire_comm *fc = (struct firewire_comm *)sc;
1916
1917	if (stat & OHCI_INT_DMA_IR) {
1918		irstat = atomic_readandclear_int(&sc->irstat);
1919		for (i = 0; i < fc->nisodma; i++) {
1920			struct fwohci_dbch *dbch;
1921
1922			if ((irstat & (1 << i)) != 0) {
1923				dbch = &sc->ir[i];
1924				if ((dbch->xferq.flag & FWXFERQ_OPEN) == 0) {
1925					device_printf(sc->fc.dev,
1926						"dma(%d) not active\n", i);
1927					continue;
1928				}
1929				fwohci_rbuf_update(sc, i);
1930			}
1931		}
1932	}
1933	if (stat & OHCI_INT_DMA_IT) {
1934		itstat = atomic_readandclear_int(&sc->itstat);
1935		for (i = 0; i < fc->nisodma; i++) {
1936			if ((itstat & (1 << i)) != 0) {
1937				fwohci_tbuf_update(sc, i);
1938			}
1939		}
1940	}
1941	if (stat & OHCI_INT_DMA_PRRS) {
1942#if 0
1943		dump_dma(sc, ARRS_CH);
1944		dump_db(sc, ARRS_CH);
1945#endif
1946		fwohci_arcv(sc, &sc->arrs, count);
1947	}
1948	if (stat & OHCI_INT_DMA_PRRQ) {
1949#if 0
1950		dump_dma(sc, ARRQ_CH);
1951		dump_db(sc, ARRQ_CH);
1952#endif
1953		fwohci_arcv(sc, &sc->arrq, count);
1954	}
1955	if (stat & OHCI_INT_CYC_LOST) {
1956		if (sc->cycle_lost >= 0)
1957			sc->cycle_lost++;
1958		if (sc->cycle_lost > 10) {
1959			sc->cycle_lost = -1;
1960#if 0
1961			OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCTIMER);
1962#endif
1963			OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST);
1964			device_printf(fc->dev, "too many cycles lost, "
1965			 "no cycle master present?\n");
1966		}
1967	}
1968	if (stat & OHCI_INT_DMA_ATRQ) {
1969		fwohci_txd(sc, &(sc->atrq));
1970	}
1971	if (stat & OHCI_INT_DMA_ATRS) {
1972		fwohci_txd(sc, &(sc->atrs));
1973	}
1974	if (stat & OHCI_INT_PW_ERR) {
1975		device_printf(fc->dev, "posted write error\n");
1976	}
1977	if (stat & OHCI_INT_ERR) {
1978		device_printf(fc->dev, "unrecoverable error\n");
1979	}
1980	if (stat & OHCI_INT_PHY_INT) {
1981		device_printf(fc->dev, "phy int\n");
1982	}
1983}
1984
1985static void
1986fwohci_task_busreset(void *arg, int pending)
1987{
1988	struct fwohci_softc *sc = (struct fwohci_softc *)arg;
1989
1990	FW_GLOCK(&sc->fc);
1991	fw_busreset(&sc->fc, FWBUSRESET);
1992	OWRITE(sc, OHCI_CROMHDR, ntohl(sc->fc.config_rom[0]));
1993	OWRITE(sc, OHCI_BUS_OPT, ntohl(sc->fc.config_rom[2]));
1994	FW_GUNLOCK(&sc->fc);
1995}
1996
1997static void
1998fwohci_task_sid(void *arg, int pending)
1999{
2000	struct fwohci_softc *sc = (struct fwohci_softc *)arg;
2001	struct firewire_comm *fc = &sc->fc;
2002	uint32_t *buf;
2003	int i, plen;
2004
2005
2006	/*
2007	 * We really should have locking
2008	 * here.  Not sure why it's not
2009	 */
2010	plen = OREAD(sc, OHCI_SID_CNT);
2011
2012	if (plen & OHCI_SID_ERR) {
2013		device_printf(fc->dev, "SID Error\n");
2014		return;
2015	}
2016	plen &= OHCI_SID_CNT_MASK;
2017	if (plen < 4 || plen > OHCI_SIDSIZE) {
2018		device_printf(fc->dev, "invalid SID len = %d\n", plen);
2019		return;
2020	}
2021	plen -= 4; /* chop control info */
2022	buf = (uint32_t *)malloc(OHCI_SIDSIZE, M_FW, M_NOWAIT);
2023	if (buf == NULL) {
2024		device_printf(fc->dev, "malloc failed\n");
2025		return;
2026	}
2027	for (i = 0; i < plen / 4; i++)
2028		buf[i] = FWOHCI_DMA_READ(sc->sid_buf[i + 1]);
2029
2030	/* pending all pre-bus_reset packets */
2031	fwohci_txd(sc, &sc->atrq);
2032	fwohci_txd(sc, &sc->atrs);
2033	fwohci_arcv(sc, &sc->arrs, -1);
2034	fwohci_arcv(sc, &sc->arrq, -1);
2035	fw_drain_txq(fc);
2036	fw_sidrcv(fc, buf, plen);
2037	free(buf, M_FW);
2038}
2039
2040static void
2041fwohci_task_dma(void *arg, int pending)
2042{
2043	struct fwohci_softc *sc = (struct fwohci_softc *)arg;
2044	uint32_t stat;
2045
2046again:
2047	stat = atomic_readandclear_int(&sc->intstat);
2048	if (stat)
2049		fwohci_intr_dma(sc, stat, -1);
2050	else
2051		return;
2052	goto again;
2053}
2054
2055static int
2056fwohci_check_stat(struct fwohci_softc *sc)
2057{
2058	uint32_t stat, irstat, itstat;
2059
2060	FW_GLOCK_ASSERT(&sc->fc);
2061	stat = OREAD(sc, FWOHCI_INTSTAT);
2062	if (stat == 0xffffffff) {
2063		if (!bus_child_present(sc->fc.dev))
2064			return (FILTER_HANDLED);
2065		device_printf(sc->fc.dev, "device physically ejected?\n");
2066		return (FILTER_STRAY);
2067	}
2068	if (stat)
2069		OWRITE(sc, FWOHCI_INTSTATCLR, stat & ~OHCI_INT_PHY_BUS_R);
2070
2071	stat &= sc->intmask;
2072	if (stat == 0)
2073		return (FILTER_STRAY);
2074
2075	atomic_set_int(&sc->intstat, stat);
2076	if (stat & OHCI_INT_DMA_IR) {
2077		irstat = OREAD(sc, OHCI_IR_STAT);
2078		OWRITE(sc, OHCI_IR_STATCLR, irstat);
2079		atomic_set_int(&sc->irstat, irstat);
2080	}
2081	if (stat & OHCI_INT_DMA_IT) {
2082		itstat = OREAD(sc, OHCI_IT_STAT);
2083		OWRITE(sc, OHCI_IT_STATCLR, itstat);
2084		atomic_set_int(&sc->itstat, itstat);
2085	}
2086
2087	fwohci_intr_core(sc, stat, -1);
2088	return (FILTER_HANDLED);
2089}
2090
2091void
2092fwohci_intr(void *arg)
2093{
2094	struct fwohci_softc *sc = (struct fwohci_softc *)arg;
2095
2096	FW_GLOCK(&sc->fc);
2097	fwohci_check_stat(sc);
2098	FW_GUNLOCK(&sc->fc);
2099}
2100
2101void
2102fwohci_poll(struct firewire_comm *fc, int quick, int count)
2103{
2104	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
2105
2106	FW_GLOCK(fc);
2107	fwohci_check_stat(sc);
2108	FW_GUNLOCK(fc);
2109}
2110
2111static void
2112fwohci_set_intr(struct firewire_comm *fc, int enable)
2113{
2114	struct fwohci_softc *sc;
2115
2116	sc = (struct fwohci_softc *)fc;
2117	if (firewire_debug)
2118		device_printf(sc->fc.dev, "fwohci_set_intr: %d\n", enable);
2119	if (enable) {
2120		sc->intmask |= OHCI_INT_EN;
2121		OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_EN);
2122	} else {
2123		sc->intmask &= ~OHCI_INT_EN;
2124		OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_EN);
2125	}
2126}
2127
2128static void
2129fwohci_tbuf_update(struct fwohci_softc *sc, int dmach)
2130{
2131	struct firewire_comm *fc = &sc->fc;
2132	struct fwohcidb *db;
2133	struct fw_bulkxfer *chunk;
2134	struct fw_xferq *it;
2135	uint32_t stat, count;
2136	int s, w=0, ldesc;
2137
2138	it = fc->it[dmach];
2139	ldesc = sc->it[dmach].ndesc - 1;
2140	s = splfw(); /* unnecessary ? */
2141	FW_GLOCK(fc);
2142	fwdma_sync_multiseg_all(sc->it[dmach].am, BUS_DMASYNC_POSTREAD);
2143	if (firewire_debug)
2144		dump_db(sc, ITX_CH + dmach);
2145	while ((chunk = STAILQ_FIRST(&it->stdma)) != NULL) {
2146		db = ((struct fwohcidb_tr *)(chunk->end))->db;
2147		stat = FWOHCI_DMA_READ(db[ldesc].db.desc.res)
2148				>> OHCI_STATUS_SHIFT;
2149		db = ((struct fwohcidb_tr *)(chunk->start))->db;
2150		/* timestamp */
2151		count = FWOHCI_DMA_READ(db[ldesc].db.desc.res)
2152				& OHCI_COUNT_MASK;
2153		if (stat == 0)
2154			break;
2155		STAILQ_REMOVE_HEAD(&it->stdma, link);
2156		switch (stat & FWOHCIEV_MASK) {
2157		case FWOHCIEV_ACKCOMPL:
2158#if 0
2159			device_printf(fc->dev, "0x%08x\n", count);
2160#endif
2161			break;
2162		default:
2163			device_printf(fc->dev,
2164				"Isochronous transmit err %02x(%s)\n",
2165					stat, fwohcicode[stat & 0x1f]);
2166		}
2167		STAILQ_INSERT_TAIL(&it->stfree, chunk, link);
2168		w++;
2169	}
2170	FW_GUNLOCK(fc);
2171	splx(s);
2172	if (w)
2173		wakeup(it);
2174}
2175
2176static void
2177fwohci_rbuf_update(struct fwohci_softc *sc, int dmach)
2178{
2179	struct firewire_comm *fc = &sc->fc;
2180	struct fwohcidb_tr *db_tr;
2181	struct fw_bulkxfer *chunk;
2182	struct fw_xferq *ir;
2183	uint32_t stat;
2184	int w = 0, ldesc;
2185
2186	ir = fc->ir[dmach];
2187	ldesc = sc->ir[dmach].ndesc - 1;
2188
2189#if 0
2190	dump_db(sc, dmach);
2191#endif
2192	if ((ir->flag & FWXFERQ_HANDLER) == 0)
2193		FW_GLOCK(fc);
2194	fwdma_sync_multiseg_all(sc->ir[dmach].am, BUS_DMASYNC_POSTREAD);
2195	while ((chunk = STAILQ_FIRST(&ir->stdma)) != NULL) {
2196		db_tr = (struct fwohcidb_tr *)chunk->end;
2197		stat = FWOHCI_DMA_READ(db_tr->db[ldesc].db.desc.res)
2198				>> OHCI_STATUS_SHIFT;
2199		if (stat == 0)
2200			break;
2201
2202		if (chunk->mbuf != NULL) {
2203			bus_dmamap_sync(sc->ir[dmach].dmat, db_tr->dma_map,
2204						BUS_DMASYNC_POSTREAD);
2205			bus_dmamap_unload(sc->ir[dmach].dmat, db_tr->dma_map);
2206		} else if (ir->buf != NULL) {
2207			fwdma_sync_multiseg(ir->buf, chunk->poffset,
2208				ir->bnpacket, BUS_DMASYNC_POSTREAD);
2209		} else {
2210			/* XXX */
2211			printf("fwohci_rbuf_update: this shouldn't happened\n");
2212		}
2213
2214		STAILQ_REMOVE_HEAD(&ir->stdma, link);
2215		STAILQ_INSERT_TAIL(&ir->stvalid, chunk, link);
2216		switch (stat & FWOHCIEV_MASK) {
2217		case FWOHCIEV_ACKCOMPL:
2218			chunk->resp = 0;
2219			break;
2220		default:
2221			chunk->resp = EINVAL;
2222			device_printf(fc->dev,
2223				"Isochronous receive err %02x(%s)\n",
2224					stat, fwohcicode[stat & 0x1f]);
2225		}
2226		w++;
2227	}
2228	if ((ir->flag & FWXFERQ_HANDLER) == 0)
2229		FW_GUNLOCK(fc);
2230	if (w == 0)
2231		return;
2232
2233	if (ir->flag & FWXFERQ_HANDLER)
2234		ir->hand(ir);
2235	else
2236		wakeup(ir);
2237}
2238
2239void
2240dump_dma(struct fwohci_softc *sc, uint32_t ch)
2241{
2242	uint32_t off, cntl, stat, cmd, match;
2243
2244	if (ch == 0) {
2245		off = OHCI_ATQOFF;
2246	} else if (ch == 1) {
2247		off = OHCI_ATSOFF;
2248	} else if (ch == 2) {
2249		off = OHCI_ARQOFF;
2250	} else if (ch == 3) {
2251		off = OHCI_ARSOFF;
2252	} else if (ch < IRX_CH) {
2253		off = OHCI_ITCTL(ch - ITX_CH);
2254	} else {
2255		off = OHCI_IRCTL(ch - IRX_CH);
2256	}
2257	cntl = stat = OREAD(sc, off);
2258	cmd = OREAD(sc, off + 0xc);
2259	match = OREAD(sc, off + 0x10);
2260
2261	device_printf(sc->fc.dev, "ch %1x cntl:0x%08x cmd:0x%08x match:0x%08x\n",
2262		ch,
2263		cntl,
2264		cmd,
2265		match);
2266	stat &= 0xffff;
2267	if (stat) {
2268		device_printf(sc->fc.dev, "dma %d ch:%s%s%s%s%s%s %s(%x)\n",
2269			ch,
2270			stat & OHCI_CNTL_DMA_RUN ? "RUN," : "",
2271			stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "",
2272			stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "",
2273			stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "",
2274			stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "",
2275			stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "",
2276			fwohcicode[stat & 0x1f],
2277			stat & 0x1f
2278		);
2279	} else {
2280		device_printf(sc->fc.dev, "dma %d ch: Nostat\n", ch);
2281	}
2282}
2283
2284void
2285dump_db(struct fwohci_softc *sc, uint32_t ch)
2286{
2287	struct fwohci_dbch *dbch;
2288	struct fwohcidb_tr *cp = NULL, *pp, *np = NULL;
2289	struct fwohcidb *curr = NULL, *prev, *next = NULL;
2290	int idb, jdb;
2291	uint32_t cmd, off;
2292
2293	if (ch == 0) {
2294		off = OHCI_ATQOFF;
2295		dbch = &sc->atrq;
2296	} else if (ch == 1) {
2297		off = OHCI_ATSOFF;
2298		dbch = &sc->atrs;
2299	} else if (ch == 2) {
2300		off = OHCI_ARQOFF;
2301		dbch = &sc->arrq;
2302	} else if (ch == 3) {
2303		off = OHCI_ARSOFF;
2304		dbch = &sc->arrs;
2305	} else if (ch < IRX_CH) {
2306		off = OHCI_ITCTL(ch - ITX_CH);
2307		dbch = &sc->it[ch - ITX_CH];
2308	} else {
2309		off = OHCI_IRCTL(ch - IRX_CH);
2310		dbch = &sc->ir[ch - IRX_CH];
2311	}
2312	cmd = OREAD(sc, off + 0xc);
2313
2314	if (dbch->ndb == 0) {
2315		device_printf(sc->fc.dev, "No DB is attached ch=%d\n", ch);
2316		return;
2317	}
2318	pp = dbch->top;
2319	prev = pp->db;
2320	for (idb = 0; idb < dbch->ndb; idb++) {
2321		cp = STAILQ_NEXT(pp, link);
2322		if (cp == NULL) {
2323			curr = NULL;
2324			goto outdb;
2325		}
2326		np = STAILQ_NEXT(cp, link);
2327		for (jdb = 0; jdb < dbch->ndesc; jdb++) {
2328			if ((cmd  & 0xfffffff0) == cp->bus_addr) {
2329				curr = cp->db;
2330				if (np != NULL) {
2331					next = np->db;
2332				} else {
2333					next = NULL;
2334				}
2335				goto outdb;
2336			}
2337		}
2338		pp = STAILQ_NEXT(pp, link);
2339		if (pp == NULL) {
2340			curr = NULL;
2341			goto outdb;
2342		}
2343		prev = pp->db;
2344	}
2345outdb:
2346	if (curr != NULL) {
2347#if 0
2348		printf("Prev DB %d\n", ch);
2349		print_db(pp, prev, ch, dbch->ndesc);
2350#endif
2351		printf("Current DB %d\n", ch);
2352		print_db(cp, curr, ch, dbch->ndesc);
2353#if 0
2354		printf("Next DB %d\n", ch);
2355		print_db(np, next, ch, dbch->ndesc);
2356#endif
2357	} else {
2358		printf("dbdump err ch = %d cmd = 0x%08x\n", ch, cmd);
2359	}
2360	return;
2361}
2362
2363void
2364print_db(struct fwohcidb_tr *db_tr, struct fwohcidb *db,
2365		uint32_t ch, uint32_t max)
2366{
2367	fwohcireg_t stat;
2368	int i, key;
2369	uint32_t cmd, res;
2370
2371	if (db == NULL) {
2372		printf("No Descriptor is found\n");
2373		return;
2374	}
2375
2376	printf("ch = %d\n%8s %s %s %s %s %4s %8s %8s %4s:%4s\n",
2377		ch,
2378		"Current",
2379		"OP  ",
2380		"KEY",
2381		"INT",
2382		"BR ",
2383		"len",
2384		"Addr",
2385		"Depend",
2386		"Stat",
2387		"Cnt");
2388	for (i = 0; i <= max; i++) {
2389		cmd = FWOHCI_DMA_READ(db[i].db.desc.cmd);
2390		res = FWOHCI_DMA_READ(db[i].db.desc.res);
2391		key = cmd & OHCI_KEY_MASK;
2392		stat = res >> OHCI_STATUS_SHIFT;
2393		printf("%08jx %s %s %s %s %5d %08x %08x %04x:%04x",
2394				(uintmax_t)db_tr->bus_addr,
2395				dbcode[(cmd >> 28) & 0xf],
2396				dbkey[(cmd >> 24) & 0x7],
2397				dbcond[(cmd >> 20) & 0x3],
2398				dbcond[(cmd >> 18) & 0x3],
2399				cmd & OHCI_COUNT_MASK,
2400				FWOHCI_DMA_READ(db[i].db.desc.addr),
2401				FWOHCI_DMA_READ(db[i].db.desc.depend),
2402				stat,
2403				res & OHCI_COUNT_MASK);
2404		if (stat & 0xff00) {
2405			printf(" %s%s%s%s%s%s %s(%x)\n",
2406				stat & OHCI_CNTL_DMA_RUN ? "RUN," : "",
2407				stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "",
2408				stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "",
2409				stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "",
2410				stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "",
2411				stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "",
2412				fwohcicode[stat & 0x1f],
2413				stat & 0x1f
2414			);
2415		} else {
2416			printf(" Nostat\n");
2417		}
2418		if (key == OHCI_KEY_ST2) {
2419			printf("0x%08x 0x%08x 0x%08x 0x%08x\n",
2420				FWOHCI_DMA_READ(db[i + 1].db.immed[0]),
2421				FWOHCI_DMA_READ(db[i + 1].db.immed[1]),
2422				FWOHCI_DMA_READ(db[i + 1].db.immed[2]),
2423				FWOHCI_DMA_READ(db[i + 1].db.immed[3]));
2424		}
2425		if (key == OHCI_KEY_DEVICE) {
2426			return;
2427		}
2428		if ((cmd & OHCI_BRANCH_MASK)
2429				== OHCI_BRANCH_ALWAYS) {
2430			return;
2431		}
2432		if ((cmd & OHCI_CMD_MASK)
2433				== OHCI_OUTPUT_LAST) {
2434			return;
2435		}
2436		if ((cmd & OHCI_CMD_MASK)
2437				== OHCI_INPUT_LAST) {
2438			return;
2439		}
2440		if (key == OHCI_KEY_ST2) {
2441			i++;
2442		}
2443	}
2444	return;
2445}
2446
2447void
2448fwohci_ibr(struct firewire_comm *fc)
2449{
2450	struct fwohci_softc *sc;
2451	uint32_t fun;
2452
2453	device_printf(fc->dev, "Initiate bus reset\n");
2454	sc = (struct fwohci_softc *)fc;
2455
2456	FW_GLOCK(fc);
2457	/*
2458	 * Make sure our cached values from the config rom are
2459	 * initialised.
2460	 */
2461	OWRITE(sc, OHCI_CROMHDR, ntohl(sc->fc.config_rom[0]));
2462	OWRITE(sc, OHCI_BUS_OPT, ntohl(sc->fc.config_rom[2]));
2463
2464	/*
2465	 * Set root hold-off bit so that non cyclemaster capable node
2466	 * shouldn't became the root node.
2467	 */
2468#if 1
2469	fun = fwphy_rddata(sc, FW_PHY_IBR_REG);
2470	fun |= FW_PHY_IBR | FW_PHY_RHB;
2471	fun = fwphy_wrdata(sc, FW_PHY_IBR_REG, fun);
2472#else	/* Short bus reset */
2473	fun = fwphy_rddata(sc, FW_PHY_ISBR_REG);
2474	fun |= FW_PHY_ISBR | FW_PHY_RHB;
2475	fun = fwphy_wrdata(sc, FW_PHY_ISBR_REG, fun);
2476#endif
2477	FW_GUNLOCK(fc);
2478}
2479
2480void
2481fwohci_txbufdb(struct fwohci_softc *sc, int dmach, struct fw_bulkxfer *bulkxfer)
2482{
2483	struct fwohcidb_tr *db_tr, *fdb_tr;
2484	struct fwohci_dbch *dbch;
2485	struct fwohcidb *db;
2486	struct fw_pkt *fp;
2487	struct fwohci_txpkthdr *ohcifp;
2488	unsigned short chtag;
2489	int idb;
2490
2491	FW_GLOCK_ASSERT(&sc->fc);
2492
2493	dbch = &sc->it[dmach];
2494	chtag = sc->it[dmach].xferq.flag & 0xff;
2495
2496	db_tr = (struct fwohcidb_tr *)(bulkxfer->start);
2497	fdb_tr = (struct fwohcidb_tr *)(bulkxfer->end);
2498/*
2499device_printf(sc->fc.dev, "DB %08x %08x %08x\n", bulkxfer, db_tr->bus_addr, fdb_tr->bus_addr);
2500*/
2501	for (idb = 0; idb < dbch->xferq.bnpacket; idb++) {
2502		db = db_tr->db;
2503		fp = (struct fw_pkt *)db_tr->buf;
2504		ohcifp = (struct fwohci_txpkthdr *) db[1].db.immed;
2505		ohcifp->mode.ld[0] = fp->mode.ld[0];
2506		ohcifp->mode.common.spd = 0 & 0x7;
2507		ohcifp->mode.stream.len = fp->mode.stream.len;
2508		ohcifp->mode.stream.chtag = chtag;
2509		ohcifp->mode.stream.tcode = 0xa;
2510#if BYTE_ORDER == BIG_ENDIAN
2511		FWOHCI_DMA_WRITE(db[1].db.immed[0], db[1].db.immed[0]);
2512		FWOHCI_DMA_WRITE(db[1].db.immed[1], db[1].db.immed[1]);
2513#endif
2514
2515		FWOHCI_DMA_CLEAR(db[2].db.desc.cmd, OHCI_COUNT_MASK);
2516		FWOHCI_DMA_SET(db[2].db.desc.cmd, fp->mode.stream.len);
2517		FWOHCI_DMA_WRITE(db[2].db.desc.res, 0);
2518#if 0 /* if bulkxfer->npackets changes */
2519		db[2].db.desc.cmd = OHCI_OUTPUT_LAST
2520			| OHCI_UPDATE
2521			| OHCI_BRANCH_ALWAYS;
2522		db[0].db.desc.depend =
2523			= db[dbch->ndesc - 1].db.desc.depend
2524			= STAILQ_NEXT(db_tr, link)->bus_addr | dbch->ndesc;
2525#else
2526		FWOHCI_DMA_SET(db[0].db.desc.depend, dbch->ndesc);
2527		FWOHCI_DMA_SET(db[dbch->ndesc - 1].db.desc.depend, dbch->ndesc);
2528#endif
2529		bulkxfer->end = (caddr_t)db_tr;
2530		db_tr = STAILQ_NEXT(db_tr, link);
2531	}
2532	db = ((struct fwohcidb_tr *)bulkxfer->end)->db;
2533	FWOHCI_DMA_CLEAR(db[0].db.desc.depend, 0xf);
2534	FWOHCI_DMA_CLEAR(db[dbch->ndesc - 1].db.desc.depend, 0xf);
2535#if 0 /* if bulkxfer->npackets changes */
2536	db[dbch->ndesc - 1].db.desc.control |= OHCI_INTERRUPT_ALWAYS;
2537	/* OHCI 1.1 and above */
2538	db[0].db.desc.control |= OHCI_INTERRUPT_ALWAYS;
2539#endif
2540/*
2541	db_tr = (struct fwohcidb_tr *)bulkxfer->start;
2542	fdb_tr = (struct fwohcidb_tr *)bulkxfer->end;
2543device_printf(sc->fc.dev, "DB %08x %3d %08x %08x\n", bulkxfer, bulkxfer->npacket, db_tr->bus_addr, fdb_tr->bus_addr);
2544*/
2545	return;
2546}
2547
2548static int
2549fwohci_add_tx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr,
2550								int poffset)
2551{
2552	struct fwohcidb *db = db_tr->db;
2553	struct fw_xferq *it;
2554	int err = 0;
2555
2556	it = &dbch->xferq;
2557	if (it->buf == 0) {
2558		err = EINVAL;
2559		return err;
2560	}
2561	db_tr->buf = fwdma_v_addr(it->buf, poffset);
2562	db_tr->dbcnt = 3;
2563
2564	FWOHCI_DMA_WRITE(db[0].db.desc.cmd,
2565		OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | 8);
2566	FWOHCI_DMA_WRITE(db[0].db.desc.addr, 0);
2567	bzero((void *)&db[1].db.immed[0], sizeof(db[1].db.immed));
2568	FWOHCI_DMA_WRITE(db[2].db.desc.addr,
2569	fwdma_bus_addr(it->buf, poffset) + sizeof(uint32_t));
2570
2571	FWOHCI_DMA_WRITE(db[2].db.desc.cmd,
2572		OHCI_OUTPUT_LAST | OHCI_UPDATE | OHCI_BRANCH_ALWAYS);
2573#if 1
2574	FWOHCI_DMA_WRITE(db[0].db.desc.res, 0);
2575	FWOHCI_DMA_WRITE(db[2].db.desc.res, 0);
2576#endif
2577	return 0;
2578}
2579
2580int
2581fwohci_add_rx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr,
2582		int poffset, struct fwdma_alloc *dummy_dma)
2583{
2584	struct fwohcidb *db = db_tr->db;
2585	struct fw_xferq *ir;
2586	int i, ldesc;
2587	bus_addr_t dbuf[2];
2588	int dsiz[2];
2589
2590	ir = &dbch->xferq;
2591	if (ir->buf == NULL && (dbch->xferq.flag & FWXFERQ_EXTBUF) == 0) {
2592		if (db_tr->buf == NULL) {
2593			db_tr->buf = fwdma_malloc_size(dbch->dmat,
2594			    &db_tr->dma_map, ir->psize, &dbuf[0],
2595			    BUS_DMA_NOWAIT);
2596			if (db_tr->buf == NULL)
2597				return (ENOMEM);
2598		}
2599		db_tr->dbcnt = 1;
2600		dsiz[0] = ir->psize;
2601		bus_dmamap_sync(dbch->dmat, db_tr->dma_map,
2602			BUS_DMASYNC_PREREAD);
2603	} else {
2604		db_tr->dbcnt = 0;
2605		if (dummy_dma != NULL) {
2606			dsiz[db_tr->dbcnt] = sizeof(uint32_t);
2607			dbuf[db_tr->dbcnt++] = dummy_dma->bus_addr;
2608		}
2609		dsiz[db_tr->dbcnt] = ir->psize;
2610		if (ir->buf != NULL) {
2611			db_tr->buf = fwdma_v_addr(ir->buf, poffset);
2612			dbuf[db_tr->dbcnt] = fwdma_bus_addr(ir->buf, poffset);
2613		}
2614		db_tr->dbcnt++;
2615	}
2616	for (i = 0; i < db_tr->dbcnt; i++) {
2617		FWOHCI_DMA_WRITE(db[i].db.desc.addr, dbuf[i]);
2618		FWOHCI_DMA_WRITE(db[i].db.desc.cmd, OHCI_INPUT_MORE | dsiz[i]);
2619		if (ir->flag & FWXFERQ_STREAM) {
2620			FWOHCI_DMA_SET(db[i].db.desc.cmd, OHCI_UPDATE);
2621		}
2622		FWOHCI_DMA_WRITE(db[i].db.desc.res, dsiz[i]);
2623	}
2624	ldesc = db_tr->dbcnt - 1;
2625	if (ir->flag & FWXFERQ_STREAM) {
2626		FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, OHCI_INPUT_LAST);
2627	}
2628	FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, OHCI_BRANCH_ALWAYS);
2629	return 0;
2630}
2631
2632
2633static int
2634fwohci_arcv_swap(struct fw_pkt *fp, int len)
2635{
2636	struct fw_pkt *fp0;
2637	uint32_t ld0;
2638	int slen, hlen;
2639#if BYTE_ORDER == BIG_ENDIAN
2640	int i;
2641#endif
2642
2643	ld0 = FWOHCI_DMA_READ(fp->mode.ld[0]);
2644#if 0
2645	printf("ld0: x%08x\n", ld0);
2646#endif
2647	fp0 = (struct fw_pkt *)&ld0;
2648	/* determine length to swap */
2649	switch (fp0->mode.common.tcode) {
2650	case FWTCODE_RREQQ:
2651	case FWTCODE_WRES:
2652	case FWTCODE_WREQQ:
2653	case FWTCODE_RRESQ:
2654	case FWOHCITCODE_PHY:
2655		slen = 12;
2656		break;
2657	case FWTCODE_RREQB:
2658	case FWTCODE_WREQB:
2659	case FWTCODE_LREQ:
2660	case FWTCODE_RRESB:
2661	case FWTCODE_LRES:
2662		slen = 16;
2663		break;
2664	default:
2665		printf("Unknown tcode %d\n", fp0->mode.common.tcode);
2666		return (0);
2667	}
2668	hlen = tinfo[fp0->mode.common.tcode].hdr_len;
2669	if (hlen > len) {
2670		if (firewire_debug)
2671			printf("splitted header\n");
2672		return (-hlen);
2673	}
2674#if BYTE_ORDER == BIG_ENDIAN
2675	for (i = 0; i < slen/4; i++)
2676		fp->mode.ld[i] = FWOHCI_DMA_READ(fp->mode.ld[i]);
2677#endif
2678	return (hlen);
2679}
2680
2681static int
2682fwohci_get_plen(struct fwohci_softc *sc, struct fwohci_dbch *dbch, struct fw_pkt *fp)
2683{
2684	struct tcode_info *info;
2685	int r;
2686
2687	info = &tinfo[fp->mode.common.tcode];
2688	r = info->hdr_len + sizeof(uint32_t);
2689	if ((info->flag & FWTI_BLOCK_ASY) != 0)
2690		r += roundup2(fp->mode.wreqb.len, sizeof(uint32_t));
2691
2692	if (r == sizeof(uint32_t)) {
2693		/* XXX */
2694		device_printf(sc->fc.dev, "Unknown tcode %d\n",
2695						fp->mode.common.tcode);
2696		return (-1);
2697	}
2698
2699	if (r > dbch->xferq.psize) {
2700		device_printf(sc->fc.dev, "Invalid packet length %d\n", r);
2701		return (-1);
2702		/* panic ? */
2703	}
2704
2705	return r;
2706}
2707
2708static void
2709fwohci_arcv_free_buf(struct fwohci_softc *sc, struct fwohci_dbch *dbch,
2710    struct fwohcidb_tr *db_tr, uint32_t off, int wake)
2711{
2712	struct fwohcidb *db = &db_tr->db[0];
2713
2714	FWOHCI_DMA_CLEAR(db->db.desc.depend, 0xf);
2715	FWOHCI_DMA_WRITE(db->db.desc.res, dbch->xferq.psize);
2716	FWOHCI_DMA_SET(dbch->bottom->db[0].db.desc.depend, 1);
2717	fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREWRITE);
2718	dbch->bottom = db_tr;
2719
2720	if (wake)
2721		OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_WAKE);
2722}
2723
2724static void
2725fwohci_arcv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count)
2726{
2727	struct fwohcidb_tr *db_tr;
2728	struct iovec vec[2];
2729	struct fw_pkt pktbuf;
2730	int nvec;
2731	struct fw_pkt *fp;
2732	uint8_t *ld;
2733	uint32_t stat, off, status, event;
2734	u_int spd;
2735	int len, plen, hlen, pcnt, offset;
2736	int s;
2737	caddr_t buf;
2738	int resCount;
2739
2740	if (&sc->arrq == dbch) {
2741		off = OHCI_ARQOFF;
2742	} else if (&sc->arrs == dbch) {
2743		off = OHCI_ARSOFF;
2744	} else {
2745		return;
2746	}
2747
2748	s = splfw();
2749	db_tr = dbch->top;
2750	pcnt = 0;
2751	/* XXX we cannot handle a packet which lies in more than two buf */
2752	fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_POSTREAD);
2753	fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_POSTWRITE);
2754	status = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) >> OHCI_STATUS_SHIFT;
2755	resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) & OHCI_COUNT_MASK;
2756	while (status & OHCI_CNTL_DMA_ACTIVE) {
2757#if 0
2758
2759		if (off == OHCI_ARQOFF)
2760			printf("buf 0x%08x, status 0x%04x, resCount 0x%04x\n",
2761			    db_tr->bus_addr, status, resCount);
2762#endif
2763		len = dbch->xferq.psize - resCount;
2764		ld = (uint8_t *)db_tr->buf;
2765		if (dbch->pdb_tr == NULL) {
2766			len -= dbch->buf_offset;
2767			ld += dbch->buf_offset;
2768		}
2769		if (len > 0)
2770			bus_dmamap_sync(dbch->dmat, db_tr->dma_map,
2771					BUS_DMASYNC_POSTREAD);
2772		while (len > 0) {
2773			if (count >= 0 && count-- == 0)
2774				goto out;
2775			if (dbch->pdb_tr != NULL) {
2776				/* we have a fragment in previous buffer */
2777				int rlen;
2778
2779				offset = dbch->buf_offset;
2780				if (offset < 0)
2781					offset = - offset;
2782				buf = dbch->pdb_tr->buf + offset;
2783				rlen = dbch->xferq.psize - offset;
2784				if (firewire_debug)
2785					printf("rlen=%d, offset=%d\n",
2786						rlen, dbch->buf_offset);
2787				if (dbch->buf_offset < 0) {
2788					/* splitted in header, pull up */
2789					char *p;
2790
2791					p = (char *)&pktbuf;
2792					bcopy(buf, p, rlen);
2793					p += rlen;
2794					/* this must be too long but harmless */
2795					rlen = sizeof(pktbuf) - rlen;
2796					if (rlen < 0)
2797						printf("why rlen < 0\n");
2798					bcopy(db_tr->buf, p, rlen);
2799					ld += rlen;
2800					len -= rlen;
2801					hlen = fwohci_arcv_swap(&pktbuf, sizeof(pktbuf));
2802					if (hlen <= 0) {
2803						printf("hlen should be positive.");
2804						goto err;
2805					}
2806					offset = sizeof(pktbuf);
2807					vec[0].iov_base = (char *)&pktbuf;
2808					vec[0].iov_len = offset;
2809				} else {
2810					/* splitted in payload */
2811					offset = rlen;
2812					vec[0].iov_base = buf;
2813					vec[0].iov_len = rlen;
2814				}
2815				fp=(struct fw_pkt *)vec[0].iov_base;
2816				nvec = 1;
2817			} else {
2818				/* no fragment in previous buffer */
2819				fp=(struct fw_pkt *)ld;
2820				hlen = fwohci_arcv_swap(fp, len);
2821				if (hlen == 0)
2822					goto err;
2823				if (hlen < 0) {
2824					dbch->pdb_tr = db_tr;
2825					dbch->buf_offset = - dbch->buf_offset;
2826					/* sanity check */
2827					if (resCount != 0) {
2828						printf("resCount=%d hlen=%d\n",
2829						    resCount, hlen);
2830						    goto err;
2831					}
2832					goto out;
2833				}
2834				offset = 0;
2835				nvec = 0;
2836			}
2837			plen = fwohci_get_plen(sc, dbch, fp) - offset;
2838			if (plen < 0) {
2839				/* minimum header size + trailer
2840				= sizeof(fw_pkt) so this shouldn't happens */
2841				printf("plen(%d) is negative! offset=%d\n",
2842				    plen, offset);
2843				goto err;
2844			}
2845			if (plen > 0) {
2846				len -= plen;
2847				if (len < 0) {
2848					dbch->pdb_tr = db_tr;
2849					if (firewire_debug)
2850						printf("splitted payload\n");
2851					/* sanity check */
2852					if (resCount != 0) {
2853						printf("resCount=%d plen=%d"
2854						    " len=%d\n",
2855						    resCount, plen, len);
2856						goto err;
2857					}
2858					goto out;
2859				}
2860				vec[nvec].iov_base = ld;
2861				vec[nvec].iov_len = plen;
2862				nvec++;
2863				ld += plen;
2864			}
2865			dbch->buf_offset = ld - (uint8_t *)db_tr->buf;
2866			if (nvec == 0)
2867				printf("nvec == 0\n");
2868
2869/* DMA result-code will be written at the tail of packet */
2870			stat = FWOHCI_DMA_READ(*(uint32_t *)(ld - sizeof(struct fwohci_trailer)));
2871#if 0
2872			printf("plen: %d, stat %x\n",
2873			    plen ,stat);
2874#endif
2875			spd = (stat >> 21) & 0x3;
2876			event = (stat >> 16) & 0x1f;
2877			switch (event) {
2878			case FWOHCIEV_ACKPEND:
2879#if 0
2880				printf("fwohci_arcv: ack pending tcode=0x%x..\n", fp->mode.common.tcode);
2881#endif
2882				/* fall through */
2883			case FWOHCIEV_ACKCOMPL:
2884			{
2885				struct fw_rcv_buf rb;
2886
2887				if ((vec[nvec-1].iov_len -=
2888					sizeof(struct fwohci_trailer)) == 0)
2889					nvec--;
2890				rb.fc = &sc->fc;
2891				rb.vec = vec;
2892				rb.nvec = nvec;
2893				rb.spd = spd;
2894				fw_rcv(&rb);
2895				break;
2896			}
2897			case FWOHCIEV_BUSRST:
2898				if ((sc->fc.status != FWBUSRESET) &&
2899				    (sc->fc.status != FWBUSINIT))
2900					printf("got BUSRST packet!?\n");
2901				break;
2902			default:
2903				device_printf(sc->fc.dev,
2904				    "Async DMA Receive error err=%02x %s"
2905				    " plen=%d offset=%d len=%d status=0x%08x"
2906				    " tcode=0x%x, stat=0x%08x\n",
2907				    event, fwohcicode[event], plen,
2908				    dbch->buf_offset, len,
2909				    OREAD(sc, OHCI_DMACTL(off)),
2910				    fp->mode.common.tcode, stat);
2911#if 1 /* XXX */
2912				goto err;
2913#endif
2914				break;
2915			}
2916			pcnt++;
2917			if (dbch->pdb_tr != NULL) {
2918				fwohci_arcv_free_buf(sc, dbch, dbch->pdb_tr,
2919				    off, 1);
2920				dbch->pdb_tr = NULL;
2921			}
2922
2923		}
2924out:
2925		if (resCount == 0) {
2926			/* done on this buffer */
2927			if (dbch->pdb_tr == NULL) {
2928				fwohci_arcv_free_buf(sc, dbch, db_tr, off, 1);
2929				dbch->buf_offset = 0;
2930			} else
2931				if (dbch->pdb_tr != db_tr)
2932					printf("pdb_tr != db_tr\n");
2933			db_tr = STAILQ_NEXT(db_tr, link);
2934			status = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res)
2935						>> OHCI_STATUS_SHIFT;
2936			resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res)
2937						& OHCI_COUNT_MASK;
2938			/* XXX check buffer overrun */
2939			dbch->top = db_tr;
2940		} else {
2941			dbch->buf_offset = dbch->xferq.psize - resCount;
2942			break;
2943		}
2944		/* XXX make sure DMA is not dead */
2945	}
2946#if 0
2947	if (pcnt < 1)
2948		printf("fwohci_arcv: no packets\n");
2949#endif
2950	splx(s);
2951	return;
2952
2953err:
2954	device_printf(sc->fc.dev, "AR DMA status=%x, ",
2955					OREAD(sc, OHCI_DMACTL(off)));
2956	dbch->pdb_tr = NULL;
2957	/* skip until resCount != 0 */
2958	printf(" skip buffer");
2959	while (resCount == 0) {
2960		printf(" #");
2961		fwohci_arcv_free_buf(sc, dbch, db_tr, off, 0);
2962		db_tr = STAILQ_NEXT(db_tr, link);
2963		resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res)
2964						& OHCI_COUNT_MASK;
2965	}
2966	printf(" done\n");
2967	dbch->top = db_tr;
2968	dbch->buf_offset = dbch->xferq.psize - resCount;
2969	OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_WAKE);
2970	splx(s);
2971}
2972