xref: /freebsd/sys/dev/firewire/fwohci.c (revision 17c3d42c9e30f171c44ecfdc072d3e755a6c80d6)
13c60ba66SKatsushi Kobayashi /*
23c60ba66SKatsushi Kobayashi  * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa
33c60ba66SKatsushi Kobayashi  * All rights reserved.
43c60ba66SKatsushi Kobayashi  *
53c60ba66SKatsushi Kobayashi  * Redistribution and use in source and binary forms, with or without
63c60ba66SKatsushi Kobayashi  * modification, are permitted provided that the following conditions
73c60ba66SKatsushi Kobayashi  * are met:
83c60ba66SKatsushi Kobayashi  * 1. Redistributions of source code must retain the above copyright
93c60ba66SKatsushi Kobayashi  *    notice, this list of conditions and the following disclaimer.
103c60ba66SKatsushi Kobayashi  * 2. Redistributions in binary form must reproduce the above copyright
113c60ba66SKatsushi Kobayashi  *    notice, this list of conditions and the following disclaimer in the
123c60ba66SKatsushi Kobayashi  *    documentation and/or other materials provided with the distribution.
133c60ba66SKatsushi Kobayashi  * 3. All advertising materials mentioning features or use of this software
143c60ba66SKatsushi Kobayashi  *    must display the acknowledgement as bellow:
153c60ba66SKatsushi Kobayashi  *
168da326fdSHidetoshi Shimokawa  *    This product includes software developed by K. Kobayashi and H. Shimokawa
173c60ba66SKatsushi Kobayashi  *
183c60ba66SKatsushi Kobayashi  * 4. The name of the author may not be used to endorse or promote products
193c60ba66SKatsushi Kobayashi  *    derived from this software without specific prior written permission.
203c60ba66SKatsushi Kobayashi  *
213c60ba66SKatsushi Kobayashi  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
223c60ba66SKatsushi Kobayashi  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
233c60ba66SKatsushi Kobayashi  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
243c60ba66SKatsushi Kobayashi  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
253c60ba66SKatsushi Kobayashi  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
263c60ba66SKatsushi Kobayashi  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
273c60ba66SKatsushi Kobayashi  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
283c60ba66SKatsushi Kobayashi  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
293c60ba66SKatsushi Kobayashi  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
303c60ba66SKatsushi Kobayashi  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
313c60ba66SKatsushi Kobayashi  * POSSIBILITY OF SUCH DAMAGE.
323c60ba66SKatsushi Kobayashi  *
333c60ba66SKatsushi Kobayashi  * $FreeBSD$
343c60ba66SKatsushi Kobayashi  *
353c60ba66SKatsushi Kobayashi  */
368da326fdSHidetoshi Shimokawa 
373c60ba66SKatsushi Kobayashi #define ATRQ_CH 0
383c60ba66SKatsushi Kobayashi #define ATRS_CH 1
393c60ba66SKatsushi Kobayashi #define ARRQ_CH 2
403c60ba66SKatsushi Kobayashi #define ARRS_CH 3
413c60ba66SKatsushi Kobayashi #define ITX_CH 4
423c60ba66SKatsushi Kobayashi #define IRX_CH 0x24
433c60ba66SKatsushi Kobayashi 
443c60ba66SKatsushi Kobayashi #include <sys/param.h>
453c60ba66SKatsushi Kobayashi #include <sys/systm.h>
463c60ba66SKatsushi Kobayashi #include <sys/types.h>
473c60ba66SKatsushi Kobayashi #include <sys/mbuf.h>
483c60ba66SKatsushi Kobayashi #include <sys/mman.h>
493c60ba66SKatsushi Kobayashi #include <sys/socket.h>
503c60ba66SKatsushi Kobayashi #include <sys/socketvar.h>
513c60ba66SKatsushi Kobayashi #include <sys/signalvar.h>
523c60ba66SKatsushi Kobayashi #include <sys/malloc.h>
533c60ba66SKatsushi Kobayashi #include <sys/uio.h>
543c60ba66SKatsushi Kobayashi #include <sys/sockio.h>
553c60ba66SKatsushi Kobayashi #include <sys/bus.h>
563c60ba66SKatsushi Kobayashi #include <sys/kernel.h>
573c60ba66SKatsushi Kobayashi #include <sys/conf.h>
583c60ba66SKatsushi Kobayashi 
593c60ba66SKatsushi Kobayashi #include <machine/bus.h>
603c60ba66SKatsushi Kobayashi #include <machine/resource.h>
613c60ba66SKatsushi Kobayashi #include <sys/rman.h>
623c60ba66SKatsushi Kobayashi 
633c60ba66SKatsushi Kobayashi #include <machine/cpufunc.h>            /* for rdtsc proto for clock.h below */
643c60ba66SKatsushi Kobayashi #include <machine/clock.h>
653c60ba66SKatsushi Kobayashi #include <pci/pcivar.h>
663c60ba66SKatsushi Kobayashi #include <pci/pcireg.h>
673c60ba66SKatsushi Kobayashi #include <vm/vm.h>
683c60ba66SKatsushi Kobayashi #include <vm/vm_extern.h>
693c60ba66SKatsushi Kobayashi #include <vm/pmap.h>            /* for vtophys proto */
703c60ba66SKatsushi Kobayashi 
713c60ba66SKatsushi Kobayashi #include <dev/firewire/firewire.h>
723c60ba66SKatsushi Kobayashi #include <dev/firewire/firewirebusreg.h>
733c60ba66SKatsushi Kobayashi #include <dev/firewire/firewirereg.h>
743c60ba66SKatsushi Kobayashi #include <dev/firewire/fwohcireg.h>
753c60ba66SKatsushi Kobayashi #include <dev/firewire/fwohcivar.h>
763c60ba66SKatsushi Kobayashi #include <dev/firewire/firewire_phy.h>
773c60ba66SKatsushi Kobayashi 
783c60ba66SKatsushi Kobayashi #undef OHCI_DEBUG
798da326fdSHidetoshi Shimokawa 
803c60ba66SKatsushi Kobayashi static char dbcode[16][0x10]={"OUTM", "OUTL","INPM","INPL",
813c60ba66SKatsushi Kobayashi 		"STOR","LOAD","NOP ","STOP",};
823c60ba66SKatsushi Kobayashi static char dbkey[8][0x10]={"ST0", "ST1","ST2","ST3",
833c60ba66SKatsushi Kobayashi 		"UNDEF","REG","SYS","DEV"};
843c60ba66SKatsushi Kobayashi char fwohcicode[32][0x20]={
853c60ba66SKatsushi Kobayashi 	"No stat","Undef","long","miss Ack err",
863c60ba66SKatsushi Kobayashi 	"underrun","overrun","desc err", "data read err",
873c60ba66SKatsushi Kobayashi 	"data write err","bus reset","timeout","tcode err",
883c60ba66SKatsushi Kobayashi 	"Undef","Undef","unknown event","flushed",
893c60ba66SKatsushi Kobayashi 	"Undef","ack complete","ack pend","Undef",
903c60ba66SKatsushi Kobayashi 	"ack busy_X","ack busy_A","ack busy_B","Undef",
913c60ba66SKatsushi Kobayashi 	"Undef","Undef","Undef","ack tardy",
923c60ba66SKatsushi Kobayashi 	"Undef","ack data_err","ack type_err",""};
933c60ba66SKatsushi Kobayashi #define MAX_SPEED 2
943c60ba66SKatsushi Kobayashi extern char linkspeed[MAX_SPEED+1][0x10];
953c60ba66SKatsushi Kobayashi extern int maxrec[MAX_SPEED+1];
963c60ba66SKatsushi Kobayashi static char dbcond[4][0x10]={"NEV","C=1", "C=0", "ALL"};
973c60ba66SKatsushi Kobayashi u_int32_t tagbit[4] = { 1 << 28, 1 << 29, 1 << 30, 1 << 31};
983c60ba66SKatsushi Kobayashi 
993c60ba66SKatsushi Kobayashi static struct tcode_info tinfo[] = {
1003c60ba66SKatsushi Kobayashi /*		hdr_len block 	flag*/
1013c60ba66SKatsushi Kobayashi /* 0 WREQQ  */ {16,	FWTI_REQ | FWTI_TLABEL},
1023c60ba66SKatsushi Kobayashi /* 1 WREQB  */ {16,	FWTI_REQ | FWTI_TLABEL | FWTI_BLOCK_ASY},
1033c60ba66SKatsushi Kobayashi /* 2 WRES   */ {12,	FWTI_RES},
1043c60ba66SKatsushi Kobayashi /* 3 XXX    */ { 0,	0},
1053c60ba66SKatsushi Kobayashi /* 4 RREQQ  */ {12,	FWTI_REQ | FWTI_TLABEL},
1063c60ba66SKatsushi Kobayashi /* 5 RREQB  */ {16,	FWTI_REQ | FWTI_TLABEL},
1073c60ba66SKatsushi Kobayashi /* 6 RRESQ  */ {16,	FWTI_RES},
1083c60ba66SKatsushi Kobayashi /* 7 RRESB  */ {16,	FWTI_RES | FWTI_BLOCK_ASY},
1093c60ba66SKatsushi Kobayashi /* 8 CYCS   */ { 0,	0},
1103c60ba66SKatsushi Kobayashi /* 9 LREQ   */ {16,	FWTI_REQ | FWTI_TLABEL | FWTI_BLOCK_ASY},
1113c60ba66SKatsushi Kobayashi /* a STREAM */ { 4,	FWTI_REQ | FWTI_BLOCK_STR},
1123c60ba66SKatsushi Kobayashi /* b LRES   */ {16,	FWTI_RES | FWTI_BLOCK_ASY},
1133c60ba66SKatsushi Kobayashi /* c XXX    */ { 0,	0},
1143c60ba66SKatsushi Kobayashi /* d XXX    */ { 0, 	0},
1153c60ba66SKatsushi Kobayashi /* e PHY    */ {12,	FWTI_REQ},
1163c60ba66SKatsushi Kobayashi /* f XXX    */ { 0,	0}
1173c60ba66SKatsushi Kobayashi };
1183c60ba66SKatsushi Kobayashi 
1193c60ba66SKatsushi Kobayashi #define OHCI_WRITE_SIGMASK 0xffff0000
1203c60ba66SKatsushi Kobayashi #define OHCI_READ_SIGMASK 0xffff0000
1213c60ba66SKatsushi Kobayashi 
1223c60ba66SKatsushi Kobayashi #define OWRITE(sc, r, x) bus_space_write_4((sc)->bst, (sc)->bsh, (r), (x))
1233c60ba66SKatsushi Kobayashi #define OREAD(sc, r) bus_space_read_4((sc)->bst, (sc)->bsh, (r))
1243c60ba66SKatsushi Kobayashi 
1253c60ba66SKatsushi Kobayashi static void fwohci_ibr __P((struct firewire_comm *));
1263c60ba66SKatsushi Kobayashi static void fwohci_db_init __P((struct fwohci_dbch *));
1273c60ba66SKatsushi Kobayashi static void fwohci_db_free __P((struct fwohci_dbch *));
128783058faSHidetoshi Shimokawa static void fwohci_arcv __P((struct fwohci_softc *, struct fwohci_dbch *, int));
129783058faSHidetoshi Shimokawa static void fwohci_ircv __P((struct fwohci_softc *, struct fwohci_dbch *, int));
1303c60ba66SKatsushi Kobayashi static void fwohci_txd __P((struct fwohci_softc *, struct fwohci_dbch *));
1313c60ba66SKatsushi Kobayashi static void fwohci_start_atq __P((struct firewire_comm *));
1323c60ba66SKatsushi Kobayashi static void fwohci_start_ats __P((struct firewire_comm *));
1333c60ba66SKatsushi Kobayashi static void fwohci_start __P((struct fwohci_softc *, struct fwohci_dbch *));
1343c60ba66SKatsushi Kobayashi static void fwohci_drain_atq __P((struct firewire_comm *, struct fw_xfer *));
1353c60ba66SKatsushi Kobayashi static void fwohci_drain_ats __P((struct firewire_comm *, struct fw_xfer *));
1363c60ba66SKatsushi Kobayashi static void fwohci_drain __P((struct firewire_comm *, struct fw_xfer *, struct fwohci_dbch *));
1373c60ba66SKatsushi Kobayashi static u_int32_t fwphy_wrdata __P(( struct fwohci_softc *, u_int32_t, u_int32_t));
1383c60ba66SKatsushi Kobayashi static u_int32_t fwphy_rddata __P(( struct fwohci_softc *, u_int32_t));
1393c60ba66SKatsushi Kobayashi static int fwohci_rx_enable __P((struct fwohci_softc *, struct fwohci_dbch *));
1403c60ba66SKatsushi Kobayashi static int fwohci_tx_enable __P((struct fwohci_softc *, struct fwohci_dbch *));
1413c60ba66SKatsushi Kobayashi static int fwohci_irx_enable __P((struct firewire_comm *, int));
1423c60ba66SKatsushi Kobayashi static int fwohci_irxpp_enable __P((struct firewire_comm *, int));
1433c60ba66SKatsushi Kobayashi static int fwohci_irxbuf_enable __P((struct firewire_comm *, int));
1443c60ba66SKatsushi Kobayashi static int fwohci_irx_disable __P((struct firewire_comm *, int));
1453c60ba66SKatsushi Kobayashi static void fwohci_irx_post __P((struct firewire_comm *, u_int32_t *));
1463c60ba66SKatsushi Kobayashi static int fwohci_itxbuf_enable __P((struct firewire_comm *, int));
1473c60ba66SKatsushi Kobayashi static int fwohci_itx_disable __P((struct firewire_comm *, int));
1483c60ba66SKatsushi Kobayashi static void fwohci_timeout __P((void *));
1493c60ba66SKatsushi Kobayashi static void fwohci_poll __P((struct firewire_comm *, int, int));
1503c60ba66SKatsushi Kobayashi static void fwohci_set_intr __P((struct firewire_comm *, int));
1513c60ba66SKatsushi Kobayashi static int fwohci_add_rx_buf __P((struct fwohcidb_tr *, unsigned short, int, void *, void *));
1523c60ba66SKatsushi Kobayashi static int fwohci_add_tx_buf __P((struct fwohcidb_tr *, unsigned short, int, void *));
1533c60ba66SKatsushi Kobayashi static void	dump_db __P((struct fwohci_softc *, u_int32_t));
1543c60ba66SKatsushi Kobayashi static void 	print_db __P((volatile struct fwohcidb *, u_int32_t , u_int32_t));
1553c60ba66SKatsushi Kobayashi static void	dump_dma __P((struct fwohci_softc *, u_int32_t));
1563c60ba66SKatsushi Kobayashi static u_int32_t fwohci_cyctimer __P((struct firewire_comm *));
1573c60ba66SKatsushi Kobayashi static void fwohci_rbuf_update __P((struct fwohci_softc *, int));
1583c60ba66SKatsushi Kobayashi static void fwohci_tbuf_update __P((struct fwohci_softc *, int));
1593c60ba66SKatsushi Kobayashi void fwohci_txbufdb __P((struct fwohci_softc *, int , struct fw_bulkxfer *));
1603c60ba66SKatsushi Kobayashi 
1613c60ba66SKatsushi Kobayashi /*
1623c60ba66SKatsushi Kobayashi  * memory allocated for DMA programs
1633c60ba66SKatsushi Kobayashi  */
1643c60ba66SKatsushi Kobayashi #define DMA_PROG_ALLOC		(8 * PAGE_SIZE)
1653c60ba66SKatsushi Kobayashi 
1663c60ba66SKatsushi Kobayashi /* #define NDB 1024 */
1673c60ba66SKatsushi Kobayashi #define NDB FWMAXQUEUE
1683c60ba66SKatsushi Kobayashi #define NDVDB (DVBUF * NDB)
1693c60ba66SKatsushi Kobayashi 
1703c60ba66SKatsushi Kobayashi #define	OHCI_VERSION		0x00
1713c60ba66SKatsushi Kobayashi #define	OHCI_CROMHDR		0x18
1723c60ba66SKatsushi Kobayashi #define	OHCI_BUS_OPT		0x20
1733c60ba66SKatsushi Kobayashi #define	OHCI_BUSIRMC		(1 << 31)
1743c60ba66SKatsushi Kobayashi #define	OHCI_BUSCMC		(1 << 30)
1753c60ba66SKatsushi Kobayashi #define	OHCI_BUSISC		(1 << 29)
1763c60ba66SKatsushi Kobayashi #define	OHCI_BUSBMC		(1 << 28)
1773c60ba66SKatsushi Kobayashi #define	OHCI_BUSPMC		(1 << 27)
1783c60ba66SKatsushi Kobayashi #define OHCI_BUSFNC		OHCI_BUSIRMC | OHCI_BUSCMC | OHCI_BUSISC |\
1793c60ba66SKatsushi Kobayashi 				OHCI_BUSBMC | OHCI_BUSPMC
1803c60ba66SKatsushi Kobayashi 
1813c60ba66SKatsushi Kobayashi #define	OHCI_EUID_HI		0x24
1823c60ba66SKatsushi Kobayashi #define	OHCI_EUID_LO		0x28
1833c60ba66SKatsushi Kobayashi 
1843c60ba66SKatsushi Kobayashi #define	OHCI_CROMPTR		0x34
1853c60ba66SKatsushi Kobayashi #define	OHCI_HCCCTL		0x50
1863c60ba66SKatsushi Kobayashi #define	OHCI_HCCCTLCLR		0x54
1873c60ba66SKatsushi Kobayashi #define	OHCI_AREQHI		0x100
1883c60ba66SKatsushi Kobayashi #define	OHCI_AREQHICLR		0x104
1893c60ba66SKatsushi Kobayashi #define	OHCI_AREQLO		0x108
1903c60ba66SKatsushi Kobayashi #define	OHCI_AREQLOCLR		0x10c
1913c60ba66SKatsushi Kobayashi #define	OHCI_PREQHI		0x110
1923c60ba66SKatsushi Kobayashi #define	OHCI_PREQHICLR		0x114
1933c60ba66SKatsushi Kobayashi #define	OHCI_PREQLO		0x118
1943c60ba66SKatsushi Kobayashi #define	OHCI_PREQLOCLR		0x11c
1953c60ba66SKatsushi Kobayashi #define	OHCI_PREQUPPER		0x120
1963c60ba66SKatsushi Kobayashi 
1973c60ba66SKatsushi Kobayashi #define	OHCI_SID_BUF		0x64
1983c60ba66SKatsushi Kobayashi #define	OHCI_SID_CNT		0x68
1993c60ba66SKatsushi Kobayashi #define OHCI_SID_CNT_MASK	0xffc
2003c60ba66SKatsushi Kobayashi 
2013c60ba66SKatsushi Kobayashi #define	OHCI_IT_STAT		0x90
2023c60ba66SKatsushi Kobayashi #define	OHCI_IT_STATCLR		0x94
2033c60ba66SKatsushi Kobayashi #define	OHCI_IT_MASK		0x98
2043c60ba66SKatsushi Kobayashi #define	OHCI_IT_MASKCLR		0x9c
2053c60ba66SKatsushi Kobayashi 
2063c60ba66SKatsushi Kobayashi #define	OHCI_IR_STAT		0xa0
2073c60ba66SKatsushi Kobayashi #define	OHCI_IR_STATCLR		0xa4
2083c60ba66SKatsushi Kobayashi #define	OHCI_IR_MASK		0xa8
2093c60ba66SKatsushi Kobayashi #define	OHCI_IR_MASKCLR		0xac
2103c60ba66SKatsushi Kobayashi 
2113c60ba66SKatsushi Kobayashi #define	OHCI_LNKCTL		0xe0
2123c60ba66SKatsushi Kobayashi #define	OHCI_LNKCTLCLR		0xe4
2133c60ba66SKatsushi Kobayashi 
2143c60ba66SKatsushi Kobayashi #define	OHCI_PHYACCESS		0xec
2153c60ba66SKatsushi Kobayashi #define	OHCI_CYCLETIMER		0xf0
2163c60ba66SKatsushi Kobayashi 
2173c60ba66SKatsushi Kobayashi #define	OHCI_DMACTL(off)	(off)
2183c60ba66SKatsushi Kobayashi #define	OHCI_DMACTLCLR(off)	(off + 4)
2193c60ba66SKatsushi Kobayashi #define	OHCI_DMACMD(off)	(off + 0xc)
2203c60ba66SKatsushi Kobayashi #define	OHCI_DMAMATCH(off)	(off + 0x10)
2213c60ba66SKatsushi Kobayashi 
2223c60ba66SKatsushi Kobayashi #define OHCI_ATQOFF		0x180
2233c60ba66SKatsushi Kobayashi #define OHCI_ATQCTL		OHCI_ATQOFF
2243c60ba66SKatsushi Kobayashi #define OHCI_ATQCTLCLR		(OHCI_ATQOFF + 4)
2253c60ba66SKatsushi Kobayashi #define OHCI_ATQCMD		(OHCI_ATQOFF + 0xc)
2263c60ba66SKatsushi Kobayashi #define OHCI_ATQMATCH		(OHCI_ATQOFF + 0x10)
2273c60ba66SKatsushi Kobayashi 
2283c60ba66SKatsushi Kobayashi #define OHCI_ATSOFF		0x1a0
2293c60ba66SKatsushi Kobayashi #define OHCI_ATSCTL		OHCI_ATSOFF
2303c60ba66SKatsushi Kobayashi #define OHCI_ATSCTLCLR		(OHCI_ATSOFF + 4)
2313c60ba66SKatsushi Kobayashi #define OHCI_ATSCMD		(OHCI_ATSOFF + 0xc)
2323c60ba66SKatsushi Kobayashi #define OHCI_ATSMATCH		(OHCI_ATSOFF + 0x10)
2333c60ba66SKatsushi Kobayashi 
2343c60ba66SKatsushi Kobayashi #define OHCI_ARQOFF		0x1c0
2353c60ba66SKatsushi Kobayashi #define OHCI_ARQCTL		OHCI_ARQOFF
2363c60ba66SKatsushi Kobayashi #define OHCI_ARQCTLCLR		(OHCI_ARQOFF + 4)
2373c60ba66SKatsushi Kobayashi #define OHCI_ARQCMD		(OHCI_ARQOFF + 0xc)
2383c60ba66SKatsushi Kobayashi #define OHCI_ARQMATCH		(OHCI_ARQOFF + 0x10)
2393c60ba66SKatsushi Kobayashi 
2403c60ba66SKatsushi Kobayashi #define OHCI_ARSOFF		0x1e0
2413c60ba66SKatsushi Kobayashi #define OHCI_ARSCTL		OHCI_ARSOFF
2423c60ba66SKatsushi Kobayashi #define OHCI_ARSCTLCLR		(OHCI_ARSOFF + 4)
2433c60ba66SKatsushi Kobayashi #define OHCI_ARSCMD		(OHCI_ARSOFF + 0xc)
2443c60ba66SKatsushi Kobayashi #define OHCI_ARSMATCH		(OHCI_ARSOFF + 0x10)
2453c60ba66SKatsushi Kobayashi 
2463c60ba66SKatsushi Kobayashi #define OHCI_ITOFF(CH)		(0x200 + 0x10 * (CH))
2473c60ba66SKatsushi Kobayashi #define OHCI_ITCTL(CH)		(OHCI_ITOFF(CH))
2483c60ba66SKatsushi Kobayashi #define OHCI_ITCTLCLR(CH)	(OHCI_ITOFF(CH) + 4)
2493c60ba66SKatsushi Kobayashi #define OHCI_ITCMD(CH)		(OHCI_ITOFF(CH) + 0xc)
2503c60ba66SKatsushi Kobayashi 
2513c60ba66SKatsushi Kobayashi #define OHCI_IROFF(CH)		(0x400 + 0x20 * (CH))
2523c60ba66SKatsushi Kobayashi #define OHCI_IRCTL(CH)		(OHCI_IROFF(CH))
2533c60ba66SKatsushi Kobayashi #define OHCI_IRCTLCLR(CH)	(OHCI_IROFF(CH) + 4)
2543c60ba66SKatsushi Kobayashi #define OHCI_IRCMD(CH)		(OHCI_IROFF(CH) + 0xc)
2553c60ba66SKatsushi Kobayashi #define OHCI_IRMATCH(CH)	(OHCI_IROFF(CH) + 0x10)
2563c60ba66SKatsushi Kobayashi 
2573c60ba66SKatsushi Kobayashi d_ioctl_t fwohci_ioctl;
2583c60ba66SKatsushi Kobayashi 
2593c60ba66SKatsushi Kobayashi /*
2603c60ba66SKatsushi Kobayashi  * Communication with PHY device
2613c60ba66SKatsushi Kobayashi  */
262c572b810SHidetoshi Shimokawa static u_int32_t
263c572b810SHidetoshi Shimokawa fwphy_wrdata( struct fwohci_softc *sc, u_int32_t addr, u_int32_t data)
2643c60ba66SKatsushi Kobayashi {
2653c60ba66SKatsushi Kobayashi 	u_int32_t fun;
2663c60ba66SKatsushi Kobayashi 
2673c60ba66SKatsushi Kobayashi 	addr &= 0xf;
2683c60ba66SKatsushi Kobayashi 	data &= 0xff;
2693c60ba66SKatsushi Kobayashi 
2703c60ba66SKatsushi Kobayashi 	fun = (PHYDEV_WRCMD | (addr << PHYDEV_REGADDR) | (data << PHYDEV_WRDATA));
2713c60ba66SKatsushi Kobayashi 	OWRITE(sc, OHCI_PHYACCESS, fun);
2723c60ba66SKatsushi Kobayashi 	DELAY(100);
2733c60ba66SKatsushi Kobayashi 
2743c60ba66SKatsushi Kobayashi 	return(fwphy_rddata( sc, addr));
2753c60ba66SKatsushi Kobayashi }
2763c60ba66SKatsushi Kobayashi 
2773c60ba66SKatsushi Kobayashi static u_int32_t
2783c60ba66SKatsushi Kobayashi fwohci_set_bus_manager(struct firewire_comm *fc, u_int node)
2793c60ba66SKatsushi Kobayashi {
2803c60ba66SKatsushi Kobayashi 	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
2813c60ba66SKatsushi Kobayashi 	int i;
2823c60ba66SKatsushi Kobayashi 	u_int32_t bm;
2833c60ba66SKatsushi Kobayashi 
2843c60ba66SKatsushi Kobayashi #define OHCI_CSR_DATA	0x0c
2853c60ba66SKatsushi Kobayashi #define OHCI_CSR_COMP	0x10
2863c60ba66SKatsushi Kobayashi #define OHCI_CSR_CONT	0x14
2873c60ba66SKatsushi Kobayashi #define OHCI_BUS_MANAGER_ID	0
2883c60ba66SKatsushi Kobayashi 
2893c60ba66SKatsushi Kobayashi 	OWRITE(sc, OHCI_CSR_DATA, node);
2903c60ba66SKatsushi Kobayashi 	OWRITE(sc, OHCI_CSR_COMP, 0x3f);
2913c60ba66SKatsushi Kobayashi 	OWRITE(sc, OHCI_CSR_CONT, OHCI_BUS_MANAGER_ID);
2923c60ba66SKatsushi Kobayashi  	for (i = 0; !(OREAD(sc, OHCI_CSR_CONT) & (1<<31)) && (i < 1000); i++)
2933c60ba66SKatsushi Kobayashi 		DELAY(100);
2943c60ba66SKatsushi Kobayashi 	bm = OREAD(sc, OHCI_CSR_DATA);
29517c3d42cSHidetoshi Shimokawa 	if((bm & 0x3f) == 0x3f)
2963c60ba66SKatsushi Kobayashi 		bm = node;
29717c3d42cSHidetoshi Shimokawa 	if (bootverbose)
29817c3d42cSHidetoshi Shimokawa 		device_printf(sc->fc.dev,
29917c3d42cSHidetoshi Shimokawa 			"fw_set_bus_manager: %d->%d (loop=%d)\n", bm, node, i);
3003c60ba66SKatsushi Kobayashi 
3013c60ba66SKatsushi Kobayashi 	return(bm);
3023c60ba66SKatsushi Kobayashi }
3033c60ba66SKatsushi Kobayashi 
304c572b810SHidetoshi Shimokawa static u_int32_t
305c572b810SHidetoshi Shimokawa fwphy_rddata(struct fwohci_softc *sc,  u_int addr)
3063c60ba66SKatsushi Kobayashi {
3073c60ba66SKatsushi Kobayashi 	u_int32_t fun;
3083c60ba66SKatsushi Kobayashi 	u_int i;
3093c60ba66SKatsushi Kobayashi 
3103c60ba66SKatsushi Kobayashi 	addr &= 0xf;
3113c60ba66SKatsushi Kobayashi 	fun = PHYDEV_RDCMD | (addr << PHYDEV_REGADDR);
3123c60ba66SKatsushi Kobayashi 	OWRITE(sc, OHCI_PHYACCESS, fun);
3133c60ba66SKatsushi Kobayashi 	for ( i = 0 ; i < 1000 ; i ++ ){
3143c60ba66SKatsushi Kobayashi 		fun = OREAD(sc, OHCI_PHYACCESS);
3153c60ba66SKatsushi Kobayashi 		if ((fun & PHYDEV_RDCMD) == 0 && (fun & PHYDEV_RDDONE) != 0)
3163c60ba66SKatsushi Kobayashi 			break;
3173c60ba66SKatsushi Kobayashi 		DELAY(1000);
3183c60ba66SKatsushi Kobayashi 	}
3193c60ba66SKatsushi Kobayashi 	if( i >= 1000)
3203c60ba66SKatsushi Kobayashi 		device_printf(sc->fc.dev, "cannot read phy\n");
3213c60ba66SKatsushi Kobayashi 	return((fun >> PHYDEV_RDDATA )& 0xff);
3223c60ba66SKatsushi Kobayashi }
3233c60ba66SKatsushi Kobayashi /* Device specific ioctl. */
3243c60ba66SKatsushi Kobayashi int
3253c60ba66SKatsushi Kobayashi fwohci_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td)
3263c60ba66SKatsushi Kobayashi {
3273c60ba66SKatsushi Kobayashi 	struct firewire_softc *sc;
3283c60ba66SKatsushi Kobayashi 	struct fwohci_softc *fc;
3293c60ba66SKatsushi Kobayashi 	int unit = DEV2UNIT(dev);
3303c60ba66SKatsushi Kobayashi 	int err = 0;
3313c60ba66SKatsushi Kobayashi 	struct fw_reg_req_t *reg  = (struct fw_reg_req_t *) data;
3323c60ba66SKatsushi Kobayashi 	u_int32_t *dmach = (u_int32_t *) data;
3333c60ba66SKatsushi Kobayashi 
3343c60ba66SKatsushi Kobayashi 	sc = devclass_get_softc(firewire_devclass, unit);
3353c60ba66SKatsushi Kobayashi 	if(sc == NULL){
3363c60ba66SKatsushi Kobayashi 		return(EINVAL);
3373c60ba66SKatsushi Kobayashi 	}
3383c60ba66SKatsushi Kobayashi 	fc = (struct fwohci_softc *)sc->fc;
3393c60ba66SKatsushi Kobayashi 
3403c60ba66SKatsushi Kobayashi 	if (!data)
3413c60ba66SKatsushi Kobayashi 		return(EINVAL);
3423c60ba66SKatsushi Kobayashi 
3433c60ba66SKatsushi Kobayashi 	switch (cmd) {
3443c60ba66SKatsushi Kobayashi 	case FWOHCI_WRREG:
3453c60ba66SKatsushi Kobayashi #define OHCI_MAX_REG 0x800
3463c60ba66SKatsushi Kobayashi 		if(reg->addr <= OHCI_MAX_REG){
3473c60ba66SKatsushi Kobayashi 			OWRITE(fc, reg->addr, reg->data);
3483c60ba66SKatsushi Kobayashi 			reg->data = OREAD(fc, reg->addr);
3493c60ba66SKatsushi Kobayashi 		}else{
3503c60ba66SKatsushi Kobayashi 			err = EINVAL;
3513c60ba66SKatsushi Kobayashi 		}
3523c60ba66SKatsushi Kobayashi 		break;
3533c60ba66SKatsushi Kobayashi 	case FWOHCI_RDREG:
3543c60ba66SKatsushi Kobayashi 		if(reg->addr <= OHCI_MAX_REG){
3553c60ba66SKatsushi Kobayashi 			reg->data = OREAD(fc, reg->addr);
3563c60ba66SKatsushi Kobayashi 		}else{
3573c60ba66SKatsushi Kobayashi 			err = EINVAL;
3583c60ba66SKatsushi Kobayashi 		}
3593c60ba66SKatsushi Kobayashi 		break;
3603c60ba66SKatsushi Kobayashi /* Read DMA descriptors for debug  */
3613c60ba66SKatsushi Kobayashi 	case DUMPDMA:
3623c60ba66SKatsushi Kobayashi 		if(*dmach <= OHCI_MAX_DMA_CH ){
3633c60ba66SKatsushi Kobayashi 			dump_dma(fc, *dmach);
3643c60ba66SKatsushi Kobayashi 			dump_db(fc, *dmach);
3653c60ba66SKatsushi Kobayashi 		}else{
3663c60ba66SKatsushi Kobayashi 			err = EINVAL;
3673c60ba66SKatsushi Kobayashi 		}
3683c60ba66SKatsushi Kobayashi 		break;
3693c60ba66SKatsushi Kobayashi 	default:
3703c60ba66SKatsushi Kobayashi 		break;
3713c60ba66SKatsushi Kobayashi 	}
3723c60ba66SKatsushi Kobayashi 	return err;
3733c60ba66SKatsushi Kobayashi }
374c572b810SHidetoshi Shimokawa 
375c572b810SHidetoshi Shimokawa int
376c572b810SHidetoshi Shimokawa fwohci_init(struct fwohci_softc *sc, device_t dev)
3773c60ba66SKatsushi Kobayashi {
3783c60ba66SKatsushi Kobayashi 	int err = 0;
3793c60ba66SKatsushi Kobayashi 	int i;
3803c60ba66SKatsushi Kobayashi 	u_int32_t reg, reg2;
3813c60ba66SKatsushi Kobayashi 	struct fwohcidb_tr *db_tr;
3823c60ba66SKatsushi Kobayashi 	int e1394a = 1;
3833c60ba66SKatsushi Kobayashi 
3843c60ba66SKatsushi Kobayashi 	reg = OREAD(sc, OHCI_VERSION);
3853c60ba66SKatsushi Kobayashi 	device_printf(dev, "OHCI version %x.%x (ROM=%d)\n",
3863c60ba66SKatsushi Kobayashi 			(reg>>16) & 0xff, reg & 0xff, (reg>>24) & 1);
3873c60ba66SKatsushi Kobayashi 
3883c60ba66SKatsushi Kobayashi /* XXX: Available Isochrounous DMA channel probe */
3893c60ba66SKatsushi Kobayashi 	for( i = 0 ; i < 0x20 ; i ++ ){
3903c60ba66SKatsushi Kobayashi 		OWRITE(sc,  OHCI_IRCTL(i), OHCI_CNTL_DMA_RUN);
3913c60ba66SKatsushi Kobayashi 		reg = OREAD(sc, OHCI_IRCTL(i));
3923c60ba66SKatsushi Kobayashi 		if(!(reg & OHCI_CNTL_DMA_RUN)) break;
3933c60ba66SKatsushi Kobayashi 		OWRITE(sc,  OHCI_ITCTL(i), OHCI_CNTL_DMA_RUN);
3943c60ba66SKatsushi Kobayashi 		reg = OREAD(sc, OHCI_ITCTL(i));
3953c60ba66SKatsushi Kobayashi 		if(!(reg & OHCI_CNTL_DMA_RUN)) break;
3963c60ba66SKatsushi Kobayashi 	}
3973c60ba66SKatsushi Kobayashi 	sc->fc.nisodma = i;
3983c60ba66SKatsushi Kobayashi 	device_printf(dev, "No. of Isochronous channel is %d.\n", i);
3993c60ba66SKatsushi Kobayashi 
4003c60ba66SKatsushi Kobayashi 	sc->fc.arq = &sc->arrq.xferq;
4013c60ba66SKatsushi Kobayashi 	sc->fc.ars = &sc->arrs.xferq;
4023c60ba66SKatsushi Kobayashi 	sc->fc.atq = &sc->atrq.xferq;
4033c60ba66SKatsushi Kobayashi 	sc->fc.ats = &sc->atrs.xferq;
4043c60ba66SKatsushi Kobayashi 
4053c60ba66SKatsushi Kobayashi 	sc->arrq.xferq.start = NULL;
4063c60ba66SKatsushi Kobayashi 	sc->arrs.xferq.start = NULL;
4073c60ba66SKatsushi Kobayashi 	sc->atrq.xferq.start = fwohci_start_atq;
4083c60ba66SKatsushi Kobayashi 	sc->atrs.xferq.start = fwohci_start_ats;
4093c60ba66SKatsushi Kobayashi 
4103c60ba66SKatsushi Kobayashi 	sc->arrq.xferq.drain = NULL;
4113c60ba66SKatsushi Kobayashi 	sc->arrs.xferq.drain = NULL;
4123c60ba66SKatsushi Kobayashi 	sc->atrq.xferq.drain = fwohci_drain_atq;
4133c60ba66SKatsushi Kobayashi 	sc->atrs.xferq.drain = fwohci_drain_ats;
4143c60ba66SKatsushi Kobayashi 
4153c60ba66SKatsushi Kobayashi 	sc->arrq.ndesc = 1;
4163c60ba66SKatsushi Kobayashi 	sc->arrs.ndesc = 1;
4173c60ba66SKatsushi Kobayashi 	sc->atrq.ndesc = 10;
4183c60ba66SKatsushi Kobayashi 	sc->atrs.ndesc = 10 / 2;
4193c60ba66SKatsushi Kobayashi 
4203c60ba66SKatsushi Kobayashi 	sc->arrq.ndb = NDB;
4213c60ba66SKatsushi Kobayashi 	sc->arrs.ndb = NDB / 2;
4223c60ba66SKatsushi Kobayashi 	sc->atrq.ndb = NDB;
4233c60ba66SKatsushi Kobayashi 	sc->atrs.ndb = NDB / 2;
4243c60ba66SKatsushi Kobayashi 
4253c60ba66SKatsushi Kobayashi 	sc->arrq.dummy = NULL;
4263c60ba66SKatsushi Kobayashi 	sc->arrs.dummy = NULL;
4273c60ba66SKatsushi Kobayashi 	sc->atrq.dummy = NULL;
4283c60ba66SKatsushi Kobayashi 	sc->atrs.dummy = NULL;
4293c60ba66SKatsushi Kobayashi 	for( i = 0 ; i < sc->fc.nisodma ; i ++ ){
4303c60ba66SKatsushi Kobayashi 		sc->fc.it[i] = &sc->it[i].xferq;
4313c60ba66SKatsushi Kobayashi 		sc->fc.ir[i] = &sc->ir[i].xferq;
4323c60ba66SKatsushi Kobayashi 		sc->it[i].ndb = 0;
4333c60ba66SKatsushi Kobayashi 		sc->ir[i].ndb = 0;
4343c60ba66SKatsushi Kobayashi 	}
4353c60ba66SKatsushi Kobayashi 
4363c60ba66SKatsushi Kobayashi 	sc->fc.tcode = tinfo;
4373c60ba66SKatsushi Kobayashi 
4383c60ba66SKatsushi Kobayashi 	sc->cromptr = (u_int32_t *)
4393c60ba66SKatsushi Kobayashi 		contigmalloc(CROMSIZE * 2, M_DEVBUF, M_NOWAIT, 0, ~0, 1<<10, 0);
4403c60ba66SKatsushi Kobayashi 
4413c60ba66SKatsushi Kobayashi 	if(sc->cromptr == NULL){
4423c60ba66SKatsushi Kobayashi 		return ENOMEM;
4433c60ba66SKatsushi Kobayashi 	}
4443c60ba66SKatsushi Kobayashi 	sc->fc.dev = dev;
4453c60ba66SKatsushi Kobayashi 	sc->fc.config_rom = &(sc->cromptr[CROMSIZE/4]);
4463c60ba66SKatsushi Kobayashi 
4473c60ba66SKatsushi Kobayashi 	sc->fc.config_rom[1] = 0x31333934;
4483c60ba66SKatsushi Kobayashi 	sc->fc.config_rom[2] = 0xf000a002;
4493c60ba66SKatsushi Kobayashi 	sc->fc.config_rom[3] = OREAD(sc, OHCI_EUID_HI);
4503c60ba66SKatsushi Kobayashi 	sc->fc.config_rom[4] = OREAD(sc, OHCI_EUID_LO);
4513c60ba66SKatsushi Kobayashi 	sc->fc.config_rom[5] = 0;
4523c60ba66SKatsushi Kobayashi 	sc->fc.config_rom[0] = (4 << 24) | (5 << 16);
4533c60ba66SKatsushi Kobayashi 
4543c60ba66SKatsushi Kobayashi 	sc->fc.config_rom[0] |= fw_crc16(&sc->fc.config_rom[1], 5*4);
4553c60ba66SKatsushi Kobayashi 
4563c60ba66SKatsushi Kobayashi 
4573c60ba66SKatsushi Kobayashi 	fw_init(&sc->fc);
4583c60ba66SKatsushi Kobayashi 
4593c60ba66SKatsushi Kobayashi /* Now stopping all DMA channel */
4603c60ba66SKatsushi Kobayashi 	OWRITE(sc,  OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN);
4613c60ba66SKatsushi Kobayashi 	OWRITE(sc,  OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN);
4623c60ba66SKatsushi Kobayashi 	OWRITE(sc,  OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN);
4633c60ba66SKatsushi Kobayashi 	OWRITE(sc,  OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
4643c60ba66SKatsushi Kobayashi 
4653c60ba66SKatsushi Kobayashi 	OWRITE(sc,  OHCI_IR_MASKCLR, ~0);
4663c60ba66SKatsushi Kobayashi 	for( i = 0 ; i < sc->fc.nisodma ; i ++ ){
4673c60ba66SKatsushi Kobayashi 		OWRITE(sc,  OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN);
4683c60ba66SKatsushi Kobayashi 		OWRITE(sc,  OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN);
4693c60ba66SKatsushi Kobayashi 	}
4703c60ba66SKatsushi Kobayashi 
4713c60ba66SKatsushi Kobayashi /* FLUSH FIFO and reset Transmitter/Reciever */
4723c60ba66SKatsushi Kobayashi 	OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_RESET);
47317c3d42cSHidetoshi Shimokawa 	if (bootverbose)
4743c60ba66SKatsushi Kobayashi 		device_printf(dev, "resetting OHCI...");
4753c60ba66SKatsushi Kobayashi 	i = 0;
4763c60ba66SKatsushi Kobayashi 	while(OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_RESET) {
4773c60ba66SKatsushi Kobayashi 		if (i++ > 100) break;
4783c60ba66SKatsushi Kobayashi 		DELAY(1000);
4793c60ba66SKatsushi Kobayashi 	}
48017c3d42cSHidetoshi Shimokawa 	if (bootverbose)
4813c60ba66SKatsushi Kobayashi 		printf("done (%d)\n", i);
4823c60ba66SKatsushi Kobayashi 	OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LPS);
4833c60ba66SKatsushi Kobayashi 	/* XXX wait for SCLK. */
484851c3ad0SHidetoshi Shimokawa 	DELAY(100000);
4853c60ba66SKatsushi Kobayashi 
4863c60ba66SKatsushi Kobayashi 	reg = OREAD(sc,  OHCI_BUS_OPT);
4873c60ba66SKatsushi Kobayashi 	reg2 = reg | OHCI_BUSFNC;
4883c60ba66SKatsushi Kobayashi 	/* XXX  */
4893c60ba66SKatsushi Kobayashi 	if (((reg & 0x0000f000) >> 12) < 10)
4903c60ba66SKatsushi Kobayashi 		reg2 = (reg2 & 0xffff0fff) | (10 << 12);
49117c3d42cSHidetoshi Shimokawa 	if (bootverbose)
4923c60ba66SKatsushi Kobayashi 		device_printf(dev, "BUS_OPT 0x%x -> 0x%x\n", reg, reg2);
4933c60ba66SKatsushi Kobayashi 	OWRITE(sc,  OHCI_BUS_OPT, reg2);
4943c60ba66SKatsushi Kobayashi 
4953c60ba66SKatsushi Kobayashi 	OWRITE(sc, OHCI_CROMHDR, sc->fc.config_rom[0]);
4963c60ba66SKatsushi Kobayashi 	OWRITE(sc, OHCI_CROMPTR, vtophys(&sc->fc.config_rom[0]));
4973c60ba66SKatsushi Kobayashi 	OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_BIGEND);
4983c60ba66SKatsushi Kobayashi 	OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_POSTWR);
4993c60ba66SKatsushi Kobayashi 
5003c60ba66SKatsushi Kobayashi /*
5013c60ba66SKatsushi Kobayashi  * probe PHY parameters
5023c60ba66SKatsushi Kobayashi  * 0. to prove PHY version, whether compliance of 1394a.
5033c60ba66SKatsushi Kobayashi  * 1. to probe maximum speed supported by the PHY and
5043c60ba66SKatsushi Kobayashi  *    number of port supported by core-logic.
5053c60ba66SKatsushi Kobayashi  *    It is not actually available port on your PC .
5063c60ba66SKatsushi Kobayashi  */
5073c60ba66SKatsushi Kobayashi 	/* Wait a while */
5083c60ba66SKatsushi Kobayashi 	reg = fwphy_rddata(sc, FW_PHY_SPD_REG);
5093c60ba66SKatsushi Kobayashi #if 0
5103c60ba66SKatsushi Kobayashi 	/* try again */
5113c60ba66SKatsushi Kobayashi 	DELAY(1000);
5123c60ba66SKatsushi Kobayashi 	reg = fwphy_rddata(sc, FW_PHY_SPD_REG);
5133c60ba66SKatsushi Kobayashi #endif
5143c60ba66SKatsushi Kobayashi 	if((reg >> 5) != 7 ){
5153c60ba66SKatsushi Kobayashi 		sc->fc.mode &= ~FWPHYASYST;
5163c60ba66SKatsushi Kobayashi 		sc->fc.nport = reg & FW_PHY_NP;
5173c60ba66SKatsushi Kobayashi 		sc->fc.speed = reg & FW_PHY_SPD >> 6;
5183c60ba66SKatsushi Kobayashi 		if (sc->fc.speed > MAX_SPEED) {
5193c60ba66SKatsushi Kobayashi 			device_printf(dev, "invalid speed %d (fixed to %d).\n",
5203c60ba66SKatsushi Kobayashi 				sc->fc.speed, MAX_SPEED);
5213c60ba66SKatsushi Kobayashi 			sc->fc.speed = MAX_SPEED;
5223c60ba66SKatsushi Kobayashi 		}
5233c60ba66SKatsushi Kobayashi 		sc->fc.maxrec = maxrec[sc->fc.speed];
5243c60ba66SKatsushi Kobayashi 		device_printf(dev,
5253c60ba66SKatsushi Kobayashi 			"Link 1394 only %s, %d ports, maxrec %d bytes.\n",
5263c60ba66SKatsushi Kobayashi 			linkspeed[sc->fc.speed], sc->fc.nport, sc->fc.maxrec);
5273c60ba66SKatsushi Kobayashi 	}else{
5283c60ba66SKatsushi Kobayashi 		reg2 = fwphy_rddata(sc, FW_PHY_ESPD_REG);
5293c60ba66SKatsushi Kobayashi 		sc->fc.mode |= FWPHYASYST;
5303c60ba66SKatsushi Kobayashi 		sc->fc.nport = reg & FW_PHY_NP;
5313c60ba66SKatsushi Kobayashi 		sc->fc.speed = (reg2 & FW_PHY_ESPD) >> 5;
5323c60ba66SKatsushi Kobayashi 		if (sc->fc.speed > MAX_SPEED) {
5333c60ba66SKatsushi Kobayashi 			device_printf(dev, "invalid speed %d (fixed to %d).\n",
5343c60ba66SKatsushi Kobayashi 				sc->fc.speed, MAX_SPEED);
5353c60ba66SKatsushi Kobayashi 			sc->fc.speed = MAX_SPEED;
5363c60ba66SKatsushi Kobayashi 		}
5373c60ba66SKatsushi Kobayashi 		sc->fc.maxrec = maxrec[sc->fc.speed];
5383c60ba66SKatsushi Kobayashi 		device_printf(dev,
5393c60ba66SKatsushi Kobayashi 			"Link 1394a available %s, %d ports, maxrec %d bytes.\n",
5403c60ba66SKatsushi Kobayashi 			linkspeed[sc->fc.speed], sc->fc.nport, sc->fc.maxrec);
5413c60ba66SKatsushi Kobayashi 
5423c60ba66SKatsushi Kobayashi 		/* check programPhyEnable */
5433c60ba66SKatsushi Kobayashi 		reg2 = fwphy_rddata(sc, 5);
5443c60ba66SKatsushi Kobayashi #if 0
5453c60ba66SKatsushi Kobayashi 		if (e1394a && (OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_PRPHY)) {
546c572b810SHidetoshi Shimokawa #else	/* XXX force to enable 1394a */
5473c60ba66SKatsushi Kobayashi 		if (e1394a) {
5483c60ba66SKatsushi Kobayashi #endif
54917c3d42cSHidetoshi Shimokawa 			if (bootverbose)
55017c3d42cSHidetoshi Shimokawa 				device_printf(dev,
55117c3d42cSHidetoshi Shimokawa 					"Enable 1394a Enhancements\n");
5523c60ba66SKatsushi Kobayashi 			/* enable EAA EMC */
5533c60ba66SKatsushi Kobayashi 			reg2 |= 0x03;
5543c60ba66SKatsushi Kobayashi 			/* set aPhyEnhanceEnable */
5553c60ba66SKatsushi Kobayashi 			OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_PHYEN);
5563c60ba66SKatsushi Kobayashi 			OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_PRPHY);
5573c60ba66SKatsushi Kobayashi 		} else {
5583c60ba66SKatsushi Kobayashi 			/* for safe */
5593c60ba66SKatsushi Kobayashi 			reg2 &= ~0x83;
5603c60ba66SKatsushi Kobayashi 		}
5613c60ba66SKatsushi Kobayashi 		reg2 = fwphy_wrdata(sc, 5, reg2);
5623c60ba66SKatsushi Kobayashi 	}
5633c60ba66SKatsushi Kobayashi 
5643c60ba66SKatsushi Kobayashi 	reg = fwphy_rddata(sc, FW_PHY_SPD_REG);
5653c60ba66SKatsushi Kobayashi 	if((reg >> 5) == 7 ){
5663c60ba66SKatsushi Kobayashi 		reg = fwphy_rddata(sc, 4);
5673c60ba66SKatsushi Kobayashi 		reg |= 1 << 6;
5683c60ba66SKatsushi Kobayashi 		fwphy_wrdata(sc, 4, reg);
5693c60ba66SKatsushi Kobayashi 		reg = fwphy_rddata(sc, 4);
5703c60ba66SKatsushi Kobayashi 	}
5713c60ba66SKatsushi Kobayashi 
5723c60ba66SKatsushi Kobayashi /* SID recieve buffer must allign 2^11 */
5733c60ba66SKatsushi Kobayashi #define	OHCI_SIDSIZE	(1 << 11)
5743c60ba66SKatsushi Kobayashi 	sc->fc.sid_buf = (u_int32_t *) vm_page_alloc_contig( OHCI_SIDSIZE,
5753c60ba66SKatsushi Kobayashi 					0x10000, 0xffffffff, OHCI_SIDSIZE);
5763c60ba66SKatsushi Kobayashi 	OWRITE(sc,  OHCI_SID_BUF, vtophys(sc->fc.sid_buf));
5773c60ba66SKatsushi Kobayashi 	sc->fc.sid_buf++;
5783c60ba66SKatsushi Kobayashi 	OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_SID);
5793c60ba66SKatsushi Kobayashi 
5803c60ba66SKatsushi Kobayashi 	fwohci_db_init(&sc->arrq);
5813c60ba66SKatsushi Kobayashi 	fwohci_db_init(&sc->arrs);
5823c60ba66SKatsushi Kobayashi 
5833c60ba66SKatsushi Kobayashi 	fwohci_db_init(&sc->atrq);
5843c60ba66SKatsushi Kobayashi 	fwohci_db_init(&sc->atrs);
5853c60ba66SKatsushi Kobayashi 
5863c60ba66SKatsushi Kobayashi 	reg = OREAD(sc, FWOHCIGUID_H);
5873c60ba66SKatsushi Kobayashi 	for( i = 0 ; i < 4 ; i ++){
5883c60ba66SKatsushi Kobayashi 		sc->fc.eui[3 - i] = reg & 0xff;
5893c60ba66SKatsushi Kobayashi 		reg = reg >> 8;
5903c60ba66SKatsushi Kobayashi 	}
5913c60ba66SKatsushi Kobayashi 	reg = OREAD(sc, FWOHCIGUID_L);
5923c60ba66SKatsushi Kobayashi 	for( i = 0 ; i < 4 ; i ++){
5933c60ba66SKatsushi Kobayashi 		sc->fc.eui[7 - i] = reg & 0xff;
5943c60ba66SKatsushi Kobayashi 		reg = reg >> 8;
5953c60ba66SKatsushi Kobayashi 	}
5963c60ba66SKatsushi Kobayashi 	device_printf(dev, "EUI64 %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
5973c60ba66SKatsushi Kobayashi 		sc->fc.eui[0], sc->fc.eui[1], sc->fc.eui[2], sc->fc.eui[3],
5983c60ba66SKatsushi Kobayashi 		sc->fc.eui[4], sc->fc.eui[5], sc->fc.eui[6], sc->fc.eui[7]);
5993c60ba66SKatsushi Kobayashi 	sc->fc.ioctl = fwohci_ioctl;
6003c60ba66SKatsushi Kobayashi 	sc->fc.cyctimer = fwohci_cyctimer;
6013c60ba66SKatsushi Kobayashi 	sc->fc.set_bmr = fwohci_set_bus_manager;
6023c60ba66SKatsushi Kobayashi 	sc->fc.ibr = fwohci_ibr;
6033c60ba66SKatsushi Kobayashi 	sc->fc.irx_enable = fwohci_irx_enable;
6043c60ba66SKatsushi Kobayashi 	sc->fc.irx_disable = fwohci_irx_disable;
6053c60ba66SKatsushi Kobayashi 
6063c60ba66SKatsushi Kobayashi 	sc->fc.itx_enable = fwohci_itxbuf_enable;
6073c60ba66SKatsushi Kobayashi 	sc->fc.itx_disable = fwohci_itx_disable;
6083c60ba66SKatsushi Kobayashi 	sc->fc.irx_post = fwohci_irx_post;
6093c60ba66SKatsushi Kobayashi 	sc->fc.itx_post = NULL;
6103c60ba66SKatsushi Kobayashi 	sc->fc.timeout = fwohci_timeout;
6113c60ba66SKatsushi Kobayashi 	sc->fc.poll = fwohci_poll;
6123c60ba66SKatsushi Kobayashi 	sc->fc.set_intr = fwohci_set_intr;
613c572b810SHidetoshi Shimokawa 
6143c60ba66SKatsushi Kobayashi 	/* enable link */
6153c60ba66SKatsushi Kobayashi 	OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LINKEN);
6163c60ba66SKatsushi Kobayashi 	fw_busreset(&sc->fc);
6173c60ba66SKatsushi Kobayashi 	fwohci_rx_enable(sc, &sc->arrq);
6183c60ba66SKatsushi Kobayashi 	fwohci_rx_enable(sc, &sc->arrs);
6193c60ba66SKatsushi Kobayashi 
6203c60ba66SKatsushi Kobayashi 	for( i = 0, db_tr = sc->atrq.top; i < sc->atrq.ndb ;
6213c60ba66SKatsushi Kobayashi 				i ++, db_tr = STAILQ_NEXT(db_tr, link)){
6223c60ba66SKatsushi Kobayashi 		db_tr->xfer = NULL;
6233c60ba66SKatsushi Kobayashi 	}
6243c60ba66SKatsushi Kobayashi 	for( i = 0, db_tr = sc->atrs.top; i < sc->atrs.ndb ;
6253c60ba66SKatsushi Kobayashi 				i ++, db_tr = STAILQ_NEXT(db_tr, link)){
6263c60ba66SKatsushi Kobayashi 		db_tr->xfer = NULL;
6273c60ba66SKatsushi Kobayashi 	}
6283c60ba66SKatsushi Kobayashi 	sc->atrq.flags = sc->atrs.flags = 0;
6293c60ba66SKatsushi Kobayashi 
6303c60ba66SKatsushi Kobayashi 	OWRITE(sc, FWOHCI_RETRY,
6313c60ba66SKatsushi Kobayashi 		(0xffff << 16 )| (0x0f << 8) | (0x0f << 4) | 0x0f) ;
6323c60ba66SKatsushi Kobayashi 	OWRITE(sc, FWOHCI_INTMASKCLR, ~0);
6333c60ba66SKatsushi Kobayashi 	OWRITE(sc, FWOHCI_INTMASK,
6343c60ba66SKatsushi Kobayashi 			OHCI_INT_ERR  | OHCI_INT_PHY_SID
6353c60ba66SKatsushi Kobayashi 			| OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS
6363c60ba66SKatsushi Kobayashi 			| OHCI_INT_DMA_PRRQ | OHCI_INT_DMA_PRRS
6373c60ba66SKatsushi Kobayashi 			| OHCI_INT_PHY_BUS_R | OHCI_INT_PW_ERR);
6383c60ba66SKatsushi Kobayashi 	fwohci_set_intr(&sc->fc, 1);
6393c60ba66SKatsushi Kobayashi 
6403c60ba66SKatsushi Kobayashi 	OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD);
6413c60ba66SKatsushi Kobayashi 	OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD);
6423c60ba66SKatsushi Kobayashi 
6433c60ba66SKatsushi Kobayashi 	return err;
6443c60ba66SKatsushi Kobayashi }
645c572b810SHidetoshi Shimokawa 
646c572b810SHidetoshi Shimokawa void
647c572b810SHidetoshi Shimokawa fwohci_timeout(void *arg)
6483c60ba66SKatsushi Kobayashi {
6493c60ba66SKatsushi Kobayashi 	struct fwohci_softc *sc;
6503c60ba66SKatsushi Kobayashi 
6513c60ba66SKatsushi Kobayashi 	sc = (struct fwohci_softc *)arg;
6523c60ba66SKatsushi Kobayashi 	sc->fc.timeouthandle = timeout(fwohci_timeout,
6533c60ba66SKatsushi Kobayashi 				(void *)sc, FW_XFERTIMEOUT * hz * 10);
6543c60ba66SKatsushi Kobayashi }
655c572b810SHidetoshi Shimokawa 
656c572b810SHidetoshi Shimokawa u_int32_t
657c572b810SHidetoshi Shimokawa fwohci_cyctimer(struct firewire_comm *fc)
6583c60ba66SKatsushi Kobayashi {
6593c60ba66SKatsushi Kobayashi 	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
6603c60ba66SKatsushi Kobayashi 	return(OREAD(sc, OHCI_CYCLETIMER));
6613c60ba66SKatsushi Kobayashi }
6623c60ba66SKatsushi Kobayashi 
6633c60ba66SKatsushi Kobayashi #define LAST_DB(dbtr, db) do {						\
6643c60ba66SKatsushi Kobayashi 	struct fwohcidb_tr *_dbtr = (dbtr);				\
6653c60ba66SKatsushi Kobayashi 	int _cnt = _dbtr->dbcnt;					\
6663c60ba66SKatsushi Kobayashi 	db = &_dbtr->db[ (_cnt > 2) ? (_cnt -1) : 0];			\
6673c60ba66SKatsushi Kobayashi } while (0)
6683c60ba66SKatsushi Kobayashi 
669c572b810SHidetoshi Shimokawa static void
670c572b810SHidetoshi Shimokawa fwohci_start(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
6713c60ba66SKatsushi Kobayashi {
6723c60ba66SKatsushi Kobayashi 	int i, s;
6733c60ba66SKatsushi Kobayashi 	int tcode, hdr_len, hdr_off, len;
6743c60ba66SKatsushi Kobayashi 	int fsegment = -1;
6753c60ba66SKatsushi Kobayashi 	u_int32_t off;
6763c60ba66SKatsushi Kobayashi 	struct fw_xfer *xfer;
6773c60ba66SKatsushi Kobayashi 	struct fw_pkt *fp;
6783c60ba66SKatsushi Kobayashi 	volatile struct fwohci_txpkthdr *ohcifp;
6793c60ba66SKatsushi Kobayashi 	struct fwohcidb_tr *db_tr;
6803c60ba66SKatsushi Kobayashi 	volatile struct fwohcidb *db;
6813c60ba66SKatsushi Kobayashi 	struct mbuf *m;
6823c60ba66SKatsushi Kobayashi 	struct tcode_info *info;
6833c60ba66SKatsushi Kobayashi 
6843c60ba66SKatsushi Kobayashi 	if(&sc->atrq == dbch){
6853c60ba66SKatsushi Kobayashi 		off = OHCI_ATQOFF;
6863c60ba66SKatsushi Kobayashi 	}else if(&sc->atrs == dbch){
6873c60ba66SKatsushi Kobayashi 		off = OHCI_ATSOFF;
6883c60ba66SKatsushi Kobayashi 	}else{
6893c60ba66SKatsushi Kobayashi 		return;
6903c60ba66SKatsushi Kobayashi 	}
6913c60ba66SKatsushi Kobayashi 
6923c60ba66SKatsushi Kobayashi 	if (dbch->flags & FWOHCI_DBCH_FULL)
6933c60ba66SKatsushi Kobayashi 		return;
6943c60ba66SKatsushi Kobayashi 
6953c60ba66SKatsushi Kobayashi 	s = splfw();
6963c60ba66SKatsushi Kobayashi 	db_tr = dbch->top;
6973c60ba66SKatsushi Kobayashi txloop:
6983c60ba66SKatsushi Kobayashi 	xfer = STAILQ_FIRST(&dbch->xferq.q);
6993c60ba66SKatsushi Kobayashi 	if(xfer == NULL){
7003c60ba66SKatsushi Kobayashi 		goto kick;
7013c60ba66SKatsushi Kobayashi 	}
7023c60ba66SKatsushi Kobayashi 	if(dbch->xferq.queued == 0 ){
7033c60ba66SKatsushi Kobayashi 		device_printf(sc->fc.dev, "TX queue empty\n");
7043c60ba66SKatsushi Kobayashi 	}
7053c60ba66SKatsushi Kobayashi 	STAILQ_REMOVE_HEAD(&dbch->xferq.q, link);
7063c60ba66SKatsushi Kobayashi 	db_tr->xfer = xfer;
7073c60ba66SKatsushi Kobayashi 	xfer->state = FWXF_START;
7083c60ba66SKatsushi Kobayashi 	dbch->xferq.packets++;
7093c60ba66SKatsushi Kobayashi 
7103c60ba66SKatsushi Kobayashi 	fp = (struct fw_pkt *)(xfer->send.buf + xfer->send.off);
7113c60ba66SKatsushi Kobayashi 	tcode = fp->mode.common.tcode;
7123c60ba66SKatsushi Kobayashi 
7133c60ba66SKatsushi Kobayashi 	ohcifp = (volatile struct fwohci_txpkthdr *) db_tr->db[1].db.immed;
7143c60ba66SKatsushi Kobayashi 	info = &tinfo[tcode];
7153c60ba66SKatsushi Kobayashi 	hdr_len = hdr_off = info->hdr_len;
7163c60ba66SKatsushi Kobayashi 	/* fw_asyreq must pass valid send.len */
7173c60ba66SKatsushi Kobayashi 	len = xfer->send.len;
7183c60ba66SKatsushi Kobayashi 	for( i = 0 ; i < hdr_off ; i+= 4){
7193c60ba66SKatsushi Kobayashi 		ohcifp->mode.ld[i/4] = ntohl(fp->mode.ld[i/4]);
7203c60ba66SKatsushi Kobayashi 	}
7213c60ba66SKatsushi Kobayashi 	ohcifp->mode.common.spd = xfer->spd;
7223c60ba66SKatsushi Kobayashi 	if (tcode == FWTCODE_STREAM ){
7233c60ba66SKatsushi Kobayashi 		hdr_len = 8;
7243c60ba66SKatsushi Kobayashi 		ohcifp->mode.stream.len = ntohs(fp->mode.stream.len);
7253c60ba66SKatsushi Kobayashi 	} else if (tcode == FWTCODE_PHY) {
7263c60ba66SKatsushi Kobayashi 		hdr_len = 12;
7273c60ba66SKatsushi Kobayashi 		ohcifp->mode.ld[1] = ntohl(fp->mode.ld[1]);
7283c60ba66SKatsushi Kobayashi 		ohcifp->mode.ld[2] = ntohl(fp->mode.ld[2]);
7293c60ba66SKatsushi Kobayashi 		ohcifp->mode.common.spd = 0;
7303c60ba66SKatsushi Kobayashi 		ohcifp->mode.common.tcode = FWOHCITCODE_PHY;
7313c60ba66SKatsushi Kobayashi 	} else {
7323c60ba66SKatsushi Kobayashi 		ohcifp->mode.asycomm.dst = ntohs(fp->mode.hdr.dst);
7333c60ba66SKatsushi Kobayashi 		ohcifp->mode.asycomm.srcbus = OHCI_ASYSRCBUS;
7343c60ba66SKatsushi Kobayashi 		ohcifp->mode.asycomm.tlrt |= FWRETRY_X;
7353c60ba66SKatsushi Kobayashi 	}
7363c60ba66SKatsushi Kobayashi 	db = &db_tr->db[0];
7373c60ba66SKatsushi Kobayashi  	db->db.desc.cmd = OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | hdr_len;
7383c60ba66SKatsushi Kobayashi  	db->db.desc.status = 0;
7393c60ba66SKatsushi Kobayashi /* Specify bound timer of asy. responce */
7403c60ba66SKatsushi Kobayashi 	if(&sc->atrs == dbch){
7413c60ba66SKatsushi Kobayashi  		db->db.desc.count
7423c60ba66SKatsushi Kobayashi 			 = (OREAD(sc, OHCI_CYCLETIMER) >> 12) + (1 << 13);
7433c60ba66SKatsushi Kobayashi 	}
7443c60ba66SKatsushi Kobayashi 
7453c60ba66SKatsushi Kobayashi 	db_tr->dbcnt = 2;
7463c60ba66SKatsushi Kobayashi 	db = &db_tr->db[db_tr->dbcnt];
7473c60ba66SKatsushi Kobayashi 	if(len > hdr_off){
7483c60ba66SKatsushi Kobayashi 		if (xfer->mbuf == NULL) {
7493c60ba66SKatsushi Kobayashi 			db->db.desc.addr
7503c60ba66SKatsushi Kobayashi 				= vtophys(xfer->send.buf + xfer->send.off) + hdr_off;
7513c60ba66SKatsushi Kobayashi 			db->db.desc.cmd
7523c60ba66SKatsushi Kobayashi 				= OHCI_OUTPUT_MORE | ((len - hdr_off) & 0xffff);
7533c60ba66SKatsushi Kobayashi  			db->db.desc.status = 0;
7543c60ba66SKatsushi Kobayashi 
7553c60ba66SKatsushi Kobayashi 			db_tr->dbcnt++;
7563c60ba66SKatsushi Kobayashi 		} else {
7573c60ba66SKatsushi Kobayashi 			/* XXX we assume mbuf chain is shorter than ndesc */
7583c60ba66SKatsushi Kobayashi 			m = xfer->mbuf;
7593c60ba66SKatsushi Kobayashi 			do {
7603c60ba66SKatsushi Kobayashi 				db->db.desc.addr
7613c60ba66SKatsushi Kobayashi 					= vtophys(mtod(m, caddr_t));
7623c60ba66SKatsushi Kobayashi 				db->db.desc.cmd = OHCI_OUTPUT_MORE | m->m_len;
7633c60ba66SKatsushi Kobayashi  				db->db.desc.status = 0;
7643c60ba66SKatsushi Kobayashi 				db++;
7653c60ba66SKatsushi Kobayashi 				db_tr->dbcnt++;
7663c60ba66SKatsushi Kobayashi 				m = m->m_next;
7673c60ba66SKatsushi Kobayashi 			} while (m != NULL);
7683c60ba66SKatsushi Kobayashi 		}
7693c60ba66SKatsushi Kobayashi 	}
7703c60ba66SKatsushi Kobayashi 	/* last db */
7713c60ba66SKatsushi Kobayashi 	LAST_DB(db_tr, db);
7723c60ba66SKatsushi Kobayashi  	db->db.desc.cmd |= OHCI_OUTPUT_LAST
7733c60ba66SKatsushi Kobayashi 			| OHCI_INTERRUPT_ALWAYS
7743c60ba66SKatsushi Kobayashi 			| OHCI_BRANCH_ALWAYS;
7753c60ba66SKatsushi Kobayashi  	db->db.desc.depend = vtophys(STAILQ_NEXT(db_tr, link)->db);
7763c60ba66SKatsushi Kobayashi 
7773c60ba66SKatsushi Kobayashi 	if(fsegment == -1 )
7783c60ba66SKatsushi Kobayashi 		fsegment = db_tr->dbcnt;
7793c60ba66SKatsushi Kobayashi 	if (dbch->pdb_tr != NULL) {
7803c60ba66SKatsushi Kobayashi 		LAST_DB(dbch->pdb_tr, db);
7813c60ba66SKatsushi Kobayashi  		db->db.desc.depend |= db_tr->dbcnt;
7823c60ba66SKatsushi Kobayashi 	}
7833c60ba66SKatsushi Kobayashi 	dbch->pdb_tr = db_tr;
7843c60ba66SKatsushi Kobayashi 	db_tr = STAILQ_NEXT(db_tr, link);
7853c60ba66SKatsushi Kobayashi 	if(db_tr != dbch->bottom){
7863c60ba66SKatsushi Kobayashi 		goto txloop;
7873c60ba66SKatsushi Kobayashi 	} else {
78817c3d42cSHidetoshi Shimokawa 		device_printf(sc->fc.dev, "fwohci_start: lack of db_trq\n");
7893c60ba66SKatsushi Kobayashi 		dbch->flags |= FWOHCI_DBCH_FULL;
7903c60ba66SKatsushi Kobayashi 	}
7913c60ba66SKatsushi Kobayashi kick:
7923c60ba66SKatsushi Kobayashi 	if (firewire_debug) printf("kick\n");
7933c60ba66SKatsushi Kobayashi 	/* kick asy q */
7943c60ba66SKatsushi Kobayashi 
7953c60ba66SKatsushi Kobayashi 	if(dbch->xferq.flag & FWXFERQ_RUNNING) {
7963c60ba66SKatsushi Kobayashi 		OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_WAKE);
7973c60ba66SKatsushi Kobayashi 	} else {
79817c3d42cSHidetoshi Shimokawa 		if (bootverbose)
79917c3d42cSHidetoshi Shimokawa 			device_printf(sc->fc.dev, "start AT DMA status=%x\n",
8003c60ba66SKatsushi Kobayashi 					OREAD(sc, OHCI_DMACTL(off)));
8013c60ba66SKatsushi Kobayashi 		OWRITE(sc, OHCI_DMACMD(off), vtophys(dbch->top->db) | fsegment);
8023c60ba66SKatsushi Kobayashi 		OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_RUN);
8033c60ba66SKatsushi Kobayashi 		dbch->xferq.flag |= FWXFERQ_RUNNING;
8043c60ba66SKatsushi Kobayashi 	}
805c572b810SHidetoshi Shimokawa 
8063c60ba66SKatsushi Kobayashi 	dbch->top = db_tr;
8073c60ba66SKatsushi Kobayashi 	splx(s);
8083c60ba66SKatsushi Kobayashi 	return;
8093c60ba66SKatsushi Kobayashi }
810c572b810SHidetoshi Shimokawa 
811c572b810SHidetoshi Shimokawa static void
812c572b810SHidetoshi Shimokawa fwohci_drain_atq(struct firewire_comm *fc, struct fw_xfer *xfer)
8133c60ba66SKatsushi Kobayashi {
8143c60ba66SKatsushi Kobayashi 	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
8153c60ba66SKatsushi Kobayashi 	fwohci_drain(&sc->fc, xfer, &(sc->atrq));
8163c60ba66SKatsushi Kobayashi 	return;
8173c60ba66SKatsushi Kobayashi }
818c572b810SHidetoshi Shimokawa 
819c572b810SHidetoshi Shimokawa static void
820c572b810SHidetoshi Shimokawa fwohci_drain_ats(struct firewire_comm *fc, struct fw_xfer *xfer)
8213c60ba66SKatsushi Kobayashi {
8223c60ba66SKatsushi Kobayashi 	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
8233c60ba66SKatsushi Kobayashi 	fwohci_drain(&sc->fc, xfer, &(sc->atrs));
8243c60ba66SKatsushi Kobayashi 	return;
8253c60ba66SKatsushi Kobayashi }
826c572b810SHidetoshi Shimokawa 
827c572b810SHidetoshi Shimokawa static void
828c572b810SHidetoshi Shimokawa fwohci_start_atq(struct firewire_comm *fc)
8293c60ba66SKatsushi Kobayashi {
8303c60ba66SKatsushi Kobayashi 	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
8313c60ba66SKatsushi Kobayashi 	fwohci_start( sc, &(sc->atrq));
8323c60ba66SKatsushi Kobayashi 	return;
8333c60ba66SKatsushi Kobayashi }
834c572b810SHidetoshi Shimokawa 
835c572b810SHidetoshi Shimokawa static void
836c572b810SHidetoshi Shimokawa fwohci_start_ats(struct firewire_comm *fc)
8373c60ba66SKatsushi Kobayashi {
8383c60ba66SKatsushi Kobayashi 	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
8393c60ba66SKatsushi Kobayashi 	fwohci_start( sc, &(sc->atrs));
8403c60ba66SKatsushi Kobayashi 	return;
8413c60ba66SKatsushi Kobayashi }
842c572b810SHidetoshi Shimokawa 
843c572b810SHidetoshi Shimokawa void
844c572b810SHidetoshi Shimokawa fwohci_txd(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
8453c60ba66SKatsushi Kobayashi {
8463c60ba66SKatsushi Kobayashi 	int s, err = 0;
8473c60ba66SKatsushi Kobayashi 	struct fwohcidb_tr *tr;
8483c60ba66SKatsushi Kobayashi 	volatile struct fwohcidb *db;
8493c60ba66SKatsushi Kobayashi 	struct fw_xfer *xfer;
8503c60ba66SKatsushi Kobayashi 	u_int32_t off;
8513c60ba66SKatsushi Kobayashi 	u_int stat;
8523c60ba66SKatsushi Kobayashi 	int	packets;
8533c60ba66SKatsushi Kobayashi 	struct firewire_comm *fc = (struct firewire_comm *)sc;
8543c60ba66SKatsushi Kobayashi 	if(&sc->atrq == dbch){
8553c60ba66SKatsushi Kobayashi 		off = OHCI_ATQOFF;
8563c60ba66SKatsushi Kobayashi 	}else if(&sc->atrs == dbch){
8573c60ba66SKatsushi Kobayashi 		off = OHCI_ATSOFF;
8583c60ba66SKatsushi Kobayashi 	}else{
8593c60ba66SKatsushi Kobayashi 		return;
8603c60ba66SKatsushi Kobayashi 	}
8613c60ba66SKatsushi Kobayashi 	s = splfw();
8623c60ba66SKatsushi Kobayashi 	tr = dbch->bottom;
8633c60ba66SKatsushi Kobayashi 	packets = 0;
8643c60ba66SKatsushi Kobayashi 	while(dbch->xferq.queued > 0){
8653c60ba66SKatsushi Kobayashi 		LAST_DB(tr, db);
8663c60ba66SKatsushi Kobayashi 		if(!(db->db.desc.status & OHCI_CNTL_DMA_ACTIVE)){
8673c60ba66SKatsushi Kobayashi 			if (fc->status != FWBUSRESET)
8683c60ba66SKatsushi Kobayashi 				/* maybe out of order?? */
8693c60ba66SKatsushi Kobayashi 				goto out;
8703c60ba66SKatsushi Kobayashi 		}
8713c60ba66SKatsushi Kobayashi 		if(db->db.desc.status & OHCI_CNTL_DMA_DEAD) {
8723c60ba66SKatsushi Kobayashi #ifdef OHCI_DEBUG
8733c60ba66SKatsushi Kobayashi 			dump_dma(sc, ch);
8743c60ba66SKatsushi Kobayashi 			dump_db(sc, ch);
8753c60ba66SKatsushi Kobayashi #endif
8763c60ba66SKatsushi Kobayashi /* Stop DMA */
8773c60ba66SKatsushi Kobayashi 			OWRITE(sc, OHCI_DMACTLCLR(off), OHCI_CNTL_DMA_RUN);
8783c60ba66SKatsushi Kobayashi 			device_printf(sc->fc.dev, "force reset AT FIFO\n");
8793c60ba66SKatsushi Kobayashi 			OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_LINKEN);
8803c60ba66SKatsushi Kobayashi 			OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LPS | OHCI_HCC_LINKEN);
8813c60ba66SKatsushi Kobayashi 			OWRITE(sc, OHCI_DMACTLCLR(off), OHCI_CNTL_DMA_RUN);
8823c60ba66SKatsushi Kobayashi 		}
8833c60ba66SKatsushi Kobayashi 		stat = db->db.desc.status & FWOHCIEV_MASK;
8843c60ba66SKatsushi Kobayashi 		switch(stat){
8853c60ba66SKatsushi Kobayashi 		case FWOHCIEV_ACKCOMPL:
8863c60ba66SKatsushi Kobayashi 		case FWOHCIEV_ACKPEND:
8873c60ba66SKatsushi Kobayashi 			err = 0;
8883c60ba66SKatsushi Kobayashi 			break;
8893c60ba66SKatsushi Kobayashi 		case FWOHCIEV_ACKBSA:
8903c60ba66SKatsushi Kobayashi 		case FWOHCIEV_ACKBSB:
8913c60ba66SKatsushi Kobayashi 			device_printf(sc->fc.dev, "txd err=%2x %s\n", stat, fwohcicode[stat]);
8923c60ba66SKatsushi Kobayashi 		case FWOHCIEV_ACKBSX:
8933c60ba66SKatsushi Kobayashi 			err = EBUSY;
8943c60ba66SKatsushi Kobayashi 			break;
8953c60ba66SKatsushi Kobayashi 		case FWOHCIEV_FLUSHED:
8963c60ba66SKatsushi Kobayashi 		case FWOHCIEV_ACKTARD:
8973c60ba66SKatsushi Kobayashi 			device_printf(sc->fc.dev, "txd err=%2x %s\n", stat, fwohcicode[stat]);
8983c60ba66SKatsushi Kobayashi 			err = EAGAIN;
8993c60ba66SKatsushi Kobayashi 			break;
9003c60ba66SKatsushi Kobayashi 		case FWOHCIEV_MISSACK:
9013c60ba66SKatsushi Kobayashi 		case FWOHCIEV_UNDRRUN:
9023c60ba66SKatsushi Kobayashi 		case FWOHCIEV_OVRRUN:
9033c60ba66SKatsushi Kobayashi 		case FWOHCIEV_DESCERR:
9043c60ba66SKatsushi Kobayashi 		case FWOHCIEV_DTRDERR:
9053c60ba66SKatsushi Kobayashi 		case FWOHCIEV_TIMEOUT:
9063c60ba66SKatsushi Kobayashi 		case FWOHCIEV_TCODERR:
9073c60ba66SKatsushi Kobayashi 		case FWOHCIEV_UNKNOWN:
9083c60ba66SKatsushi Kobayashi 		case FWOHCIEV_ACKDERR:
9093c60ba66SKatsushi Kobayashi 		case FWOHCIEV_ACKTERR:
9103c60ba66SKatsushi Kobayashi 		default:
9113c60ba66SKatsushi Kobayashi 			device_printf(sc->fc.dev, "txd err=%2x %s\n",
9123c60ba66SKatsushi Kobayashi 							stat, fwohcicode[stat]);
9133c60ba66SKatsushi Kobayashi 			err = EINVAL;
9143c60ba66SKatsushi Kobayashi 			break;
9153c60ba66SKatsushi Kobayashi 		}
9163c60ba66SKatsushi Kobayashi 		if(tr->xfer != NULL){
9173c60ba66SKatsushi Kobayashi 			xfer = tr->xfer;
9183c60ba66SKatsushi Kobayashi 			xfer->state = FWXF_SENT;
9193c60ba66SKatsushi Kobayashi 			if(err == EBUSY && fc->status != FWBUSRESET){
9203c60ba66SKatsushi Kobayashi 				xfer->state = FWXF_BUSY;
9213c60ba66SKatsushi Kobayashi 				switch(xfer->act_type){
9223c60ba66SKatsushi Kobayashi 				case FWACT_XFER:
9233c60ba66SKatsushi Kobayashi 					xfer->resp = err;
9243c60ba66SKatsushi Kobayashi 					if(xfer->retry_req != NULL){
9253c60ba66SKatsushi Kobayashi 						xfer->retry_req(xfer);
9263c60ba66SKatsushi Kobayashi 					}
9273c60ba66SKatsushi Kobayashi 					break;
9283c60ba66SKatsushi Kobayashi 				default:
9293c60ba66SKatsushi Kobayashi 					break;
9303c60ba66SKatsushi Kobayashi 				}
9313c60ba66SKatsushi Kobayashi 			} else if( stat != FWOHCIEV_ACKPEND){
9323c60ba66SKatsushi Kobayashi 				if (stat != FWOHCIEV_ACKCOMPL)
9333c60ba66SKatsushi Kobayashi 					xfer->state = FWXF_SENTERR;
9343c60ba66SKatsushi Kobayashi 				xfer->resp = err;
9353c60ba66SKatsushi Kobayashi 				switch(xfer->act_type){
9363c60ba66SKatsushi Kobayashi 				case FWACT_XFER:
9373c60ba66SKatsushi Kobayashi 					fw_xfer_done(xfer);
9383c60ba66SKatsushi Kobayashi 					break;
9393c60ba66SKatsushi Kobayashi 				default:
9403c60ba66SKatsushi Kobayashi 					break;
9413c60ba66SKatsushi Kobayashi 				}
9423c60ba66SKatsushi Kobayashi 			}
9433c60ba66SKatsushi Kobayashi 			dbch->xferq.queued --;
9443c60ba66SKatsushi Kobayashi 		}
9453c60ba66SKatsushi Kobayashi 		tr->xfer = NULL;
9463c60ba66SKatsushi Kobayashi 
9473c60ba66SKatsushi Kobayashi 		packets ++;
9483c60ba66SKatsushi Kobayashi 		tr = STAILQ_NEXT(tr, link);
9493c60ba66SKatsushi Kobayashi 		dbch->bottom = tr;
9503c60ba66SKatsushi Kobayashi 	}
9513c60ba66SKatsushi Kobayashi out:
9523c60ba66SKatsushi Kobayashi 	if ((dbch->flags & FWOHCI_DBCH_FULL) && packets > 0) {
9533c60ba66SKatsushi Kobayashi 		printf("make free slot\n");
9543c60ba66SKatsushi Kobayashi 		dbch->flags &= ~FWOHCI_DBCH_FULL;
9553c60ba66SKatsushi Kobayashi 		fwohci_start(sc, dbch);
9563c60ba66SKatsushi Kobayashi 	}
9573c60ba66SKatsushi Kobayashi 	splx(s);
9583c60ba66SKatsushi Kobayashi }
959c572b810SHidetoshi Shimokawa 
960c572b810SHidetoshi Shimokawa static void
961c572b810SHidetoshi Shimokawa fwohci_drain(struct firewire_comm *fc, struct fw_xfer *xfer, struct fwohci_dbch *dbch)
9623c60ba66SKatsushi Kobayashi {
9633c60ba66SKatsushi Kobayashi 	int i, s;
9643c60ba66SKatsushi Kobayashi 	struct fwohcidb_tr *tr;
9653c60ba66SKatsushi Kobayashi 
9663c60ba66SKatsushi Kobayashi 	if(xfer->state != FWXF_START) return;
9673c60ba66SKatsushi Kobayashi 
9683c60ba66SKatsushi Kobayashi 	s = splfw();
9693c60ba66SKatsushi Kobayashi 	tr = dbch->bottom;
9703c60ba66SKatsushi Kobayashi 	for( i = 0 ; i <= dbch->xferq.queued  ; i ++){
9713c60ba66SKatsushi Kobayashi 		if(tr->xfer == xfer){
9723c60ba66SKatsushi Kobayashi 			s = splfw();
9733c60ba66SKatsushi Kobayashi 			tr->xfer = NULL;
9743c60ba66SKatsushi Kobayashi 			dbch->xferq.queued --;
9753c60ba66SKatsushi Kobayashi #if 1
9763c60ba66SKatsushi Kobayashi 			/* XXX */
9773c60ba66SKatsushi Kobayashi 			if (tr == dbch->bottom)
9783c60ba66SKatsushi Kobayashi 				dbch->bottom = STAILQ_NEXT(tr, link);
9793c60ba66SKatsushi Kobayashi #endif
9803c60ba66SKatsushi Kobayashi 			if (dbch->flags & FWOHCI_DBCH_FULL) {
9813c60ba66SKatsushi Kobayashi 				printf("fwohci_drain: make slot\n");
9823c60ba66SKatsushi Kobayashi 				dbch->flags &= ~FWOHCI_DBCH_FULL;
9833c60ba66SKatsushi Kobayashi 				fwohci_start((struct fwohci_softc *)fc, dbch);
9843c60ba66SKatsushi Kobayashi 			}
9853c60ba66SKatsushi Kobayashi 
9863c60ba66SKatsushi Kobayashi 			splx(s);
9873c60ba66SKatsushi Kobayashi 			break;
9883c60ba66SKatsushi Kobayashi 		}
9893c60ba66SKatsushi Kobayashi 		tr = STAILQ_NEXT(tr, link);
9903c60ba66SKatsushi Kobayashi 	}
9913c60ba66SKatsushi Kobayashi 	splx(s);
9923c60ba66SKatsushi Kobayashi 	return;
9933c60ba66SKatsushi Kobayashi }
9943c60ba66SKatsushi Kobayashi 
995c572b810SHidetoshi Shimokawa static void
996c572b810SHidetoshi Shimokawa fwohci_db_free(struct fwohci_dbch *dbch)
9973c60ba66SKatsushi Kobayashi {
9983c60ba66SKatsushi Kobayashi 	struct fwohcidb_tr *db_tr;
9993c60ba66SKatsushi Kobayashi 	int idb;
10003c60ba66SKatsushi Kobayashi 
10013c60ba66SKatsushi Kobayashi 	if(!(dbch->xferq.flag & FWXFERQ_EXTBUF)){
10023c60ba66SKatsushi Kobayashi 		for(db_tr = STAILQ_FIRST(&dbch->db_trq), idb = 0;
10033c60ba66SKatsushi Kobayashi 			idb < dbch->ndb;
10043c60ba66SKatsushi Kobayashi 			db_tr = STAILQ_NEXT(db_tr, link), idb++){
10053c60ba66SKatsushi Kobayashi 			free(db_tr->buf, M_DEVBUF);
10063c60ba66SKatsushi Kobayashi 			db_tr->buf = NULL;
10073c60ba66SKatsushi Kobayashi 		}
10083c60ba66SKatsushi Kobayashi 	}
10093c60ba66SKatsushi Kobayashi 	dbch->ndb = 0;
10103c60ba66SKatsushi Kobayashi 	db_tr = STAILQ_FIRST(&dbch->db_trq);
10113c60ba66SKatsushi Kobayashi 	contigfree((void *)(uintptr_t)(volatile void *)db_tr->db,
10123c60ba66SKatsushi Kobayashi 		sizeof(struct fwohcidb) * dbch->ndesc * dbch->ndb, M_DEVBUF);
10133c60ba66SKatsushi Kobayashi 	/* Attach DB to DMA ch. */
10143c60ba66SKatsushi Kobayashi 	free(db_tr, M_DEVBUF);
10153c60ba66SKatsushi Kobayashi 	STAILQ_INIT(&dbch->db_trq);
10163c60ba66SKatsushi Kobayashi }
1017c572b810SHidetoshi Shimokawa 
1018c572b810SHidetoshi Shimokawa static void
1019c572b810SHidetoshi Shimokawa fwohci_db_init(struct fwohci_dbch *dbch)
10203c60ba66SKatsushi Kobayashi {
10213c60ba66SKatsushi Kobayashi 	int	idb;
10223c60ba66SKatsushi Kobayashi 	struct fwohcidb *db;
10233c60ba66SKatsushi Kobayashi 	struct fwohcidb_tr *db_tr;
10243c60ba66SKatsushi Kobayashi 	/* allocate DB entries and attach one to each DMA channels */
10253c60ba66SKatsushi Kobayashi 	/* DB entry must start at 16 bytes bounary. */
10263c60ba66SKatsushi Kobayashi 	dbch->frag.buf = NULL;
10273c60ba66SKatsushi Kobayashi 	dbch->frag.len = 0;
10283c60ba66SKatsushi Kobayashi 	dbch->frag.plen = 0;
10293c60ba66SKatsushi Kobayashi 	dbch->xferq.queued = 0;
10303c60ba66SKatsushi Kobayashi 	dbch->pdb_tr = NULL;
10313c60ba66SKatsushi Kobayashi 
10323c60ba66SKatsushi Kobayashi 	STAILQ_INIT(&dbch->db_trq);
10333c60ba66SKatsushi Kobayashi 	db_tr = (struct fwohcidb_tr *)
10343c60ba66SKatsushi Kobayashi 		malloc(sizeof(struct fwohcidb_tr) * dbch->ndb,
10353c60ba66SKatsushi Kobayashi 		M_DEVBUF, M_DONTWAIT);
10363c60ba66SKatsushi Kobayashi 	if(db_tr == NULL){
10373c60ba66SKatsushi Kobayashi 		return;
10383c60ba66SKatsushi Kobayashi 	}
10393c60ba66SKatsushi Kobayashi 	db = (struct fwohcidb *)
10403c60ba66SKatsushi Kobayashi 		contigmalloc(sizeof (struct fwohcidb) * dbch->ndesc * dbch->ndb,
10413c60ba66SKatsushi Kobayashi 		M_DEVBUF, M_DONTWAIT, 0x10000, 0xffffffff, PAGE_SIZE, 0ul);
10423c60ba66SKatsushi Kobayashi 	if(db == NULL){
10433c60ba66SKatsushi Kobayashi 		printf("fwochi_db_init: contigmalloc failed\n");
10443c60ba66SKatsushi Kobayashi 		return;
10453c60ba66SKatsushi Kobayashi 	}
10463c60ba66SKatsushi Kobayashi 	bzero(db, sizeof (struct fwohcidb) * dbch->ndesc * dbch->ndb);
10473c60ba66SKatsushi Kobayashi 	/* Attach DB to DMA ch. */
10483c60ba66SKatsushi Kobayashi 	for(idb = 0 ; idb < dbch->ndb ; idb++){
10493c60ba66SKatsushi Kobayashi 		db_tr->dbcnt = 0;
10503c60ba66SKatsushi Kobayashi 		db_tr->db = &db[idb * dbch->ndesc];
10513c60ba66SKatsushi Kobayashi 		STAILQ_INSERT_TAIL(&dbch->db_trq, db_tr, link);
10523c60ba66SKatsushi Kobayashi 		if(!(dbch->xferq.flag & FWXFERQ_PACKET) &&
10533c60ba66SKatsushi Kobayashi 			(idb % dbch->xferq.bnpacket == 0)){
10543c60ba66SKatsushi Kobayashi 			dbch->xferq.bulkxfer[idb/dbch->xferq.bnpacket].start
10553c60ba66SKatsushi Kobayashi 				= (caddr_t)db_tr;
10563c60ba66SKatsushi Kobayashi 		}
10573c60ba66SKatsushi Kobayashi 		if((!(dbch->xferq.flag & FWXFERQ_PACKET)) &&
10583c60ba66SKatsushi Kobayashi 			((idb + 1)% dbch->xferq.bnpacket == 0)){
10593c60ba66SKatsushi Kobayashi 			dbch->xferq.bulkxfer[idb/dbch->xferq.bnpacket].end
10603c60ba66SKatsushi Kobayashi 				= (caddr_t)db_tr;
10613c60ba66SKatsushi Kobayashi 		}
10623c60ba66SKatsushi Kobayashi 		db_tr++;
10633c60ba66SKatsushi Kobayashi 	}
10643c60ba66SKatsushi Kobayashi 	STAILQ_LAST(&dbch->db_trq, fwohcidb_tr,link)->link.stqe_next
10653c60ba66SKatsushi Kobayashi 			= STAILQ_FIRST(&dbch->db_trq);
10663c60ba66SKatsushi Kobayashi 	dbch->top = STAILQ_FIRST(&dbch->db_trq);
10673c60ba66SKatsushi Kobayashi 	dbch->bottom = dbch->top;
10683c60ba66SKatsushi Kobayashi }
1069c572b810SHidetoshi Shimokawa 
1070c572b810SHidetoshi Shimokawa static int
1071c572b810SHidetoshi Shimokawa fwohci_itx_disable(struct firewire_comm *fc, int dmach)
10723c60ba66SKatsushi Kobayashi {
10733c60ba66SKatsushi Kobayashi 	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
10743c60ba66SKatsushi Kobayashi 	OWRITE(sc, OHCI_ITCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
10753c60ba66SKatsushi Kobayashi 	OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach);
10763c60ba66SKatsushi Kobayashi 	OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach);
10773c60ba66SKatsushi Kobayashi 	fwohci_db_free(&sc->it[dmach]);
10783c60ba66SKatsushi Kobayashi 	sc->it[dmach].xferq.flag &= ~FWXFERQ_RUNNING;
10793c60ba66SKatsushi Kobayashi 	return 0;
10803c60ba66SKatsushi Kobayashi }
1081c572b810SHidetoshi Shimokawa 
1082c572b810SHidetoshi Shimokawa static int
1083c572b810SHidetoshi Shimokawa fwohci_irx_disable(struct firewire_comm *fc, int dmach)
10843c60ba66SKatsushi Kobayashi {
10853c60ba66SKatsushi Kobayashi 	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
10863c60ba66SKatsushi Kobayashi 
10873c60ba66SKatsushi Kobayashi 	OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
10883c60ba66SKatsushi Kobayashi 	OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach);
10893c60ba66SKatsushi Kobayashi 	OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach);
10903c60ba66SKatsushi Kobayashi 	if(sc->ir[dmach].dummy != NULL){
10913c60ba66SKatsushi Kobayashi 		free(sc->ir[dmach].dummy, M_DEVBUF);
10923c60ba66SKatsushi Kobayashi 	}
10933c60ba66SKatsushi Kobayashi 	sc->ir[dmach].dummy = NULL;
10943c60ba66SKatsushi Kobayashi 	fwohci_db_free(&sc->ir[dmach]);
10953c60ba66SKatsushi Kobayashi 	sc->ir[dmach].xferq.flag &= ~FWXFERQ_RUNNING;
10963c60ba66SKatsushi Kobayashi 	return 0;
10973c60ba66SKatsushi Kobayashi }
1098c572b810SHidetoshi Shimokawa 
1099c572b810SHidetoshi Shimokawa static void
1100c572b810SHidetoshi Shimokawa fwohci_irx_post (struct firewire_comm *fc , u_int32_t *qld)
11013c60ba66SKatsushi Kobayashi {
11023c60ba66SKatsushi Kobayashi 	qld[0] = ntohl(qld[0]);
11033c60ba66SKatsushi Kobayashi 	return;
11043c60ba66SKatsushi Kobayashi }
1105c572b810SHidetoshi Shimokawa 
1106c572b810SHidetoshi Shimokawa static int
1107c572b810SHidetoshi Shimokawa fwohci_irxpp_enable(struct firewire_comm *fc, int dmach)
11083c60ba66SKatsushi Kobayashi {
11093c60ba66SKatsushi Kobayashi 	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
11103c60ba66SKatsushi Kobayashi 	int err = 0;
11113c60ba66SKatsushi Kobayashi 	unsigned short tag, ich;
11123c60ba66SKatsushi Kobayashi 
11133c60ba66SKatsushi Kobayashi 	tag = (sc->ir[dmach].xferq.flag >> 6) & 3;
11143c60ba66SKatsushi Kobayashi 	ich = sc->ir[dmach].xferq.flag & 0x3f;
11153c60ba66SKatsushi Kobayashi 
11163c60ba66SKatsushi Kobayashi #if 0
11173c60ba66SKatsushi Kobayashi 	if(STAILQ_FIRST(&fc->ir[dmach]->q) != NULL){
11183c60ba66SKatsushi Kobayashi 		wakeup(fc->ir[dmach]);
11193c60ba66SKatsushi Kobayashi 		return err;
11203c60ba66SKatsushi Kobayashi 	}
11213c60ba66SKatsushi Kobayashi #endif
11223c60ba66SKatsushi Kobayashi 
11233c60ba66SKatsushi Kobayashi 	OWRITE(sc, OHCI_IRMATCH(dmach), tagbit[tag] | ich);
11243c60ba66SKatsushi Kobayashi 	if(!(sc->ir[dmach].xferq.flag & FWXFERQ_RUNNING)){
11253c60ba66SKatsushi Kobayashi 		sc->ir[dmach].xferq.queued = 0;
11263c60ba66SKatsushi Kobayashi 		sc->ir[dmach].ndb = NDB;
11273c60ba66SKatsushi Kobayashi 		sc->ir[dmach].xferq.psize = FWPMAX_S400;
11283c60ba66SKatsushi Kobayashi 		sc->ir[dmach].ndesc = 1;
11293c60ba66SKatsushi Kobayashi 		fwohci_db_init(&sc->ir[dmach]);
11303c60ba66SKatsushi Kobayashi 		err = fwohci_rx_enable(sc, &sc->ir[dmach]);
11313c60ba66SKatsushi Kobayashi 	}
11323c60ba66SKatsushi Kobayashi 	if(err){
11333c60ba66SKatsushi Kobayashi 		device_printf(sc->fc.dev, "err in IRX setting\n");
11343c60ba66SKatsushi Kobayashi 		return err;
11353c60ba66SKatsushi Kobayashi 	}
11363c60ba66SKatsushi Kobayashi 	if(!(OREAD(sc, OHCI_IRCTL(dmach)) & OHCI_CNTL_DMA_ACTIVE)){
11373c60ba66SKatsushi Kobayashi 		OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
11383c60ba66SKatsushi Kobayashi 		OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach);
11393c60ba66SKatsushi Kobayashi 		OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach);
11403c60ba66SKatsushi Kobayashi 		OWRITE(sc, OHCI_IR_MASK, 1 << dmach);
11413c60ba66SKatsushi Kobayashi 		OWRITE(sc, OHCI_IRCTLCLR(dmach), 0xf8000000);
11423c60ba66SKatsushi Kobayashi 		OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_ISOHDR);
11433c60ba66SKatsushi Kobayashi 		OWRITE(sc, OHCI_IRCMD(dmach),
11443c60ba66SKatsushi Kobayashi 			vtophys(sc->ir[dmach].top->db) | 1);
11453c60ba66SKatsushi Kobayashi 		OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_DMA_RUN);
11463c60ba66SKatsushi Kobayashi 		OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IR);
11473c60ba66SKatsushi Kobayashi 	}
11483c60ba66SKatsushi Kobayashi 	return err;
11493c60ba66SKatsushi Kobayashi }
1150c572b810SHidetoshi Shimokawa 
1151c572b810SHidetoshi Shimokawa static int
1152c572b810SHidetoshi Shimokawa fwohci_tx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
11533c60ba66SKatsushi Kobayashi {
11543c60ba66SKatsushi Kobayashi 	int err = 0;
11553c60ba66SKatsushi Kobayashi 	int idb, z, i, dmach = 0;
11563c60ba66SKatsushi Kobayashi 	u_int32_t off = NULL;
11573c60ba66SKatsushi Kobayashi 	struct fwohcidb_tr *db_tr;
11583c60ba66SKatsushi Kobayashi 
11593c60ba66SKatsushi Kobayashi 	if(!(dbch->xferq.flag & FWXFERQ_EXTBUF)){
11603c60ba66SKatsushi Kobayashi 		err = EINVAL;
11613c60ba66SKatsushi Kobayashi 		return err;
11623c60ba66SKatsushi Kobayashi 	}
11633c60ba66SKatsushi Kobayashi 	z = dbch->ndesc;
11643c60ba66SKatsushi Kobayashi 	for(dmach = 0 ; dmach < sc->fc.nisodma ; dmach++){
11653c60ba66SKatsushi Kobayashi 		if( &sc->it[dmach] == dbch){
11663c60ba66SKatsushi Kobayashi 			off = OHCI_ITOFF(dmach);
11673c60ba66SKatsushi Kobayashi 			break;
11683c60ba66SKatsushi Kobayashi 		}
11693c60ba66SKatsushi Kobayashi 	}
11703c60ba66SKatsushi Kobayashi 	if(off == NULL){
11713c60ba66SKatsushi Kobayashi 		err = EINVAL;
11723c60ba66SKatsushi Kobayashi 		return err;
11733c60ba66SKatsushi Kobayashi 	}
11743c60ba66SKatsushi Kobayashi 	if(dbch->xferq.flag & FWXFERQ_RUNNING)
11753c60ba66SKatsushi Kobayashi 		return err;
11763c60ba66SKatsushi Kobayashi 	dbch->xferq.flag |= FWXFERQ_RUNNING;
11773c60ba66SKatsushi Kobayashi 	for( i = 0, dbch->bottom = dbch->top; i < (dbch->ndb - 1); i++){
11783c60ba66SKatsushi Kobayashi 		dbch->bottom = STAILQ_NEXT(dbch->bottom, link);
11793c60ba66SKatsushi Kobayashi 	}
11803c60ba66SKatsushi Kobayashi 	db_tr = dbch->top;
11813c60ba66SKatsushi Kobayashi 	for( idb = 0 ; idb < dbch->ndb ; idb ++){
11823c60ba66SKatsushi Kobayashi 		fwohci_add_tx_buf(db_tr,
11833c60ba66SKatsushi Kobayashi 			dbch->xferq.psize, dbch->xferq.flag,
11843c60ba66SKatsushi Kobayashi 			dbch->xferq.buf + dbch->xferq.psize * idb);
11853c60ba66SKatsushi Kobayashi 		if(STAILQ_NEXT(db_tr, link) == NULL){
11863c60ba66SKatsushi Kobayashi 			break;
11873c60ba66SKatsushi Kobayashi 		}
11883c60ba66SKatsushi Kobayashi 		db_tr->db[0].db.desc.depend
11893c60ba66SKatsushi Kobayashi 			= vtophys(STAILQ_NEXT(db_tr, link)->db) | z;
11903c60ba66SKatsushi Kobayashi 		db_tr->db[db_tr->dbcnt - 1].db.desc.depend
11913c60ba66SKatsushi Kobayashi 			= vtophys(STAILQ_NEXT(db_tr, link)->db) | z;
11923c60ba66SKatsushi Kobayashi 		if(dbch->xferq.flag & FWXFERQ_EXTBUF){
11933c60ba66SKatsushi Kobayashi 			if(((idb + 1 ) % dbch->xferq.bnpacket) == 0){
11943c60ba66SKatsushi Kobayashi 				db_tr->db[db_tr->dbcnt - 1].db.desc.cmd
11953c60ba66SKatsushi Kobayashi 					|= OHCI_INTERRUPT_ALWAYS;
11963c60ba66SKatsushi Kobayashi 				db_tr->db[0].db.desc.depend &= ~0xf;
11973c60ba66SKatsushi Kobayashi 				db_tr->db[db_tr->dbcnt - 1].db.desc.depend &=
11983c60ba66SKatsushi Kobayashi 						~0xf;
11993c60ba66SKatsushi Kobayashi 			}
12003c60ba66SKatsushi Kobayashi 		}
12013c60ba66SKatsushi Kobayashi 		db_tr = STAILQ_NEXT(db_tr, link);
12023c60ba66SKatsushi Kobayashi 	}
12033c60ba66SKatsushi Kobayashi 	dbch->bottom->db[db_tr->dbcnt - 1].db.desc.depend &= 0xfffffff0;
12043c60ba66SKatsushi Kobayashi 	return err;
12053c60ba66SKatsushi Kobayashi }
1206c572b810SHidetoshi Shimokawa 
1207c572b810SHidetoshi Shimokawa static int
1208c572b810SHidetoshi Shimokawa fwohci_rx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
12093c60ba66SKatsushi Kobayashi {
12103c60ba66SKatsushi Kobayashi 	int err = 0;
12113c60ba66SKatsushi Kobayashi 	int idb, z, i, dmach = 0;
12123c60ba66SKatsushi Kobayashi 	u_int32_t off = NULL;
12133c60ba66SKatsushi Kobayashi 	struct fwohcidb_tr *db_tr;
12143c60ba66SKatsushi Kobayashi 
12153c60ba66SKatsushi Kobayashi 	z = dbch->ndesc;
12163c60ba66SKatsushi Kobayashi 	if(&sc->arrq == dbch){
12173c60ba66SKatsushi Kobayashi 		off = OHCI_ARQOFF;
12183c60ba66SKatsushi Kobayashi 	}else if(&sc->arrs == dbch){
12193c60ba66SKatsushi Kobayashi 		off = OHCI_ARSOFF;
12203c60ba66SKatsushi Kobayashi 	}else{
12213c60ba66SKatsushi Kobayashi 		for(dmach = 0 ; dmach < sc->fc.nisodma ; dmach++){
12223c60ba66SKatsushi Kobayashi 			if( &sc->ir[dmach] == dbch){
12233c60ba66SKatsushi Kobayashi 				off = OHCI_IROFF(dmach);
12243c60ba66SKatsushi Kobayashi 				break;
12253c60ba66SKatsushi Kobayashi 			}
12263c60ba66SKatsushi Kobayashi 		}
12273c60ba66SKatsushi Kobayashi 	}
12283c60ba66SKatsushi Kobayashi 	if(off == NULL){
12293c60ba66SKatsushi Kobayashi 		err = EINVAL;
12303c60ba66SKatsushi Kobayashi 		return err;
12313c60ba66SKatsushi Kobayashi 	}
12323c60ba66SKatsushi Kobayashi 	if(dbch->xferq.flag & FWXFERQ_STREAM){
12333c60ba66SKatsushi Kobayashi 		if(dbch->xferq.flag & FWXFERQ_RUNNING)
12343c60ba66SKatsushi Kobayashi 			return err;
12353c60ba66SKatsushi Kobayashi 	}else{
12363c60ba66SKatsushi Kobayashi 		if(dbch->xferq.flag & FWXFERQ_RUNNING){
12373c60ba66SKatsushi Kobayashi 			err = EBUSY;
12383c60ba66SKatsushi Kobayashi 			return err;
12393c60ba66SKatsushi Kobayashi 		}
12403c60ba66SKatsushi Kobayashi 	}
12413c60ba66SKatsushi Kobayashi 	dbch->xferq.flag |= FWXFERQ_RUNNING;
12423c60ba66SKatsushi Kobayashi 	for( i = 0, dbch->bottom = dbch->top; i < (dbch->ndb - 1); i++){
12433c60ba66SKatsushi Kobayashi 		dbch->bottom = STAILQ_NEXT(dbch->bottom, link);
12443c60ba66SKatsushi Kobayashi 	}
12453c60ba66SKatsushi Kobayashi 	db_tr = dbch->top;
12463c60ba66SKatsushi Kobayashi 	for( idb = 0 ; idb < dbch->ndb ; idb ++){
12473c60ba66SKatsushi Kobayashi 		if(!(dbch->xferq.flag & FWXFERQ_EXTBUF)){
12483c60ba66SKatsushi Kobayashi 			fwohci_add_rx_buf(db_tr,
12493c60ba66SKatsushi Kobayashi 				dbch->xferq.psize, dbch->xferq.flag, 0, NULL);
12503c60ba66SKatsushi Kobayashi 		}else{
12513c60ba66SKatsushi Kobayashi 			fwohci_add_rx_buf(db_tr,
12523c60ba66SKatsushi Kobayashi 				dbch->xferq.psize, dbch->xferq.flag,
12533c60ba66SKatsushi Kobayashi 				dbch->xferq.buf + dbch->xferq.psize * idb,
12543c60ba66SKatsushi Kobayashi 				dbch->dummy + sizeof(u_int32_t) * idb);
12553c60ba66SKatsushi Kobayashi 		}
12563c60ba66SKatsushi Kobayashi 		if(STAILQ_NEXT(db_tr, link) == NULL){
12573c60ba66SKatsushi Kobayashi 			break;
12583c60ba66SKatsushi Kobayashi 		}
12593c60ba66SKatsushi Kobayashi 		db_tr->db[db_tr->dbcnt - 1].db.desc.depend
12603c60ba66SKatsushi Kobayashi 			= vtophys(STAILQ_NEXT(db_tr, link)->db) | z;
12613c60ba66SKatsushi Kobayashi 		if(dbch->xferq.flag & FWXFERQ_EXTBUF){
12623c60ba66SKatsushi Kobayashi 			if(((idb + 1 ) % dbch->xferq.bnpacket) == 0){
12633c60ba66SKatsushi Kobayashi 				db_tr->db[db_tr->dbcnt - 1].db.desc.cmd
12643c60ba66SKatsushi Kobayashi 					|= OHCI_INTERRUPT_ALWAYS;
12653c60ba66SKatsushi Kobayashi 				db_tr->db[db_tr->dbcnt - 1].db.desc.depend &=
12663c60ba66SKatsushi Kobayashi 						~0xf;
12673c60ba66SKatsushi Kobayashi 			}
12683c60ba66SKatsushi Kobayashi 		}
12693c60ba66SKatsushi Kobayashi 		db_tr = STAILQ_NEXT(db_tr, link);
12703c60ba66SKatsushi Kobayashi 	}
12713c60ba66SKatsushi Kobayashi 	dbch->bottom->db[db_tr->dbcnt - 1].db.desc.depend &= 0xfffffff0;
12723c60ba66SKatsushi Kobayashi 	dbch->buf_offset = 0;
12733c60ba66SKatsushi Kobayashi 	if(dbch->xferq.flag & FWXFERQ_STREAM){
12743c60ba66SKatsushi Kobayashi 		return err;
12753c60ba66SKatsushi Kobayashi 	}else{
12763c60ba66SKatsushi Kobayashi 		OWRITE(sc, OHCI_DMACMD(off), vtophys(dbch->top->db) | z);
12773c60ba66SKatsushi Kobayashi 	}
12783c60ba66SKatsushi Kobayashi 	OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_RUN);
12793c60ba66SKatsushi Kobayashi 	return err;
12803c60ba66SKatsushi Kobayashi }
1281c572b810SHidetoshi Shimokawa 
1282c572b810SHidetoshi Shimokawa static int
1283c572b810SHidetoshi Shimokawa fwohci_itxbuf_enable(struct firewire_comm *fc, int dmach)
12843c60ba66SKatsushi Kobayashi {
12853c60ba66SKatsushi Kobayashi 	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
12863c60ba66SKatsushi Kobayashi 	int err = 0;
12873c60ba66SKatsushi Kobayashi 	unsigned short tag, ich;
12883c60ba66SKatsushi Kobayashi 	struct fwohci_dbch *dbch;
12893c60ba66SKatsushi Kobayashi 	struct fw_pkt *fp;
12903c60ba66SKatsushi Kobayashi 	struct fwohcidb_tr *db_tr;
12913c60ba66SKatsushi Kobayashi 
12923c60ba66SKatsushi Kobayashi 	tag = (sc->it[dmach].xferq.flag >> 6) & 3;
12933c60ba66SKatsushi Kobayashi 	ich = sc->it[dmach].xferq.flag & 0x3f;
12943c60ba66SKatsushi Kobayashi 	dbch = &sc->it[dmach];
12953c60ba66SKatsushi Kobayashi 	if(dbch->ndb == 0){
12963c60ba66SKatsushi Kobayashi 		dbch->xferq.queued = 0;
12973c60ba66SKatsushi Kobayashi 		dbch->ndb = dbch->xferq.bnpacket * dbch->xferq.bnchunk;
12983c60ba66SKatsushi Kobayashi 		dbch->ndesc = 3;
12993c60ba66SKatsushi Kobayashi 		fwohci_db_init(dbch);
13003c60ba66SKatsushi Kobayashi 		err = fwohci_tx_enable(sc, dbch);
13013c60ba66SKatsushi Kobayashi 	}
13023c60ba66SKatsushi Kobayashi 	if(err)
13033c60ba66SKatsushi Kobayashi 		return err;
13043c60ba66SKatsushi Kobayashi 	if(OREAD(sc, OHCI_ITCTL(dmach)) & OHCI_CNTL_DMA_ACTIVE){
13053c60ba66SKatsushi Kobayashi 		if(dbch->xferq.stdma2 != NULL){
13063c60ba66SKatsushi Kobayashi 			fwohci_txbufdb(sc, dmach, dbch->xferq.stdma2);
13073c60ba66SKatsushi Kobayashi 			((struct fwohcidb_tr *)
13083c60ba66SKatsushi Kobayashi 		(dbch->xferq.stdma->end))->db[dbch->ndesc - 1].db.desc.cmd
13093c60ba66SKatsushi Kobayashi 			|= OHCI_BRANCH_ALWAYS;
13103c60ba66SKatsushi Kobayashi 			((struct fwohcidb_tr *)
13113c60ba66SKatsushi Kobayashi 		(dbch->xferq.stdma->end))->db[dbch->ndesc - 1].db.desc.depend =
13123c60ba66SKatsushi Kobayashi 	    vtophys(((struct fwohcidb_tr *)(dbch->xferq.stdma2->start))->db) | dbch->ndesc;
13133c60ba66SKatsushi Kobayashi 			((struct fwohcidb_tr *)(dbch->xferq.stdma->end))->db[0].db.desc.depend =
13143c60ba66SKatsushi Kobayashi 	    vtophys(((struct fwohcidb_tr *)(dbch->xferq.stdma2->start))->db) | dbch->ndesc;
13153c60ba66SKatsushi Kobayashi 			((struct fwohcidb_tr *)(dbch->xferq.stdma2->end))->db[dbch->ndesc - 1].db.desc.depend &= ~0xf;
13163c60ba66SKatsushi Kobayashi 			((struct fwohcidb_tr *)(dbch->xferq.stdma2->end))->db[0].db.desc.depend &= ~0xf;
13173c60ba66SKatsushi Kobayashi 		}
13183c60ba66SKatsushi Kobayashi 	}else if(!(OREAD(sc, OHCI_ITCTL(dmach)) & OHCI_CNTL_DMA_ACTIVE)){
13193c60ba66SKatsushi Kobayashi 		fw_tbuf_update(&sc->fc, dmach, 0);
13203c60ba66SKatsushi Kobayashi 		if(dbch->xferq.stdma == NULL){
13213c60ba66SKatsushi Kobayashi 			return err;
13223c60ba66SKatsushi Kobayashi 		}
13233c60ba66SKatsushi Kobayashi 		OWRITE(sc, OHCI_ITCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
13243c60ba66SKatsushi Kobayashi 		OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach);
13253c60ba66SKatsushi Kobayashi 		OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach);
13263c60ba66SKatsushi Kobayashi 		OWRITE(sc, OHCI_IT_MASK, 1 << dmach);
13273c60ba66SKatsushi Kobayashi 		OWRITE(sc, OHCI_ITCTLCLR(dmach), 0xf0000000);
13283c60ba66SKatsushi Kobayashi 		fwohci_txbufdb(sc, dmach, dbch->xferq.stdma);
13293c60ba66SKatsushi Kobayashi 		if(dbch->xferq.stdma2 != NULL){
13303c60ba66SKatsushi Kobayashi 			fwohci_txbufdb(sc, dmach, dbch->xferq.stdma2);
13313c60ba66SKatsushi Kobayashi 			((struct fwohcidb_tr *)
13323c60ba66SKatsushi Kobayashi 		(dbch->xferq.stdma->end))->db[dbch->ndesc - 1].db.desc.cmd
13333c60ba66SKatsushi Kobayashi 			|= OHCI_BRANCH_ALWAYS;
13343c60ba66SKatsushi Kobayashi 			((struct fwohcidb_tr *)(dbch->xferq.stdma->end))->db[dbch->ndesc - 1].db.desc.depend =
13353c60ba66SKatsushi Kobayashi 		    vtophys(((struct fwohcidb_tr *)(dbch->xferq.stdma2->start))->db) | dbch->ndesc;
13363c60ba66SKatsushi Kobayashi 			((struct fwohcidb_tr *)(dbch->xferq.stdma->end))->db[0].db.desc.depend =
13373c60ba66SKatsushi Kobayashi 		    vtophys(((struct fwohcidb_tr *)(dbch->xferq.stdma2->start))->db) | dbch->ndesc;
13383c60ba66SKatsushi Kobayashi 			((struct fwohcidb_tr *)(dbch->xferq.stdma2->end))->db[dbch->ndesc - 1].db.desc.depend &= ~0xf;
13393c60ba66SKatsushi Kobayashi 			((struct fwohcidb_tr *) (dbch->xferq.stdma2->end))->db[0].db.desc.depend &= ~0xf;
13403c60ba66SKatsushi Kobayashi 		}else{
13413c60ba66SKatsushi Kobayashi 			((struct fwohcidb_tr *) (dbch->xferq.stdma->end))->db[dbch->ndesc - 1].db.desc.depend &= ~0xf;
13423c60ba66SKatsushi Kobayashi 			((struct fwohcidb_tr *) (dbch->xferq.stdma->end))->db[0].db.desc.depend &= ~0xf;
13433c60ba66SKatsushi Kobayashi 		}
13443c60ba66SKatsushi Kobayashi 		OWRITE(sc, OHCI_ITCMD(dmach),
13453c60ba66SKatsushi Kobayashi 			vtophys(((struct fwohcidb_tr *)
13463c60ba66SKatsushi Kobayashi 				(dbch->xferq.stdma->start))->db) | dbch->ndesc);
13473c60ba66SKatsushi Kobayashi 		if(dbch->xferq.flag & FWXFERQ_DV){
13483c60ba66SKatsushi Kobayashi 			db_tr = (struct fwohcidb_tr *)dbch->xferq.stdma->start;
13493c60ba66SKatsushi Kobayashi 			fp = (struct fw_pkt *)db_tr->buf;
13503c60ba66SKatsushi Kobayashi 			fp->mode.ld[2] = htonl(0x80000000 +
13513c60ba66SKatsushi Kobayashi 				((fc->cyctimer(fc) + 0x3000) & 0xf000));
13523c60ba66SKatsushi Kobayashi 		}
13533c60ba66SKatsushi Kobayashi 
13543c60ba66SKatsushi Kobayashi 		OWRITE(sc, OHCI_ITCTL(dmach), OHCI_CNTL_DMA_RUN);
13553c60ba66SKatsushi Kobayashi 		OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IT);
13563c60ba66SKatsushi Kobayashi 	}
13573c60ba66SKatsushi Kobayashi 	return err;
13583c60ba66SKatsushi Kobayashi }
1359c572b810SHidetoshi Shimokawa 
1360c572b810SHidetoshi Shimokawa static int
1361c572b810SHidetoshi Shimokawa fwohci_irxbuf_enable(struct firewire_comm *fc, int dmach)
13623c60ba66SKatsushi Kobayashi {
13633c60ba66SKatsushi Kobayashi 	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
13643c60ba66SKatsushi Kobayashi 	int err = 0;
13653c60ba66SKatsushi Kobayashi 	unsigned short tag, ich;
13663c60ba66SKatsushi Kobayashi 	tag = (sc->ir[dmach].xferq.flag >> 6) & 3;
13673c60ba66SKatsushi Kobayashi 	ich = sc->ir[dmach].xferq.flag & 0x3f;
13683c60ba66SKatsushi Kobayashi 	OWRITE(sc, OHCI_IRMATCH(dmach), tagbit[tag] | ich);
13693c60ba66SKatsushi Kobayashi 
13703c60ba66SKatsushi Kobayashi 	if(!(sc->ir[dmach].xferq.flag & FWXFERQ_RUNNING)){
13713c60ba66SKatsushi Kobayashi 		sc->ir[dmach].xferq.queued = 0;
13723c60ba66SKatsushi Kobayashi 		sc->ir[dmach].ndb = sc->ir[dmach].xferq.bnpacket *
13733c60ba66SKatsushi Kobayashi 				sc->ir[dmach].xferq.bnchunk;
13743c60ba66SKatsushi Kobayashi 		sc->ir[dmach].dummy =
13753c60ba66SKatsushi Kobayashi 			malloc(sizeof(u_int32_t) * sc->ir[dmach].ndb,
13763c60ba66SKatsushi Kobayashi 			   M_DEVBUF, M_DONTWAIT);
13773c60ba66SKatsushi Kobayashi 		if(sc->ir[dmach].dummy == NULL){
13783c60ba66SKatsushi Kobayashi 			err = ENOMEM;
13793c60ba66SKatsushi Kobayashi 			return err;
13803c60ba66SKatsushi Kobayashi 		}
13813c60ba66SKatsushi Kobayashi 		sc->ir[dmach].ndesc = 2;
13823c60ba66SKatsushi Kobayashi 		fwohci_db_init(&sc->ir[dmach]);
13833c60ba66SKatsushi Kobayashi 		err = fwohci_rx_enable(sc, &sc->ir[dmach]);
13843c60ba66SKatsushi Kobayashi 	}
13853c60ba66SKatsushi Kobayashi 	if(err)
13863c60ba66SKatsushi Kobayashi 		return err;
13873c60ba66SKatsushi Kobayashi 
13883c60ba66SKatsushi Kobayashi 	if(OREAD(sc, OHCI_IRCTL(dmach)) & OHCI_CNTL_DMA_ACTIVE){
13893c60ba66SKatsushi Kobayashi 		if(sc->ir[dmach].xferq.stdma2 != NULL){
13903c60ba66SKatsushi Kobayashi 			((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[sc->ir[dmach].ndesc - 1].db.desc.depend =
13913c60ba66SKatsushi Kobayashi 	    vtophys(((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->start))->db) | sc->ir[dmach].ndesc;
13923c60ba66SKatsushi Kobayashi 			((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[0].db.desc.depend =
13933c60ba66SKatsushi Kobayashi 	    vtophys(((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->start))->db);
13943c60ba66SKatsushi Kobayashi 			((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->end))->db[sc->ir[dmach].ndesc - 1].db.desc.depend &= ~0xf;
13953c60ba66SKatsushi Kobayashi 			((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->end))->db[0].db.desc.depend &= ~0xf;
13963c60ba66SKatsushi Kobayashi 		}
13973c60ba66SKatsushi Kobayashi 	}else if(!(OREAD(sc, OHCI_IRCTL(dmach)) & OHCI_CNTL_DMA_ACTIVE)
13983c60ba66SKatsushi Kobayashi 		&& !(sc->ir[dmach].xferq.flag & FWXFERQ_PACKET)){
13993c60ba66SKatsushi Kobayashi 		fw_rbuf_update(&sc->fc, dmach, 0);
14003c60ba66SKatsushi Kobayashi 
14013c60ba66SKatsushi Kobayashi 		OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
14023c60ba66SKatsushi Kobayashi 		OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach);
14033c60ba66SKatsushi Kobayashi 		OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach);
14043c60ba66SKatsushi Kobayashi 		OWRITE(sc, OHCI_IR_MASK, 1 << dmach);
14053c60ba66SKatsushi Kobayashi 		OWRITE(sc, OHCI_IRCTLCLR(dmach), 0xf0000000);
14063c60ba66SKatsushi Kobayashi 		OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_ISOHDR);
14073c60ba66SKatsushi Kobayashi 		if(sc->ir[dmach].xferq.stdma2 != NULL){
14083c60ba66SKatsushi Kobayashi 			((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[sc->ir[dmach].ndesc - 1].db.desc.depend =
14093c60ba66SKatsushi Kobayashi 		    vtophys(((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->start))->db) | sc->ir[dmach].ndesc;
14103c60ba66SKatsushi Kobayashi 			((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[0].db.desc.depend =
14113c60ba66SKatsushi Kobayashi 		    vtophys(((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->start))->db);
14123c60ba66SKatsushi Kobayashi 			((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->end))->db[sc->ir[dmach].ndesc - 1].db.desc.depend &= ~0xf;
14133c60ba66SKatsushi Kobayashi 		}else{
14143c60ba66SKatsushi Kobayashi 			((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[sc->ir[dmach].ndesc - 1].db.desc.depend &= ~0xf;
14153c60ba66SKatsushi Kobayashi 			((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[0].db.desc.depend &= ~0xf;
14163c60ba66SKatsushi Kobayashi 		}
14173c60ba66SKatsushi Kobayashi 		OWRITE(sc, OHCI_IRCMD(dmach),
14183c60ba66SKatsushi Kobayashi 			vtophys(((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->start))->db) | sc->ir[dmach].ndesc);
14193c60ba66SKatsushi Kobayashi 		OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_DMA_RUN);
14203c60ba66SKatsushi Kobayashi 	}
14213c60ba66SKatsushi Kobayashi 	OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IR);
14223c60ba66SKatsushi Kobayashi 	return err;
14233c60ba66SKatsushi Kobayashi }
1424c572b810SHidetoshi Shimokawa 
1425c572b810SHidetoshi Shimokawa static int
1426c572b810SHidetoshi Shimokawa fwohci_irx_enable(struct firewire_comm *fc, int dmach)
14273c60ba66SKatsushi Kobayashi {
14283c60ba66SKatsushi Kobayashi 	struct fwohci_softc *sc = (struct fwohci_softc *)fc;
14293c60ba66SKatsushi Kobayashi 	int err = 0;
14303c60ba66SKatsushi Kobayashi 
14313c60ba66SKatsushi Kobayashi 	if(sc->ir[dmach].xferq.flag & FWXFERQ_PACKET){
14323c60ba66SKatsushi Kobayashi 		err = fwohci_irxpp_enable(fc, dmach);
14333c60ba66SKatsushi Kobayashi 		return err;
14343c60ba66SKatsushi Kobayashi 	}else{
14353c60ba66SKatsushi Kobayashi 		err = fwohci_irxbuf_enable(fc, dmach);
14363c60ba66SKatsushi Kobayashi 		return err;
14373c60ba66SKatsushi Kobayashi 	}
14383c60ba66SKatsushi Kobayashi }
1439c572b810SHidetoshi Shimokawa 
1440c572b810SHidetoshi Shimokawa int
1441c572b810SHidetoshi Shimokawa fwohci_shutdown(device_t dev)
14423c60ba66SKatsushi Kobayashi {
14433c60ba66SKatsushi Kobayashi 	u_int i;
14443c60ba66SKatsushi Kobayashi 	struct fwohci_softc *sc = device_get_softc(dev);
14453c60ba66SKatsushi Kobayashi 
14463c60ba66SKatsushi Kobayashi /* Now stopping all DMA channel */
14473c60ba66SKatsushi Kobayashi 	OWRITE(sc,  OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN);
14483c60ba66SKatsushi Kobayashi 	OWRITE(sc,  OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN);
14493c60ba66SKatsushi Kobayashi 	OWRITE(sc,  OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN);
14503c60ba66SKatsushi Kobayashi 	OWRITE(sc,  OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
14513c60ba66SKatsushi Kobayashi 
14523c60ba66SKatsushi Kobayashi 	for( i = 0 ; i < sc->fc.nisodma ; i ++ ){
14533c60ba66SKatsushi Kobayashi 		OWRITE(sc,  OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN);
14543c60ba66SKatsushi Kobayashi 		OWRITE(sc,  OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN);
14553c60ba66SKatsushi Kobayashi 	}
14563c60ba66SKatsushi Kobayashi 
14573c60ba66SKatsushi Kobayashi /* FLUSH FIFO and reset Transmitter/Reciever */
14583c60ba66SKatsushi Kobayashi 	OWRITE(sc,  OHCI_HCCCTL, OHCI_HCC_RESET);
14593c60ba66SKatsushi Kobayashi 
14603c60ba66SKatsushi Kobayashi /* Stop interrupt */
14613c60ba66SKatsushi Kobayashi 	OWRITE(sc, FWOHCI_INTMASKCLR,
14623c60ba66SKatsushi Kobayashi 			OHCI_INT_EN | OHCI_INT_ERR | OHCI_INT_PHY_SID
14633c60ba66SKatsushi Kobayashi 			| OHCI_INT_PHY_INT
14643c60ba66SKatsushi Kobayashi 			| OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS
14653c60ba66SKatsushi Kobayashi 			| OHCI_INT_DMA_PRRQ | OHCI_INT_DMA_PRRS
14663c60ba66SKatsushi Kobayashi 			| OHCI_INT_DMA_ARRQ | OHCI_INT_DMA_ARRS
14673c60ba66SKatsushi Kobayashi 			| OHCI_INT_PHY_BUS_R);
14683c60ba66SKatsushi Kobayashi 	return 0;
14693c60ba66SKatsushi Kobayashi }
14703c60ba66SKatsushi Kobayashi 
14713c60ba66SKatsushi Kobayashi #define ACK_ALL
14723c60ba66SKatsushi Kobayashi static void
1473783058faSHidetoshi Shimokawa fwohci_intr_body(struct fwohci_softc *sc, u_int32_t stat, int count)
14743c60ba66SKatsushi Kobayashi {
14753c60ba66SKatsushi Kobayashi 	u_int32_t irstat, itstat;
14763c60ba66SKatsushi Kobayashi 	u_int i;
14773c60ba66SKatsushi Kobayashi 	struct firewire_comm *fc = (struct firewire_comm *)sc;
14783c60ba66SKatsushi Kobayashi 
14793c60ba66SKatsushi Kobayashi #ifdef OHCI_DEBUG
14803c60ba66SKatsushi Kobayashi 	if(stat & OREAD(sc, FWOHCI_INTMASK))
14813c60ba66SKatsushi Kobayashi 		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",
14823c60ba66SKatsushi Kobayashi 			stat & OHCI_INT_EN ? "DMA_EN ":"",
14833c60ba66SKatsushi Kobayashi 			stat & OHCI_INT_PHY_REG ? "PHY_REG ":"",
14843c60ba66SKatsushi Kobayashi 			stat & OHCI_INT_CYC_LONG ? "CYC_LONG ":"",
14853c60ba66SKatsushi Kobayashi 			stat & OHCI_INT_ERR ? "INT_ERR ":"",
14863c60ba66SKatsushi Kobayashi 			stat & OHCI_INT_CYC_ERR ? "CYC_ERR ":"",
14873c60ba66SKatsushi Kobayashi 			stat & OHCI_INT_CYC_LOST ? "CYC_LOST ":"",
14883c60ba66SKatsushi Kobayashi 			stat & OHCI_INT_CYC_64SECOND ? "CYC_64SECOND ":"",
14893c60ba66SKatsushi Kobayashi 			stat & OHCI_INT_CYC_START ? "CYC_START ":"",
14903c60ba66SKatsushi Kobayashi 			stat & OHCI_INT_PHY_INT ? "PHY_INT ":"",
14913c60ba66SKatsushi Kobayashi 			stat & OHCI_INT_PHY_BUS_R ? "BUS_RESET ":"",
14923c60ba66SKatsushi Kobayashi 			stat & OHCI_INT_PHY_SID ? "SID ":"",
14933c60ba66SKatsushi Kobayashi 			stat & OHCI_INT_LR_ERR ? "DMA_LR_ERR ":"",
14943c60ba66SKatsushi Kobayashi 			stat & OHCI_INT_PW_ERR ? "DMA_PW_ERR ":"",
14953c60ba66SKatsushi Kobayashi 			stat & OHCI_INT_DMA_IR ? "DMA_IR ":"",
14963c60ba66SKatsushi Kobayashi 			stat & OHCI_INT_DMA_IT  ? "DMA_IT " :"",
14973c60ba66SKatsushi Kobayashi 			stat & OHCI_INT_DMA_PRRS  ? "DMA_PRRS " :"",
14983c60ba66SKatsushi Kobayashi 			stat & OHCI_INT_DMA_PRRQ  ? "DMA_PRRQ " :"",
14993c60ba66SKatsushi Kobayashi 			stat & OHCI_INT_DMA_ARRS  ? "DMA_ARRS " :"",
15003c60ba66SKatsushi Kobayashi 			stat & OHCI_INT_DMA_ARRQ  ? "DMA_ARRQ " :"",
15013c60ba66SKatsushi Kobayashi 			stat & OHCI_INT_DMA_ATRS  ? "DMA_ATRS " :"",
15023c60ba66SKatsushi Kobayashi 			stat & OHCI_INT_DMA_ATRQ  ? "DMA_ATRQ " :"",
15033c60ba66SKatsushi Kobayashi 			stat, OREAD(sc, FWOHCI_INTMASK)
15043c60ba66SKatsushi Kobayashi 		);
15053c60ba66SKatsushi Kobayashi #endif
15063c60ba66SKatsushi Kobayashi /* Bus reset */
15073c60ba66SKatsushi Kobayashi 	if(stat & OHCI_INT_PHY_BUS_R ){
15083c60ba66SKatsushi Kobayashi 		device_printf(fc->dev, "BUS reset\n");
15093c60ba66SKatsushi Kobayashi 		OWRITE(sc, FWOHCI_INTMASKCLR,  OHCI_INT_CYC_LOST);
15103c60ba66SKatsushi Kobayashi 		OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCSRC);
15113c60ba66SKatsushi Kobayashi 
15123c60ba66SKatsushi Kobayashi 		OWRITE(sc,  OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN);
15133c60ba66SKatsushi Kobayashi 		sc->atrq.xferq.flag &= ~FWXFERQ_RUNNING;
15143c60ba66SKatsushi Kobayashi 		OWRITE(sc,  OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
15153c60ba66SKatsushi Kobayashi 		sc->atrs.xferq.flag &= ~FWXFERQ_RUNNING;
15163c60ba66SKatsushi Kobayashi 
15173c60ba66SKatsushi Kobayashi #if 0
15183c60ba66SKatsushi Kobayashi 		for( i = 0 ; i < fc->nisodma ; i ++ ){
15193c60ba66SKatsushi Kobayashi 			OWRITE(sc,  OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN);
15203c60ba66SKatsushi Kobayashi 			OWRITE(sc,  OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN);
15213c60ba66SKatsushi Kobayashi 		}
15223c60ba66SKatsushi Kobayashi 
15233c60ba66SKatsushi Kobayashi #endif
15243c60ba66SKatsushi Kobayashi 		fw_busreset(fc);
15253c60ba66SKatsushi Kobayashi 
15263c60ba66SKatsushi Kobayashi 		/* XXX need to wait DMA to stop */
15273c60ba66SKatsushi Kobayashi #ifndef ACK_ALL
15283c60ba66SKatsushi Kobayashi 		OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_BUS_R);
15293c60ba66SKatsushi Kobayashi #endif
15303c60ba66SKatsushi Kobayashi #if 1
15313c60ba66SKatsushi Kobayashi 		/* pending all pre-bus_reset packets */
15323c60ba66SKatsushi Kobayashi 		fwohci_txd(sc, &sc->atrq);
15333c60ba66SKatsushi Kobayashi 		fwohci_txd(sc, &sc->atrs);
1534783058faSHidetoshi Shimokawa 		fwohci_arcv(sc, &sc->arrs, -1);
1535783058faSHidetoshi Shimokawa 		fwohci_arcv(sc, &sc->arrq, -1);
15363c60ba66SKatsushi Kobayashi #endif
15373c60ba66SKatsushi Kobayashi 
15383c60ba66SKatsushi Kobayashi 
15393c60ba66SKatsushi Kobayashi 		OWRITE(sc, OHCI_AREQHI, 1 << 31);
15403c60ba66SKatsushi Kobayashi 		/* XXX insecure ?? */
15413c60ba66SKatsushi Kobayashi 		OWRITE(sc, OHCI_PREQHI, 0x7fffffff);
15423c60ba66SKatsushi Kobayashi 		OWRITE(sc, OHCI_PREQLO, 0xffffffff);
15433c60ba66SKatsushi Kobayashi 		OWRITE(sc, OHCI_PREQUPPER, 0x10000);
15443c60ba66SKatsushi Kobayashi 
15453c60ba66SKatsushi Kobayashi 	}
15463c60ba66SKatsushi Kobayashi 	if((stat & OHCI_INT_DMA_IR )){
15473c60ba66SKatsushi Kobayashi #ifndef ACK_ALL
15483c60ba66SKatsushi Kobayashi 		OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_IR);
15493c60ba66SKatsushi Kobayashi #endif
15503c60ba66SKatsushi Kobayashi 		irstat = OREAD(sc, OHCI_IR_STAT);
15513c60ba66SKatsushi Kobayashi 		OWRITE(sc, OHCI_IR_STATCLR, ~0);
15523c60ba66SKatsushi Kobayashi 		for(i = 0; i < fc->nisodma ; i++){
15533c60ba66SKatsushi Kobayashi 			if((irstat & (1 << i)) != 0){
15543c60ba66SKatsushi Kobayashi 				if(sc->ir[i].xferq.flag & FWXFERQ_PACKET){
1555783058faSHidetoshi Shimokawa 					fwohci_ircv(sc, &sc->ir[i], count);
15563c60ba66SKatsushi Kobayashi 				}else{
15573c60ba66SKatsushi Kobayashi 					fwohci_rbuf_update(sc, i);
15583c60ba66SKatsushi Kobayashi 				}
15593c60ba66SKatsushi Kobayashi 			}
15603c60ba66SKatsushi Kobayashi 		}
15613c60ba66SKatsushi Kobayashi 	}
15623c60ba66SKatsushi Kobayashi 	if((stat & OHCI_INT_DMA_IT )){
15633c60ba66SKatsushi Kobayashi #ifndef ACK_ALL
15643c60ba66SKatsushi Kobayashi 		OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_IT);
15653c60ba66SKatsushi Kobayashi #endif
15663c60ba66SKatsushi Kobayashi 		itstat = OREAD(sc, OHCI_IT_STAT);
15673c60ba66SKatsushi Kobayashi 		OWRITE(sc, OHCI_IT_STATCLR, ~0);
15683c60ba66SKatsushi Kobayashi 		for(i = 0; i < fc->nisodma ; i++){
15693c60ba66SKatsushi Kobayashi 			if((itstat & (1 << i)) != 0){
15703c60ba66SKatsushi Kobayashi 				fwohci_tbuf_update(sc, i);
15713c60ba66SKatsushi Kobayashi 			}
15723c60ba66SKatsushi Kobayashi 		}
15733c60ba66SKatsushi Kobayashi 	}
15743c60ba66SKatsushi Kobayashi 	if((stat & OHCI_INT_DMA_PRRS )){
15753c60ba66SKatsushi Kobayashi #ifndef ACK_ALL
15763c60ba66SKatsushi Kobayashi 		OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_PRRS);
15773c60ba66SKatsushi Kobayashi #endif
15783c60ba66SKatsushi Kobayashi #if 0
15793c60ba66SKatsushi Kobayashi 		dump_dma(sc, ARRS_CH);
15803c60ba66SKatsushi Kobayashi 		dump_db(sc, ARRS_CH);
15813c60ba66SKatsushi Kobayashi #endif
1582783058faSHidetoshi Shimokawa 		fwohci_arcv(sc, &sc->arrs, count);
15833c60ba66SKatsushi Kobayashi 	}
15843c60ba66SKatsushi Kobayashi 	if((stat & OHCI_INT_DMA_PRRQ )){
15853c60ba66SKatsushi Kobayashi #ifndef ACK_ALL
15863c60ba66SKatsushi Kobayashi 		OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_PRRQ);
15873c60ba66SKatsushi Kobayashi #endif
15883c60ba66SKatsushi Kobayashi #if 0
15893c60ba66SKatsushi Kobayashi 		dump_dma(sc, ARRQ_CH);
15903c60ba66SKatsushi Kobayashi 		dump_db(sc, ARRQ_CH);
15913c60ba66SKatsushi Kobayashi #endif
1592783058faSHidetoshi Shimokawa 		fwohci_arcv(sc, &sc->arrq, count);
15933c60ba66SKatsushi Kobayashi 	}
15943c60ba66SKatsushi Kobayashi 	if(stat & OHCI_INT_PHY_SID){
15953c60ba66SKatsushi Kobayashi 		caddr_t buf;
15963c60ba66SKatsushi Kobayashi 		int plen;
15973c60ba66SKatsushi Kobayashi 
15983c60ba66SKatsushi Kobayashi #ifndef ACK_ALL
15993c60ba66SKatsushi Kobayashi 		OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_SID);
16003c60ba66SKatsushi Kobayashi #endif
16013c60ba66SKatsushi Kobayashi /*
16023c60ba66SKatsushi Kobayashi ** Checking whether the node is root or not. If root, turn on
16033c60ba66SKatsushi Kobayashi ** cycle master.
16043c60ba66SKatsushi Kobayashi */
16053c60ba66SKatsushi Kobayashi 		device_printf(fc->dev, "node_id = 0x%08x, ", OREAD(sc, FWOHCI_NODEID));
16063c60ba66SKatsushi Kobayashi 		if(!(OREAD(sc, FWOHCI_NODEID) & OHCI_NODE_VALID)){
16073c60ba66SKatsushi Kobayashi 			printf("Bus reset failure\n");
16083c60ba66SKatsushi Kobayashi 			goto sidout;
16093c60ba66SKatsushi Kobayashi 		}
16103c60ba66SKatsushi Kobayashi 		if( OREAD(sc, FWOHCI_NODEID) & OHCI_NODE_ROOT ){
16113c60ba66SKatsushi Kobayashi 			printf("CYCLEMASTER mode\n");
16123c60ba66SKatsushi Kobayashi 			OWRITE(sc, OHCI_LNKCTL,
16133c60ba66SKatsushi Kobayashi 				OHCI_CNTL_CYCMTR | OHCI_CNTL_CYCTIMER);
16143c60ba66SKatsushi Kobayashi 		}else{
16153c60ba66SKatsushi Kobayashi 			printf("non CYCLEMASTER mode\n");
16163c60ba66SKatsushi Kobayashi 			OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCMTR);
16173c60ba66SKatsushi Kobayashi 			OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_CYCTIMER);
16183c60ba66SKatsushi Kobayashi 		}
16193c60ba66SKatsushi Kobayashi 		fc->nodeid = OREAD(sc, FWOHCI_NODEID) & 0x3f;
16203c60ba66SKatsushi Kobayashi 
16213c60ba66SKatsushi Kobayashi 		plen = OREAD(sc, OHCI_SID_CNT) & OHCI_SID_CNT_MASK;
16223c60ba66SKatsushi Kobayashi 		plen -= 4; /* chop control info */
16233c60ba66SKatsushi Kobayashi 		buf = malloc( FWPMAX_S400, M_DEVBUF, M_NOWAIT);
16243c60ba66SKatsushi Kobayashi 		if(buf == NULL) goto sidout;
16253c60ba66SKatsushi Kobayashi 		bcopy((void *)(uintptr_t)(volatile void *)fc->sid_buf,
16263c60ba66SKatsushi Kobayashi 								buf, plen);
16273c60ba66SKatsushi Kobayashi 		fw_sidrcv(fc, buf, plen, 0);
16283c60ba66SKatsushi Kobayashi 	}
16293c60ba66SKatsushi Kobayashi sidout:
16303c60ba66SKatsushi Kobayashi 	if((stat & OHCI_INT_DMA_ATRQ )){
16313c60ba66SKatsushi Kobayashi #ifndef ACK_ALL
16323c60ba66SKatsushi Kobayashi 		OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_ATRQ);
16333c60ba66SKatsushi Kobayashi #endif
16343c60ba66SKatsushi Kobayashi 		fwohci_txd(sc, &(sc->atrq));
16353c60ba66SKatsushi Kobayashi 	}
16363c60ba66SKatsushi Kobayashi 	if((stat & OHCI_INT_DMA_ATRS )){
16373c60ba66SKatsushi Kobayashi #ifndef ACK_ALL
16383c60ba66SKatsushi Kobayashi 		OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_ATRS);
16393c60ba66SKatsushi Kobayashi #endif
16403c60ba66SKatsushi Kobayashi 		fwohci_txd(sc, &(sc->atrs));
16413c60ba66SKatsushi Kobayashi 	}
16423c60ba66SKatsushi Kobayashi 	if((stat & OHCI_INT_PW_ERR )){
16433c60ba66SKatsushi Kobayashi #ifndef ACK_ALL
16443c60ba66SKatsushi Kobayashi 		OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PW_ERR);
16453c60ba66SKatsushi Kobayashi #endif
16463c60ba66SKatsushi Kobayashi 		device_printf(fc->dev, "posted write error\n");
16473c60ba66SKatsushi Kobayashi 	}
16483c60ba66SKatsushi Kobayashi 	if((stat & OHCI_INT_ERR )){
16493c60ba66SKatsushi Kobayashi #ifndef ACK_ALL
16503c60ba66SKatsushi Kobayashi 		OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_ERR);
16513c60ba66SKatsushi Kobayashi #endif
16523c60ba66SKatsushi Kobayashi 		device_printf(fc->dev, "unrecoverable error\n");
16533c60ba66SKatsushi Kobayashi 	}
16543c60ba66SKatsushi Kobayashi 	if((stat & OHCI_INT_PHY_INT)) {
16553c60ba66SKatsushi Kobayashi #ifndef ACK_ALL
16563c60ba66SKatsushi Kobayashi 		OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_INT);
16573c60ba66SKatsushi Kobayashi #endif
16583c60ba66SKatsushi Kobayashi 		device_printf(fc->dev, "phy int\n");
16593c60ba66SKatsushi Kobayashi 	}
16603c60ba66SKatsushi Kobayashi 
16613c60ba66SKatsushi Kobayashi 	return;
16623c60ba66SKatsushi Kobayashi }
16633c60ba66SKatsushi Kobayashi 
16643c60ba66SKatsushi Kobayashi void
16653c60ba66SKatsushi Kobayashi fwohci_intr(void *arg)
16663c60ba66SKatsushi Kobayashi {
16673c60ba66SKatsushi Kobayashi 	struct fwohci_softc *sc = (struct fwohci_softc *)arg;
16683c60ba66SKatsushi Kobayashi 	u_int32_t stat;
16693c60ba66SKatsushi Kobayashi 
16703c60ba66SKatsushi Kobayashi 	if (!(sc->intmask & OHCI_INT_EN)) {
16713c60ba66SKatsushi Kobayashi 		/* polling mode */
16723c60ba66SKatsushi Kobayashi 		return;
16733c60ba66SKatsushi Kobayashi 	}
16743c60ba66SKatsushi Kobayashi 
16753c60ba66SKatsushi Kobayashi 	while ((stat = OREAD(sc, FWOHCI_INTSTAT)) != 0) {
16763c60ba66SKatsushi Kobayashi 		if (stat == 0xffffffff) {
16773c60ba66SKatsushi Kobayashi 			device_printf(sc->fc.dev,
16783c60ba66SKatsushi Kobayashi 				"device physically ejected?\n");
16793c60ba66SKatsushi Kobayashi 			return;
16803c60ba66SKatsushi Kobayashi 		}
16813c60ba66SKatsushi Kobayashi #ifdef ACK_ALL
16823c60ba66SKatsushi Kobayashi 		OWRITE(sc, FWOHCI_INTSTATCLR, stat);
16833c60ba66SKatsushi Kobayashi #endif
1684783058faSHidetoshi Shimokawa 		fwohci_intr_body(sc, stat, -1);
16853c60ba66SKatsushi Kobayashi 	}
16863c60ba66SKatsushi Kobayashi }
16873c60ba66SKatsushi Kobayashi 
16883c60ba66SKatsushi Kobayashi static void
16893c60ba66SKatsushi Kobayashi fwohci_poll(struct firewire_comm *fc, int quick, int count)
16903c60ba66SKatsushi Kobayashi {
16913c60ba66SKatsushi Kobayashi 	int s;
16923c60ba66SKatsushi Kobayashi 	u_int32_t stat;
16933c60ba66SKatsushi Kobayashi 	struct fwohci_softc *sc;
16943c60ba66SKatsushi Kobayashi 
16953c60ba66SKatsushi Kobayashi 
16963c60ba66SKatsushi Kobayashi 	sc = (struct fwohci_softc *)fc;
16973c60ba66SKatsushi Kobayashi 	stat = OHCI_INT_DMA_IR | OHCI_INT_DMA_IT |
16983c60ba66SKatsushi Kobayashi 		OHCI_INT_DMA_PRRS | OHCI_INT_DMA_PRRQ |
16993c60ba66SKatsushi Kobayashi 		OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS;
17003c60ba66SKatsushi Kobayashi #if 0
17013c60ba66SKatsushi Kobayashi 	if (!quick) {
17023c60ba66SKatsushi Kobayashi #else
17033c60ba66SKatsushi Kobayashi 	if (1) {
17043c60ba66SKatsushi Kobayashi #endif
17053c60ba66SKatsushi Kobayashi 		stat = OREAD(sc, FWOHCI_INTSTAT);
17063c60ba66SKatsushi Kobayashi 		if (stat == 0)
17073c60ba66SKatsushi Kobayashi 			return;
17083c60ba66SKatsushi Kobayashi 		if (stat == 0xffffffff) {
17093c60ba66SKatsushi Kobayashi 			device_printf(sc->fc.dev,
17103c60ba66SKatsushi Kobayashi 				"device physically ejected?\n");
17113c60ba66SKatsushi Kobayashi 			return;
17123c60ba66SKatsushi Kobayashi 		}
17133c60ba66SKatsushi Kobayashi #ifdef ACK_ALL
17143c60ba66SKatsushi Kobayashi 		OWRITE(sc, FWOHCI_INTSTATCLR, stat);
17153c60ba66SKatsushi Kobayashi #endif
17163c60ba66SKatsushi Kobayashi 	}
17173c60ba66SKatsushi Kobayashi 	s = splfw();
1718783058faSHidetoshi Shimokawa 	fwohci_intr_body(sc, stat, count);
17193c60ba66SKatsushi Kobayashi 	splx(s);
17203c60ba66SKatsushi Kobayashi }
17213c60ba66SKatsushi Kobayashi 
17223c60ba66SKatsushi Kobayashi static void
17233c60ba66SKatsushi Kobayashi fwohci_set_intr(struct firewire_comm *fc, int enable)
17243c60ba66SKatsushi Kobayashi {
17253c60ba66SKatsushi Kobayashi 	struct fwohci_softc *sc;
17263c60ba66SKatsushi Kobayashi 
17273c60ba66SKatsushi Kobayashi 	sc = (struct fwohci_softc *)fc;
172817c3d42cSHidetoshi Shimokawa 	if (bootverbose)
172917c3d42cSHidetoshi Shimokawa 		device_printf(sc->fc.dev, "fwochi_set_intr: %d\n", enable);
17303c60ba66SKatsushi Kobayashi 	if (enable) {
17313c60ba66SKatsushi Kobayashi 		sc->intmask |= OHCI_INT_EN;
17323c60ba66SKatsushi Kobayashi 		OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_EN);
17333c60ba66SKatsushi Kobayashi 	} else {
17343c60ba66SKatsushi Kobayashi 		sc->intmask &= ~OHCI_INT_EN;
17353c60ba66SKatsushi Kobayashi 		OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_EN);
17363c60ba66SKatsushi Kobayashi 	}
17373c60ba66SKatsushi Kobayashi }
17383c60ba66SKatsushi Kobayashi 
1739c572b810SHidetoshi Shimokawa static void
1740c572b810SHidetoshi Shimokawa fwohci_tbuf_update(struct fwohci_softc *sc, int dmach)
17413c60ba66SKatsushi Kobayashi {
17423c60ba66SKatsushi Kobayashi 	int stat;
17433c60ba66SKatsushi Kobayashi 	struct firewire_comm *fc = &sc->fc;
17443c60ba66SKatsushi Kobayashi 	struct fw_pkt *fp;
17453c60ba66SKatsushi Kobayashi 	struct fwohci_dbch *dbch;
17463c60ba66SKatsushi Kobayashi 	struct fwohcidb_tr *db_tr;
17473c60ba66SKatsushi Kobayashi 
17483c60ba66SKatsushi Kobayashi 	dbch = &sc->it[dmach];
17493c60ba66SKatsushi Kobayashi 	if((dbch->xferq.flag & FWXFERQ_DV) && (dbch->xferq.stdma2 != NULL)){
17503c60ba66SKatsushi Kobayashi 		db_tr = (struct fwohcidb_tr *)dbch->xferq.stdma2->start;
17513c60ba66SKatsushi Kobayashi /*
17523c60ba66SKatsushi Kobayashi  * Overwrite highest significant 4 bits timestamp information
17533c60ba66SKatsushi Kobayashi  */
17543c60ba66SKatsushi Kobayashi 		fp = (struct fw_pkt *)db_tr->buf;
17553c60ba66SKatsushi Kobayashi 		fp->mode.ld[2] |= htonl(0x80000000 |
17563c60ba66SKatsushi Kobayashi 				((fc->cyctimer(fc) + 0x4000) & 0xf000));
17573c60ba66SKatsushi Kobayashi 	}
17583c60ba66SKatsushi Kobayashi 	stat = OREAD(sc, OHCI_ITCTL(dmach)) & 0x1f;
17593c60ba66SKatsushi Kobayashi 	switch(stat){
17603c60ba66SKatsushi Kobayashi 	case FWOHCIEV_ACKCOMPL:
17613c60ba66SKatsushi Kobayashi 		fw_tbuf_update(fc, dmach, 1);
17623c60ba66SKatsushi Kobayashi 		break;
17633c60ba66SKatsushi Kobayashi 	default:
17643c60ba66SKatsushi Kobayashi 		fw_tbuf_update(fc, dmach, 0);
17653c60ba66SKatsushi Kobayashi 		break;
17663c60ba66SKatsushi Kobayashi 	}
17673c60ba66SKatsushi Kobayashi 	fwohci_itxbuf_enable(&sc->fc, dmach);
17683c60ba66SKatsushi Kobayashi }
1769c572b810SHidetoshi Shimokawa 
1770c572b810SHidetoshi Shimokawa static void
1771c572b810SHidetoshi Shimokawa fwohci_rbuf_update(struct fwohci_softc *sc, int dmach)
17723c60ba66SKatsushi Kobayashi {
17733c60ba66SKatsushi Kobayashi 	int stat;
17743c60ba66SKatsushi Kobayashi 	stat = OREAD(sc, OHCI_IRCTL(dmach)) & 0x1f;
17753c60ba66SKatsushi Kobayashi 	switch(stat){
17763c60ba66SKatsushi Kobayashi 	case FWOHCIEV_ACKCOMPL:
17773c60ba66SKatsushi Kobayashi 		fw_rbuf_update(&sc->fc, dmach, 1);
17783c60ba66SKatsushi Kobayashi 		wakeup(sc->fc.ir[dmach]);
17793c60ba66SKatsushi Kobayashi 		fwohci_irx_enable(&sc->fc, dmach);
17803c60ba66SKatsushi Kobayashi 		break;
17813c60ba66SKatsushi Kobayashi 	default:
17823c60ba66SKatsushi Kobayashi 		break;
17833c60ba66SKatsushi Kobayashi 	}
17843c60ba66SKatsushi Kobayashi }
1785c572b810SHidetoshi Shimokawa 
1786c572b810SHidetoshi Shimokawa void
1787c572b810SHidetoshi Shimokawa dump_dma(struct fwohci_softc *sc, u_int32_t ch)
1788c572b810SHidetoshi Shimokawa {
17893c60ba66SKatsushi Kobayashi 	u_int32_t off, cntl, stat, cmd, match;
17903c60ba66SKatsushi Kobayashi 
17913c60ba66SKatsushi Kobayashi 	if(ch == 0){
17923c60ba66SKatsushi Kobayashi 		off = OHCI_ATQOFF;
17933c60ba66SKatsushi Kobayashi 	}else if(ch == 1){
17943c60ba66SKatsushi Kobayashi 		off = OHCI_ATSOFF;
17953c60ba66SKatsushi Kobayashi 	}else if(ch == 2){
17963c60ba66SKatsushi Kobayashi 		off = OHCI_ARQOFF;
17973c60ba66SKatsushi Kobayashi 	}else if(ch == 3){
17983c60ba66SKatsushi Kobayashi 		off = OHCI_ARSOFF;
17993c60ba66SKatsushi Kobayashi 	}else if(ch < IRX_CH){
18003c60ba66SKatsushi Kobayashi 		off = OHCI_ITCTL(ch - ITX_CH);
18013c60ba66SKatsushi Kobayashi 	}else{
18023c60ba66SKatsushi Kobayashi 		off = OHCI_IRCTL(ch - IRX_CH);
18033c60ba66SKatsushi Kobayashi 	}
18043c60ba66SKatsushi Kobayashi 	cntl = stat = OREAD(sc, off);
18053c60ba66SKatsushi Kobayashi 	cmd = OREAD(sc, off + 0xc);
18063c60ba66SKatsushi Kobayashi 	match = OREAD(sc, off + 0x10);
18073c60ba66SKatsushi Kobayashi 
18083c60ba66SKatsushi Kobayashi 	device_printf(sc->fc.dev, "dma ch %1x:dma regs 0x%08x 0x%08x 0x%08x 0x%08x \n",
18093c60ba66SKatsushi Kobayashi 		ch,
18103c60ba66SKatsushi Kobayashi 		cntl,
18113c60ba66SKatsushi Kobayashi 		stat,
18123c60ba66SKatsushi Kobayashi 		cmd,
18133c60ba66SKatsushi Kobayashi 		match);
18143c60ba66SKatsushi Kobayashi 	stat &= 0xffff ;
18153c60ba66SKatsushi Kobayashi 	if(stat & 0xff00){
18163c60ba66SKatsushi Kobayashi 		device_printf(sc->fc.dev, "dma %d ch:%s%s%s%s%s%s %s(%x)\n",
18173c60ba66SKatsushi Kobayashi 			ch,
18183c60ba66SKatsushi Kobayashi 			stat & OHCI_CNTL_DMA_RUN ? "RUN," : "",
18193c60ba66SKatsushi Kobayashi 			stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "",
18203c60ba66SKatsushi Kobayashi 			stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "",
18213c60ba66SKatsushi Kobayashi 			stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "",
18223c60ba66SKatsushi Kobayashi 			stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "",
18233c60ba66SKatsushi Kobayashi 			stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "",
18243c60ba66SKatsushi Kobayashi 			fwohcicode[stat & 0x1f],
18253c60ba66SKatsushi Kobayashi 			stat & 0x1f
18263c60ba66SKatsushi Kobayashi 		);
18273c60ba66SKatsushi Kobayashi 	}else{
18283c60ba66SKatsushi Kobayashi 		device_printf(sc->fc.dev, "dma %d ch: Nostat\n", ch);
18293c60ba66SKatsushi Kobayashi 	}
18303c60ba66SKatsushi Kobayashi }
1831c572b810SHidetoshi Shimokawa 
1832c572b810SHidetoshi Shimokawa void
1833c572b810SHidetoshi Shimokawa dump_db(struct fwohci_softc *sc, u_int32_t ch)
1834c572b810SHidetoshi Shimokawa {
18353c60ba66SKatsushi Kobayashi 	struct fwohci_dbch *dbch;
18363c60ba66SKatsushi Kobayashi 	struct fwohcidb_tr *cp = NULL, *pp, *np;
18373c60ba66SKatsushi Kobayashi 	volatile struct fwohcidb *curr = NULL, *prev, *next = NULL;
18383c60ba66SKatsushi Kobayashi 	int idb, jdb;
18393c60ba66SKatsushi Kobayashi 	u_int32_t cmd, off;
18403c60ba66SKatsushi Kobayashi 	if(ch == 0){
18413c60ba66SKatsushi Kobayashi 		off = OHCI_ATQOFF;
18423c60ba66SKatsushi Kobayashi 		dbch = &sc->atrq;
18433c60ba66SKatsushi Kobayashi 	}else if(ch == 1){
18443c60ba66SKatsushi Kobayashi 		off = OHCI_ATSOFF;
18453c60ba66SKatsushi Kobayashi 		dbch = &sc->atrs;
18463c60ba66SKatsushi Kobayashi 	}else if(ch == 2){
18473c60ba66SKatsushi Kobayashi 		off = OHCI_ARQOFF;
18483c60ba66SKatsushi Kobayashi 		dbch = &sc->arrq;
18493c60ba66SKatsushi Kobayashi 	}else if(ch == 3){
18503c60ba66SKatsushi Kobayashi 		off = OHCI_ARSOFF;
18513c60ba66SKatsushi Kobayashi 		dbch = &sc->arrs;
18523c60ba66SKatsushi Kobayashi 	}else if(ch < IRX_CH){
18533c60ba66SKatsushi Kobayashi 		off = OHCI_ITCTL(ch - ITX_CH);
18543c60ba66SKatsushi Kobayashi 		dbch = &sc->it[ch - ITX_CH];
18553c60ba66SKatsushi Kobayashi 	}else {
18563c60ba66SKatsushi Kobayashi 		off = OHCI_IRCTL(ch - IRX_CH);
18573c60ba66SKatsushi Kobayashi 		dbch = &sc->ir[ch - IRX_CH];
18583c60ba66SKatsushi Kobayashi 	}
18593c60ba66SKatsushi Kobayashi 	cmd = OREAD(sc, off + 0xc);
18603c60ba66SKatsushi Kobayashi 
18613c60ba66SKatsushi Kobayashi 	if( dbch->ndb == 0 ){
18623c60ba66SKatsushi Kobayashi 		device_printf(sc->fc.dev, "No DB is attached ch=%d\n", ch);
18633c60ba66SKatsushi Kobayashi 		return;
18643c60ba66SKatsushi Kobayashi 	}
18653c60ba66SKatsushi Kobayashi 	pp = dbch->top;
18663c60ba66SKatsushi Kobayashi 	prev = pp->db;
18673c60ba66SKatsushi Kobayashi 	for(idb = 0 ; idb < dbch->ndb ; idb ++ ){
18683c60ba66SKatsushi Kobayashi 		if(pp == NULL){
18693c60ba66SKatsushi Kobayashi 			curr = NULL;
18703c60ba66SKatsushi Kobayashi 			goto outdb;
18713c60ba66SKatsushi Kobayashi 		}
18723c60ba66SKatsushi Kobayashi 		cp = STAILQ_NEXT(pp, link);
18733c60ba66SKatsushi Kobayashi 		if(cp == NULL){
18743c60ba66SKatsushi Kobayashi 			curr = NULL;
18753c60ba66SKatsushi Kobayashi 			goto outdb;
18763c60ba66SKatsushi Kobayashi 		}
18773c60ba66SKatsushi Kobayashi 		np = STAILQ_NEXT(cp, link);
18783c60ba66SKatsushi Kobayashi 		if(cp == NULL) break;
18793c60ba66SKatsushi Kobayashi 		for(jdb = 0 ; jdb < dbch->ndesc ; jdb ++ ){
18803c60ba66SKatsushi Kobayashi 			if((cmd  & 0xfffffff0)
18813c60ba66SKatsushi Kobayashi 				== vtophys(&(cp->db[jdb]))){
18823c60ba66SKatsushi Kobayashi 				curr = cp->db;
18833c60ba66SKatsushi Kobayashi 				if(np != NULL){
18843c60ba66SKatsushi Kobayashi 					next = np->db;
18853c60ba66SKatsushi Kobayashi 				}else{
18863c60ba66SKatsushi Kobayashi 					next = NULL;
18873c60ba66SKatsushi Kobayashi 				}
18883c60ba66SKatsushi Kobayashi 				goto outdb;
18893c60ba66SKatsushi Kobayashi 			}
18903c60ba66SKatsushi Kobayashi 		}
18913c60ba66SKatsushi Kobayashi 		pp = STAILQ_NEXT(pp, link);
18923c60ba66SKatsushi Kobayashi 		prev = pp->db;
18933c60ba66SKatsushi Kobayashi 	}
18943c60ba66SKatsushi Kobayashi outdb:
18953c60ba66SKatsushi Kobayashi 	if( curr != NULL){
18963c60ba66SKatsushi Kobayashi 		printf("Prev DB %d\n", ch);
18973c60ba66SKatsushi Kobayashi 		print_db(prev, ch, dbch->ndesc);
18983c60ba66SKatsushi Kobayashi 		printf("Current DB %d\n", ch);
18993c60ba66SKatsushi Kobayashi 		print_db(curr, ch, dbch->ndesc);
19003c60ba66SKatsushi Kobayashi 		printf("Next DB %d\n", ch);
19013c60ba66SKatsushi Kobayashi 		print_db(next, ch, dbch->ndesc);
19023c60ba66SKatsushi Kobayashi 	}else{
19033c60ba66SKatsushi Kobayashi 		printf("dbdump err ch = %d cmd = 0x%08x\n", ch, cmd);
19043c60ba66SKatsushi Kobayashi 	}
19053c60ba66SKatsushi Kobayashi 	return;
19063c60ba66SKatsushi Kobayashi }
1907c572b810SHidetoshi Shimokawa 
1908c572b810SHidetoshi Shimokawa void
1909c572b810SHidetoshi Shimokawa print_db(volatile struct fwohcidb *db, u_int32_t ch, u_int32_t max)
1910c572b810SHidetoshi Shimokawa {
19113c60ba66SKatsushi Kobayashi 	fwohcireg_t stat;
19123c60ba66SKatsushi Kobayashi 	int i, key;
19133c60ba66SKatsushi Kobayashi 
19143c60ba66SKatsushi Kobayashi 	if(db == NULL){
19153c60ba66SKatsushi Kobayashi 		printf("No Descriptor is found\n");
19163c60ba66SKatsushi Kobayashi 		return;
19173c60ba66SKatsushi Kobayashi 	}
19183c60ba66SKatsushi Kobayashi 
19193c60ba66SKatsushi Kobayashi 	printf("ch = %d\n%8s %s %s %s %s %4s %8s %8s %4s:%4s\n",
19203c60ba66SKatsushi Kobayashi 		ch,
19213c60ba66SKatsushi Kobayashi 		"Current",
19223c60ba66SKatsushi Kobayashi 		"OP  ",
19233c60ba66SKatsushi Kobayashi 		"KEY",
19243c60ba66SKatsushi Kobayashi 		"INT",
19253c60ba66SKatsushi Kobayashi 		"BR ",
19263c60ba66SKatsushi Kobayashi 		"len",
19273c60ba66SKatsushi Kobayashi 		"Addr",
19283c60ba66SKatsushi Kobayashi 		"Depend",
19293c60ba66SKatsushi Kobayashi 		"Stat",
19303c60ba66SKatsushi Kobayashi 		"Cnt");
19313c60ba66SKatsushi Kobayashi 	for( i = 0 ; i <= max ; i ++){
19323c60ba66SKatsushi Kobayashi 		key = db[i].db.desc.cmd & OHCI_KEY_MASK;
193370ce30b5SHidetoshi Shimokawa 		printf("%08tx %s %s %s %s %5d %08x %08x %04x:%04x",
19343c60ba66SKatsushi Kobayashi 				vtophys(&db[i]),
19353c60ba66SKatsushi Kobayashi 				dbcode[(db[i].db.desc.cmd >> 28) & 0xf],
19363c60ba66SKatsushi Kobayashi 				dbkey[(db[i].db.desc.cmd >> 24) & 0x7],
19373c60ba66SKatsushi Kobayashi 				dbcond[(db[i].db.desc.cmd >> 20) & 0x3],
19383c60ba66SKatsushi Kobayashi 				dbcond[(db[i].db.desc.cmd >> 18) & 0x3],
19393c60ba66SKatsushi Kobayashi 				db[i].db.desc.cmd & 0xffff,
19403c60ba66SKatsushi Kobayashi 				db[i].db.desc.addr,
19413c60ba66SKatsushi Kobayashi 				db[i].db.desc.depend,
19423c60ba66SKatsushi Kobayashi 				db[i].db.desc.status,
19433c60ba66SKatsushi Kobayashi 				db[i].db.desc.count);
19443c60ba66SKatsushi Kobayashi 		stat = db[i].db.desc.status;
19453c60ba66SKatsushi Kobayashi 		if(stat & 0xff00){
19463c60ba66SKatsushi Kobayashi 			printf(" %s%s%s%s%s%s %s(%x)\n",
19473c60ba66SKatsushi Kobayashi 				stat & OHCI_CNTL_DMA_RUN ? "RUN," : "",
19483c60ba66SKatsushi Kobayashi 				stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "",
19493c60ba66SKatsushi Kobayashi 				stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "",
19503c60ba66SKatsushi Kobayashi 				stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "",
19513c60ba66SKatsushi Kobayashi 				stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "",
19523c60ba66SKatsushi Kobayashi 				stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "",
19533c60ba66SKatsushi Kobayashi 				fwohcicode[stat & 0x1f],
19543c60ba66SKatsushi Kobayashi 				stat & 0x1f
19553c60ba66SKatsushi Kobayashi 			);
19563c60ba66SKatsushi Kobayashi 		}else{
19573c60ba66SKatsushi Kobayashi 			printf(" Nostat\n");
19583c60ba66SKatsushi Kobayashi 		}
19593c60ba66SKatsushi Kobayashi 		if(key == OHCI_KEY_ST2 ){
19603c60ba66SKatsushi Kobayashi 			printf("0x%08x 0x%08x 0x%08x 0x%08x\n",
19613c60ba66SKatsushi Kobayashi 				db[i+1].db.immed[0],
19623c60ba66SKatsushi Kobayashi 				db[i+1].db.immed[1],
19633c60ba66SKatsushi Kobayashi 				db[i+1].db.immed[2],
19643c60ba66SKatsushi Kobayashi 				db[i+1].db.immed[3]);
19653c60ba66SKatsushi Kobayashi 		}
19663c60ba66SKatsushi Kobayashi 		if(key == OHCI_KEY_DEVICE){
19673c60ba66SKatsushi Kobayashi 			return;
19683c60ba66SKatsushi Kobayashi 		}
19693c60ba66SKatsushi Kobayashi 		if((db[i].db.desc.cmd & OHCI_BRANCH_MASK)
19703c60ba66SKatsushi Kobayashi 				== OHCI_BRANCH_ALWAYS){
19713c60ba66SKatsushi Kobayashi 			return;
19723c60ba66SKatsushi Kobayashi 		}
19733c60ba66SKatsushi Kobayashi 		if((db[i].db.desc.cmd & OHCI_CMD_MASK)
19743c60ba66SKatsushi Kobayashi 				== OHCI_OUTPUT_LAST){
19753c60ba66SKatsushi Kobayashi 			return;
19763c60ba66SKatsushi Kobayashi 		}
19773c60ba66SKatsushi Kobayashi 		if((db[i].db.desc.cmd & OHCI_CMD_MASK)
19783c60ba66SKatsushi Kobayashi 				== OHCI_INPUT_LAST){
19793c60ba66SKatsushi Kobayashi 			return;
19803c60ba66SKatsushi Kobayashi 		}
19813c60ba66SKatsushi Kobayashi 		if(key == OHCI_KEY_ST2 ){
19823c60ba66SKatsushi Kobayashi 			i++;
19833c60ba66SKatsushi Kobayashi 		}
19843c60ba66SKatsushi Kobayashi 	}
19853c60ba66SKatsushi Kobayashi 	return;
19863c60ba66SKatsushi Kobayashi }
1987c572b810SHidetoshi Shimokawa 
1988c572b810SHidetoshi Shimokawa void
1989c572b810SHidetoshi Shimokawa fwohci_ibr(struct firewire_comm *fc)
19903c60ba66SKatsushi Kobayashi {
19913c60ba66SKatsushi Kobayashi 	struct fwohci_softc *sc;
19923c60ba66SKatsushi Kobayashi 	u_int32_t fun;
19933c60ba66SKatsushi Kobayashi 
19943c60ba66SKatsushi Kobayashi 	sc = (struct fwohci_softc *)fc;
19953c60ba66SKatsushi Kobayashi #if 1
19963c60ba66SKatsushi Kobayashi 	fun = fwphy_rddata(sc, FW_PHY_IBR_REG);
19973c60ba66SKatsushi Kobayashi 	fun |= FW_PHY_IBR;
19983c60ba66SKatsushi Kobayashi 	fun = fwphy_wrdata(sc, FW_PHY_IBR_REG, fun);
19993c60ba66SKatsushi Kobayashi #else
20003c60ba66SKatsushi Kobayashi 	fun = fwphy_rddata(sc, FW_PHY_ISBR_REG);
20013c60ba66SKatsushi Kobayashi 	fun |= FW_PHY_ISBR;
20023c60ba66SKatsushi Kobayashi 	fun = fwphy_wrdata(sc, FW_PHY_ISBR_REG, fun);
20033c60ba66SKatsushi Kobayashi #endif
20043c60ba66SKatsushi Kobayashi }
2005c572b810SHidetoshi Shimokawa 
2006c572b810SHidetoshi Shimokawa void
2007c572b810SHidetoshi Shimokawa fwohci_txbufdb(struct fwohci_softc *sc, int dmach, struct fw_bulkxfer *bulkxfer)
20083c60ba66SKatsushi Kobayashi {
20093c60ba66SKatsushi Kobayashi 	struct fwohcidb_tr *db_tr, *fdb_tr;
20103c60ba66SKatsushi Kobayashi 	struct fwohci_dbch *dbch;
20113c60ba66SKatsushi Kobayashi 	struct fw_pkt *fp;
20123c60ba66SKatsushi Kobayashi 	volatile struct fwohci_txpkthdr *ohcifp;
20133c60ba66SKatsushi Kobayashi 	unsigned short chtag;
20143c60ba66SKatsushi Kobayashi 	int idb;
20153c60ba66SKatsushi Kobayashi 
20163c60ba66SKatsushi Kobayashi 	dbch = &sc->it[dmach];
20173c60ba66SKatsushi Kobayashi 	chtag = sc->it[dmach].xferq.flag & 0xff;
20183c60ba66SKatsushi Kobayashi 
20193c60ba66SKatsushi Kobayashi 	db_tr = (struct fwohcidb_tr *)(bulkxfer->start);
20203c60ba66SKatsushi Kobayashi 	fdb_tr = (struct fwohcidb_tr *)(bulkxfer->end);
20213c60ba66SKatsushi Kobayashi /*
20223c60ba66SKatsushi Kobayashi device_printf(sc->fc.dev, "DB %08x %08x %08x\n", bulkxfer, vtophys(db_tr->db), vtophys(fdb_tr->db));
20233c60ba66SKatsushi Kobayashi */
20243c60ba66SKatsushi Kobayashi 	if(bulkxfer->flag != 0){
20253c60ba66SKatsushi Kobayashi 		return;
20263c60ba66SKatsushi Kobayashi 	}
20273c60ba66SKatsushi Kobayashi 	bulkxfer->flag = 1;
20283c60ba66SKatsushi Kobayashi 	for( idb = 0 ; idb < bulkxfer->npacket ; idb ++){
20293c60ba66SKatsushi Kobayashi 		db_tr->db[0].db.desc.cmd
20303c60ba66SKatsushi Kobayashi 			= OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | 8;
20313c60ba66SKatsushi Kobayashi 		fp = (struct fw_pkt *)db_tr->buf;
20323c60ba66SKatsushi Kobayashi 		ohcifp = (volatile struct fwohci_txpkthdr *)
20333c60ba66SKatsushi Kobayashi 						db_tr->db[1].db.immed;
20343c60ba66SKatsushi Kobayashi 		ohcifp->mode.ld[0] = ntohl(fp->mode.ld[0]);
20353c60ba66SKatsushi Kobayashi 		ohcifp->mode.stream.len = ntohs(fp->mode.stream.len);
20363c60ba66SKatsushi Kobayashi 		ohcifp->mode.stream.chtag = chtag;
20373c60ba66SKatsushi Kobayashi 		ohcifp->mode.stream.tcode = 0xa;
20383c60ba66SKatsushi Kobayashi 		ohcifp->mode.stream.spd = 4;
20393c60ba66SKatsushi Kobayashi 		ohcifp->mode.ld[2] = ntohl(fp->mode.ld[1]);
20403c60ba66SKatsushi Kobayashi 		ohcifp->mode.ld[3] = ntohl(fp->mode.ld[2]);
20413c60ba66SKatsushi Kobayashi 
20423c60ba66SKatsushi Kobayashi 		db_tr->db[2].db.desc.cmd
20433c60ba66SKatsushi Kobayashi 			= OHCI_OUTPUT_LAST
20443c60ba66SKatsushi Kobayashi 			| OHCI_UPDATE
20453c60ba66SKatsushi Kobayashi 			| OHCI_BRANCH_ALWAYS
20463c60ba66SKatsushi Kobayashi 			| ((ntohs(fp->mode.stream.len) ) & 0xffff);
20473c60ba66SKatsushi Kobayashi 		db_tr->db[2].db.desc.status = 0;
20483c60ba66SKatsushi Kobayashi 		db_tr->db[2].db.desc.count = 0;
20493c60ba66SKatsushi Kobayashi 		if(dbch->xferq.flag & FWXFERQ_DV){
20503c60ba66SKatsushi Kobayashi 			db_tr->db[0].db.desc.depend
20513c60ba66SKatsushi Kobayashi 				= vtophys(STAILQ_NEXT(db_tr, link)->db) | dbch->ndesc;
20523c60ba66SKatsushi Kobayashi 			db_tr->db[dbch->ndesc - 1].db.desc.depend
20533c60ba66SKatsushi Kobayashi 				= vtophys(STAILQ_NEXT(db_tr, link)->db) | dbch->ndesc;
20543c60ba66SKatsushi Kobayashi 		}else{
20553c60ba66SKatsushi Kobayashi 			db_tr->db[0].db.desc.depend
20563c60ba66SKatsushi Kobayashi 				= vtophys(STAILQ_NEXT(db_tr, link)->db) | dbch->ndesc;
20573c60ba66SKatsushi Kobayashi 			db_tr->db[dbch->ndesc - 1].db.desc.depend
20583c60ba66SKatsushi Kobayashi 				= vtophys(STAILQ_NEXT(db_tr, link)->db) | dbch->ndesc;
20593c60ba66SKatsushi Kobayashi 		}
20603c60ba66SKatsushi Kobayashi 		bulkxfer->end = (caddr_t)db_tr;
20613c60ba66SKatsushi Kobayashi 		db_tr = STAILQ_NEXT(db_tr, link);
20623c60ba66SKatsushi Kobayashi 	}
20633c60ba66SKatsushi Kobayashi 	db_tr = (struct fwohcidb_tr *)bulkxfer->end;
20643c60ba66SKatsushi Kobayashi 	db_tr->db[0].db.desc.depend &= ~0xf;
20653c60ba66SKatsushi Kobayashi 	db_tr->db[dbch->ndesc - 1].db.desc.depend &= ~0xf;
20663c60ba66SKatsushi Kobayashi /**/
20673c60ba66SKatsushi Kobayashi 	db_tr->db[dbch->ndesc - 1].db.desc.cmd &= ~OHCI_BRANCH_ALWAYS;
20683c60ba66SKatsushi Kobayashi 	db_tr->db[dbch->ndesc - 1].db.desc.cmd |= OHCI_BRANCH_NEVER;
20693c60ba66SKatsushi Kobayashi /**/
20703c60ba66SKatsushi Kobayashi 	db_tr->db[dbch->ndesc - 1].db.desc.cmd |= OHCI_INTERRUPT_ALWAYS;
20713c60ba66SKatsushi Kobayashi 
20723c60ba66SKatsushi Kobayashi 	db_tr = (struct fwohcidb_tr *)bulkxfer->start;
20733c60ba66SKatsushi Kobayashi 	fdb_tr = (struct fwohcidb_tr *)bulkxfer->end;
20743c60ba66SKatsushi Kobayashi /*
20753c60ba66SKatsushi Kobayashi device_printf(sc->fc.dev, "DB %08x %3d %08x %08x\n", bulkxfer, bulkxfer->npacket, vtophys(db_tr->db), vtophys(fdb_tr->db));
20763c60ba66SKatsushi Kobayashi */
20773c60ba66SKatsushi Kobayashi 	return;
20783c60ba66SKatsushi Kobayashi }
2079c572b810SHidetoshi Shimokawa 
2080c572b810SHidetoshi Shimokawa static int
2081c572b810SHidetoshi Shimokawa fwohci_add_tx_buf(struct fwohcidb_tr *db_tr, unsigned short size,
2082c572b810SHidetoshi Shimokawa 	int mode, void *buf)
20833c60ba66SKatsushi Kobayashi {
20843c60ba66SKatsushi Kobayashi 	volatile struct fwohcidb *db = db_tr->db;
20853c60ba66SKatsushi Kobayashi 	int err = 0;
20863c60ba66SKatsushi Kobayashi 	if(buf == 0){
20873c60ba66SKatsushi Kobayashi 		err = EINVAL;
20883c60ba66SKatsushi Kobayashi 		return err;
20893c60ba66SKatsushi Kobayashi 	}
20903c60ba66SKatsushi Kobayashi 	db_tr->buf = buf;
20913c60ba66SKatsushi Kobayashi 	db_tr->dbcnt = 3;
20923c60ba66SKatsushi Kobayashi 	db_tr->dummy = NULL;
20933c60ba66SKatsushi Kobayashi 
20943c60ba66SKatsushi Kobayashi 	db[0].db.desc.cmd = OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | 8;
20953c60ba66SKatsushi Kobayashi 
20963c60ba66SKatsushi Kobayashi 	db[2].db.desc.depend = 0;
20973c60ba66SKatsushi Kobayashi 	db[2].db.desc.addr = vtophys(buf) + sizeof(u_int32_t);
20983c60ba66SKatsushi Kobayashi 	db[2].db.desc.cmd = OHCI_OUTPUT_MORE;
20993c60ba66SKatsushi Kobayashi 
21003c60ba66SKatsushi Kobayashi 	db[0].db.desc.status = 0;
21013c60ba66SKatsushi Kobayashi 	db[0].db.desc.count = 0;
21023c60ba66SKatsushi Kobayashi 
21033c60ba66SKatsushi Kobayashi 	db[2].db.desc.status = 0;
21043c60ba66SKatsushi Kobayashi 	db[2].db.desc.count = 0;
21053c60ba66SKatsushi Kobayashi 	if( mode & FWXFERQ_STREAM ){
21063c60ba66SKatsushi Kobayashi 		db[2].db.desc.cmd |= OHCI_OUTPUT_LAST;
21073c60ba66SKatsushi Kobayashi 		if(mode & FWXFERQ_PACKET ){
21083c60ba66SKatsushi Kobayashi 			db[2].db.desc.cmd
21093c60ba66SKatsushi Kobayashi 					|= OHCI_INTERRUPT_ALWAYS;
21103c60ba66SKatsushi Kobayashi 		}
21113c60ba66SKatsushi Kobayashi 	}
21123c60ba66SKatsushi Kobayashi 	db[2].db.desc.cmd |= OHCI_BRANCH_ALWAYS;
21133c60ba66SKatsushi Kobayashi 	return 1;
21143c60ba66SKatsushi Kobayashi }
2115c572b810SHidetoshi Shimokawa 
2116c572b810SHidetoshi Shimokawa int
2117c572b810SHidetoshi Shimokawa fwohci_add_rx_buf(struct fwohcidb_tr *db_tr, unsigned short size, int mode,
2118c572b810SHidetoshi Shimokawa 	void *buf, void *dummy)
21193c60ba66SKatsushi Kobayashi {
21203c60ba66SKatsushi Kobayashi 	volatile struct fwohcidb *db = db_tr->db;
21213c60ba66SKatsushi Kobayashi 	int i;
21223c60ba66SKatsushi Kobayashi 	void *dbuf[2];
21233c60ba66SKatsushi Kobayashi 	int dsiz[2];
21243c60ba66SKatsushi Kobayashi 
21253c60ba66SKatsushi Kobayashi 	if(buf == 0){
21263c60ba66SKatsushi Kobayashi 		buf = malloc(size, M_DEVBUF, M_NOWAIT);
21273c60ba66SKatsushi Kobayashi 		if(buf == NULL) return 0;
21283c60ba66SKatsushi Kobayashi 		db_tr->buf = buf;
21293c60ba66SKatsushi Kobayashi 		db_tr->dbcnt = 1;
21303c60ba66SKatsushi Kobayashi 		db_tr->dummy = NULL;
21313c60ba66SKatsushi Kobayashi 		dsiz[0] = size;
21323c60ba66SKatsushi Kobayashi 		dbuf[0] = buf;
21333c60ba66SKatsushi Kobayashi 	}else if(dummy == NULL){
21343c60ba66SKatsushi Kobayashi 		db_tr->buf = buf;
21353c60ba66SKatsushi Kobayashi 		db_tr->dbcnt = 1;
21363c60ba66SKatsushi Kobayashi 		db_tr->dummy = NULL;
21373c60ba66SKatsushi Kobayashi 		dsiz[0] = size;
21383c60ba66SKatsushi Kobayashi 		dbuf[0] = buf;
21393c60ba66SKatsushi Kobayashi 	}else{
21403c60ba66SKatsushi Kobayashi 		db_tr->buf = buf;
21413c60ba66SKatsushi Kobayashi 		db_tr->dbcnt = 2;
21423c60ba66SKatsushi Kobayashi 		db_tr->dummy = dummy;
21433c60ba66SKatsushi Kobayashi 		dsiz[0] = sizeof(u_int32_t);
21443c60ba66SKatsushi Kobayashi 		dsiz[1] = size;
21453c60ba66SKatsushi Kobayashi 		dbuf[0] = dummy;
21463c60ba66SKatsushi Kobayashi 		dbuf[1] = buf;
21473c60ba66SKatsushi Kobayashi 	}
21483c60ba66SKatsushi Kobayashi 	for(i = 0 ; i < db_tr->dbcnt ; i++){
21493c60ba66SKatsushi Kobayashi 		db[i].db.desc.addr = vtophys(dbuf[i]) ;
21503c60ba66SKatsushi Kobayashi 		db[i].db.desc.cmd = OHCI_INPUT_MORE | dsiz[i];
21513c60ba66SKatsushi Kobayashi 		if( mode & FWXFERQ_STREAM ){
21523c60ba66SKatsushi Kobayashi 			db[i].db.desc.cmd |= OHCI_UPDATE;
21533c60ba66SKatsushi Kobayashi 		}
21543c60ba66SKatsushi Kobayashi 		db[i].db.desc.status = 0;
21553c60ba66SKatsushi Kobayashi 		db[i].db.desc.count = dsiz[i];
21563c60ba66SKatsushi Kobayashi 	}
21573c60ba66SKatsushi Kobayashi 	if( mode & FWXFERQ_STREAM ){
21583c60ba66SKatsushi Kobayashi 		db[db_tr->dbcnt - 1].db.desc.cmd |= OHCI_INPUT_LAST;
21593c60ba66SKatsushi Kobayashi 		if(mode & FWXFERQ_PACKET ){
21603c60ba66SKatsushi Kobayashi 			db[db_tr->dbcnt - 1].db.desc.cmd
21613c60ba66SKatsushi Kobayashi 					|= OHCI_INTERRUPT_ALWAYS;
21623c60ba66SKatsushi Kobayashi 		}
21633c60ba66SKatsushi Kobayashi 	}
21643c60ba66SKatsushi Kobayashi 	db[db_tr->dbcnt - 1].db.desc.cmd |= OHCI_BRANCH_ALWAYS;
21653c60ba66SKatsushi Kobayashi 	return 1;
21663c60ba66SKatsushi Kobayashi }
2167c572b810SHidetoshi Shimokawa 
2168c572b810SHidetoshi Shimokawa static void
2169c572b810SHidetoshi Shimokawa fwohci_ircv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count)
21703c60ba66SKatsushi Kobayashi {
21713c60ba66SKatsushi Kobayashi 	struct fwohcidb_tr *db_tr = dbch->top, *odb_tr;
21723c60ba66SKatsushi Kobayashi 	struct firewire_comm *fc = (struct firewire_comm *)sc;
21733c60ba66SKatsushi Kobayashi 	int z = 1;
21743c60ba66SKatsushi Kobayashi 	struct fw_pkt *fp;
21753c60ba66SKatsushi Kobayashi 	u_int8_t *ld;
21763c60ba66SKatsushi Kobayashi 	u_int32_t off = NULL;
21773c60ba66SKatsushi Kobayashi 	u_int32_t stat;
21783c60ba66SKatsushi Kobayashi 	u_int32_t *qld;
21793c60ba66SKatsushi Kobayashi 	u_int32_t reg;
21803c60ba66SKatsushi Kobayashi 	u_int spd;
21813c60ba66SKatsushi Kobayashi 	u_int dmach;
21823c60ba66SKatsushi Kobayashi 	int len, i, plen;
21833c60ba66SKatsushi Kobayashi 	caddr_t buf;
21843c60ba66SKatsushi Kobayashi 
21853c60ba66SKatsushi Kobayashi 	for(dmach = 0 ; dmach < sc->fc.nisodma ; dmach++){
21863c60ba66SKatsushi Kobayashi 		if( &sc->ir[dmach] == dbch){
21873c60ba66SKatsushi Kobayashi 			off = OHCI_IROFF(dmach);
21883c60ba66SKatsushi Kobayashi 			break;
21893c60ba66SKatsushi Kobayashi 		}
21903c60ba66SKatsushi Kobayashi 	}
21913c60ba66SKatsushi Kobayashi 	if(off == NULL){
21923c60ba66SKatsushi Kobayashi 		return;
21933c60ba66SKatsushi Kobayashi 	}
21943c60ba66SKatsushi Kobayashi 	if(!(dbch->xferq.flag & FWXFERQ_RUNNING)){
21953c60ba66SKatsushi Kobayashi 		fwohci_irx_disable(&sc->fc, dmach);
21963c60ba66SKatsushi Kobayashi 		return;
21973c60ba66SKatsushi Kobayashi 	}
21983c60ba66SKatsushi Kobayashi 
21993c60ba66SKatsushi Kobayashi 	odb_tr = NULL;
22003c60ba66SKatsushi Kobayashi 	db_tr = dbch->top;
22013c60ba66SKatsushi Kobayashi 	i = 0;
22023c60ba66SKatsushi Kobayashi 	while ((reg = db_tr->db[0].db.desc.status) & 0x1f) {
2203783058faSHidetoshi Shimokawa 		if (count >= 0 && count-- == 0)
2204783058faSHidetoshi Shimokawa 			break;
22053c60ba66SKatsushi Kobayashi 		ld = (u_int8_t *)db_tr->buf;
22063c60ba66SKatsushi Kobayashi 		if (dbch->xferq.flag & FWXFERQ_PACKET) {
22073c60ba66SKatsushi Kobayashi 			/* skip timeStamp */
22083c60ba66SKatsushi Kobayashi 			ld += sizeof(struct fwohci_trailer);
22093c60ba66SKatsushi Kobayashi 		}
22103c60ba66SKatsushi Kobayashi 		qld = (u_int32_t *)ld;
22113c60ba66SKatsushi Kobayashi 		len = dbch->xferq.psize - (db_tr->db[0].db.desc.count);
22123c60ba66SKatsushi Kobayashi /*
22133c60ba66SKatsushi Kobayashi {
22143c60ba66SKatsushi Kobayashi device_printf(sc->fc.dev, "%04x %2x 0x%08x 0x%08x 0x%08x 0x%08x\n", len,
22153c60ba66SKatsushi Kobayashi 		db_tr->db[0].db.desc.status & 0x1f, qld[0],qld[1],qld[2],qld[3]);
22163c60ba66SKatsushi Kobayashi }
22173c60ba66SKatsushi Kobayashi */
22183c60ba66SKatsushi Kobayashi 		fp=(struct fw_pkt *)ld;
22193c60ba66SKatsushi Kobayashi 		qld[0] = htonl(qld[0]);
22203c60ba66SKatsushi Kobayashi 		plen = sizeof(struct fw_isohdr)
22213c60ba66SKatsushi Kobayashi 			+ ntohs(fp->mode.stream.len) + sizeof(u_int32_t);
22223c60ba66SKatsushi Kobayashi 		ld += plen;
22233c60ba66SKatsushi Kobayashi 		len -= plen;
22243c60ba66SKatsushi Kobayashi 		buf = db_tr->buf;
22253c60ba66SKatsushi Kobayashi 		db_tr->buf = NULL;
22263c60ba66SKatsushi Kobayashi 		stat = reg & 0x1f;
22273c60ba66SKatsushi Kobayashi 		spd =  reg & 0x3;
22283c60ba66SKatsushi Kobayashi 		switch(stat){
22293c60ba66SKatsushi Kobayashi 			case FWOHCIEV_ACKCOMPL:
22303c60ba66SKatsushi Kobayashi 			case FWOHCIEV_ACKPEND:
22313c60ba66SKatsushi Kobayashi 				fw_rcv(&sc->fc, buf, plen - sizeof(u_int32_t), dmach, sizeof(u_int32_t), spd);
22323c60ba66SKatsushi Kobayashi 				break;
22333c60ba66SKatsushi Kobayashi 			default:
22343c60ba66SKatsushi Kobayashi 				free(buf, M_DEVBUF);
22353c60ba66SKatsushi Kobayashi 				device_printf(sc->fc.dev, "Isochronous receive err %02x\n", stat);
22363c60ba66SKatsushi Kobayashi 				break;
22373c60ba66SKatsushi Kobayashi 		}
22383c60ba66SKatsushi Kobayashi 		i++;
22393c60ba66SKatsushi Kobayashi 		fwohci_add_rx_buf(db_tr, dbch->xferq.psize,
22403c60ba66SKatsushi Kobayashi 					dbch->xferq.flag, 0, NULL);
22413c60ba66SKatsushi Kobayashi 		db_tr->db[0].db.desc.depend &= ~0xf;
22423c60ba66SKatsushi Kobayashi 		if(dbch->pdb_tr != NULL){
22433c60ba66SKatsushi Kobayashi 			dbch->pdb_tr->db[0].db.desc.depend |= z;
22443c60ba66SKatsushi Kobayashi 		} else {
22453c60ba66SKatsushi Kobayashi 			/* XXX should be rewritten in better way */
22463c60ba66SKatsushi Kobayashi 			dbch->bottom->db[0].db.desc.depend |= z;
22473c60ba66SKatsushi Kobayashi 		}
22483c60ba66SKatsushi Kobayashi 		dbch->pdb_tr = db_tr;
22493c60ba66SKatsushi Kobayashi 		db_tr = STAILQ_NEXT(db_tr, link);
22503c60ba66SKatsushi Kobayashi 	}
22513c60ba66SKatsushi Kobayashi 	dbch->top = db_tr;
22523c60ba66SKatsushi Kobayashi 	reg = OREAD(sc, OHCI_DMACTL(off));
22533c60ba66SKatsushi Kobayashi 	if (reg & OHCI_CNTL_DMA_ACTIVE)
22543c60ba66SKatsushi Kobayashi 		return;
22553c60ba66SKatsushi Kobayashi 	device_printf(sc->fc.dev, "IR DMA %d stopped at %x status=%x (%d)\n",
22563c60ba66SKatsushi Kobayashi 			dmach, OREAD(sc, OHCI_DMACMD(off)), reg, i);
22573c60ba66SKatsushi Kobayashi 	dbch->top = db_tr;
22583c60ba66SKatsushi Kobayashi 	fwohci_irx_enable(fc, dmach);
22593c60ba66SKatsushi Kobayashi }
22603c60ba66SKatsushi Kobayashi 
22613c60ba66SKatsushi Kobayashi #define PLEN(x)	(((ntohs(x))+0x3) & ~0x3)
22623c60ba66SKatsushi Kobayashi static int
22633c60ba66SKatsushi Kobayashi fwohci_get_plen(struct fwohci_softc *sc, struct fw_pkt *fp, int hlen)
22643c60ba66SKatsushi Kobayashi {
22653c60ba66SKatsushi Kobayashi 	int i;
22663c60ba66SKatsushi Kobayashi 
22673c60ba66SKatsushi Kobayashi 	for( i = 4; i < hlen ; i+=4){
22683c60ba66SKatsushi Kobayashi 		fp->mode.ld[i/4] = htonl(fp->mode.ld[i/4]);
22693c60ba66SKatsushi Kobayashi 	}
22703c60ba66SKatsushi Kobayashi 
22713c60ba66SKatsushi Kobayashi 	switch(fp->mode.common.tcode){
22723c60ba66SKatsushi Kobayashi 	case FWTCODE_RREQQ:
22733c60ba66SKatsushi Kobayashi 		return sizeof(fp->mode.rreqq) + sizeof(u_int32_t);
22743c60ba66SKatsushi Kobayashi 	case FWTCODE_WRES:
22753c60ba66SKatsushi Kobayashi 		return sizeof(fp->mode.wres) + sizeof(u_int32_t);
22763c60ba66SKatsushi Kobayashi 	case FWTCODE_WREQQ:
22773c60ba66SKatsushi Kobayashi 		return sizeof(fp->mode.wreqq) + sizeof(u_int32_t);
22783c60ba66SKatsushi Kobayashi 	case FWTCODE_RREQB:
22793c60ba66SKatsushi Kobayashi 		return sizeof(fp->mode.rreqb) + sizeof(u_int32_t);
22803c60ba66SKatsushi Kobayashi 	case FWTCODE_RRESQ:
22813c60ba66SKatsushi Kobayashi 		return sizeof(fp->mode.rresq) + sizeof(u_int32_t);
22823c60ba66SKatsushi Kobayashi 	case FWTCODE_WREQB:
22833c60ba66SKatsushi Kobayashi 		return sizeof(struct fw_asyhdr) + PLEN(fp->mode.wreqb.len)
22843c60ba66SKatsushi Kobayashi 						+ sizeof(u_int32_t);
22853c60ba66SKatsushi Kobayashi 	case FWTCODE_LREQ:
22863c60ba66SKatsushi Kobayashi 		return sizeof(struct fw_asyhdr) + PLEN(fp->mode.lreq.len)
22873c60ba66SKatsushi Kobayashi 						+ sizeof(u_int32_t);
22883c60ba66SKatsushi Kobayashi 	case FWTCODE_RRESB:
22893c60ba66SKatsushi Kobayashi 		return sizeof(struct fw_asyhdr) + PLEN(fp->mode.rresb.len)
22903c60ba66SKatsushi Kobayashi 						+ sizeof(u_int32_t);
22913c60ba66SKatsushi Kobayashi 	case FWTCODE_LRES:
22923c60ba66SKatsushi Kobayashi 		return sizeof(struct fw_asyhdr) + PLEN(fp->mode.lres.len)
22933c60ba66SKatsushi Kobayashi 						+ sizeof(u_int32_t);
22943c60ba66SKatsushi Kobayashi 	case FWOHCITCODE_PHY:
22953c60ba66SKatsushi Kobayashi 		return 16;
22963c60ba66SKatsushi Kobayashi 	}
22973c60ba66SKatsushi Kobayashi 	device_printf(sc->fc.dev, "Unknown tcode %d\n", fp->mode.common.tcode);
22983c60ba66SKatsushi Kobayashi 	return 0;
22993c60ba66SKatsushi Kobayashi }
23003c60ba66SKatsushi Kobayashi 
2301c572b810SHidetoshi Shimokawa static void
2302c572b810SHidetoshi Shimokawa fwohci_arcv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count)
23033c60ba66SKatsushi Kobayashi {
23043c60ba66SKatsushi Kobayashi 	struct fwohcidb_tr *db_tr;
23053c60ba66SKatsushi Kobayashi 	int z = 1;
23063c60ba66SKatsushi Kobayashi 	struct fw_pkt *fp;
23073c60ba66SKatsushi Kobayashi 	u_int8_t *ld;
23083c60ba66SKatsushi Kobayashi 	u_int32_t stat, off;
23093c60ba66SKatsushi Kobayashi 	u_int spd;
23103c60ba66SKatsushi Kobayashi 	int len, plen, hlen, pcnt, poff = 0, rlen;
23113c60ba66SKatsushi Kobayashi 	int s;
23123c60ba66SKatsushi Kobayashi 	caddr_t buf;
23133c60ba66SKatsushi Kobayashi 	int resCount;
23143c60ba66SKatsushi Kobayashi 
23153c60ba66SKatsushi Kobayashi 	if(&sc->arrq == dbch){
23163c60ba66SKatsushi Kobayashi 		off = OHCI_ARQOFF;
23173c60ba66SKatsushi Kobayashi 	}else if(&sc->arrs == dbch){
23183c60ba66SKatsushi Kobayashi 		off = OHCI_ARSOFF;
23193c60ba66SKatsushi Kobayashi 	}else{
23203c60ba66SKatsushi Kobayashi 		return;
23213c60ba66SKatsushi Kobayashi 	}
23223c60ba66SKatsushi Kobayashi 
23233c60ba66SKatsushi Kobayashi 	s = splfw();
23243c60ba66SKatsushi Kobayashi 	db_tr = dbch->top;
23253c60ba66SKatsushi Kobayashi 	pcnt = 0;
23263c60ba66SKatsushi Kobayashi 	/* XXX we cannot handle a packet which lies in more than two buf */
23273c60ba66SKatsushi Kobayashi 	while (db_tr->db[0].db.desc.status & OHCI_CNTL_DMA_ACTIVE) {
23283c60ba66SKatsushi Kobayashi 		ld = (u_int8_t *)db_tr->buf + dbch->buf_offset;
23293c60ba66SKatsushi Kobayashi 		resCount = db_tr->db[0].db.desc.count;
23303c60ba66SKatsushi Kobayashi 		len = dbch->xferq.psize - resCount
23313c60ba66SKatsushi Kobayashi 					- dbch->buf_offset;
23323c60ba66SKatsushi Kobayashi 		while (len > 0 ) {
2333783058faSHidetoshi Shimokawa 			if (count >= 0 && count-- == 0)
2334783058faSHidetoshi Shimokawa 				goto out;
23353c60ba66SKatsushi Kobayashi 			if(dbch->frag.buf != NULL){
23363c60ba66SKatsushi Kobayashi 				buf = dbch->frag.buf;
23373c60ba66SKatsushi Kobayashi 				if (dbch->frag.plen < 0) {
23383c60ba66SKatsushi Kobayashi 					/* incomplete header */
23393c60ba66SKatsushi Kobayashi 					int hlen;
23403c60ba66SKatsushi Kobayashi 
23413c60ba66SKatsushi Kobayashi 					hlen = - dbch->frag.plen;
23423c60ba66SKatsushi Kobayashi 					rlen = hlen - dbch->frag.len;
23433c60ba66SKatsushi Kobayashi 					bcopy(ld, dbch->frag.buf + dbch->frag.len, rlen);
23443c60ba66SKatsushi Kobayashi 					ld += rlen;
23453c60ba66SKatsushi Kobayashi 					len -= rlen;
23463c60ba66SKatsushi Kobayashi 					dbch->frag.len += rlen;
23473c60ba66SKatsushi Kobayashi #if 0
23483c60ba66SKatsushi Kobayashi 					printf("(1)frag.plen=%d frag.len=%d rlen=%d len=%d\n", dbch->frag.plen, dbch->frag.len, rlen, len);
23493c60ba66SKatsushi Kobayashi #endif
23503c60ba66SKatsushi Kobayashi 					fp=(struct fw_pkt *)dbch->frag.buf;
23513c60ba66SKatsushi Kobayashi 					dbch->frag.plen
23523c60ba66SKatsushi Kobayashi 						= fwohci_get_plen(sc, fp, hlen);
23533c60ba66SKatsushi Kobayashi 					if (dbch->frag.plen == 0)
23543c60ba66SKatsushi Kobayashi 						goto out;
23553c60ba66SKatsushi Kobayashi 				}
23563c60ba66SKatsushi Kobayashi 				rlen = dbch->frag.plen - dbch->frag.len;
23573c60ba66SKatsushi Kobayashi #if 0
23583c60ba66SKatsushi Kobayashi 				printf("(2)frag.plen=%d frag.len=%d rlen=%d len=%d\n", dbch->frag.plen, dbch->frag.len, rlen, len);
23593c60ba66SKatsushi Kobayashi #endif
23603c60ba66SKatsushi Kobayashi 				bcopy(ld, dbch->frag.buf + dbch->frag.len,
23613c60ba66SKatsushi Kobayashi 						rlen);
23623c60ba66SKatsushi Kobayashi 				ld += rlen;
23633c60ba66SKatsushi Kobayashi 				len -= rlen;
23643c60ba66SKatsushi Kobayashi 				plen = dbch->frag.plen;
23653c60ba66SKatsushi Kobayashi 				dbch->frag.buf = NULL;
23663c60ba66SKatsushi Kobayashi 				dbch->frag.plen = 0;
23673c60ba66SKatsushi Kobayashi 				dbch->frag.len = 0;
23683c60ba66SKatsushi Kobayashi 				poff = 0;
23693c60ba66SKatsushi Kobayashi 			}else{
23703c60ba66SKatsushi Kobayashi 				fp=(struct fw_pkt *)ld;
23713c60ba66SKatsushi Kobayashi 				fp->mode.ld[0] = htonl(fp->mode.ld[0]);
23723c60ba66SKatsushi Kobayashi 				switch(fp->mode.common.tcode){
23733c60ba66SKatsushi Kobayashi 				case FWTCODE_RREQQ:
23743c60ba66SKatsushi Kobayashi 				case FWTCODE_WRES:
23753c60ba66SKatsushi Kobayashi 				case FWTCODE_WREQQ:
23763c60ba66SKatsushi Kobayashi 				case FWTCODE_RRESQ:
23773c60ba66SKatsushi Kobayashi 				case FWOHCITCODE_PHY:
23783c60ba66SKatsushi Kobayashi 					hlen = 12;
23793c60ba66SKatsushi Kobayashi 					break;
23803c60ba66SKatsushi Kobayashi 				case FWTCODE_RREQB:
23813c60ba66SKatsushi Kobayashi 				case FWTCODE_WREQB:
23823c60ba66SKatsushi Kobayashi 				case FWTCODE_LREQ:
23833c60ba66SKatsushi Kobayashi 				case FWTCODE_RRESB:
23843c60ba66SKatsushi Kobayashi 				case FWTCODE_LRES:
23853c60ba66SKatsushi Kobayashi 					hlen = 16;
23863c60ba66SKatsushi Kobayashi 					break;
23873c60ba66SKatsushi Kobayashi 				default:
23883c60ba66SKatsushi Kobayashi 					device_printf(sc->fc.dev, "Unknown tcode %d\n", fp->mode.common.tcode);
23893c60ba66SKatsushi Kobayashi 					goto out;
23903c60ba66SKatsushi Kobayashi 				}
23913c60ba66SKatsushi Kobayashi 				if (len >= hlen) {
23923c60ba66SKatsushi Kobayashi 					plen = fwohci_get_plen(sc, fp, hlen);
23933c60ba66SKatsushi Kobayashi 					if (plen == 0)
23943c60ba66SKatsushi Kobayashi 						goto out;
23953c60ba66SKatsushi Kobayashi 					plen = (plen + 3) & ~3;
23963c60ba66SKatsushi Kobayashi 					len -= plen;
23973c60ba66SKatsushi Kobayashi 				} else {
23983c60ba66SKatsushi Kobayashi 					plen = -hlen;
23993c60ba66SKatsushi Kobayashi 					len -= hlen;
24003c60ba66SKatsushi Kobayashi 				}
24013c60ba66SKatsushi Kobayashi 				if(resCount > 0 || len > 0){
24023c60ba66SKatsushi Kobayashi 					buf = malloc( dbch->xferq.psize,
24033c60ba66SKatsushi Kobayashi 							M_DEVBUF, M_NOWAIT);
24043c60ba66SKatsushi Kobayashi 					if(buf == NULL){
24053c60ba66SKatsushi Kobayashi 						printf("cannot malloc!\n");
24063c60ba66SKatsushi Kobayashi 						free(db_tr->buf, M_DEVBUF);
24073c60ba66SKatsushi Kobayashi 						goto out;
24083c60ba66SKatsushi Kobayashi 					}
24093c60ba66SKatsushi Kobayashi 					bcopy(ld, buf, plen);
24103c60ba66SKatsushi Kobayashi 					poff = 0;
24113c60ba66SKatsushi Kobayashi 					dbch->frag.buf = NULL;
24123c60ba66SKatsushi Kobayashi 					dbch->frag.plen = 0;
24133c60ba66SKatsushi Kobayashi 					dbch->frag.len = 0;
24143c60ba66SKatsushi Kobayashi 				}else if(len < 0){
24153c60ba66SKatsushi Kobayashi 					dbch->frag.buf = db_tr->buf;
24163c60ba66SKatsushi Kobayashi 					if (plen < 0) {
24173c60ba66SKatsushi Kobayashi #if 0
24183c60ba66SKatsushi Kobayashi 						printf("plen < 0:"
24193c60ba66SKatsushi Kobayashi 						"hlen: %d  len: %d\n",
24203c60ba66SKatsushi Kobayashi 						hlen, len);
24213c60ba66SKatsushi Kobayashi #endif
24223c60ba66SKatsushi Kobayashi 						dbch->frag.len = hlen + len;
24233c60ba66SKatsushi Kobayashi 						dbch->frag.plen = -hlen;
24243c60ba66SKatsushi Kobayashi 					} else {
24253c60ba66SKatsushi Kobayashi 						dbch->frag.len = plen + len;
24263c60ba66SKatsushi Kobayashi 						dbch->frag.plen = plen;
24273c60ba66SKatsushi Kobayashi 					}
24283c60ba66SKatsushi Kobayashi 					bcopy(ld, db_tr->buf, dbch->frag.len);
24293c60ba66SKatsushi Kobayashi 					buf = NULL;
24303c60ba66SKatsushi Kobayashi 				}else{
24313c60ba66SKatsushi Kobayashi 					buf = db_tr->buf;
24323c60ba66SKatsushi Kobayashi 					poff = ld - (u_int8_t *)buf;
24333c60ba66SKatsushi Kobayashi 					dbch->frag.buf = NULL;
24343c60ba66SKatsushi Kobayashi 					dbch->frag.plen = 0;
24353c60ba66SKatsushi Kobayashi 					dbch->frag.len = 0;
24363c60ba66SKatsushi Kobayashi 				}
24373c60ba66SKatsushi Kobayashi 				ld += plen;
24383c60ba66SKatsushi Kobayashi 			}
24393c60ba66SKatsushi Kobayashi 			if( buf != NULL){
24403c60ba66SKatsushi Kobayashi /* DMA result-code will be written at the tail of packet */
24413c60ba66SKatsushi Kobayashi 				stat = ((struct fwohci_trailer *)(ld - sizeof(struct fwohci_trailer)))->stat;
24423c60ba66SKatsushi Kobayashi 				spd = (stat >> 5) & 0x3;
24433c60ba66SKatsushi Kobayashi 				stat &= 0x1f;
24443c60ba66SKatsushi Kobayashi 				switch(stat){
24453c60ba66SKatsushi Kobayashi 				case FWOHCIEV_ACKPEND:
24463c60ba66SKatsushi Kobayashi #if 0
24473c60ba66SKatsushi Kobayashi 					printf("fwohci_arcv: ack pending..\n");
24483c60ba66SKatsushi Kobayashi #endif
24493c60ba66SKatsushi Kobayashi 					/* fall through */
24503c60ba66SKatsushi Kobayashi 				case FWOHCIEV_ACKCOMPL:
24513c60ba66SKatsushi Kobayashi 					if( poff != 0 )
24523c60ba66SKatsushi Kobayashi 						bcopy(buf+poff, buf, plen - 4);
24533c60ba66SKatsushi Kobayashi 					fw_rcv(&sc->fc, buf, plen - sizeof(struct fwohci_trailer), 0, 0, spd);
24543c60ba66SKatsushi Kobayashi 					break;
24553c60ba66SKatsushi Kobayashi 				case FWOHCIEV_BUSRST:
24563c60ba66SKatsushi Kobayashi 					free(buf, M_DEVBUF);
24573c60ba66SKatsushi Kobayashi 					if (sc->fc.status != FWBUSRESET)
24583c60ba66SKatsushi Kobayashi 						printf("got BUSRST packet!?\n");
24593c60ba66SKatsushi Kobayashi 					break;
24603c60ba66SKatsushi Kobayashi 				default:
24613c60ba66SKatsushi Kobayashi 					device_printf(sc->fc.dev, "Async DMA Receive error err = %02x %s\n", stat, fwohcicode[stat]);
24623c60ba66SKatsushi Kobayashi #if 0 /* XXX */
24633c60ba66SKatsushi Kobayashi 					goto out;
24643c60ba66SKatsushi Kobayashi #endif
24653c60ba66SKatsushi Kobayashi 					break;
24663c60ba66SKatsushi Kobayashi 				}
24673c60ba66SKatsushi Kobayashi 			}
24683c60ba66SKatsushi Kobayashi 			pcnt ++;
24693c60ba66SKatsushi Kobayashi 		};
24703c60ba66SKatsushi Kobayashi out:
24713c60ba66SKatsushi Kobayashi 		if (resCount == 0) {
24723c60ba66SKatsushi Kobayashi 			/* done on this buffer */
24733c60ba66SKatsushi Kobayashi 			fwohci_add_rx_buf(db_tr, dbch->xferq.psize,
24743c60ba66SKatsushi Kobayashi 						dbch->xferq.flag, 0, NULL);
24753c60ba66SKatsushi Kobayashi 			dbch->bottom->db[0].db.desc.depend |= z;
24763c60ba66SKatsushi Kobayashi 			dbch->bottom = db_tr;
24773c60ba66SKatsushi Kobayashi 			db_tr = STAILQ_NEXT(db_tr, link);
24783c60ba66SKatsushi Kobayashi 			dbch->top = db_tr;
24793c60ba66SKatsushi Kobayashi 			dbch->buf_offset = 0;
24803c60ba66SKatsushi Kobayashi 		} else {
24813c60ba66SKatsushi Kobayashi 			dbch->buf_offset = dbch->xferq.psize - resCount;
24823c60ba66SKatsushi Kobayashi 			break;
24833c60ba66SKatsushi Kobayashi 		}
24843c60ba66SKatsushi Kobayashi 		/* XXX make sure DMA is not dead */
24853c60ba66SKatsushi Kobayashi 	}
24863c60ba66SKatsushi Kobayashi #if 0
24873c60ba66SKatsushi Kobayashi 	if (pcnt < 1)
24883c60ba66SKatsushi Kobayashi 		printf("fwohci_arcv: no packets\n");
24893c60ba66SKatsushi Kobayashi #endif
24903c60ba66SKatsushi Kobayashi 	splx(s);
24913c60ba66SKatsushi Kobayashi }
2492