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