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