Home | History | Annotate | Line # | Download | only in ieee1394
fwohci.c revision 1.78.2.4
      1  1.78.2.4     skrll /*	$NetBSD: fwohci.c,v 1.78.2.4 2004/09/21 13:29:41 skrll Exp $	*/
      2      1.14     enami 
      3       1.1      matt /*-
      4       1.1      matt  * Copyright (c) 2000 The NetBSD Foundation, Inc.
      5       1.1      matt  * All rights reserved.
      6       1.1      matt  *
      7       1.1      matt  * This code is derived from software contributed to The NetBSD Foundation
      8       1.1      matt  * by Matt Thomas of 3am Software Foundry.
      9       1.1      matt  *
     10       1.1      matt  * Redistribution and use in source and binary forms, with or without
     11       1.1      matt  * modification, are permitted provided that the following conditions
     12       1.1      matt  * are met:
     13       1.1      matt  * 1. Redistributions of source code must retain the above copyright
     14       1.1      matt  *    notice, this list of conditions and the following disclaimer.
     15       1.1      matt  * 2. Redistributions in binary form must reproduce the above copyright
     16       1.1      matt  *    notice, this list of conditions and the following disclaimer in the
     17       1.1      matt  *    documentation and/or other materials provided with the distribution.
     18       1.1      matt  * 3. All advertising materials mentioning features or use of this software
     19       1.1      matt  *    must display the following acknowledgement:
     20       1.1      matt  *        This product includes software developed by the NetBSD
     21       1.1      matt  *        Foundation, Inc. and its contributors.
     22       1.1      matt  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23       1.1      matt  *    contributors may be used to endorse or promote products derived
     24       1.1      matt  *    from this software without specific prior written permission.
     25       1.1      matt  *
     26       1.1      matt  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27       1.1      matt  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28       1.1      matt  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29       1.1      matt  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30       1.1      matt  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31       1.1      matt  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32       1.1      matt  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33       1.1      matt  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34       1.1      matt  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35       1.1      matt  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36       1.1      matt  * POSSIBILITY OF SUCH DAMAGE.
     37       1.1      matt  */
     38       1.1      matt 
     39       1.3      onoe /*
     40       1.3      onoe  * IEEE1394 Open Host Controller Interface
     41       1.3      onoe  *	based on OHCI Specification 1.1 (January 6, 2000)
     42       1.3      onoe  * The first version to support network interface part is wrtten by
     43  1.78.2.2     skrll  * Atsushi Onoe <onoe (at) NetBSD.org>.
     44       1.3      onoe  */
     45       1.3      onoe 
     46      1.40      haya /*
     47      1.40      haya  * The first version to support isochronous acquisition part is wrtten
     48  1.78.2.2     skrll  * by HAYAKAWA Koichi <haya (at) NetBSD.org>.
     49      1.40      haya  */
     50      1.45     lukem 
     51      1.45     lukem #include <sys/cdefs.h>
     52  1.78.2.4     skrll __KERNEL_RCSID(0, "$NetBSD: fwohci.c,v 1.78.2.4 2004/09/21 13:29:41 skrll Exp $");
     53      1.45     lukem 
     54      1.62      haya #define FWOHCI_WAIT_DEBUG 1
     55      1.62      haya 
     56      1.62      haya #define FWOHCI_IT_BUFNUM 4
     57      1.40      haya 
     58       1.3      onoe #include "opt_inet.h"
     59      1.62      haya #include "fwiso.h"
     60       1.3      onoe 
     61       1.1      matt #include <sys/param.h>
     62       1.2  augustss #include <sys/systm.h>
     63      1.24       jmc #include <sys/kthread.h>
     64       1.1      matt #include <sys/socket.h>
     65       1.7      onoe #include <sys/callout.h>
     66       1.1      matt #include <sys/device.h>
     67       1.7      onoe #include <sys/kernel.h>
     68       1.3      onoe #include <sys/malloc.h>
     69       1.3      onoe #include <sys/mbuf.h>
     70      1.62      haya #include <sys/poll.h>
     71      1.62      haya #include <sys/select.h>
     72       1.1      matt 
     73       1.7      onoe #if __NetBSD_Version__ >= 105010000
     74       1.7      onoe #include <uvm/uvm_extern.h>
     75       1.7      onoe #else
     76       1.7      onoe #include <vm/vm.h>
     77       1.7      onoe #endif
     78       1.7      onoe 
     79       1.1      matt #include <machine/bus.h>
     80      1.24       jmc #include <machine/intr.h>
     81       1.1      matt 
     82       1.1      matt #include <dev/ieee1394/ieee1394reg.h>
     83       1.1      matt #include <dev/ieee1394/fwohcireg.h>
     84       1.1      matt 
     85       1.1      matt #include <dev/ieee1394/ieee1394var.h>
     86       1.1      matt #include <dev/ieee1394/fwohcivar.h>
     87      1.62      haya #include <dev/ieee1394/fwisovar.h>
     88       1.1      matt 
     89       1.1      matt static const char * const ieee1394_speeds[] = { IEEE1394_SPD_STRINGS };
     90       1.1      matt 
     91       1.5      matt #if 0
     92      1.26     enami static int fwohci_dnamem_alloc(struct fwohci_softc *sc, int size,
     93      1.28       jmc     int alignment, bus_dmamap_t *mapp, caddr_t *kvap, int flags);
     94       1.5      matt #endif
     95      1.24       jmc static void fwohci_create_event_thread(void *);
     96      1.24       jmc static void fwohci_thread_init(void *);
     97      1.24       jmc 
     98      1.24       jmc static void fwohci_event_thread(struct fwohci_softc *);
     99       1.7      onoe static void fwohci_hw_init(struct fwohci_softc *);
    100       1.7      onoe static void fwohci_power(int, void *);
    101       1.7      onoe static void fwohci_shutdown(void *);
    102       1.5      matt 
    103       1.3      onoe static int  fwohci_desc_alloc(struct fwohci_softc *);
    104       1.9      onoe static struct fwohci_desc *fwohci_desc_get(struct fwohci_softc *, int);
    105       1.9      onoe static void fwohci_desc_put(struct fwohci_softc *, struct fwohci_desc *, int);
    106       1.3      onoe 
    107       1.3      onoe static int  fwohci_ctx_alloc(struct fwohci_softc *, struct fwohci_ctx **,
    108      1.40      haya     int, int, int);
    109       1.9      onoe static void fwohci_ctx_free(struct fwohci_softc *, struct fwohci_ctx *);
    110       1.3      onoe static void fwohci_ctx_init(struct fwohci_softc *, struct fwohci_ctx *);
    111       1.3      onoe 
    112      1.62      haya static int fwohci_misc_dmabuf_alloc(bus_dma_tag_t, int, int,
    113      1.62      haya     bus_dma_segment_t *, bus_dmamap_t *, void **, const char *);
    114      1.62      haya static void fwohci_misc_dmabuf_free(bus_dma_tag_t, int, int,
    115      1.62      haya     bus_dma_segment_t *, bus_dmamap_t *, caddr_t);
    116      1.62      haya 
    117      1.62      haya static struct fwohci_ir_ctx *fwohci_ir_ctx_construct(struct fwohci_softc *,
    118      1.62      haya     int, int, int, int, int, int);
    119      1.62      haya static void fwohci_ir_ctx_destruct(struct fwohci_ir_ctx *);
    120      1.62      haya 
    121      1.62      haya static int fwohci_ir_buf_setup(struct fwohci_ir_ctx *);
    122      1.62      haya static int fwohci_ir_init(struct fwohci_ir_ctx *);
    123      1.62      haya static int fwohci_ir_start(struct fwohci_ir_ctx *);
    124      1.62      haya static void fwohci_ir_intr(struct fwohci_softc *, struct fwohci_ir_ctx *);
    125      1.62      haya static int fwohci_ir_stop(struct fwohci_ir_ctx *);
    126      1.62      haya static int fwohci_ir_ctx_packetnum(struct fwohci_ir_ctx *);
    127      1.62      haya #ifdef USEDRAIN
    128      1.62      haya static int fwohci_ir_ctx_drain(struct fwohci_ir_ctx *);
    129      1.62      haya #endif /* USEDRAIN */
    130      1.62      haya 
    131      1.62      haya static int fwohci_it_desc_alloc(struct fwohci_it_ctx *);
    132      1.62      haya static void fwohci_it_desc_free(struct fwohci_it_ctx *itc);
    133      1.62      haya struct fwohci_it_ctx *fwohci_it_ctx_construct(struct fwohci_softc *,
    134      1.62      haya     int, int, int, int);
    135      1.62      haya void fwohci_it_ctx_destruct(struct fwohci_it_ctx *);
    136      1.62      haya int fwohci_it_ctx_writedata(ieee1394_it_tag_t, int,
    137      1.62      haya     struct ieee1394_it_datalist *, int);
    138      1.62      haya static void fwohci_it_ctx_run(struct fwohci_it_ctx *);
    139      1.62      haya int fwohci_it_ctx_flush(ieee1394_it_tag_t);
    140      1.62      haya static void fwohci_it_intr(struct fwohci_softc *, struct fwohci_it_ctx *);
    141      1.62      haya 
    142      1.62      haya int fwohci_itd_construct(struct fwohci_it_ctx *, struct fwohci_it_dmabuf *,
    143      1.62      haya     int, struct fwohci_desc *, bus_addr_t, int, int, paddr_t);
    144      1.62      haya void fwohci_itd_destruct(struct fwohci_it_dmabuf *);
    145      1.62      haya static int fwohci_itd_dmabuf_alloc(struct fwohci_it_dmabuf *);
    146      1.62      haya static void fwohci_itd_dmabuf_free(struct fwohci_it_dmabuf *);
    147      1.62      haya int fwohci_itd_link(struct fwohci_it_dmabuf *, struct fwohci_it_dmabuf *);
    148      1.62      haya int fwohci_itd_unlink(struct fwohci_it_dmabuf *);
    149      1.62      haya int fwohci_itd_writedata(struct fwohci_it_dmabuf *, int,
    150      1.62      haya     struct ieee1394_it_datalist *);
    151      1.62      haya int fwohci_itd_isfilled(struct fwohci_it_dmabuf *);
    152      1.62      haya 
    153       1.3      onoe static int  fwohci_buf_alloc(struct fwohci_softc *, struct fwohci_buf *);
    154       1.3      onoe static void fwohci_buf_free(struct fwohci_softc *, struct fwohci_buf *);
    155      1.36      onoe static void fwohci_buf_init_rx(struct fwohci_softc *);
    156      1.36      onoe static void fwohci_buf_start_rx(struct fwohci_softc *);
    157      1.36      onoe static void fwohci_buf_stop_tx(struct fwohci_softc *);
    158      1.36      onoe static void fwohci_buf_stop_rx(struct fwohci_softc *);
    159       1.3      onoe static void fwohci_buf_next(struct fwohci_softc *, struct fwohci_ctx *);
    160      1.39      onoe static int  fwohci_buf_pktget(struct fwohci_softc *, struct fwohci_buf **,
    161      1.28       jmc     caddr_t *, int);
    162       1.3      onoe static int  fwohci_buf_input(struct fwohci_softc *, struct fwohci_ctx *,
    163      1.28       jmc     struct fwohci_pkt *);
    164      1.36      onoe static int  fwohci_buf_input_ppb(struct fwohci_softc *, struct fwohci_ctx *,
    165      1.36      onoe     struct fwohci_pkt *);
    166       1.3      onoe 
    167       1.7      onoe static u_int8_t fwohci_phy_read(struct fwohci_softc *, u_int8_t);
    168       1.7      onoe static void fwohci_phy_write(struct fwohci_softc *, u_int8_t, u_int8_t);
    169       1.3      onoe static void fwohci_phy_busreset(struct fwohci_softc *);
    170       1.7      onoe static void fwohci_phy_input(struct fwohci_softc *, struct fwohci_pkt *);
    171       1.3      onoe 
    172       1.3      onoe static int  fwohci_handler_set(struct fwohci_softc *, int, u_int32_t, u_int32_t,
    173      1.67       jmc     u_int32_t, int (*)(struct fwohci_softc *, void *, struct fwohci_pkt *),
    174      1.67       jmc     void *);
    175       1.3      onoe 
    176      1.62      haya ieee1394_ir_tag_t fwohci_ir_ctx_set(struct device *, int, int, int, int, int);
    177      1.62      haya int fwohci_ir_ctx_clear(struct device *, ieee1394_ir_tag_t);
    178      1.62      haya int fwohci_ir_read(struct device *, ieee1394_ir_tag_t, struct uio *,
    179      1.62      haya     int, int);
    180      1.62      haya int fwohci_ir_wait(struct device *, ieee1394_ir_tag_t, void *, char *name);
    181  1.78.2.4     skrll int fwohci_ir_select(struct device *, ieee1394_ir_tag_t, struct lwp *);
    182      1.62      haya 
    183      1.62      haya 
    184      1.62      haya 
    185      1.62      haya ieee1394_it_tag_t fwohci_it_set(struct ieee1394_softc *, int, int);
    186      1.62      haya static ieee1394_it_tag_t fwohci_it_ctx_set(struct fwohci_softc *, int, int, int);
    187      1.62      haya int fwohci_it_ctx_clear(ieee1394_it_tag_t *);
    188      1.62      haya 
    189       1.3      onoe static void fwohci_arrq_input(struct fwohci_softc *, struct fwohci_ctx *);
    190       1.3      onoe static void fwohci_arrs_input(struct fwohci_softc *, struct fwohci_ctx *);
    191      1.62      haya static void fwohci_as_input(struct fwohci_softc *, struct fwohci_ctx *);
    192       1.3      onoe 
    193       1.3      onoe static int  fwohci_at_output(struct fwohci_softc *, struct fwohci_ctx *,
    194      1.28       jmc     struct fwohci_pkt *);
    195       1.9      onoe static void fwohci_at_done(struct fwohci_softc *, struct fwohci_ctx *, int);
    196       1.3      onoe static void fwohci_atrs_output(struct fwohci_softc *, int, struct fwohci_pkt *,
    197      1.28       jmc     struct fwohci_pkt *);
    198       1.3      onoe 
    199      1.16      onoe static int  fwohci_guidrom_init(struct fwohci_softc *);
    200       1.3      onoe static void fwohci_configrom_init(struct fwohci_softc *);
    201      1.24       jmc static int  fwohci_configrom_input(struct fwohci_softc *, void *,
    202      1.28       jmc     struct fwohci_pkt *);
    203       1.3      onoe static void fwohci_selfid_init(struct fwohci_softc *);
    204       1.7      onoe static int  fwohci_selfid_input(struct fwohci_softc *);
    205       1.3      onoe 
    206       1.3      onoe static void fwohci_csr_init(struct fwohci_softc *);
    207       1.3      onoe static int  fwohci_csr_input(struct fwohci_softc *, void *,
    208      1.28       jmc     struct fwohci_pkt *);
    209       1.3      onoe 
    210       1.3      onoe static void fwohci_uid_collect(struct fwohci_softc *);
    211      1.36      onoe static void fwohci_uid_req(struct fwohci_softc *, int);
    212       1.3      onoe static int  fwohci_uid_input(struct fwohci_softc *, void *,
    213      1.28       jmc     struct fwohci_pkt *);
    214       1.8      onoe static int  fwohci_uid_lookup(struct fwohci_softc *, const u_int8_t *);
    215      1.24       jmc static void fwohci_check_nodes(struct fwohci_softc *);
    216       1.3      onoe 
    217       1.3      onoe static int  fwohci_if_inreg(struct device *, u_int32_t, u_int32_t,
    218      1.28       jmc     void (*)(struct device *, struct mbuf *));
    219       1.3      onoe static int  fwohci_if_input(struct fwohci_softc *, void *, struct fwohci_pkt *);
    220      1.40      haya static int  fwohci_if_input_iso(struct fwohci_softc *, void *, struct fwohci_pkt *);
    221      1.62      haya 
    222       1.3      onoe static int  fwohci_if_output(struct device *, struct mbuf *,
    223      1.28       jmc     void (*)(struct device *, struct mbuf *));
    224      1.41      onoe static int fwohci_if_setiso(struct device *, u_int32_t, u_int32_t, u_int32_t,
    225      1.40      haya     void (*)(struct device *, struct mbuf *));
    226      1.29       jmc static int  fwohci_read(struct ieee1394_abuf *);
    227      1.29       jmc static int  fwohci_write(struct ieee1394_abuf *);
    228      1.31       jmc static int  fwohci_read_resp(struct fwohci_softc *, void *, struct fwohci_pkt *);
    229      1.31       jmc static int  fwohci_write_ack(struct fwohci_softc *, void *, struct fwohci_pkt *);
    230      1.31       jmc static int  fwohci_read_multi_resp(struct fwohci_softc *, void *,
    231      1.28       jmc     struct fwohci_pkt *);
    232      1.24       jmc static int  fwohci_inreg(struct ieee1394_abuf *, int);
    233      1.51       jmc static int  fwohci_unreg(struct ieee1394_abuf *, int);
    234      1.24       jmc static int  fwohci_parse_input(struct fwohci_softc *, void *,
    235      1.28       jmc     struct fwohci_pkt *);
    236  1.78.2.3     skrll static int  fwohci_submatch(struct device *, struct cfdata *,
    237  1.78.2.3     skrll 			    const locdesc_t *, void *);
    238       1.3      onoe 
    239      1.62      haya /* XXX */
    240      1.62      haya u_int16_t fwohci_cycletimer(struct fwohci_softc *);
    241      1.62      haya u_int16_t fwohci_it_cycletimer(ieee1394_it_tag_t);
    242      1.62      haya 
    243       1.8      onoe #ifdef FW_DEBUG
    244      1.33      onoe static void fwohci_show_intr(struct fwohci_softc *, u_int32_t);
    245      1.33      onoe static void fwohci_show_phypkt(struct fwohci_softc *, u_int32_t);
    246      1.28       jmc 
    247      1.28       jmc /* 1 is normal debug, 2 is verbose debug, 3 is complete (packet dumps). */
    248      1.28       jmc 
    249      1.28       jmc #define DPRINTF(x)      if (fwdebug) printf x
    250      1.28       jmc #define DPRINTFN(n,x)   if (fwdebug>(n)) printf x
    251      1.53       jmc int     fwdebug = 1;
    252      1.28       jmc #else
    253      1.28       jmc #define DPRINTF(x)
    254      1.28       jmc #define DPRINTFN(n,x)
    255       1.8      onoe #endif
    256       1.8      onoe 
    257      1.62      haya #define OHCI_ITHEADER_SPD_MASK		0x00070000
    258      1.62      haya #define OHCI_ITHEADER_SPD_BITPOS	16
    259      1.62      haya #define OHCI_ITHEADER_TAG_MASK		0x0000c000
    260      1.62      haya #define OHCI_ITHEADER_TAG_BITPOS	14
    261      1.62      haya #define OHCI_ITHEADER_CHAN_MASK		0x00003f00
    262      1.62      haya #define OHCI_ITHEADER_CHAN_BITPOS	8
    263      1.62      haya #define OHCI_ITHEADER_TCODE_MASK	0x000000f0
    264      1.62      haya #define OHCI_ITHEADER_TCODE_BITPOS	4
    265      1.62      haya #define OHCI_ITHEADER_SY_MASK		0x0000000f
    266      1.62      haya #define OHCI_ITHEADER_SY_BITPOS		0
    267      1.62      haya 
    268      1.62      haya #define OHCI_ITHEADER_VAL(fld, val) \
    269      1.62      haya 	(OHCI_ITHEADER_##fld##_MASK & ((val) << OHCI_ITHEADER_##fld##_BITPOS))
    270      1.62      haya 
    271       1.1      matt int
    272       1.5      matt fwohci_init(struct fwohci_softc *sc, const struct evcnt *ev)
    273       1.1      matt {
    274       1.3      onoe 	int i;
    275       1.1      matt 	u_int32_t val;
    276       1.5      matt #if 0
    277       1.5      matt 	int error;
    278       1.5      matt #endif
    279       1.5      matt 
    280       1.5      matt 	evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, ev,
    281       1.5      matt 	    sc->sc_sc1394.sc1394_dev.dv_xname, "intr");
    282       1.1      matt 
    283      1.40      haya 	evcnt_attach_dynamic(&sc->sc_isocnt, EVCNT_TYPE_MISC, ev,
    284      1.62      haya 	    sc->sc_sc1394.sc1394_dev.dv_xname, "isorcvs");
    285      1.62      haya 	evcnt_attach_dynamic(&sc->sc_ascnt, EVCNT_TYPE_MISC, ev,
    286      1.62      haya 	    sc->sc_sc1394.sc1394_dev.dv_xname, "asrcvs");
    287      1.62      haya 	evcnt_attach_dynamic(&sc->sc_itintrcnt, EVCNT_TYPE_INTR, ev,
    288      1.62      haya 	    sc->sc_sc1394.sc1394_dev.dv_xname, "itintr");
    289      1.40      haya 
    290       1.3      onoe 	/*
    291       1.3      onoe 	 * Wait for reset completion
    292       1.3      onoe 	 */
    293       1.3      onoe 	for (i = 0; i < OHCI_LOOP; i++) {
    294       1.3      onoe 		val = OHCI_CSR_READ(sc, OHCI_REG_HCControlClear);
    295       1.3      onoe 		if ((val & OHCI_HCControl_SoftReset) == 0)
    296       1.3      onoe 			break;
    297      1.36      onoe 		DELAY(10);
    298       1.3      onoe 	}
    299       1.3      onoe 
    300       1.1      matt 	/* What dialect of OHCI is this device?
    301       1.1      matt 	 */
    302       1.1      matt 	val = OHCI_CSR_READ(sc, OHCI_REG_Version);
    303      1.73   thorpej 	aprint_normal("%s: OHCI %u.%u", sc->sc_sc1394.sc1394_dev.dv_xname,
    304       1.1      matt 	    OHCI_Version_GET_Version(val), OHCI_Version_GET_Revision(val));
    305       1.1      matt 
    306      1.24       jmc 	LIST_INIT(&sc->sc_nodelist);
    307      1.26     enami 
    308      1.16      onoe 	if (fwohci_guidrom_init(sc) != 0) {
    309      1.73   thorpej 		aprint_error("\n%s: fatal: no global UID ROM\n",
    310      1.16      onoe 		    sc->sc_sc1394.sc1394_dev.dv_xname);
    311       1.1      matt 		return -1;
    312       1.1      matt 	}
    313       1.1      matt 
    314      1.73   thorpej 	aprint_normal(", %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
    315       1.1      matt 	    sc->sc_sc1394.sc1394_guid[0], sc->sc_sc1394.sc1394_guid[1],
    316       1.1      matt 	    sc->sc_sc1394.sc1394_guid[2], sc->sc_sc1394.sc1394_guid[3],
    317       1.1      matt 	    sc->sc_sc1394.sc1394_guid[4], sc->sc_sc1394.sc1394_guid[5],
    318       1.1      matt 	    sc->sc_sc1394.sc1394_guid[6], sc->sc_sc1394.sc1394_guid[7]);
    319       1.1      matt 
    320       1.1      matt 	/* Get the maximum link speed and receive size
    321       1.1      matt 	 */
    322       1.1      matt 	val = OHCI_CSR_READ(sc, OHCI_REG_BusOptions);
    323       1.1      matt 	sc->sc_sc1394.sc1394_link_speed =
    324      1.18      onoe 	    OHCI_BITVAL(val, OHCI_BusOptions_LinkSpd);
    325       1.1      matt 	if (sc->sc_sc1394.sc1394_link_speed < IEEE1394_SPD_MAX) {
    326      1.73   thorpej 		aprint_normal(", %s",
    327      1.26     enami 		    ieee1394_speeds[sc->sc_sc1394.sc1394_link_speed]);
    328       1.1      matt 	} else {
    329      1.73   thorpej 		aprint_normal(", unknown speed %u",
    330      1.73   thorpej 		    sc->sc_sc1394.sc1394_link_speed);
    331       1.1      matt 	}
    332      1.28       jmc 
    333       1.1      matt 	/* MaxRec is encoded as log2(max_rec_octets)-1
    334       1.1      matt 	 */
    335       1.1      matt 	sc->sc_sc1394.sc1394_max_receive =
    336      1.18      onoe 	    1 << (OHCI_BITVAL(val, OHCI_BusOptions_MaxRec) + 1);
    337      1.73   thorpej 	aprint_normal(", %u max_rec", sc->sc_sc1394.sc1394_max_receive);
    338       1.3      onoe 
    339       1.3      onoe 	/*
    340      1.62      haya 	 * Count how many isochronous receive ctx we have.
    341       1.3      onoe 	 */
    342       1.7      onoe 	OHCI_CSR_WRITE(sc, OHCI_REG_IsoRecvIntMaskSet, ~0);
    343       1.3      onoe 	val = OHCI_CSR_READ(sc, OHCI_REG_IsoRecvIntMaskClear);
    344       1.7      onoe 	OHCI_CSR_WRITE(sc, OHCI_REG_IsoRecvIntMaskClear, ~0);
    345       1.3      onoe 	for (i = 0; val != 0; val >>= 1) {
    346       1.3      onoe 		if (val & 0x1)
    347       1.3      onoe 			i++;
    348       1.3      onoe 	}
    349       1.3      onoe 	sc->sc_isoctx = i;
    350      1.73   thorpej 	aprint_normal(", %d ir_ctx", sc->sc_isoctx);
    351      1.62      haya 
    352      1.62      haya 	/*
    353      1.62      haya 	 * Count how many isochronous transmit ctx we have.
    354      1.62      haya 	 */
    355      1.62      haya 	OHCI_CSR_WRITE(sc, OHCI_REG_IsoXmitIntMaskSet, ~0);
    356      1.62      haya 	val = OHCI_CSR_READ(sc, OHCI_REG_IsoXmitIntMaskClear);
    357      1.62      haya 	OHCI_CSR_WRITE(sc, OHCI_REG_IsoXmitIntMaskClear, ~0);
    358      1.62      haya 	for (i = 0; val != 0; val >>= 1) {
    359      1.62      haya 		if (val & 0x1) {
    360      1.62      haya 			i++;
    361      1.62      haya 			OHCI_SYNC_TX_DMA_WRITE(sc, i,OHCI_SUBREG_CommandPtr,0);
    362      1.62      haya 		}
    363      1.62      haya 	}
    364      1.62      haya 	sc->sc_itctx = i;
    365      1.62      haya 
    366      1.73   thorpej 	aprint_normal(", %d it_ctx", sc->sc_itctx);
    367      1.62      haya 
    368      1.73   thorpej 	aprint_normal("\n");
    369       1.3      onoe 
    370       1.5      matt #if 0
    371      1.26     enami 	error = fwohci_dnamem_alloc(sc, OHCI_CONFIG_SIZE,
    372      1.26     enami 	    OHCI_CONFIG_ALIGNMENT, &sc->sc_configrom_map,
    373      1.26     enami 	    (caddr_t *) &sc->sc_configrom, BUS_DMA_WAITOK|BUS_DMA_COHERENT);
    374       1.5      matt 	return error;
    375       1.5      matt #endif
    376       1.5      matt 
    377      1.24       jmc 	sc->sc_dying = 0;
    378      1.36      onoe 	sc->sc_nodeid = 0xffff;		/* invalid */
    379       1.3      onoe 
    380      1.58       jmc 	sc->sc_sc1394.sc1394_callback.sc1394_read = fwohci_read;
    381      1.58       jmc 	sc->sc_sc1394.sc1394_callback.sc1394_write = fwohci_write;
    382      1.58       jmc 	sc->sc_sc1394.sc1394_callback.sc1394_inreg = fwohci_inreg;
    383      1.58       jmc 	sc->sc_sc1394.sc1394_callback.sc1394_unreg = fwohci_unreg;
    384      1.58       jmc 
    385      1.26     enami 	kthread_create(fwohci_create_event_thread, sc);
    386       1.1      matt 	return 0;
    387       1.1      matt }
    388       1.1      matt 
    389      1.40      haya static int
    390      1.41      onoe fwohci_if_setiso(struct device *self, u_int32_t channel, u_int32_t tag,
    391      1.41      onoe     u_int32_t direction, void (*handler)(struct device *, struct mbuf *))
    392      1.40      haya {
    393      1.40      haya 	struct fwohci_softc *sc = (struct fwohci_softc *)self;
    394      1.40      haya 	int retval;
    395      1.40      haya 	int s;
    396      1.40      haya 
    397      1.40      haya 	if (direction == 1) {
    398      1.40      haya 		return EIO;
    399      1.40      haya 	}
    400      1.40      haya 
    401      1.40      haya 	s = splnet();
    402      1.40      haya 	retval = fwohci_handler_set(sc, IEEE1394_TCODE_STREAM_DATA,
    403      1.67       jmc 	    channel, 1 << tag, 0, fwohci_if_input_iso, handler);
    404      1.40      haya 	splx(s);
    405      1.40      haya 
    406      1.40      haya 	if (!retval) {
    407      1.40      haya 		printf("%s: dummy iso handler set\n",
    408      1.40      haya 		    sc->sc_sc1394.sc1394_dev.dv_xname);
    409      1.40      haya 	} else {
    410      1.40      haya 		printf("%s: dummy iso handler cannot set\n",
    411      1.40      haya 		    sc->sc_sc1394.sc1394_dev.dv_xname);
    412      1.40      haya 	}
    413      1.40      haya 
    414      1.40      haya 	return retval;
    415      1.40      haya }
    416      1.40      haya 
    417       1.1      matt int
    418       1.1      matt fwohci_intr(void *arg)
    419       1.1      matt {
    420       1.1      matt 	struct fwohci_softc * const sc = arg;
    421       1.1      matt 	int progress = 0;
    422       1.3      onoe 	u_int32_t intmask, iso;
    423       1.1      matt 
    424       1.1      matt 	for (;;) {
    425       1.3      onoe 		intmask = OHCI_CSR_READ(sc, OHCI_REG_IntEventClear);
    426      1.24       jmc 
    427      1.26     enami 		/*
    428      1.26     enami 		 * On a bus reset, everything except bus reset gets
    429      1.26     enami 		 * cleared.  That can't get cleared until the selfid
    430      1.26     enami 		 * phase completes (which happens outside the
    431      1.26     enami 		 * interrupt routines). So if just a bus reset is left
    432      1.26     enami 		 * in the mask and it's already in the sc_intmask,
    433      1.26     enami 		 * just return.
    434      1.26     enami 		 */
    435      1.26     enami 
    436      1.26     enami 		if ((intmask == 0) ||
    437      1.26     enami 		    (progress && (intmask == OHCI_Int_BusReset) &&
    438      1.26     enami 			(sc->sc_intmask & OHCI_Int_BusReset))) {
    439      1.26     enami 			if (progress)
    440      1.26     enami 				wakeup(fwohci_event_thread);
    441      1.26     enami 			return progress;
    442      1.26     enami 		}
    443       1.7      onoe 		OHCI_CSR_WRITE(sc, OHCI_REG_IntEventClear,
    444       1.7      onoe 		    intmask & ~OHCI_Int_BusReset);
    445       1.3      onoe #ifdef FW_DEBUG
    446      1.33      onoe 		if (fwdebug > 1)
    447      1.33      onoe 			fwohci_show_intr(sc, intmask);
    448      1.33      onoe #endif
    449      1.28       jmc 
    450       1.3      onoe 		if (intmask & OHCI_Int_BusReset) {
    451       1.7      onoe 			/*
    452       1.7      onoe 			 * According to OHCI spec 6.1.1 "busReset",
    453       1.7      onoe 			 * All asynchronous transmit must be stopped before
    454       1.7      onoe 			 * clearing BusReset.  Moreover, the BusReset
    455       1.7      onoe 			 * interrupt bit should not be cleared during the
    456       1.7      onoe 			 * SelfID phase.  Thus we turned off interrupt mask
    457       1.7      onoe 			 * bit of BusReset instead until SelfID completion
    458       1.7      onoe 			 * or SelfID timeout.
    459       1.7      onoe 			 */
    460       1.9      onoe 			intmask &= OHCI_Int_SelfIDComplete;
    461      1.26     enami 			OHCI_CSR_WRITE(sc, OHCI_REG_IntMaskClear,
    462      1.26     enami 			    OHCI_Int_BusReset);
    463      1.34      onoe 			sc->sc_intmask = OHCI_Int_BusReset;
    464       1.9      onoe 		}
    465      1.34      onoe 		sc->sc_intmask |= intmask;
    466       1.9      onoe 
    467       1.3      onoe 		if (intmask & OHCI_Int_IsochTx) {
    468      1.62      haya 			int i;
    469      1.62      haya 
    470      1.26     enami 			iso = OHCI_CSR_READ(sc, OHCI_REG_IsoXmitIntEventClear);
    471      1.26     enami 			OHCI_CSR_WRITE(sc, OHCI_REG_IsoXmitIntEventClear, iso);
    472      1.62      haya 
    473      1.62      haya 			sc->sc_itintrcnt.ev_count++;
    474      1.62      haya 			for (i = 0; i < sc->sc_itctx; ++i) {
    475      1.62      haya 				if ((iso & (1<<i)) == 0 ||
    476      1.62      haya 				    sc->sc_ctx_it[i] == NULL) {
    477      1.62      haya 					continue;
    478      1.62      haya 				}
    479      1.62      haya 
    480      1.62      haya 				fwohci_it_intr(sc, sc->sc_ctx_it[i]);
    481      1.62      haya 			}
    482      1.26     enami 		}
    483       1.3      onoe 		if (intmask & OHCI_Int_IsochRx) {
    484      1.40      haya 			int i;
    485      1.40      haya 
    486      1.26     enami 			iso = OHCI_CSR_READ(sc, OHCI_REG_IsoRecvIntEventClear);
    487      1.26     enami 			OHCI_CSR_WRITE(sc, OHCI_REG_IsoRecvIntEventClear, iso);
    488      1.62      haya 
    489      1.40      haya 			for (i = 0; i < sc->sc_isoctx; i++) {
    490      1.62      haya 				if ((iso & (1 << i))
    491      1.62      haya 				    && sc->sc_ctx_ir[i] != NULL) {
    492      1.62      haya 					iso &= ~(1 << i);
    493      1.62      haya 					fwohci_ir_intr(sc, sc->sc_ctx_ir[i]);
    494      1.40      haya 				}
    495      1.40      haya 			}
    496      1.62      haya 
    497      1.62      haya 			if (iso == 0) {
    498      1.40      haya 				sc->sc_intmask &= ~OHCI_Int_IsochRx;
    499      1.40      haya 			}
    500      1.26     enami 			sc->sc_iso |= iso;
    501      1.26     enami 		}
    502       1.3      onoe 
    503       1.5      matt 		if (!progress) {
    504       1.5      matt 			sc->sc_intrcnt.ev_count++;
    505       1.5      matt 			progress = 1;
    506       1.5      matt 		}
    507       1.1      matt 	}
    508       1.3      onoe }
    509       1.3      onoe 
    510      1.24       jmc static void
    511      1.24       jmc fwohci_create_event_thread(void *arg)
    512      1.24       jmc {
    513      1.26     enami 	struct fwohci_softc  *sc = arg;
    514      1.24       jmc 
    515      1.26     enami 	if (kthread_create1(fwohci_thread_init, sc, &sc->sc_event_thread, "%s",
    516      1.26     enami 	    sc->sc_sc1394.sc1394_dev.dv_xname)) {
    517      1.26     enami 		printf("%s: unable to create event thread\n",
    518      1.26     enami 		    sc->sc_sc1394.sc1394_dev.dv_xname);
    519      1.26     enami 		panic("fwohci_create_event_thread");
    520      1.26     enami 	}
    521      1.24       jmc }
    522      1.24       jmc 
    523      1.24       jmc static void
    524      1.24       jmc fwohci_thread_init(void *arg)
    525      1.24       jmc {
    526      1.26     enami 	struct fwohci_softc *sc = arg;
    527      1.26     enami 	int i;
    528      1.26     enami 
    529      1.26     enami 	/*
    530      1.24       jmc 	 * Allocate descriptors
    531      1.24       jmc 	 */
    532      1.26     enami 	if (fwohci_desc_alloc(sc)) {
    533      1.26     enami 		printf("%s: not enabling interrupts\n",
    534      1.26     enami 		    sc->sc_sc1394.sc1394_dev.dv_xname);
    535      1.26     enami 		kthread_exit(1);
    536      1.26     enami 	}
    537      1.24       jmc 
    538      1.24       jmc 	/*
    539      1.24       jmc 	 * Enable Link Power
    540      1.24       jmc 	 */
    541      1.24       jmc 
    542      1.24       jmc 	OHCI_CSR_WRITE(sc, OHCI_REG_HCControlSet, OHCI_HCControl_LPS);
    543      1.24       jmc 
    544      1.24       jmc 	/*
    545      1.24       jmc 	 * Allocate DMA Context
    546      1.24       jmc 	 */
    547      1.24       jmc 	fwohci_ctx_alloc(sc, &sc->sc_ctx_arrq, OHCI_BUF_ARRQ_CNT,
    548      1.40      haya 	    OHCI_CTX_ASYNC_RX_REQUEST, FWOHCI_CTX_ASYNC);
    549      1.24       jmc 	fwohci_ctx_alloc(sc, &sc->sc_ctx_arrs, OHCI_BUF_ARRS_CNT,
    550      1.40      haya 	    OHCI_CTX_ASYNC_RX_RESPONSE, FWOHCI_CTX_ASYNC);
    551      1.40      haya 	fwohci_ctx_alloc(sc, &sc->sc_ctx_atrq, 0, OHCI_CTX_ASYNC_TX_REQUEST,
    552      1.40      haya 	    FWOHCI_CTX_ASYNC);
    553      1.40      haya 	fwohci_ctx_alloc(sc, &sc->sc_ctx_atrs, 0, OHCI_CTX_ASYNC_TX_RESPONSE,
    554      1.40      haya 	    FWOHCI_CTX_ASYNC);
    555      1.62      haya 	sc->sc_ctx_as = malloc(sizeof(sc->sc_ctx_as[0]) * sc->sc_isoctx,
    556      1.62      haya 	    M_DEVBUF, M_WAITOK);
    557      1.62      haya 	if (sc->sc_ctx_as == NULL) {
    558      1.62      haya 		printf("no asynchronous stream\n");
    559      1.62      haya 	} else {
    560      1.62      haya 		for (i = 0; i < sc->sc_isoctx; i++)
    561      1.62      haya 			sc->sc_ctx_as[i] = NULL;
    562      1.62      haya 	}
    563      1.24       jmc 	sc->sc_ctx_ir = malloc(sizeof(sc->sc_ctx_ir[0]) * sc->sc_isoctx,
    564      1.62      haya 	    M_DEVBUF, M_WAITOK|M_ZERO);
    565      1.62      haya 	sc->sc_ctx_it = malloc(sizeof(sc->sc_ctx_it[0]) * sc->sc_itctx,
    566      1.62      haya 	    M_DEVBUF, M_WAITOK|M_ZERO);
    567      1.24       jmc 
    568      1.24       jmc 	/*
    569      1.24       jmc 	 * Allocate buffer for configuration ROM and SelfID buffer
    570      1.24       jmc 	 */
    571      1.24       jmc 	fwohci_buf_alloc(sc, &sc->sc_buf_cnfrom);
    572      1.24       jmc 	fwohci_buf_alloc(sc, &sc->sc_buf_selfid);
    573      1.24       jmc 
    574      1.26     enami 	callout_init(&sc->sc_selfid_callout);
    575      1.24       jmc 
    576      1.24       jmc 	sc->sc_sc1394.sc1394_ifinreg = fwohci_if_inreg;
    577      1.24       jmc 	sc->sc_sc1394.sc1394_ifoutput = fwohci_if_output;
    578      1.40      haya 	sc->sc_sc1394.sc1394_ifsetiso = fwohci_if_setiso;
    579      1.24       jmc 
    580      1.62      haya 	sc->sc_sc1394.sc1394_ir_open = fwohci_ir_ctx_set;
    581      1.62      haya 	sc->sc_sc1394.sc1394_ir_close = fwohci_ir_ctx_clear;
    582      1.62      haya 	sc->sc_sc1394.sc1394_ir_read = fwohci_ir_read;
    583      1.62      haya 	sc->sc_sc1394.sc1394_ir_wait = fwohci_ir_wait;
    584      1.62      haya 	sc->sc_sc1394.sc1394_ir_select = fwohci_ir_select;
    585      1.62      haya 
    586      1.62      haya #if 0
    587      1.62      haya 	sc->sc_sc1394.sc1394_it_open = fwohci_it_open;
    588      1.62      haya 	sc->sc_sc1394.sc1394_it_write = fwohci_it_write;
    589      1.62      haya 	sc->sc_sc1394.sc1394_it_close = fwohci_it_close;
    590      1.62      haya 	/* XXX: need fwohci_it_flush? */
    591      1.62      haya #endif
    592      1.62      haya 
    593      1.24       jmc 	/*
    594      1.24       jmc 	 * establish hooks for shutdown and suspend/resume
    595      1.24       jmc 	 */
    596      1.24       jmc 	sc->sc_shutdownhook = shutdownhook_establish(fwohci_shutdown, sc);
    597      1.24       jmc 	sc->sc_powerhook = powerhook_establish(fwohci_power, sc);
    598      1.24       jmc 
    599      1.26     enami 	sc->sc_sc1394.sc1394_if = config_found(&sc->sc_sc1394.sc1394_dev, "fw",
    600      1.26     enami 	    fwohci_print);
    601      1.24       jmc 
    602      1.62      haya #if NFWISO > 0
    603      1.62      haya 	fwiso_register_if(&sc->sc_sc1394);
    604      1.62      haya #endif
    605      1.62      haya 
    606      1.26     enami 	/* Main loop. It's not coming back normally. */
    607      1.24       jmc 
    608      1.26     enami 	fwohci_event_thread(sc);
    609      1.24       jmc 
    610      1.26     enami 	kthread_exit(0);
    611      1.24       jmc }
    612      1.24       jmc 
    613      1.24       jmc static void
    614      1.24       jmc fwohci_event_thread(struct fwohci_softc *sc)
    615      1.24       jmc {
    616      1.26     enami 	int i, s;
    617      1.26     enami 	u_int32_t intmask, iso;
    618      1.26     enami 
    619      1.26     enami 	s = splbio();
    620      1.26     enami 
    621      1.26     enami 	/*
    622      1.26     enami 	 * Initialize hardware registers.
    623      1.26     enami 	 */
    624      1.26     enami 
    625      1.26     enami 	fwohci_hw_init(sc);
    626      1.26     enami 
    627      1.26     enami 	/* Initial Bus Reset */
    628      1.26     enami 	fwohci_phy_busreset(sc);
    629      1.26     enami 	splx(s);
    630      1.26     enami 
    631      1.26     enami 	while (!sc->sc_dying) {
    632      1.35      onoe 		s = splbio();
    633      1.35      onoe 		intmask = sc->sc_intmask;
    634      1.35      onoe 		if (intmask == 0) {
    635      1.36      onoe 			tsleep(fwohci_event_thread, PZERO, "fwohciev", 0);
    636      1.35      onoe 			splx(s);
    637      1.35      onoe 			continue;
    638      1.35      onoe 		}
    639      1.35      onoe 		sc->sc_intmask = 0;
    640      1.35      onoe 		splx(s);
    641      1.35      onoe 
    642      1.35      onoe 		if (intmask & OHCI_Int_BusReset) {
    643      1.36      onoe 			fwohci_buf_stop_tx(sc);
    644      1.35      onoe 			if (sc->sc_uidtbl != NULL) {
    645      1.35      onoe 				free(sc->sc_uidtbl, M_DEVBUF);
    646      1.35      onoe 				sc->sc_uidtbl = NULL;
    647      1.35      onoe 			}
    648      1.35      onoe 
    649      1.35      onoe 			callout_reset(&sc->sc_selfid_callout,
    650      1.35      onoe 			    OHCI_SELFID_TIMEOUT,
    651      1.35      onoe 			    (void (*)(void *))fwohci_phy_busreset, sc);
    652      1.35      onoe 			sc->sc_nodeid = 0xffff;	/* indicate invalid */
    653      1.35      onoe 			sc->sc_rootid = 0;
    654      1.35      onoe 			sc->sc_irmid = IEEE1394_BCAST_PHY_ID;
    655      1.35      onoe 		}
    656      1.35      onoe 		if (intmask & OHCI_Int_SelfIDComplete) {
    657      1.26     enami 			s = splbio();
    658      1.35      onoe 			OHCI_CSR_WRITE(sc, OHCI_REG_IntEventClear,
    659      1.35      onoe 			    OHCI_Int_BusReset);
    660      1.35      onoe 			OHCI_CSR_WRITE(sc, OHCI_REG_IntMaskSet,
    661      1.35      onoe 			    OHCI_Int_BusReset);
    662      1.35      onoe 			splx(s);
    663      1.35      onoe 			callout_stop(&sc->sc_selfid_callout);
    664      1.35      onoe 			if (fwohci_selfid_input(sc) == 0) {
    665      1.36      onoe 				fwohci_buf_start_rx(sc);
    666      1.35      onoe 				fwohci_uid_collect(sc);
    667      1.35      onoe 			}
    668      1.35      onoe 		}
    669      1.35      onoe 		if (intmask & OHCI_Int_ReqTxComplete)
    670      1.35      onoe 			fwohci_at_done(sc, sc->sc_ctx_atrq, 0);
    671      1.35      onoe 		if (intmask & OHCI_Int_RespTxComplete)
    672      1.35      onoe 			fwohci_at_done(sc, sc->sc_ctx_atrs, 0);
    673      1.35      onoe 		if (intmask & OHCI_Int_RQPkt)
    674      1.35      onoe 			fwohci_arrq_input(sc, sc->sc_ctx_arrq);
    675      1.35      onoe 		if (intmask & OHCI_Int_RSPkt)
    676      1.35      onoe 			fwohci_arrs_input(sc, sc->sc_ctx_arrs);
    677      1.35      onoe 		if (intmask & OHCI_Int_IsochRx) {
    678      1.62      haya 			if (sc->sc_ctx_as == NULL) {
    679      1.62      haya 				continue;
    680      1.62      haya 			}
    681      1.35      onoe 			s = splbio();
    682      1.35      onoe 			iso = sc->sc_iso;
    683      1.35      onoe 			sc->sc_iso = 0;
    684      1.35      onoe 			splx(s);
    685      1.35      onoe 			for (i = 0; i < sc->sc_isoctx; i++) {
    686      1.35      onoe 				if ((iso & (1 << i)) &&
    687      1.62      haya 				    sc->sc_ctx_as[i] != NULL) {
    688      1.62      haya 					fwohci_as_input(sc, sc->sc_ctx_as[i]);
    689      1.62      haya 					sc->sc_ascnt.ev_count++;
    690      1.40      haya 				}
    691      1.35      onoe 			}
    692      1.26     enami 		}
    693      1.26     enami 	}
    694      1.24       jmc }
    695      1.24       jmc 
    696       1.5      matt #if 0
    697       1.5      matt static int
    698       1.5      matt fwohci_dnamem_alloc(struct fwohci_softc *sc, int size, int alignment,
    699      1.26     enami     bus_dmamap_t *mapp, caddr_t *kvap, int flags)
    700       1.5      matt {
    701       1.5      matt 	bus_dma_segment_t segs[1];
    702       1.5      matt 	int error, nsegs, steps;
    703       1.5      matt 
    704       1.5      matt 	steps = 0;
    705       1.5      matt 	error = bus_dmamem_alloc(sc->sc_dmat, size, alignment, alignment,
    706      1.26     enami 	    segs, 1, &nsegs, flags);
    707       1.5      matt 	if (error)
    708       1.5      matt 		goto cleanup;
    709       1.5      matt 
    710       1.5      matt 	steps = 1;
    711       1.5      matt 	error = bus_dmamem_map(sc->sc_dmat, segs, nsegs, segs[0].ds_len,
    712      1.26     enami 	    kvap, flags);
    713       1.5      matt 	if (error)
    714       1.5      matt 		goto cleanup;
    715       1.5      matt 
    716       1.5      matt 	if (error == 0)
    717       1.5      matt 		error = bus_dmamap_create(sc->sc_dmat, size, 1, alignment,
    718      1.26     enami 		    size, flags, mapp);
    719       1.5      matt 	if (error)
    720       1.5      matt 		goto cleanup;
    721       1.5      matt 	if (error == 0)
    722      1.26     enami 		error = bus_dmamap_load(sc->sc_dmat, *mapp, *kvap, size, NULL,
    723      1.26     enami 		    flags);
    724       1.5      matt 	if (error)
    725       1.5      matt 		goto cleanup;
    726       1.5      matt 
    727      1.26     enami  cleanup:
    728       1.5      matt 	switch (steps) {
    729       1.5      matt 	case 1:
    730       1.5      matt 		bus_dmamem_free(sc->sc_dmat, segs, nsegs);
    731       1.5      matt 	}
    732       1.5      matt 
    733       1.5      matt 	return error;
    734       1.5      matt }
    735       1.5      matt #endif
    736       1.5      matt 
    737       1.3      onoe int
    738       1.3      onoe fwohci_print(void *aux, const char *pnp)
    739       1.3      onoe {
    740       1.3      onoe 	char *name = aux;
    741       1.3      onoe 
    742       1.3      onoe 	if (pnp)
    743      1.69   thorpej 		aprint_normal("%s at %s", name, pnp);
    744       1.3      onoe 
    745      1.48  drochner 	return UNCONF;
    746       1.3      onoe }
    747       1.3      onoe 
    748       1.7      onoe static void
    749       1.7      onoe fwohci_hw_init(struct fwohci_softc *sc)
    750       1.7      onoe {
    751       1.7      onoe 	int i;
    752       1.7      onoe 	u_int32_t val;
    753       1.7      onoe 
    754       1.7      onoe 	/*
    755       1.7      onoe 	 * Software Reset.
    756       1.7      onoe 	 */
    757       1.7      onoe 	OHCI_CSR_WRITE(sc, OHCI_REG_HCControlSet, OHCI_HCControl_SoftReset);
    758       1.7      onoe 	for (i = 0; i < OHCI_LOOP; i++) {
    759       1.7      onoe 		val = OHCI_CSR_READ(sc, OHCI_REG_HCControlClear);
    760       1.7      onoe 		if ((val & OHCI_HCControl_SoftReset) == 0)
    761       1.7      onoe 			break;
    762      1.36      onoe 		DELAY(10);
    763       1.7      onoe 	}
    764       1.7      onoe 
    765       1.7      onoe 	OHCI_CSR_WRITE(sc, OHCI_REG_HCControlSet, OHCI_HCControl_LPS);
    766       1.7      onoe 
    767       1.7      onoe 	/*
    768       1.7      onoe 	 * First, initilize CSRs with undefined value to default settings.
    769       1.7      onoe 	 */
    770       1.7      onoe 	val = OHCI_CSR_READ(sc, OHCI_REG_BusOptions);
    771       1.7      onoe 	val |= OHCI_BusOptions_ISC | OHCI_BusOptions_CMC;
    772       1.7      onoe #if 0
    773       1.7      onoe 	val |= OHCI_BusOptions_BMC | OHCI_BusOptions_IRMC;
    774       1.7      onoe #else
    775       1.7      onoe 	val &= ~(OHCI_BusOptions_BMC | OHCI_BusOptions_IRMC);
    776       1.7      onoe #endif
    777       1.7      onoe 	OHCI_CSR_WRITE(sc, OHCI_REG_BusOptions, val);
    778       1.7      onoe 	for (i = 0; i < sc->sc_isoctx; i++) {
    779       1.7      onoe 		OHCI_SYNC_RX_DMA_WRITE(sc, i, OHCI_SUBREG_ContextControlClear,
    780       1.7      onoe 		    ~0);
    781       1.7      onoe 	}
    782      1.62      haya 	for (i = 0; i < sc->sc_itctx; i++) {
    783      1.62      haya 		OHCI_SYNC_TX_DMA_WRITE(sc, i, OHCI_SUBREG_ContextControlClear,
    784      1.62      haya 		    ~0);
    785      1.62      haya 	}
    786       1.7      onoe 	OHCI_CSR_WRITE(sc, OHCI_REG_LinkControlClear, ~0);
    787       1.7      onoe 
    788       1.7      onoe 	fwohci_configrom_init(sc);
    789       1.7      onoe 	fwohci_selfid_init(sc);
    790      1.36      onoe 	fwohci_buf_init_rx(sc);
    791       1.7      onoe 	fwohci_csr_init(sc);
    792       1.7      onoe 
    793       1.7      onoe 	/*
    794       1.7      onoe 	 * Final CSR settings.
    795       1.7      onoe 	 */
    796       1.7      onoe 	OHCI_CSR_WRITE(sc, OHCI_REG_LinkControlSet,
    797       1.7      onoe 	    OHCI_LinkControl_CycleTimerEnable |
    798       1.7      onoe 	    OHCI_LinkControl_RcvSelfID | OHCI_LinkControl_RcvPhyPkt);
    799       1.7      onoe 
    800       1.7      onoe 	OHCI_CSR_WRITE(sc, OHCI_REG_ATRetries, 0x00000888);	/*XXX*/
    801       1.7      onoe 
    802       1.7      onoe 	/* clear receive filter */
    803       1.7      onoe 	OHCI_CSR_WRITE(sc, OHCI_REG_IRMultiChanMaskHiClear, ~0);
    804       1.7      onoe 	OHCI_CSR_WRITE(sc, OHCI_REG_IRMultiChanMaskLoClear, ~0);
    805       1.7      onoe 	OHCI_CSR_WRITE(sc, OHCI_REG_AsynchronousRequestFilterHiSet, 0x80000000);
    806       1.7      onoe 
    807       1.7      onoe 	OHCI_CSR_WRITE(sc, OHCI_REG_HCControlClear,
    808       1.7      onoe 	    OHCI_HCControl_NoByteSwapData | OHCI_HCControl_APhyEnhanceEnable);
    809      1.22     enami #if BYTE_ORDER == BIG_ENDIAN
    810      1.22     enami 	OHCI_CSR_WRITE(sc, OHCI_REG_HCControlSet,
    811      1.22     enami 	    OHCI_HCControl_NoByteSwapData);
    812      1.22     enami #endif
    813       1.7      onoe 
    814       1.7      onoe 	OHCI_CSR_WRITE(sc, OHCI_REG_IntMaskClear, ~0);
    815       1.7      onoe 	OHCI_CSR_WRITE(sc, OHCI_REG_IntMaskSet, OHCI_Int_BusReset |
    816       1.7      onoe 	    OHCI_Int_SelfIDComplete | OHCI_Int_IsochRx | OHCI_Int_IsochTx |
    817       1.7      onoe 	    OHCI_Int_RSPkt | OHCI_Int_RQPkt | OHCI_Int_ARRS | OHCI_Int_ARRQ |
    818       1.7      onoe 	    OHCI_Int_RespTxComplete | OHCI_Int_ReqTxComplete);
    819       1.7      onoe 	OHCI_CSR_WRITE(sc, OHCI_REG_IntMaskSet, OHCI_Int_CycleTooLong |
    820       1.7      onoe 	    OHCI_Int_UnrecoverableError | OHCI_Int_CycleInconsistent |
    821       1.7      onoe 	    OHCI_Int_LockRespErr | OHCI_Int_PostedWriteErr);
    822       1.7      onoe 	OHCI_CSR_WRITE(sc, OHCI_REG_IsoXmitIntMaskSet, ~0);
    823       1.7      onoe 	OHCI_CSR_WRITE(sc, OHCI_REG_IsoRecvIntMaskSet, ~0);
    824       1.7      onoe 	OHCI_CSR_WRITE(sc, OHCI_REG_IntMaskSet, OHCI_Int_MasterEnable);
    825       1.7      onoe 
    826       1.7      onoe 	OHCI_CSR_WRITE(sc, OHCI_REG_HCControlSet, OHCI_HCControl_LinkEnable);
    827       1.7      onoe 
    828       1.7      onoe 	/*
    829       1.7      onoe 	 * Start the receivers
    830       1.7      onoe 	 */
    831      1.36      onoe 	fwohci_buf_start_rx(sc);
    832       1.7      onoe }
    833       1.7      onoe 
    834       1.7      onoe static void
    835       1.7      onoe fwohci_power(int why, void *arg)
    836       1.7      onoe {
    837       1.7      onoe 	struct fwohci_softc *sc = arg;
    838       1.7      onoe 	int s;
    839       1.7      onoe 
    840      1.24       jmc 	s = splbio();
    841      1.10  takemura 	switch (why) {
    842      1.10  takemura 	case PWR_SUSPEND:
    843      1.10  takemura 	case PWR_STANDBY:
    844      1.10  takemura 		fwohci_shutdown(sc);
    845      1.10  takemura 		break;
    846      1.10  takemura 	case PWR_RESUME:
    847       1.7      onoe 		fwohci_hw_init(sc);
    848       1.7      onoe 		fwohci_phy_busreset(sc);
    849      1.10  takemura 		break;
    850      1.10  takemura 	case PWR_SOFTSUSPEND:
    851      1.10  takemura 	case PWR_SOFTSTANDBY:
    852      1.10  takemura 	case PWR_SOFTRESUME:
    853      1.10  takemura 		break;
    854       1.7      onoe 	}
    855       1.7      onoe 	splx(s);
    856       1.7      onoe }
    857       1.7      onoe 
    858       1.7      onoe static void
    859       1.7      onoe fwohci_shutdown(void *arg)
    860       1.7      onoe {
    861       1.7      onoe 	struct fwohci_softc *sc = arg;
    862       1.7      onoe 	u_int32_t val;
    863       1.7      onoe 
    864       1.7      onoe 	callout_stop(&sc->sc_selfid_callout);
    865       1.7      onoe 	/* disable all interrupt */
    866       1.7      onoe 	OHCI_CSR_WRITE(sc, OHCI_REG_IntMaskClear, OHCI_Int_MasterEnable);
    867      1.36      onoe 	fwohci_buf_stop_tx(sc);
    868      1.36      onoe 	fwohci_buf_stop_rx(sc);
    869       1.7      onoe 	val = OHCI_CSR_READ(sc, OHCI_REG_BusOptions);
    870       1.7      onoe 	val &= ~(OHCI_BusOptions_BMC | OHCI_BusOptions_ISC |
    871       1.7      onoe 		OHCI_BusOptions_CMC | OHCI_BusOptions_IRMC);
    872       1.7      onoe 	OHCI_CSR_WRITE(sc, OHCI_REG_BusOptions, val);
    873       1.7      onoe 	fwohci_phy_busreset(sc);
    874      1.36      onoe 	OHCI_CSR_WRITE(sc, OHCI_REG_HCControlClear, OHCI_HCControl_LinkEnable);
    875       1.7      onoe 	OHCI_CSR_WRITE(sc, OHCI_REG_HCControlClear, OHCI_HCControl_LPS);
    876       1.7      onoe 	OHCI_CSR_WRITE(sc, OHCI_REG_HCControlSet, OHCI_HCControl_SoftReset);
    877       1.7      onoe }
    878       1.7      onoe 
    879       1.3      onoe /*
    880       1.3      onoe  * COMMON FUNCTIONS
    881       1.3      onoe  */
    882       1.3      onoe 
    883       1.3      onoe /*
    884       1.7      onoe  * read the PHY Register.
    885       1.3      onoe  */
    886       1.7      onoe static u_int8_t
    887       1.7      onoe fwohci_phy_read(struct fwohci_softc *sc, u_int8_t reg)
    888       1.3      onoe {
    889       1.3      onoe 	int i;
    890       1.3      onoe 	u_int32_t val;
    891       1.3      onoe 
    892       1.3      onoe 	OHCI_CSR_WRITE(sc, OHCI_REG_PhyControl,
    893       1.3      onoe 	    OHCI_PhyControl_RdReg | (reg << OHCI_PhyControl_RegAddr_BITPOS));
    894       1.3      onoe 	for (i = 0; i < OHCI_LOOP; i++) {
    895       1.3      onoe 		if (OHCI_CSR_READ(sc, OHCI_REG_PhyControl) &
    896       1.3      onoe 		    OHCI_PhyControl_RdDone)
    897       1.3      onoe 			break;
    898      1.36      onoe 		DELAY(10);
    899       1.3      onoe 	}
    900       1.3      onoe 	val = OHCI_CSR_READ(sc, OHCI_REG_PhyControl);
    901       1.7      onoe 	return (val & OHCI_PhyControl_RdData) >> OHCI_PhyControl_RdData_BITPOS;
    902       1.7      onoe }
    903       1.7      onoe 
    904       1.7      onoe /*
    905       1.7      onoe  * write the PHY Register.
    906       1.7      onoe  */
    907       1.7      onoe static void
    908       1.7      onoe fwohci_phy_write(struct fwohci_softc *sc, u_int8_t reg, u_int8_t val)
    909       1.7      onoe {
    910       1.7      onoe 	int i;
    911       1.7      onoe 
    912       1.3      onoe 	OHCI_CSR_WRITE(sc, OHCI_REG_PhyControl, OHCI_PhyControl_WrReg |
    913       1.3      onoe 	    (reg << OHCI_PhyControl_RegAddr_BITPOS) |
    914       1.3      onoe 	    (val << OHCI_PhyControl_WrData_BITPOS));
    915       1.3      onoe 	for (i = 0; i < OHCI_LOOP; i++) {
    916       1.3      onoe 		if (!(OHCI_CSR_READ(sc, OHCI_REG_PhyControl) &
    917       1.3      onoe 		    OHCI_PhyControl_WrReg))
    918       1.3      onoe 			break;
    919      1.36      onoe 		DELAY(10);
    920       1.3      onoe 	}
    921       1.3      onoe }
    922       1.3      onoe 
    923       1.3      onoe /*
    924       1.7      onoe  * Initiate Bus Reset
    925       1.7      onoe  */
    926       1.7      onoe static void
    927       1.7      onoe fwohci_phy_busreset(struct fwohci_softc *sc)
    928       1.7      onoe {
    929       1.7      onoe 	int s;
    930       1.7      onoe 	u_int8_t val;
    931       1.7      onoe 
    932      1.24       jmc 	s = splbio();
    933      1.26     enami 	OHCI_CSR_WRITE(sc, OHCI_REG_IntEventClear,
    934       1.7      onoe 	    OHCI_Int_BusReset | OHCI_Int_SelfIDComplete);
    935       1.7      onoe 	OHCI_CSR_WRITE(sc, OHCI_REG_IntMaskSet, OHCI_Int_BusReset);
    936       1.7      onoe 	callout_stop(&sc->sc_selfid_callout);
    937       1.7      onoe 	val = fwohci_phy_read(sc, 1);
    938       1.7      onoe 	val = (val & 0x80) |			/* preserve RHB (force root) */
    939       1.7      onoe 	    0x40 |				/* Initiate Bus Reset */
    940       1.7      onoe 	    0x3f;				/* default GAP count */
    941       1.7      onoe 	fwohci_phy_write(sc, 1, val);
    942       1.7      onoe 	splx(s);
    943       1.7      onoe }
    944       1.7      onoe 
    945       1.7      onoe /*
    946       1.7      onoe  * PHY Packet
    947       1.7      onoe  */
    948       1.7      onoe static void
    949       1.7      onoe fwohci_phy_input(struct fwohci_softc *sc, struct fwohci_pkt *pkt)
    950       1.7      onoe {
    951       1.7      onoe 	u_int32_t val;
    952       1.7      onoe 
    953       1.7      onoe 	val = pkt->fp_hdr[1];
    954       1.7      onoe 	if (val != ~pkt->fp_hdr[2]) {
    955       1.7      onoe 		if (val == 0 && ((*pkt->fp_trail & 0x001f0000) >> 16) ==
    956       1.7      onoe 		    OHCI_CTXCTL_EVENT_BUS_RESET) {
    957      1.28       jmc 			DPRINTFN(1, ("fwohci_phy_input: BusReset: 0x%08x\n",
    958      1.28       jmc 			    pkt->fp_hdr[2]));
    959       1.7      onoe 		} else {
    960       1.7      onoe 			printf("%s: phy packet corrupted (0x%08x, 0x%08x)\n",
    961       1.7      onoe 			    sc->sc_sc1394.sc1394_dev.dv_xname, val,
    962       1.7      onoe 			    pkt->fp_hdr[2]);
    963       1.7      onoe 		}
    964       1.7      onoe 		return;
    965       1.7      onoe 	}
    966       1.7      onoe #ifdef FW_DEBUG
    967      1.33      onoe 	if (fwdebug > 1)
    968      1.33      onoe 		fwohci_show_phypkt(sc, val);
    969       1.7      onoe #endif
    970       1.7      onoe }
    971       1.7      onoe 
    972       1.7      onoe /*
    973       1.3      onoe  * Descriptor for context DMA.
    974       1.3      onoe  */
    975       1.3      onoe static int
    976       1.3      onoe fwohci_desc_alloc(struct fwohci_softc *sc)
    977       1.3      onoe {
    978       1.9      onoe 	int error, mapsize, dsize;
    979       1.3      onoe 
    980       1.3      onoe 	/*
    981       1.3      onoe 	 * allocate descriptor buffer
    982       1.3      onoe 	 */
    983       1.3      onoe 
    984       1.9      onoe 	sc->sc_descsize = OHCI_BUF_ARRQ_CNT + OHCI_BUF_ARRS_CNT +
    985       1.3      onoe 	    OHCI_BUF_ATRQ_CNT + OHCI_BUF_ATRS_CNT +
    986       1.9      onoe 	    OHCI_BUF_IR_CNT * sc->sc_isoctx + 2;
    987       1.9      onoe 	dsize = sizeof(struct fwohci_desc) * sc->sc_descsize;
    988       1.9      onoe 	mapsize = howmany(sc->sc_descsize, NBBY);
    989      1.49   tsutsui 	sc->sc_descmap = malloc(mapsize, M_DEVBUF, M_WAITOK|M_ZERO);
    990       1.3      onoe 
    991      1.62      haya 	if (sc->sc_descmap == NULL) {
    992      1.62      haya 		printf("fwohci_desc_alloc: cannot get memory\n");
    993      1.62      haya 		return -1;
    994      1.62      haya 	}
    995      1.62      haya 
    996       1.9      onoe 	if ((error = bus_dmamem_alloc(sc->sc_dmat, dsize, PAGE_SIZE, 0,
    997       1.9      onoe 	    &sc->sc_dseg, 1, &sc->sc_dnseg, 0)) != 0) {
    998       1.3      onoe 		printf("%s: unable to allocate descriptor buffer, error = %d\n",
    999       1.3      onoe 		    sc->sc_sc1394.sc1394_dev.dv_xname, error);
   1000       1.3      onoe 		goto fail_0;
   1001       1.3      onoe 	}
   1002       1.3      onoe 
   1003       1.3      onoe 	if ((error = bus_dmamem_map(sc->sc_dmat, &sc->sc_dseg, sc->sc_dnseg,
   1004       1.9      onoe 	    dsize, (caddr_t *)&sc->sc_desc, BUS_DMA_COHERENT | BUS_DMA_WAITOK))
   1005       1.9      onoe 	    != 0) {
   1006       1.3      onoe 		printf("%s: unable to map descriptor buffer, error = %d\n",
   1007       1.3      onoe 		    sc->sc_sc1394.sc1394_dev.dv_xname, error);
   1008       1.3      onoe 		goto fail_1;
   1009       1.3      onoe 	}
   1010       1.3      onoe 
   1011       1.9      onoe 	if ((error = bus_dmamap_create(sc->sc_dmat, dsize, sc->sc_dnseg,
   1012      1.11     enami 	    dsize, 0, BUS_DMA_WAITOK, &sc->sc_ddmamap)) != 0) {
   1013       1.3      onoe 		printf("%s: unable to create descriptor buffer DMA map, "
   1014       1.3      onoe 		    "error = %d\n", sc->sc_sc1394.sc1394_dev.dv_xname, error);
   1015       1.3      onoe 		goto fail_2;
   1016       1.3      onoe 	}
   1017       1.3      onoe 
   1018       1.3      onoe 	if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_ddmamap, sc->sc_desc,
   1019       1.9      onoe 	    dsize, NULL, BUS_DMA_WAITOK)) != 0) {
   1020       1.3      onoe 		printf("%s: unable to load descriptor buffer DMA map, "
   1021       1.3      onoe 		    "error = %d\n", sc->sc_sc1394.sc1394_dev.dv_xname, error);
   1022       1.3      onoe 		goto fail_3;
   1023       1.3      onoe 	}
   1024       1.3      onoe 
   1025       1.3      onoe 	return 0;
   1026       1.3      onoe 
   1027       1.3      onoe   fail_3:
   1028       1.3      onoe 	bus_dmamap_destroy(sc->sc_dmat, sc->sc_ddmamap);
   1029       1.3      onoe   fail_2:
   1030       1.9      onoe 	bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_desc, dsize);
   1031       1.3      onoe   fail_1:
   1032       1.3      onoe 	bus_dmamem_free(sc->sc_dmat, &sc->sc_dseg, sc->sc_dnseg);
   1033       1.3      onoe   fail_0:
   1034       1.3      onoe 	return error;
   1035       1.3      onoe }
   1036       1.3      onoe 
   1037       1.9      onoe static struct fwohci_desc *
   1038       1.9      onoe fwohci_desc_get(struct fwohci_softc *sc, int ndesc)
   1039       1.9      onoe {
   1040       1.9      onoe 	int i, n;
   1041       1.9      onoe 
   1042       1.9      onoe 	for (n = 0; n <= sc->sc_descsize - ndesc; n++) {
   1043       1.9      onoe 		for (i = 0; ; i++) {
   1044       1.9      onoe 			if (i == ndesc) {
   1045       1.9      onoe 				for (i = 0; i < ndesc; i++)
   1046       1.9      onoe 					setbit(sc->sc_descmap, n + i);
   1047       1.9      onoe 				return sc->sc_desc + n;
   1048       1.9      onoe 			}
   1049       1.9      onoe 			if (isset(sc->sc_descmap, n + i))
   1050       1.9      onoe 				break;
   1051       1.9      onoe 		}
   1052       1.9      onoe 	}
   1053       1.9      onoe 	return NULL;
   1054       1.9      onoe }
   1055       1.9      onoe 
   1056       1.9      onoe static void
   1057       1.9      onoe fwohci_desc_put(struct fwohci_softc *sc, struct fwohci_desc *fd, int ndesc)
   1058       1.9      onoe {
   1059       1.9      onoe 	int i, n;
   1060       1.9      onoe 
   1061       1.9      onoe 	n = fd - sc->sc_desc;
   1062       1.9      onoe 	for (i = 0; i < ndesc; i++, n++) {
   1063      1.28       jmc #ifdef DIAGNOSTIC
   1064       1.9      onoe 		if (isclr(sc->sc_descmap, n))
   1065       1.9      onoe 			panic("fwohci_desc_put: duplicated free");
   1066       1.9      onoe #endif
   1067       1.9      onoe 		clrbit(sc->sc_descmap, n);
   1068       1.9      onoe 	}
   1069       1.9      onoe }
   1070       1.9      onoe 
   1071       1.3      onoe /*
   1072      1.72       wiz  * Asynchronous/Isochronous Transmit/Receive Context
   1073       1.3      onoe  */
   1074       1.3      onoe static int
   1075       1.3      onoe fwohci_ctx_alloc(struct fwohci_softc *sc, struct fwohci_ctx **fcp,
   1076      1.40      haya     int bufcnt, int ctx, int ctxtype)
   1077       1.3      onoe {
   1078       1.3      onoe 	int i, error;
   1079       1.3      onoe 	struct fwohci_ctx *fc;
   1080       1.3      onoe 	struct fwohci_buf *fb;
   1081       1.3      onoe 	struct fwohci_desc *fd;
   1082      1.44      haya #if DOUBLEBUF
   1083      1.40      haya 	int buf2cnt;
   1084      1.44      haya #endif
   1085       1.3      onoe 
   1086      1.50       eeh 	fc = malloc(sizeof(*fc), M_DEVBUF, M_WAITOK|M_ZERO);
   1087       1.3      onoe 	LIST_INIT(&fc->fc_handler);
   1088       1.3      onoe 	TAILQ_INIT(&fc->fc_buf);
   1089       1.3      onoe 	fc->fc_ctx = ctx;
   1090      1.50       eeh 	fc->fc_buffers = fb = malloc(sizeof(*fb) * bufcnt, M_DEVBUF, M_WAITOK|M_ZERO);
   1091       1.3      onoe 	fc->fc_bufcnt = bufcnt;
   1092      1.40      haya #if DOUBLEBUF
   1093      1.40      haya 	TAILQ_INIT(&fc->fc_buf2); /* for isochronous */
   1094      1.40      haya 	if (ctxtype == FWOHCI_CTX_ISO_MULTI) {
   1095      1.40      haya 		buf2cnt = bufcnt/2;
   1096      1.40      haya 		bufcnt -= buf2cnt;
   1097      1.40      haya 		if (buf2cnt == 0) {
   1098      1.40      haya 			panic("cannot allocate iso buffer");
   1099      1.40      haya 		}
   1100      1.40      haya 	}
   1101      1.40      haya #endif
   1102       1.3      onoe 	for (i = 0; i < bufcnt; i++, fb++) {
   1103       1.3      onoe 		if ((error = fwohci_buf_alloc(sc, fb)) != 0)
   1104       1.3      onoe 			goto fail;
   1105       1.9      onoe 		if ((fd = fwohci_desc_get(sc, 1)) == NULL) {
   1106       1.9      onoe 			error = ENOBUFS;
   1107       1.9      onoe 			goto fail;
   1108       1.9      onoe 		}
   1109       1.3      onoe 		fb->fb_desc = fd;
   1110       1.3      onoe 		fb->fb_daddr = sc->sc_ddmamap->dm_segs[0].ds_addr +
   1111       1.7      onoe 		    ((caddr_t)fd - (caddr_t)sc->sc_desc);
   1112       1.3      onoe 		fd->fd_flags = OHCI_DESC_INPUT | OHCI_DESC_STATUS |
   1113       1.3      onoe 		    OHCI_DESC_INTR_ALWAYS | OHCI_DESC_BRANCH;
   1114       1.3      onoe 		fd->fd_reqcount = fb->fb_dmamap->dm_segs[0].ds_len;
   1115       1.3      onoe 		fd->fd_data = fb->fb_dmamap->dm_segs[0].ds_addr;
   1116       1.3      onoe 		TAILQ_INSERT_TAIL(&fc->fc_buf, fb, fb_list);
   1117       1.3      onoe 	}
   1118      1.40      haya #if DOUBLEBUF
   1119      1.40      haya 	if (ctxtype == FWOHCI_CTX_ISO_MULTI) {
   1120      1.40      haya 		for (i = bufcnt; i < bufcnt + buf2cnt; i++, fb++) {
   1121      1.40      haya 			if ((error = fwohci_buf_alloc(sc, fb)) != 0)
   1122      1.40      haya 				goto fail;
   1123      1.40      haya 			if ((fd = fwohci_desc_get(sc, 1)) == NULL) {
   1124      1.40      haya 				error = ENOBUFS;
   1125      1.40      haya 				goto fail;
   1126      1.40      haya 			}
   1127      1.40      haya 			fb->fb_desc = fd;
   1128      1.40      haya 			fb->fb_daddr = sc->sc_ddmamap->dm_segs[0].ds_addr +
   1129      1.40      haya 			    ((caddr_t)fd - (caddr_t)sc->sc_desc);
   1130      1.40      haya 			bus_dmamap_sync(sc->sc_dmat, sc->sc_ddmamap,
   1131      1.40      haya 			    (caddr_t)fd - (caddr_t)sc->sc_desc, sizeof(struct fwohci_desc),
   1132      1.40      haya 			    BUS_DMASYNC_PREWRITE);
   1133      1.40      haya 			fd->fd_flags = OHCI_DESC_INPUT | OHCI_DESC_STATUS |
   1134      1.40      haya 			    OHCI_DESC_INTR_ALWAYS | OHCI_DESC_BRANCH;
   1135      1.40      haya 			fd->fd_reqcount = fb->fb_dmamap->dm_segs[0].ds_len;
   1136      1.40      haya 			fd->fd_data = fb->fb_dmamap->dm_segs[0].ds_addr;
   1137      1.40      haya 			TAILQ_INSERT_TAIL(&fc->fc_buf2, fb, fb_list);
   1138      1.40      haya 			bus_dmamap_sync(sc->sc_dmat, sc->sc_ddmamap,
   1139      1.40      haya 			    (caddr_t)fd - (caddr_t)sc->sc_desc, sizeof(struct fwohci_desc),
   1140      1.40      haya 			    BUS_DMASYNC_POSTWRITE);
   1141      1.40      haya 		}
   1142      1.40      haya 	}
   1143      1.40      haya #endif /* DOUBLEBUF */
   1144      1.40      haya 	fc->fc_type = ctxtype;
   1145       1.3      onoe 	*fcp = fc;
   1146       1.3      onoe 	return 0;
   1147       1.3      onoe 
   1148       1.3      onoe   fail:
   1149      1.38      onoe 	while (i-- > 0) {
   1150      1.38      onoe 		fb--;
   1151      1.38      onoe 		if (fb->fb_desc)
   1152      1.38      onoe 			fwohci_desc_put(sc, fb->fb_desc, 1);
   1153      1.38      onoe 		fwohci_buf_free(sc, fb);
   1154      1.38      onoe 	}
   1155       1.3      onoe 	free(fc, M_DEVBUF);
   1156       1.3      onoe 	return error;
   1157       1.3      onoe }
   1158       1.3      onoe 
   1159       1.3      onoe static void
   1160       1.9      onoe fwohci_ctx_free(struct fwohci_softc *sc, struct fwohci_ctx *fc)
   1161       1.9      onoe {
   1162       1.9      onoe 	struct fwohci_buf *fb;
   1163       1.9      onoe 	struct fwohci_handler *fh;
   1164       1.9      onoe 
   1165      1.42      haya #if DOUBLEBUF
   1166      1.44      haya 	if ((fc->fc_type == FWOHCI_CTX_ISO_MULTI) &&
   1167      1.44      haya 	    (TAILQ_FIRST(&fc->fc_buf) > TAILQ_FIRST(&fc->fc_buf2))) {
   1168      1.42      haya 		struct fwohci_buf_s fctmp;
   1169      1.42      haya 
   1170      1.42      haya 		fctmp = fc->fc_buf;
   1171      1.42      haya 		fc->fc_buf = fc->fc_buf2;
   1172      1.42      haya 		fc->fc_buf2 = fctmp;
   1173      1.42      haya 	}
   1174      1.42      haya #endif
   1175       1.9      onoe 	while ((fh = LIST_FIRST(&fc->fc_handler)) != NULL)
   1176       1.9      onoe 		fwohci_handler_set(sc, fh->fh_tcode, fh->fh_key1, fh->fh_key2,
   1177      1.67       jmc 		    fh->fh_key3, NULL, NULL);
   1178       1.9      onoe 	while ((fb = TAILQ_FIRST(&fc->fc_buf)) != NULL) {
   1179       1.9      onoe 		TAILQ_REMOVE(&fc->fc_buf, fb, fb_list);
   1180      1.38      onoe 		if (fb->fb_desc)
   1181      1.38      onoe 			fwohci_desc_put(sc, fb->fb_desc, 1);
   1182       1.9      onoe 		fwohci_buf_free(sc, fb);
   1183       1.9      onoe 	}
   1184      1.40      haya #if DOUBLEBUF
   1185      1.40      haya 	while ((fb = TAILQ_FIRST(&fc->fc_buf2)) != NULL) {
   1186      1.40      haya 		TAILQ_REMOVE(&fc->fc_buf2, fb, fb_list);
   1187      1.40      haya 		if (fb->fb_desc)
   1188      1.40      haya 			fwohci_desc_put(sc, fb->fb_desc, 1);
   1189      1.40      haya 		fwohci_buf_free(sc, fb);
   1190      1.40      haya 	}
   1191      1.40      haya #endif /* DOUBLEBUF */
   1192      1.50       eeh 	free(fc->fc_buffers, M_DEVBUF);
   1193       1.9      onoe 	free(fc, M_DEVBUF);
   1194       1.9      onoe }
   1195       1.9      onoe 
   1196       1.9      onoe static void
   1197       1.3      onoe fwohci_ctx_init(struct fwohci_softc *sc, struct fwohci_ctx *fc)
   1198       1.3      onoe {
   1199       1.3      onoe 	struct fwohci_buf *fb, *nfb;
   1200       1.3      onoe 	struct fwohci_desc *fd;
   1201      1.19      onoe 	struct fwohci_handler *fh;
   1202       1.9      onoe 	int n;
   1203       1.3      onoe 
   1204       1.3      onoe 	for (fb = TAILQ_FIRST(&fc->fc_buf); fb != NULL; fb = nfb) {
   1205       1.3      onoe 		nfb = TAILQ_NEXT(fb, fb_list);
   1206       1.3      onoe 		fb->fb_off = 0;
   1207       1.3      onoe 		fd = fb->fb_desc;
   1208       1.3      onoe 		fd->fd_branch = (nfb != NULL) ? (nfb->fb_daddr | 1) : 0;
   1209       1.3      onoe 		fd->fd_rescount = fd->fd_reqcount;
   1210       1.3      onoe 	}
   1211       1.9      onoe 
   1212      1.40      haya #if DOUBLEBUF
   1213      1.40      haya 	for (fb = TAILQ_FIRST(&fc->fc_buf2); fb != NULL; fb = nfb) {
   1214      1.40      haya 		bus_dmamap_sync(sc->sc_dmat, sc->sc_ddmamap,
   1215      1.40      haya 		    (caddr_t)fd - (caddr_t)sc->sc_desc, sizeof(struct fwohci_desc),
   1216      1.40      haya 		    BUS_DMASYNC_PREWRITE);
   1217      1.40      haya 		nfb = TAILQ_NEXT(fb, fb_list);
   1218      1.40      haya 		fb->fb_off = 0;
   1219      1.40      haya 		fd = fb->fb_desc;
   1220      1.40      haya 		fd->fd_branch = (nfb != NULL) ? (nfb->fb_daddr | 1) : 0;
   1221      1.40      haya 		fd->fd_rescount = fd->fd_reqcount;
   1222      1.40      haya 		bus_dmamap_sync(sc->sc_dmat, sc->sc_ddmamap,
   1223      1.40      haya 		    (caddr_t)fd - (caddr_t)sc->sc_desc, sizeof(struct fwohci_desc),
   1224      1.40      haya 		    BUS_DMASYNC_POSTWRITE);
   1225      1.40      haya 	}
   1226      1.40      haya #endif /* DOUBLEBUF */
   1227      1.40      haya 
   1228       1.9      onoe 	n = fc->fc_ctx;
   1229       1.9      onoe 	fb = TAILQ_FIRST(&fc->fc_buf);
   1230      1.40      haya 	if (fc->fc_type != FWOHCI_CTX_ASYNC) {
   1231       1.9      onoe 		OHCI_SYNC_RX_DMA_WRITE(sc, n, OHCI_SUBREG_CommandPtr,
   1232       1.9      onoe 		    fb->fb_daddr | 1);
   1233       1.9      onoe 		OHCI_SYNC_RX_DMA_WRITE(sc, n, OHCI_SUBREG_ContextControlClear,
   1234       1.9      onoe 		    OHCI_CTXCTL_RX_BUFFER_FILL |
   1235       1.9      onoe 		    OHCI_CTXCTL_RX_CYCLE_MATCH_ENABLE |
   1236       1.9      onoe 		    OHCI_CTXCTL_RX_MULTI_CHAN_MODE |
   1237       1.9      onoe 		    OHCI_CTXCTL_RX_DUAL_BUFFER_MODE);
   1238       1.9      onoe 		OHCI_SYNC_RX_DMA_WRITE(sc, n, OHCI_SUBREG_ContextControlSet,
   1239       1.9      onoe 		    OHCI_CTXCTL_RX_ISOCH_HEADER);
   1240      1.40      haya 		if (fc->fc_type == FWOHCI_CTX_ISO_MULTI) {
   1241      1.40      haya 			OHCI_SYNC_RX_DMA_WRITE(sc, n,
   1242      1.40      haya 			    OHCI_SUBREG_ContextControlSet,
   1243      1.40      haya 			    OHCI_CTXCTL_RX_BUFFER_FILL);
   1244      1.40      haya 		}
   1245      1.19      onoe 		fh = LIST_FIRST(&fc->fc_handler);
   1246      1.62      haya 
   1247      1.62      haya 		if (fh->fh_key1 == IEEE1394_ISO_CHANNEL_ANY) {
   1248      1.62      haya 			OHCI_SYNC_RX_DMA_WRITE(sc, n,
   1249      1.62      haya 			    OHCI_SUBREG_ContextControlSet,
   1250      1.62      haya 			    OHCI_CTXCTL_RX_MULTI_CHAN_MODE);
   1251      1.62      haya 
   1252      1.62      haya 			/* Receive all the isochronous channels */
   1253      1.62      haya 			OHCI_CSR_WRITE(sc, OHCI_REG_IRMultiChanMaskHiSet,
   1254      1.62      haya 			    0xffffffff);
   1255      1.62      haya 			OHCI_CSR_WRITE(sc, OHCI_REG_IRMultiChanMaskLoSet,
   1256      1.62      haya 			    0xffffffff);
   1257      1.62      haya 			DPRINTF(("%s: CTXCTL 0x%08x\n",
   1258      1.62      haya 			    sc->sc_sc1394.sc1394_dev.dv_xname,
   1259      1.62      haya 			    OHCI_SYNC_RX_DMA_READ(sc, n,
   1260      1.62      haya 				OHCI_SUBREG_ContextControlSet)));
   1261      1.62      haya 		}
   1262      1.19      onoe 		OHCI_SYNC_RX_DMA_WRITE(sc, n, OHCI_SUBREG_ContextMatch,
   1263      1.62      haya 		    (fh->fh_key2 << OHCI_CTXMATCH_TAG_BITPOS) |
   1264      1.62      haya 		    (fh->fh_key1 & IEEE1394_ISO_CHANNEL_MASK));
   1265       1.9      onoe 	} else {
   1266       1.9      onoe 		OHCI_ASYNC_DMA_WRITE(sc, n, OHCI_SUBREG_CommandPtr,
   1267       1.9      onoe 		    fb->fb_daddr | 1);
   1268       1.9      onoe 	}
   1269       1.3      onoe }
   1270       1.3      onoe 
   1271       1.3      onoe /*
   1272       1.3      onoe  * DMA data buffer
   1273       1.3      onoe  */
   1274       1.3      onoe static int
   1275       1.3      onoe fwohci_buf_alloc(struct fwohci_softc *sc, struct fwohci_buf *fb)
   1276       1.3      onoe {
   1277       1.3      onoe 	int error;
   1278       1.3      onoe 
   1279       1.7      onoe 	if ((error = bus_dmamem_alloc(sc->sc_dmat, PAGE_SIZE, PAGE_SIZE,
   1280       1.7      onoe 	    PAGE_SIZE, &fb->fb_seg, 1, &fb->fb_nseg, BUS_DMA_WAITOK)) != 0) {
   1281       1.3      onoe 		printf("%s: unable to allocate buffer, error = %d\n",
   1282       1.3      onoe 		    sc->sc_sc1394.sc1394_dev.dv_xname, error);
   1283       1.3      onoe 		goto fail_0;
   1284       1.3      onoe 	}
   1285       1.3      onoe 
   1286       1.3      onoe 	if ((error = bus_dmamem_map(sc->sc_dmat, &fb->fb_seg,
   1287       1.7      onoe 	    fb->fb_nseg, PAGE_SIZE, &fb->fb_buf, BUS_DMA_WAITOK)) != 0) {
   1288       1.3      onoe 		printf("%s: unable to map buffer, error = %d\n",
   1289       1.3      onoe 		    sc->sc_sc1394.sc1394_dev.dv_xname, error);
   1290       1.3      onoe 		goto fail_1;
   1291       1.3      onoe 	}
   1292       1.3      onoe 
   1293       1.7      onoe 	if ((error = bus_dmamap_create(sc->sc_dmat, PAGE_SIZE, fb->fb_nseg,
   1294       1.7      onoe 	    PAGE_SIZE, 0, BUS_DMA_WAITOK, &fb->fb_dmamap)) != 0) {
   1295       1.3      onoe 		printf("%s: unable to create buffer DMA map, "
   1296       1.3      onoe 		    "error = %d\n", sc->sc_sc1394.sc1394_dev.dv_xname,
   1297       1.3      onoe 		    error);
   1298       1.3      onoe 		goto fail_2;
   1299       1.3      onoe 	}
   1300       1.3      onoe 
   1301       1.3      onoe 	if ((error = bus_dmamap_load(sc->sc_dmat, fb->fb_dmamap,
   1302       1.7      onoe 	    fb->fb_buf, PAGE_SIZE, NULL, BUS_DMA_WAITOK)) != 0) {
   1303       1.3      onoe 		printf("%s: unable to load buffer DMA map, "
   1304       1.3      onoe 		    "error = %d\n", sc->sc_sc1394.sc1394_dev.dv_xname,
   1305       1.3      onoe 		    error);
   1306       1.3      onoe 		goto fail_3;
   1307       1.3      onoe 	}
   1308       1.3      onoe 
   1309       1.3      onoe 	return 0;
   1310       1.3      onoe 
   1311       1.3      onoe 	bus_dmamap_unload(sc->sc_dmat, fb->fb_dmamap);
   1312       1.3      onoe   fail_3:
   1313       1.3      onoe 	bus_dmamap_destroy(sc->sc_dmat, fb->fb_dmamap);
   1314       1.3      onoe   fail_2:
   1315       1.7      onoe 	bus_dmamem_unmap(sc->sc_dmat, fb->fb_buf, PAGE_SIZE);
   1316       1.3      onoe   fail_1:
   1317       1.3      onoe 	bus_dmamem_free(sc->sc_dmat, &fb->fb_seg, fb->fb_nseg);
   1318       1.3      onoe   fail_0:
   1319       1.3      onoe 	return error;
   1320       1.3      onoe }
   1321       1.3      onoe 
   1322       1.3      onoe static void
   1323       1.3      onoe fwohci_buf_free(struct fwohci_softc *sc, struct fwohci_buf *fb)
   1324       1.3      onoe {
   1325       1.3      onoe 
   1326       1.3      onoe 	bus_dmamap_unload(sc->sc_dmat, fb->fb_dmamap);
   1327       1.3      onoe 	bus_dmamap_destroy(sc->sc_dmat, fb->fb_dmamap);
   1328       1.7      onoe 	bus_dmamem_unmap(sc->sc_dmat, fb->fb_buf, PAGE_SIZE);
   1329       1.3      onoe 	bus_dmamem_free(sc->sc_dmat, &fb->fb_seg, fb->fb_nseg);
   1330       1.3      onoe }
   1331       1.3      onoe 
   1332       1.3      onoe static void
   1333      1.36      onoe fwohci_buf_init_rx(struct fwohci_softc *sc)
   1334       1.3      onoe {
   1335       1.3      onoe 	int i;
   1336       1.3      onoe 
   1337       1.3      onoe 	/*
   1338       1.9      onoe 	 * Initialize for Asynchronous Receive Queue.
   1339       1.3      onoe 	 */
   1340       1.3      onoe 	fwohci_ctx_init(sc, sc->sc_ctx_arrq);
   1341       1.3      onoe 	fwohci_ctx_init(sc, sc->sc_ctx_arrs);
   1342       1.3      onoe 
   1343       1.3      onoe 	/*
   1344       1.9      onoe 	 * Initialize for Isochronous Receive Queue.
   1345       1.3      onoe 	 */
   1346      1.62      haya 	if (sc->sc_ctx_as != NULL) {
   1347      1.62      haya 		for (i = 0; i < sc->sc_isoctx; i++) {
   1348      1.62      haya 			if (sc->sc_ctx_as[i] != NULL)
   1349      1.62      haya 				fwohci_ctx_init(sc, sc->sc_ctx_as[i]);
   1350      1.62      haya 		}
   1351       1.7      onoe 	}
   1352       1.7      onoe }
   1353       1.7      onoe 
   1354       1.7      onoe static void
   1355      1.36      onoe fwohci_buf_start_rx(struct fwohci_softc *sc)
   1356       1.7      onoe {
   1357       1.7      onoe 	int i;
   1358       1.7      onoe 
   1359       1.7      onoe 	OHCI_ASYNC_DMA_WRITE(sc, OHCI_CTX_ASYNC_RX_REQUEST,
   1360       1.7      onoe 	    OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_RUN);
   1361       1.7      onoe 	OHCI_ASYNC_DMA_WRITE(sc, OHCI_CTX_ASYNC_RX_RESPONSE,
   1362       1.7      onoe 	    OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_RUN);
   1363      1.62      haya 	if (sc->sc_ctx_as != NULL) {
   1364      1.62      haya 		for (i = 0; i < sc->sc_isoctx; i++) {
   1365      1.62      haya 			if (sc->sc_ctx_as[i] != NULL)
   1366      1.62      haya 				OHCI_SYNC_RX_DMA_WRITE(sc, i,
   1367      1.62      haya 				    OHCI_SUBREG_ContextControlSet,
   1368      1.62      haya 				    OHCI_CTXCTL_RUN);
   1369      1.62      haya 		}
   1370       1.3      onoe 	}
   1371       1.3      onoe }
   1372       1.3      onoe 
   1373       1.3      onoe static void
   1374      1.36      onoe fwohci_buf_stop_tx(struct fwohci_softc *sc)
   1375       1.7      onoe {
   1376      1.36      onoe 	int i;
   1377       1.7      onoe 
   1378       1.7      onoe 	OHCI_ASYNC_DMA_WRITE(sc, OHCI_CTX_ASYNC_TX_REQUEST,
   1379       1.7      onoe 	    OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
   1380       1.7      onoe 	OHCI_ASYNC_DMA_WRITE(sc, OHCI_CTX_ASYNC_TX_RESPONSE,
   1381       1.7      onoe 	    OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
   1382       1.7      onoe 
   1383       1.7      onoe 	/*
   1384       1.7      onoe 	 * Make sure the transmitter is stopped.
   1385       1.7      onoe 	 */
   1386      1.36      onoe 	for (i = 0; i < OHCI_LOOP; i++) {
   1387      1.36      onoe 		DELAY(10);
   1388       1.7      onoe 		if (OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_TX_REQUEST,
   1389       1.7      onoe 		    OHCI_SUBREG_ContextControlClear) & OHCI_CTXCTL_ACTIVE)
   1390       1.7      onoe 			continue;
   1391       1.7      onoe 		if (OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_TX_RESPONSE,
   1392       1.7      onoe 		    OHCI_SUBREG_ContextControlClear) & OHCI_CTXCTL_ACTIVE)
   1393       1.7      onoe 			continue;
   1394       1.7      onoe 		break;
   1395       1.7      onoe 	}
   1396      1.36      onoe 
   1397      1.36      onoe 	/*
   1398      1.36      onoe 	 * Initialize for Asynchronous Transmit Queue.
   1399      1.36      onoe 	 */
   1400      1.36      onoe 	fwohci_at_done(sc, sc->sc_ctx_atrq, 1);
   1401      1.36      onoe 	fwohci_at_done(sc, sc->sc_ctx_atrs, 1);
   1402      1.36      onoe }
   1403      1.36      onoe 
   1404      1.36      onoe static void
   1405      1.36      onoe fwohci_buf_stop_rx(struct fwohci_softc *sc)
   1406      1.36      onoe {
   1407      1.36      onoe 	int i;
   1408      1.36      onoe 
   1409      1.36      onoe 	OHCI_ASYNC_DMA_WRITE(sc, OHCI_CTX_ASYNC_RX_REQUEST,
   1410      1.36      onoe 	    OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
   1411      1.36      onoe 	OHCI_ASYNC_DMA_WRITE(sc, OHCI_CTX_ASYNC_RX_RESPONSE,
   1412      1.36      onoe 	    OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
   1413      1.36      onoe 	for (i = 0; i < sc->sc_isoctx; i++) {
   1414      1.36      onoe 		OHCI_SYNC_RX_DMA_WRITE(sc, i,
   1415      1.36      onoe 		    OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
   1416      1.36      onoe 	}
   1417       1.7      onoe }
   1418       1.7      onoe 
   1419       1.7      onoe static void
   1420       1.3      onoe fwohci_buf_next(struct fwohci_softc *sc, struct fwohci_ctx *fc)
   1421       1.3      onoe {
   1422       1.3      onoe 	struct fwohci_buf *fb, *tfb;
   1423       1.3      onoe 
   1424      1.40      haya #if DOUBLEBUF
   1425      1.40      haya 	if (fc->fc_type != FWOHCI_CTX_ISO_MULTI) {
   1426      1.40      haya #endif
   1427      1.40      haya 		while ((fb = TAILQ_FIRST(&fc->fc_buf)) != NULL) {
   1428      1.40      haya 			if (fc->fc_type) {
   1429      1.40      haya 				if (fb->fb_off == 0)
   1430      1.40      haya 					break;
   1431      1.40      haya 			} else {
   1432      1.40      haya 				if (fb->fb_off != fb->fb_desc->fd_reqcount ||
   1433      1.40      haya 				    fb->fb_desc->fd_rescount != 0)
   1434      1.40      haya 					break;
   1435      1.40      haya 			}
   1436      1.40      haya 			TAILQ_REMOVE(&fc->fc_buf, fb, fb_list);
   1437      1.40      haya 			fb->fb_desc->fd_rescount = fb->fb_desc->fd_reqcount;
   1438      1.40      haya 			fb->fb_off = 0;
   1439      1.40      haya 			fb->fb_desc->fd_branch = 0;
   1440      1.40      haya 			tfb = TAILQ_LAST(&fc->fc_buf, fwohci_buf_s);
   1441      1.40      haya 			tfb->fb_desc->fd_branch = fb->fb_daddr | 1;
   1442      1.40      haya 			TAILQ_INSERT_TAIL(&fc->fc_buf, fb, fb_list);
   1443      1.40      haya 		}
   1444      1.40      haya #if DOUBLEBUF
   1445      1.40      haya 	} else {
   1446      1.40      haya 		struct fwohci_buf_s fctmp;
   1447      1.40      haya 
   1448      1.40      haya 		/* cleaning buffer */
   1449      1.40      haya 		for (fb = TAILQ_FIRST(&fc->fc_buf); fb != NULL;
   1450      1.40      haya 		     fb = TAILQ_NEXT(fb, fb_list)) {
   1451      1.40      haya 			fb->fb_off = 0;
   1452      1.40      haya 			fb->fb_desc->fd_rescount = fb->fb_desc->fd_reqcount;
   1453      1.36      onoe 		}
   1454      1.40      haya 
   1455      1.40      haya 		/* rotating buffer */
   1456      1.40      haya 		fctmp = fc->fc_buf;
   1457      1.40      haya 		fc->fc_buf = fc->fc_buf2;
   1458      1.40      haya 		fc->fc_buf2 = fctmp;
   1459       1.3      onoe 	}
   1460      1.40      haya #endif
   1461       1.3      onoe }
   1462       1.3      onoe 
   1463       1.3      onoe static int
   1464      1.39      onoe fwohci_buf_pktget(struct fwohci_softc *sc, struct fwohci_buf **fbp, caddr_t *pp,
   1465       1.3      onoe     int len)
   1466       1.3      onoe {
   1467       1.3      onoe 	struct fwohci_buf *fb;
   1468       1.3      onoe 	struct fwohci_desc *fd;
   1469       1.3      onoe 	int bufend;
   1470       1.3      onoe 
   1471      1.39      onoe 	fb = *fbp;
   1472       1.3      onoe   again:
   1473       1.3      onoe 	fd = fb->fb_desc;
   1474      1.28       jmc 	DPRINTFN(1, ("fwohci_buf_pktget: desc %ld, off %d, req %d, res %d,"
   1475      1.28       jmc 	    " len %d, avail %d\n", (long)(fd - sc->sc_desc), fb->fb_off,
   1476      1.28       jmc 	    fd->fd_reqcount, fd->fd_rescount, len,
   1477      1.28       jmc 	    fd->fd_reqcount - fd->fd_rescount - fb->fb_off));
   1478       1.3      onoe 	bufend = fd->fd_reqcount - fd->fd_rescount;
   1479       1.3      onoe 	if (fb->fb_off >= bufend) {
   1480      1.40      haya 		DPRINTFN(5, ("buf %x finish req %d res %d off %d ",
   1481      1.40      haya 		    fb->fb_desc->fd_data, fd->fd_reqcount, fd->fd_rescount,
   1482      1.40      haya 		    fb->fb_off));
   1483       1.3      onoe 		if (fd->fd_rescount == 0) {
   1484      1.39      onoe 			*fbp = fb = TAILQ_NEXT(fb, fb_list);
   1485      1.39      onoe 			if (fb != NULL)
   1486       1.3      onoe 				goto again;
   1487       1.3      onoe 		}
   1488       1.3      onoe 		return 0;
   1489       1.3      onoe 	}
   1490       1.3      onoe 	if (fb->fb_off + len > bufend)
   1491       1.3      onoe 		len = bufend - fb->fb_off;
   1492       1.7      onoe 	bus_dmamap_sync(sc->sc_dmat, fb->fb_dmamap, fb->fb_off, len,
   1493       1.7      onoe 	    BUS_DMASYNC_POSTREAD);
   1494       1.3      onoe 	*pp = fb->fb_buf + fb->fb_off;
   1495       1.3      onoe 	fb->fb_off += roundup(len, 4);
   1496       1.3      onoe 	return len;
   1497       1.3      onoe }
   1498       1.3      onoe 
   1499       1.3      onoe static int
   1500       1.3      onoe fwohci_buf_input(struct fwohci_softc *sc, struct fwohci_ctx *fc,
   1501       1.3      onoe     struct fwohci_pkt *pkt)
   1502       1.3      onoe {
   1503       1.3      onoe 	caddr_t p;
   1504      1.39      onoe 	struct fwohci_buf *fb;
   1505       1.3      onoe 	int len, count, i;
   1506      1.60       jmc #ifdef FW_DEBUG
   1507      1.60       jmc 	int tlabel;
   1508      1.60       jmc #endif
   1509       1.3      onoe 
   1510       1.9      onoe 	memset(pkt, 0, sizeof(*pkt));
   1511       1.9      onoe 	pkt->fp_uio.uio_iov = pkt->fp_iov;
   1512       1.9      onoe 	pkt->fp_uio.uio_rw = UIO_WRITE;
   1513       1.9      onoe 	pkt->fp_uio.uio_segflg = UIO_SYSSPACE;
   1514       1.9      onoe 
   1515       1.3      onoe 	/* get first quadlet */
   1516      1.39      onoe 	fb = TAILQ_FIRST(&fc->fc_buf);
   1517       1.3      onoe 	count = 4;
   1518      1.39      onoe 	len = fwohci_buf_pktget(sc, &fb, &p, count);
   1519       1.3      onoe 	if (len <= 0) {
   1520      1.28       jmc 		DPRINTFN(1, ("fwohci_buf_input: no input for %d\n",
   1521      1.28       jmc 		    fc->fc_ctx));
   1522       1.3      onoe 		return 0;
   1523       1.3      onoe 	}
   1524       1.3      onoe 	pkt->fp_hdr[0] = *(u_int32_t *)p;
   1525       1.3      onoe 	pkt->fp_tcode = (pkt->fp_hdr[0] & 0x000000f0) >> 4;
   1526       1.3      onoe 	switch (pkt->fp_tcode) {
   1527       1.3      onoe 	case IEEE1394_TCODE_WRITE_REQ_QUAD:
   1528       1.3      onoe 	case IEEE1394_TCODE_READ_RESP_QUAD:
   1529       1.3      onoe 		pkt->fp_hlen = 12;
   1530       1.3      onoe 		pkt->fp_dlen = 4;
   1531       1.3      onoe 		break;
   1532      1.24       jmc 	case IEEE1394_TCODE_READ_REQ_BLOCK:
   1533      1.24       jmc 		pkt->fp_hlen = 16;
   1534      1.26     enami 		pkt->fp_dlen = 0;
   1535      1.26     enami 		break;
   1536      1.26     enami 	case IEEE1394_TCODE_WRITE_REQ_BLOCK:
   1537      1.26     enami 	case IEEE1394_TCODE_READ_RESP_BLOCK:
   1538       1.3      onoe 	case IEEE1394_TCODE_LOCK_REQ:
   1539       1.3      onoe 	case IEEE1394_TCODE_LOCK_RESP:
   1540       1.3      onoe 		pkt->fp_hlen = 16;
   1541       1.3      onoe 		break;
   1542      1.40      haya 	case IEEE1394_TCODE_STREAM_DATA:
   1543      1.39      onoe #ifdef DIAGNOSTIC
   1544      1.40      haya 		if (fc->fc_type == FWOHCI_CTX_ISO_MULTI)
   1545      1.40      haya #endif
   1546      1.40      haya 		{
   1547      1.40      haya 			pkt->fp_hlen = 4;
   1548      1.40      haya 			pkt->fp_dlen = pkt->fp_hdr[0] >> 16;
   1549      1.40      haya 			DPRINTFN(5, ("[%d]", pkt->fp_dlen));
   1550      1.40      haya 			break;
   1551      1.40      haya 		}
   1552      1.40      haya #ifdef DIAGNOSTIC
   1553      1.40      haya 		else {
   1554      1.40      haya 			printf("fwohci_buf_input: bad tcode: STREAM_DATA\n");
   1555      1.40      haya 			return 0;
   1556      1.40      haya 		}
   1557      1.36      onoe #endif
   1558       1.3      onoe 	default:
   1559       1.3      onoe 		pkt->fp_hlen = 12;
   1560       1.3      onoe 		pkt->fp_dlen = 0;
   1561       1.3      onoe 		break;
   1562       1.3      onoe 	}
   1563       1.3      onoe 
   1564       1.3      onoe 	/* get header */
   1565       1.3      onoe 	while (count < pkt->fp_hlen) {
   1566      1.39      onoe 		len = fwohci_buf_pktget(sc, &fb, &p, pkt->fp_hlen - count);
   1567       1.3      onoe 		if (len == 0) {
   1568       1.3      onoe 			printf("fwohci_buf_input: malformed input 1: %d\n",
   1569       1.3      onoe 			    pkt->fp_hlen - count);
   1570       1.3      onoe 			return 0;
   1571       1.3      onoe 		}
   1572       1.3      onoe 		memcpy((caddr_t)pkt->fp_hdr + count, p, len);
   1573       1.3      onoe 		count += len;
   1574       1.3      onoe 	}
   1575      1.36      onoe 	if (pkt->fp_hlen == 16 &&
   1576      1.26     enami 	    pkt->fp_tcode != IEEE1394_TCODE_READ_REQ_BLOCK)
   1577      1.26     enami 		pkt->fp_dlen = pkt->fp_hdr[3] >> 16;
   1578      1.60       jmc #ifdef FW_DEBUG
   1579      1.60       jmc 	tlabel = (pkt->fp_hdr[0] & 0x0000fc00) >> 10;
   1580      1.60       jmc #endif
   1581      1.60       jmc 	DPRINTFN(1, ("fwohci_buf_input: tcode=0x%x, tlabel=0x%x, hlen=%d, "
   1582      1.60       jmc 	    "dlen=%d\n", pkt->fp_tcode, tlabel, pkt->fp_hlen, pkt->fp_dlen));
   1583       1.3      onoe 
   1584       1.3      onoe 	/* get data */
   1585       1.3      onoe 	count = 0;
   1586       1.3      onoe 	i = 0;
   1587       1.3      onoe 	while (count < pkt->fp_dlen) {
   1588      1.39      onoe 		len = fwohci_buf_pktget(sc, &fb,
   1589       1.3      onoe 		    (caddr_t *)&pkt->fp_iov[i].iov_base,
   1590       1.3      onoe 		    pkt->fp_dlen - count);
   1591       1.3      onoe 		if (len == 0) {
   1592       1.3      onoe 			printf("fwohci_buf_input: malformed input 2: %d\n",
   1593      1.36      onoe 			    pkt->fp_dlen - count);
   1594       1.3      onoe 			return 0;
   1595       1.3      onoe 		}
   1596       1.3      onoe 		pkt->fp_iov[i++].iov_len = len;
   1597       1.3      onoe 		count += len;
   1598       1.3      onoe 	}
   1599       1.9      onoe 	pkt->fp_uio.uio_iovcnt = i;
   1600       1.9      onoe 	pkt->fp_uio.uio_resid = count;
   1601       1.3      onoe 
   1602      1.36      onoe 	/* get trailer */
   1603      1.39      onoe 	len = fwohci_buf_pktget(sc, &fb, (caddr_t *)&pkt->fp_trail,
   1604      1.36      onoe 	    sizeof(*pkt->fp_trail));
   1605      1.36      onoe 	if (len <= 0) {
   1606      1.36      onoe 		printf("fwohci_buf_input: malformed input 3: %d\n",
   1607      1.36      onoe 		    pkt->fp_hlen - count);
   1608      1.36      onoe 		return 0;
   1609      1.36      onoe 	}
   1610      1.36      onoe 	return 1;
   1611      1.36      onoe }
   1612      1.36      onoe 
   1613      1.36      onoe static int
   1614      1.36      onoe fwohci_buf_input_ppb(struct fwohci_softc *sc, struct fwohci_ctx *fc,
   1615      1.36      onoe     struct fwohci_pkt *pkt)
   1616      1.36      onoe {
   1617      1.36      onoe 	caddr_t p;
   1618      1.36      onoe 	int len;
   1619      1.36      onoe 	struct fwohci_buf *fb;
   1620      1.36      onoe 	struct fwohci_desc *fd;
   1621      1.36      onoe 
   1622      1.40      haya 	if (fc->fc_type ==  FWOHCI_CTX_ISO_MULTI) {
   1623      1.40      haya 		return fwohci_buf_input(sc, fc, pkt);
   1624      1.40      haya 	}
   1625      1.40      haya 
   1626      1.36      onoe 	memset(pkt, 0, sizeof(*pkt));
   1627      1.36      onoe 	pkt->fp_uio.uio_iov = pkt->fp_iov;
   1628      1.36      onoe 	pkt->fp_uio.uio_rw = UIO_WRITE;
   1629      1.36      onoe 	pkt->fp_uio.uio_segflg = UIO_SYSSPACE;
   1630      1.36      onoe 
   1631      1.36      onoe 	for (fb = TAILQ_FIRST(&fc->fc_buf); ; fb = TAILQ_NEXT(fb, fb_list)) {
   1632      1.36      onoe 		if (fb == NULL)
   1633       1.3      onoe 			return 0;
   1634      1.36      onoe 		if (fb->fb_off == 0)
   1635      1.36      onoe 			break;
   1636      1.36      onoe 	}
   1637      1.36      onoe 	fd = fb->fb_desc;
   1638      1.36      onoe 	len = fd->fd_reqcount - fd->fd_rescount;
   1639      1.36      onoe 	if (len == 0)
   1640      1.36      onoe 		return 0;
   1641      1.36      onoe 	bus_dmamap_sync(sc->sc_dmat, fb->fb_dmamap, fb->fb_off, len,
   1642      1.36      onoe 	    BUS_DMASYNC_POSTREAD);
   1643      1.36      onoe 
   1644      1.36      onoe 	p = fb->fb_buf;
   1645      1.36      onoe 	fb->fb_off += roundup(len, 4);
   1646      1.36      onoe 	if (len < 8) {
   1647      1.36      onoe 		printf("fwohci_buf_input_ppb: malformed input 1: %d\n", len);
   1648      1.36      onoe 		return 0;
   1649      1.36      onoe 	}
   1650      1.36      onoe 
   1651      1.36      onoe 	/*
   1652      1.36      onoe 	 * get trailer first, may be bogus data unless status update
   1653      1.36      onoe 	 * in descriptor is set.
   1654      1.36      onoe 	 */
   1655      1.36      onoe 	pkt->fp_trail = (u_int32_t *)p;
   1656      1.36      onoe 	*pkt->fp_trail = (*pkt->fp_trail & 0xffff) | (fd->fd_status << 16);
   1657      1.36      onoe 	pkt->fp_hdr[0] = ((u_int32_t *)p)[1];
   1658      1.36      onoe 	pkt->fp_tcode = (pkt->fp_hdr[0] & 0x000000f0) >> 4;
   1659      1.39      onoe #ifdef DIAGNOSTIC
   1660      1.36      onoe 	if (pkt->fp_tcode != IEEE1394_TCODE_STREAM_DATA) {
   1661      1.36      onoe 		printf("fwohci_buf_input_ppb: bad tcode: 0x%x\n",
   1662      1.36      onoe 		    pkt->fp_tcode);
   1663      1.36      onoe 		return 0;
   1664      1.36      onoe 	}
   1665      1.36      onoe #endif
   1666      1.36      onoe 	pkt->fp_hlen = 4;
   1667      1.36      onoe 	pkt->fp_dlen = pkt->fp_hdr[0] >> 16;
   1668      1.36      onoe 	p += 8;
   1669      1.36      onoe 	len -= 8;
   1670      1.36      onoe 	if (pkt->fp_dlen != len) {
   1671      1.36      onoe 		printf("fwohci_buf_input_ppb: malformed input 2: %d != %d\n",
   1672      1.36      onoe 		    pkt->fp_dlen, len);
   1673      1.36      onoe 		return 0;
   1674       1.3      onoe 	}
   1675      1.36      onoe 	DPRINTFN(1, ("fwohci_buf_input_ppb: tcode=0x%x, hlen=%d, dlen=%d\n",
   1676      1.36      onoe 	    pkt->fp_tcode, pkt->fp_hlen, pkt->fp_dlen));
   1677      1.36      onoe 	pkt->fp_iov[0].iov_base = p;
   1678      1.36      onoe 	pkt->fp_iov[0].iov_len = len;
   1679      1.36      onoe 	pkt->fp_uio.uio_iovcnt = 0;
   1680      1.36      onoe 	pkt->fp_uio.uio_resid = len;
   1681       1.3      onoe 	return 1;
   1682       1.3      onoe }
   1683       1.3      onoe 
   1684       1.3      onoe static int
   1685       1.3      onoe fwohci_handler_set(struct fwohci_softc *sc,
   1686      1.67       jmc     int tcode, u_int32_t key1, u_int32_t key2, u_int32_t key3,
   1687       1.3      onoe     int (*handler)(struct fwohci_softc *, void *, struct fwohci_pkt *),
   1688       1.3      onoe     void *arg)
   1689       1.3      onoe {
   1690       1.3      onoe 	struct fwohci_ctx *fc;
   1691       1.3      onoe 	struct fwohci_handler *fh;
   1692      1.67       jmc 	u_int64_t addr, naddr;
   1693      1.67       jmc 	u_int32_t off;
   1694       1.9      onoe 	int i, j;
   1695       1.3      onoe 
   1696      1.62      haya 	if (tcode == IEEE1394_TCODE_STREAM_DATA &&
   1697      1.62      haya 	    (((key1 & OHCI_ASYNC_STREAM) && sc->sc_ctx_as != NULL)
   1698      1.62      haya 		    || (key1 & OHCI_ASYNC_STREAM) == 0)) {
   1699      1.40      haya 		int isasync = key1 & OHCI_ASYNC_STREAM;
   1700      1.40      haya 
   1701      1.62      haya 		key1 = key1 & IEEE1394_ISO_CHANNEL_ANY ?
   1702      1.62      haya 		    IEEE1394_ISO_CHANNEL_ANY : (key1 & IEEE1394_ISOCH_MASK);
   1703      1.62      haya 		if (key1 & IEEE1394_ISO_CHANNEL_ANY) {
   1704      1.62      haya 			printf("%s: key changed to %x\n",
   1705      1.62      haya 			    sc->sc_sc1394.sc1394_dev.dv_xname, key1);
   1706      1.62      haya 		}
   1707      1.26     enami 		j = sc->sc_isoctx;
   1708       1.9      onoe 		fh = NULL;
   1709      1.62      haya 
   1710       1.9      onoe 		for (i = 0; i < sc->sc_isoctx; i++) {
   1711      1.62      haya 			if ((fc = sc->sc_ctx_as[i]) == NULL) {
   1712       1.9      onoe 				if (j == sc->sc_isoctx)
   1713       1.9      onoe 					j = i;
   1714       1.9      onoe 				continue;
   1715       1.3      onoe 			}
   1716       1.3      onoe 			fh = LIST_FIRST(&fc->fc_handler);
   1717       1.9      onoe 			if (fh->fh_tcode == tcode &&
   1718       1.9      onoe 			    fh->fh_key1 == key1 && fh->fh_key2 == key2)
   1719       1.3      onoe 				break;
   1720       1.9      onoe 			fh = NULL;
   1721       1.9      onoe 		}
   1722       1.9      onoe 		if (fh == NULL) {
   1723       1.9      onoe 			if (handler == NULL)
   1724       1.9      onoe 				return 0;
   1725       1.9      onoe 			if (j == sc->sc_isoctx) {
   1726      1.28       jmc 				DPRINTF(("fwohci_handler_set: no more free "
   1727      1.28       jmc 				    "context\n"));
   1728       1.9      onoe 				return ENOMEM;
   1729       1.9      onoe 			}
   1730      1.62      haya 			if ((fc = sc->sc_ctx_as[j]) == NULL) {
   1731      1.40      haya 				fwohci_ctx_alloc(sc, &fc, OHCI_BUF_IR_CNT, j,
   1732      1.40      haya 				    isasync ? FWOHCI_CTX_ISO_SINGLE :
   1733      1.40      haya 				    FWOHCI_CTX_ISO_MULTI);
   1734      1.62      haya 				sc->sc_ctx_as[j] = fc;
   1735       1.9      onoe 			}
   1736       1.3      onoe 		}
   1737      1.62      haya #ifdef FW_DEBUG
   1738      1.62      haya 		if (fh == NULL && handler != NULL) {
   1739      1.62      haya 			printf("use ir context %d\n", j);
   1740      1.62      haya 		} else if (fh != NULL && handler == NULL) {
   1741      1.62      haya 			printf("remove ir context %d\n", i);
   1742      1.62      haya 		}
   1743      1.62      haya #endif
   1744       1.3      onoe 	} else {
   1745       1.3      onoe 		switch (tcode) {
   1746       1.3      onoe 		case IEEE1394_TCODE_WRITE_REQ_QUAD:
   1747       1.3      onoe 		case IEEE1394_TCODE_WRITE_REQ_BLOCK:
   1748       1.3      onoe 		case IEEE1394_TCODE_READ_REQ_QUAD:
   1749       1.3      onoe 		case IEEE1394_TCODE_READ_REQ_BLOCK:
   1750       1.3      onoe 		case IEEE1394_TCODE_LOCK_REQ:
   1751       1.3      onoe 			fc = sc->sc_ctx_arrq;
   1752       1.3      onoe 			break;
   1753       1.3      onoe 		case IEEE1394_TCODE_WRITE_RESP:
   1754       1.3      onoe 		case IEEE1394_TCODE_READ_RESP_QUAD:
   1755       1.3      onoe 		case IEEE1394_TCODE_READ_RESP_BLOCK:
   1756       1.3      onoe 		case IEEE1394_TCODE_LOCK_RESP:
   1757       1.3      onoe 			fc = sc->sc_ctx_arrs;
   1758       1.3      onoe 			break;
   1759       1.3      onoe 		default:
   1760       1.3      onoe 			return EIO;
   1761       1.3      onoe 		}
   1762      1.67       jmc 		naddr = ((u_int64_t)key1 << 32) + key2;
   1763      1.67       jmc 
   1764       1.3      onoe 		for (fh = LIST_FIRST(&fc->fc_handler); fh != NULL;
   1765       1.3      onoe 		    fh = LIST_NEXT(fh, fh_list)) {
   1766      1.67       jmc 			if (fh->fh_tcode == tcode) {
   1767      1.67       jmc 				if (fh->fh_key1 == key1 &&
   1768      1.67       jmc 				    fh->fh_key2 == key2 && fh->fh_key3 == key3)
   1769      1.67       jmc 					break;
   1770      1.67       jmc 				/* Make sure it's not within a current range. */
   1771      1.67       jmc 				addr = ((u_int64_t)fh->fh_key1 << 32) +
   1772      1.67       jmc 				    fh->fh_key2;
   1773      1.67       jmc 				off = fh->fh_key3;
   1774      1.67       jmc 				if (key3 &&
   1775      1.67       jmc 				    (((naddr >= addr) &&
   1776      1.67       jmc 				     (naddr < (addr + off))) ||
   1777      1.67       jmc 				    (((naddr + key3) > addr) &&
   1778      1.67       jmc 				     ((naddr + key3) <= (addr + off))) ||
   1779      1.67       jmc 				    ((addr > naddr) &&
   1780      1.67       jmc 				      (addr < (naddr + key3)))))
   1781      1.67       jmc 					if (handler)
   1782      1.67       jmc 						return EEXIST;
   1783      1.67       jmc 			}
   1784       1.3      onoe 		}
   1785       1.3      onoe 	}
   1786       1.3      onoe 	if (handler == NULL) {
   1787       1.9      onoe 		if (fh != NULL) {
   1788      1.26     enami 			LIST_REMOVE(fh, fh_list);
   1789      1.26     enami 			free(fh, M_DEVBUF);
   1790       1.9      onoe 		}
   1791       1.9      onoe 		if (tcode == IEEE1394_TCODE_STREAM_DATA) {
   1792      1.38      onoe 			OHCI_SYNC_RX_DMA_WRITE(sc, fc->fc_ctx,
   1793      1.38      onoe 			    OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
   1794      1.62      haya 			sc->sc_ctx_as[fc->fc_ctx] = NULL;
   1795       1.9      onoe 			fwohci_ctx_free(sc, fc);
   1796       1.9      onoe 		}
   1797       1.3      onoe 		return 0;
   1798       1.3      onoe 	}
   1799       1.3      onoe 	if (fh == NULL) {
   1800      1.24       jmc 		fh = malloc(sizeof(*fh), M_DEVBUF, M_WAITOK);
   1801      1.26     enami 		LIST_INSERT_HEAD(&fc->fc_handler, fh, fh_list);
   1802       1.3      onoe 	}
   1803      1.26     enami 	fh->fh_tcode = tcode;
   1804       1.3      onoe 	fh->fh_key1 = key1;
   1805       1.3      onoe 	fh->fh_key2 = key2;
   1806      1.67       jmc 	fh->fh_key3 = key3;
   1807       1.3      onoe 	fh->fh_handler = handler;
   1808       1.3      onoe 	fh->fh_handarg = arg;
   1809      1.67       jmc 	DPRINTFN(1, ("fwohci_handler_set: ctx %d, tcode %x, key 0x%x, 0x%x, "
   1810      1.67       jmc 	    "0x%x\n", fc->fc_ctx, tcode, key1, key2, key3));
   1811       1.3      onoe 
   1812       1.3      onoe 	if (tcode == IEEE1394_TCODE_STREAM_DATA) {
   1813       1.7      onoe 		fwohci_ctx_init(sc, fc);
   1814      1.28       jmc 		DPRINTFN(1, ("fwohci_handler_set: SYNC desc %ld\n",
   1815      1.28       jmc 		    (long)(TAILQ_FIRST(&fc->fc_buf)->fb_desc - sc->sc_desc)));
   1816       1.7      onoe 		OHCI_SYNC_RX_DMA_WRITE(sc, fc->fc_ctx,
   1817       1.7      onoe 		    OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_RUN);
   1818       1.3      onoe 	}
   1819       1.3      onoe 	return 0;
   1820       1.3      onoe }
   1821       1.3      onoe 
   1822      1.62      haya /*
   1823      1.62      haya  * static ieee1394_ir_tag_t
   1824      1.62      haya  * fwohci_ir_ctx_set(struct device *dev, int channel, int tagbm,
   1825      1.62      haya  *	int bufnum, int maxsize, int flags)
   1826      1.62      haya  *
   1827      1.62      haya  *	This function will return non-negative value if it succeeds.
   1828      1.62      haya  *	This return value is pointer to the context of isochronous
   1829      1.62      haya  *	transmission.  This function will return NULL value if it
   1830      1.62      haya  *	fails.
   1831      1.62      haya  */
   1832      1.62      haya ieee1394_ir_tag_t
   1833      1.62      haya fwohci_ir_ctx_set(struct device *dev, int channel, int tagbm,
   1834      1.62      haya     int bufnum, int maxsize, int flags)
   1835      1.62      haya {
   1836      1.62      haya 	int i, openctx;
   1837      1.62      haya 	struct fwohci_ir_ctx *irc;
   1838      1.62      haya 	struct fwohci_softc *sc = (struct fwohci_softc *)dev;
   1839      1.62      haya 	const char *xname = sc->sc_sc1394.sc1394_dev.dv_xname;
   1840      1.62      haya 
   1841      1.62      haya 	printf("%s: ir_ctx_set channel %d tagbm 0x%x maxsize %d bufnum %d\n",
   1842      1.62      haya 	    xname, channel, tagbm, maxsize, bufnum);
   1843      1.62      haya 	/*
   1844      1.62      haya 	 * This loop will find the smallest vacant context and check
   1845      1.62      haya 	 * whether other channel uses the same channel.
   1846      1.62      haya 	 */
   1847      1.62      haya 	openctx = sc->sc_isoctx;
   1848      1.62      haya 	for (i = 0; i < sc->sc_isoctx; ++i) {
   1849      1.62      haya 		if (sc->sc_ctx_ir[i] == NULL) {
   1850      1.62      haya 			/*
   1851      1.62      haya 			 * Find a vacant contet.  If this has the
   1852      1.62      haya 			 * smallest context number, register it.
   1853      1.62      haya 			 */
   1854      1.62      haya 			if (openctx == sc->sc_isoctx) {
   1855      1.62      haya 				openctx = i;
   1856      1.62      haya 			}
   1857      1.62      haya 		} else {
   1858      1.62      haya 			/*
   1859      1.62      haya 			 * This context is used.  Check whether this
   1860      1.62      haya 			 * context uses the same channel as ours.
   1861      1.62      haya 			 */
   1862      1.62      haya 			if (sc->sc_ctx_ir[i]->irc_channel == channel) {
   1863      1.62      haya 				/* Using same channel. */
   1864      1.62      haya 				printf("%s: channel %d occupied by ctx%d\n",
   1865      1.62      haya 				    xname, channel, i);
   1866      1.62      haya 				return NULL;
   1867      1.62      haya 			}
   1868      1.62      haya 		}
   1869      1.62      haya 	}
   1870      1.62      haya 
   1871      1.62      haya 	/*
   1872      1.62      haya 	 * If there is a vacant context, allocate isochronous transmit
   1873      1.62      haya 	 * context for it.
   1874      1.62      haya 	 */
   1875      1.62      haya 	if (openctx != sc->sc_isoctx) {
   1876      1.62      haya 		printf("%s using ctx %d for iso receive\n", xname, openctx);
   1877      1.62      haya 		if ((irc = fwohci_ir_ctx_construct(sc, openctx, channel,
   1878      1.62      haya 		    tagbm, bufnum, maxsize, flags)) == NULL) {
   1879      1.62      haya 			return NULL;
   1880      1.62      haya 		}
   1881      1.62      haya #ifndef IR_CTX_OPENTEST
   1882      1.62      haya 		sc->sc_ctx_ir[openctx] = irc;
   1883      1.62      haya #else
   1884      1.62      haya 		fwohci_ir_ctx_destruct(irc);
   1885      1.62      haya 		irc = NULL;
   1886      1.62      haya #endif
   1887      1.62      haya 	} else {
   1888      1.62      haya 		printf("%s: cannot find any vacant contexts\n", xname);
   1889      1.62      haya 		irc = NULL;
   1890      1.62      haya 	}
   1891      1.62      haya 
   1892      1.62      haya 	return (ieee1394_ir_tag_t)irc;
   1893      1.62      haya }
   1894      1.62      haya 
   1895      1.62      haya 
   1896      1.62      haya /*
   1897      1.62      haya  * int fwohci_ir_ctx_clear(struct device *dev, ieee1394_ir_tag_t *ir)
   1898      1.62      haya  *
   1899      1.62      haya  *	This function will return 0 if it succeed.  Otherwise return
   1900      1.62      haya  *	negative value.
   1901      1.62      haya  */
   1902      1.62      haya int
   1903      1.62      haya fwohci_ir_ctx_clear(struct device *dev, ieee1394_ir_tag_t ir)
   1904      1.62      haya {
   1905      1.62      haya 	struct fwohci_ir_ctx *irc = (struct fwohci_ir_ctx *)ir;
   1906      1.62      haya 	struct fwohci_softc *sc = irc->irc_sc;
   1907      1.62      haya 	int i;
   1908      1.62      haya 
   1909      1.62      haya 	if (sc->sc_ctx_ir[irc->irc_num] != irc) {
   1910      1.62      haya 		printf("fwohci_ir_ctx_clear: irc differs %p %p\n",
   1911      1.62      haya 		    sc->sc_ctx_ir[irc->irc_num], irc);
   1912      1.62      haya 		return -1;
   1913      1.62      haya 	}
   1914      1.62      haya 
   1915      1.62      haya 	i = 0;
   1916      1.62      haya 	while (irc->irc_status & IRC_STATUS_RUN) {
   1917      1.62      haya 		tsleep((void *)irc, PWAIT|PCATCH, "IEEE1394 iso receive", 100);
   1918      1.62      haya 		if (irc->irc_status & IRC_STATUS_RUN) {
   1919      1.62      haya 			if (fwohci_ir_stop(irc) == 0) {
   1920      1.62      haya 				irc->irc_status &= ~IRC_STATUS_RUN;
   1921      1.62      haya 			}
   1922      1.62      haya 
   1923      1.62      haya 		}
   1924      1.62      haya 		if (++i > 20) {
   1925      1.62      haya 			u_int32_t reg
   1926      1.62      haya 			    = OHCI_SYNC_RX_DMA_READ(sc, irc->irc_num,
   1927      1.62      haya 				OHCI_SUBREG_ContextControlSet);
   1928      1.62      haya 
   1929      1.62      haya 			printf("fwochi_ir_ctx_clear: "
   1930      1.62      haya 			    "Cannot stop iso receive engine\n");
   1931      1.62      haya 			printf("%s:  intr IR_CommandPtr 0x%08x "
   1932      1.62      haya 			    "ContextCtrl 0x%08x%s%s%s%s\n",
   1933      1.62      haya 			    sc->sc_sc1394.sc1394_dev.dv_xname,
   1934      1.62      haya 			    OHCI_SYNC_RX_DMA_READ(sc, irc->irc_num,
   1935      1.62      haya 				OHCI_SUBREG_CommandPtr),
   1936      1.62      haya 			    reg,
   1937      1.62      haya 			    reg & OHCI_CTXCTL_RUN ? " run" : "",
   1938      1.62      haya 			    reg & OHCI_CTXCTL_WAKE ? " wake" : "",
   1939      1.62      haya 			    reg & OHCI_CTXCTL_DEAD ? " dead" : "",
   1940      1.62      haya 			    reg & OHCI_CTXCTL_ACTIVE ? " active" : "");
   1941      1.62      haya 
   1942      1.62      haya 			return EBUSY;
   1943      1.62      haya 		}
   1944      1.62      haya 	}
   1945      1.62      haya 
   1946      1.62      haya 	printf("fwohci_ir_ctx_clear: DMA engine is stopped. get %d frames max queuelen %d pos %d\n",
   1947      1.62      haya 	    irc->irc_pktcount, irc->irc_maxqueuelen, irc->irc_maxqueuepos);
   1948      1.62      haya 
   1949      1.62      haya 	fwohci_ir_ctx_destruct(irc);
   1950      1.62      haya 
   1951      1.62      haya 	sc->sc_ctx_ir[irc->irc_num] = NULL;
   1952      1.62      haya 
   1953      1.62      haya 	return 0;
   1954      1.62      haya }
   1955      1.62      haya 
   1956      1.62      haya 
   1957      1.62      haya 
   1958      1.62      haya 
   1959      1.62      haya 
   1960      1.62      haya 
   1961      1.62      haya 
   1962      1.62      haya 
   1963      1.62      haya ieee1394_it_tag_t
   1964      1.62      haya fwohci_it_set(struct ieee1394_softc *isc, int channel, int tagbm)
   1965      1.62      haya {
   1966      1.62      haya 	ieee1394_it_tag_t rv;
   1967      1.62      haya 	int tag;
   1968      1.62      haya 
   1969      1.62      haya 	for (tag = 0; tagbm != 0 && (tagbm & 0x01) == 0; tagbm >>= 1, ++tag);
   1970      1.62      haya 
   1971      1.62      haya 	rv = fwohci_it_ctx_set((struct fwohci_softc *)isc, channel, tag, 488);
   1972      1.62      haya 
   1973      1.62      haya 	return rv;
   1974      1.62      haya }
   1975      1.62      haya 
   1976      1.62      haya /*
   1977      1.62      haya  * static ieee1394_it_tag_t
   1978      1.62      haya  * fwohci_it_ctx_set(struct fwohci_softc *sc,
   1979      1.62      haya  *    u_int32_t key1 (channel), u_int32_t key2 (tag), int maxsize)
   1980      1.62      haya  *
   1981      1.62      haya  *	This function will return non-negative value if it succeeds.
   1982      1.62      haya  *	This return value is pointer to the context of isochronous
   1983      1.62      haya  *	transmission.  This function will return NULL value if it
   1984      1.62      haya  *	fails.
   1985      1.62      haya  */
   1986      1.62      haya static ieee1394_it_tag_t
   1987      1.62      haya fwohci_it_ctx_set(struct fwohci_softc *sc, int channel, int tag, int maxsize)
   1988      1.62      haya {
   1989      1.62      haya 	int i, openctx;
   1990      1.62      haya 	struct fwohci_it_ctx *itc;
   1991      1.62      haya 	const char *xname = sc->sc_sc1394.sc1394_dev.dv_xname;
   1992      1.62      haya #ifdef TEST_CHAIN
   1993      1.62      haya 	extern int fwohci_test_chain(struct fwohci_it_ctx *);
   1994      1.62      haya #endif /* TEST_CHAIN */
   1995      1.62      haya #ifdef TEST_WRITE
   1996      1.62      haya 	extern void fwohci_test_write(struct fwohci_it_ctx *itc);
   1997      1.62      haya #endif /* TEST_WRITE */
   1998      1.62      haya 
   1999      1.62      haya 	printf("%s: it_ctx_set channel %d tag %d maxsize %d\n",
   2000      1.62      haya 	    xname, channel, tag, maxsize);
   2001      1.62      haya 
   2002      1.62      haya 	/*
   2003      1.62      haya 	 * This loop will find the smallest vacant context and check
   2004      1.62      haya 	 * whether other channel uses the same channel.
   2005      1.62      haya 	 */
   2006      1.62      haya 	openctx = sc->sc_itctx;
   2007      1.62      haya 	for (i = 0; i < sc->sc_itctx; ++i) {
   2008      1.62      haya 		if (sc->sc_ctx_it[i] == NULL) {
   2009      1.62      haya 			/*
   2010      1.62      haya 			 * Find a vacant contet.  If this has the
   2011      1.62      haya 			 * smallest context number, register it.
   2012      1.62      haya 			 */
   2013      1.62      haya 			if (openctx == sc->sc_itctx) {
   2014      1.62      haya 				openctx = i;
   2015      1.62      haya 			}
   2016      1.62      haya 		} else {
   2017      1.62      haya 			/*
   2018      1.62      haya 			 * This context is used.  Check whether this
   2019      1.62      haya 			 * context uses the same channel as ours.
   2020      1.62      haya 			 */
   2021      1.62      haya 			if (sc->sc_ctx_it[i]->itc_channel == channel) {
   2022      1.62      haya 				/* Using same channel. */
   2023      1.62      haya 				printf("%s: channel %d occupied by ctx%d\n",
   2024      1.62      haya 				    xname, channel, i);
   2025      1.62      haya 				return NULL;
   2026      1.62      haya 			}
   2027      1.62      haya 		}
   2028      1.62      haya 	}
   2029      1.62      haya 
   2030      1.62      haya 	/*
   2031      1.62      haya 	 * If there is a vacant context, allocate isochronous transmit
   2032      1.62      haya 	 * context for it.
   2033      1.62      haya 	 */
   2034      1.62      haya 	if (openctx != sc->sc_itctx) {
   2035      1.62      haya 		printf("%s using ctx %d for iso trasmit\n", xname, openctx);
   2036      1.62      haya 		if ((itc = fwohci_it_ctx_construct(sc, openctx, channel,
   2037      1.62      haya 		    tag, maxsize)) == NULL) {
   2038      1.62      haya 			return NULL;
   2039      1.62      haya 		}
   2040      1.62      haya 		sc->sc_ctx_it[openctx] = itc;
   2041      1.62      haya 
   2042      1.62      haya #ifdef TEST_CHAIN
   2043      1.62      haya 		fwohci_test_chain(itc);
   2044      1.62      haya #endif /* TEST_CHAIN */
   2045      1.62      haya #ifdef TEST_WRITE
   2046      1.62      haya 		fwohci_test_write(itc);
   2047      1.62      haya 		itc = NULL;
   2048      1.62      haya #endif /* TEST_WRITE */
   2049      1.62      haya 
   2050      1.62      haya 	} else {
   2051      1.62      haya 		printf("%s: cannot find any vacant contexts\n", xname);
   2052      1.62      haya 		itc = NULL;
   2053      1.62      haya 	}
   2054      1.62      haya 
   2055      1.62      haya 	return (ieee1394_it_tag_t)itc;
   2056      1.62      haya }
   2057      1.62      haya 
   2058      1.62      haya 
   2059      1.62      haya /*
   2060      1.62      haya  * int fwohci_it_ctx_clear(ieee1394_it_tag_t *it)
   2061      1.62      haya  *
   2062      1.62      haya  *	This function will return 0 if it succeed.  Otherwise return
   2063      1.62      haya  *	negative value.
   2064      1.62      haya  */
   2065      1.62      haya int
   2066      1.62      haya fwohci_it_ctx_clear(ieee1394_it_tag_t *it)
   2067      1.62      haya {
   2068      1.62      haya 	struct fwohci_it_ctx *itc = (struct fwohci_it_ctx *)it;
   2069      1.62      haya 	struct fwohci_softc *sc = itc->itc_sc;
   2070      1.62      haya 	int i;
   2071      1.62      haya 
   2072      1.62      haya 	if (sc->sc_ctx_it[itc->itc_num] != itc) {
   2073      1.62      haya 		printf("fwohci_it_ctx_clear: itc differs %p %p\n",
   2074      1.62      haya 		    sc->sc_ctx_it[itc->itc_num], itc);
   2075      1.62      haya 		return -1;
   2076      1.62      haya 	}
   2077      1.62      haya 
   2078      1.62      haya 	fwohci_it_ctx_flush(it);
   2079      1.62      haya 
   2080      1.62      haya 	i = 0;
   2081      1.62      haya 	while (itc->itc_flags & ITC_FLAGS_RUN) {
   2082      1.62      haya 		tsleep((void *)itc, PWAIT|PCATCH, "IEEE1394 iso transmit", 100);
   2083      1.62      haya 		if (itc->itc_flags & ITC_FLAGS_RUN) {
   2084      1.62      haya 			u_int32_t reg;
   2085      1.62      haya 
   2086      1.62      haya 			reg = OHCI_SYNC_TX_DMA_READ(sc, itc->itc_num,
   2087      1.62      haya 			    OHCI_SUBREG_ContextControlSet);
   2088      1.62      haya 
   2089      1.62      haya 			if ((reg & OHCI_CTXCTL_WAKE) == 0) {
   2090      1.62      haya 				itc->itc_flags &= ~ITC_FLAGS_RUN;
   2091      1.62      haya 				printf("fwochi_it_ctx_clear: "
   2092      1.62      haya 				    "DMA engine stopped without intr\n");
   2093      1.62      haya 			}
   2094      1.62      haya 			printf("%s: %d intr IT_CommandPtr 0x%08x "
   2095      1.62      haya 			    "ContextCtrl 0x%08x%s%s%s%s\n",
   2096      1.62      haya 			    sc->sc_sc1394.sc1394_dev.dv_xname, i,
   2097      1.62      haya 			    OHCI_SYNC_TX_DMA_READ(sc, itc->itc_num,
   2098      1.62      haya 				OHCI_SUBREG_CommandPtr),
   2099      1.62      haya 			    reg,
   2100      1.62      haya 			    reg & OHCI_CTXCTL_RUN ? " run" : "",
   2101      1.62      haya 			    reg & OHCI_CTXCTL_WAKE ? " wake" : "",
   2102      1.62      haya 			    reg & OHCI_CTXCTL_DEAD ? " dead" : "",
   2103      1.62      haya 			    reg & OHCI_CTXCTL_ACTIVE ? " active" : "");
   2104      1.62      haya 
   2105      1.62      haya 
   2106      1.62      haya 		}
   2107      1.62      haya 		if (++i > 20) {
   2108      1.62      haya 			u_int32_t reg
   2109      1.62      haya 			    = OHCI_SYNC_TX_DMA_READ(sc, itc->itc_num,
   2110      1.62      haya 				OHCI_SUBREG_ContextControlSet);
   2111      1.62      haya 
   2112      1.62      haya 			printf("fwochi_it_ctx_clear: "
   2113      1.62      haya 			    "Cannot stop iso transmit engine\n");
   2114      1.62      haya 			printf("%s:  intr IT_CommandPtr 0x%08x "
   2115      1.62      haya 			    "ContextCtrl 0x%08x%s%s%s%s\n",
   2116      1.62      haya 			    sc->sc_sc1394.sc1394_dev.dv_xname,
   2117      1.62      haya 			    OHCI_SYNC_TX_DMA_READ(sc, itc->itc_num,
   2118      1.62      haya 				OHCI_SUBREG_CommandPtr),
   2119      1.62      haya 			    reg,
   2120      1.62      haya 			    reg & OHCI_CTXCTL_RUN ? " run" : "",
   2121      1.62      haya 			    reg & OHCI_CTXCTL_WAKE ? " wake" : "",
   2122      1.62      haya 			    reg & OHCI_CTXCTL_DEAD ? " dead" : "",
   2123      1.62      haya 			    reg & OHCI_CTXCTL_ACTIVE ? " active" : "");
   2124      1.62      haya 
   2125      1.62      haya 			return EBUSY;
   2126      1.62      haya 		}
   2127      1.62      haya 	}
   2128      1.62      haya 
   2129      1.62      haya 	printf("fwohci_it_ctx_clear: DMA engine is stopped.\n");
   2130      1.62      haya 
   2131      1.62      haya 	fwohci_it_ctx_destruct(itc);
   2132      1.62      haya 
   2133      1.62      haya 	sc->sc_ctx_it[itc->itc_num] = NULL;
   2134      1.62      haya 
   2135      1.62      haya 
   2136      1.62      haya 	return 0;
   2137      1.62      haya }
   2138      1.62      haya 
   2139      1.62      haya 
   2140      1.62      haya 
   2141      1.62      haya 
   2142      1.62      haya 
   2143      1.62      haya 
   2144       1.3      onoe /*
   2145      1.72       wiz  * Asynchronous Receive Requests input frontend.
   2146       1.3      onoe  */
   2147       1.3      onoe static void
   2148       1.3      onoe fwohci_arrq_input(struct fwohci_softc *sc, struct fwohci_ctx *fc)
   2149       1.3      onoe {
   2150       1.3      onoe 	int rcode;
   2151      1.67       jmc 	u_int16_t len;
   2152      1.67       jmc 	u_int32_t key1, key2, off;
   2153      1.67       jmc 	u_int64_t addr, naddr;
   2154       1.3      onoe 	struct fwohci_handler *fh;
   2155       1.3      onoe 	struct fwohci_pkt pkt, res;
   2156       1.3      onoe 
   2157      1.36      onoe 	/*
   2158      1.36      onoe 	 * Do not return if next packet is in the buffer, or the next
   2159      1.36      onoe 	 * packet cannot be received until the next receive interrupt.
   2160      1.36      onoe 	 */
   2161      1.26     enami 	while (fwohci_buf_input(sc, fc, &pkt)) {
   2162      1.26     enami 		if (pkt.fp_tcode == OHCI_TCODE_PHY) {
   2163      1.26     enami 			fwohci_phy_input(sc, &pkt);
   2164      1.36      onoe 			continue;
   2165      1.26     enami 		}
   2166      1.26     enami 		key1 = pkt.fp_hdr[1] & 0xffff;
   2167      1.26     enami 		key2 = pkt.fp_hdr[2];
   2168      1.67       jmc 		if ((pkt.fp_tcode == IEEE1394_TCODE_WRITE_REQ_BLOCK) ||
   2169      1.67       jmc 		    (pkt.fp_tcode == IEEE1394_TCODE_READ_REQ_BLOCK)) {
   2170      1.67       jmc 			len = (pkt.fp_hdr[3] & 0xffff0000) >> 16;
   2171      1.67       jmc 			naddr = ((u_int64_t)key1 << 32) + key2;
   2172  1.78.2.2     skrll 		} else {
   2173      1.67       jmc 			len = 0;
   2174  1.78.2.2     skrll 			naddr = 0; /* XXX: gcc */
   2175  1.78.2.2     skrll 		}
   2176      1.26     enami 		for (fh = LIST_FIRST(&fc->fc_handler); fh != NULL;
   2177      1.26     enami 		    fh = LIST_NEXT(fh, fh_list)) {
   2178      1.67       jmc 			if (pkt.fp_tcode == fh->fh_tcode) {
   2179      1.67       jmc 				/* Assume length check happens in handler */
   2180      1.67       jmc 				if (key1 == fh->fh_key1 &&
   2181      1.67       jmc 				    key2 == fh->fh_key2) {
   2182      1.67       jmc 					rcode = (*fh->fh_handler)(sc,
   2183      1.67       jmc 					    fh->fh_handarg, &pkt);
   2184      1.67       jmc 					break;
   2185      1.67       jmc 				}
   2186      1.67       jmc 				addr = ((u_int64_t)fh->fh_key1 << 32) +
   2187      1.67       jmc 				    fh->fh_key2;
   2188      1.67       jmc 				off = fh->fh_key3;
   2189      1.67       jmc 				/* Check for a range qualifier */
   2190      1.67       jmc 				if (len &&
   2191      1.67       jmc 				    ((naddr >= addr) && (naddr < (addr + off))
   2192      1.67       jmc 				     && (naddr + len <= (addr + off)))) {
   2193      1.67       jmc 					rcode = (*fh->fh_handler)(sc,
   2194      1.67       jmc 					    fh->fh_handarg, &pkt);
   2195      1.67       jmc 					break;
   2196      1.67       jmc 				}
   2197      1.26     enami 			}
   2198      1.26     enami 		}
   2199      1.26     enami 		if (fh == NULL) {
   2200      1.26     enami 			rcode = IEEE1394_RCODE_ADDRESS_ERROR;
   2201      1.28       jmc 			DPRINTFN(1, ("fwohci_arrq_input: no listener: tcode "
   2202      1.28       jmc 			    "0x%x, addr=0x%04x %08x\n", pkt.fp_tcode, key1,
   2203      1.28       jmc 			    key2));
   2204      1.68       jmc 			DPRINTFN(2, ("fwohci_arrq_input: no listener: hdr[0]: "
   2205      1.68       jmc 			    "0x%08x, hdr[1]: 0x%08x,  hdr[2]: 0x%08x, hdr[3]: "
   2206      1.68       jmc 			    "0x%08x\n",  pkt.fp_hdr[0],  pkt.fp_hdr[1],
   2207      1.68       jmc 			     pkt.fp_hdr[2],  pkt.fp_hdr[3]));
   2208      1.26     enami 		}
   2209      1.26     enami 		if (((*pkt.fp_trail & 0x001f0000) >> 16) !=
   2210      1.26     enami 		    OHCI_CTXCTL_EVENT_ACK_PENDING)
   2211      1.36      onoe 			continue;
   2212      1.67       jmc 		if (rcode != -1) {
   2213      1.67       jmc 			memset(&res, 0, sizeof(res));
   2214      1.67       jmc 			res.fp_uio.uio_rw = UIO_WRITE;
   2215      1.67       jmc 			res.fp_uio.uio_segflg = UIO_SYSSPACE;
   2216      1.26     enami 			fwohci_atrs_output(sc, rcode, &pkt, &res);
   2217      1.67       jmc 		}
   2218      1.26     enami 	}
   2219      1.26     enami 	fwohci_buf_next(sc, fc);
   2220      1.26     enami 	OHCI_ASYNC_DMA_WRITE(sc, fc->fc_ctx,
   2221      1.26     enami 	    OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_WAKE);
   2222       1.3      onoe }
   2223       1.3      onoe 
   2224      1.24       jmc 
   2225       1.3      onoe /*
   2226       1.3      onoe  * Asynchronous Receive Response input frontend.
   2227       1.3      onoe  */
   2228       1.3      onoe static void
   2229       1.3      onoe fwohci_arrs_input(struct fwohci_softc *sc, struct fwohci_ctx *fc)
   2230       1.3      onoe {
   2231      1.26     enami 	struct fwohci_pkt pkt;
   2232      1.26     enami 	struct fwohci_handler *fh;
   2233       1.3      onoe 	u_int16_t srcid;
   2234       1.3      onoe 	int rcode, tlabel;
   2235       1.3      onoe 
   2236      1.26     enami 	while (fwohci_buf_input(sc, fc, &pkt)) {
   2237      1.26     enami 		srcid = pkt.fp_hdr[1] >> 16;
   2238      1.26     enami 		rcode = (pkt.fp_hdr[1] & 0x0000f000) >> 12;
   2239      1.26     enami 		tlabel = (pkt.fp_hdr[0] & 0x0000fc00) >> 10;
   2240      1.28       jmc 		DPRINTFN(1, ("fwohci_arrs_input: tcode 0x%x, from 0x%04x,"
   2241      1.28       jmc 		    " tlabel 0x%x, rcode 0x%x, hlen %d, dlen %d\n",
   2242      1.28       jmc 		    pkt.fp_tcode, srcid, tlabel, rcode, pkt.fp_hlen,
   2243      1.28       jmc 		    pkt.fp_dlen));
   2244      1.26     enami 		for (fh = LIST_FIRST(&fc->fc_handler); fh != NULL;
   2245      1.26     enami 		    fh = LIST_NEXT(fh, fh_list)) {
   2246      1.26     enami 			if (pkt.fp_tcode == fh->fh_tcode &&
   2247      1.26     enami 			    (srcid & OHCI_NodeId_NodeNumber) == fh->fh_key1 &&
   2248      1.26     enami 			    tlabel == fh->fh_key2) {
   2249      1.26     enami 				(*fh->fh_handler)(sc, fh->fh_handarg, &pkt);
   2250      1.26     enami 				LIST_REMOVE(fh, fh_list);
   2251      1.26     enami 				free(fh, M_DEVBUF);
   2252      1.26     enami 				break;
   2253      1.26     enami 			}
   2254      1.26     enami 		}
   2255      1.31       jmc 		if (fh == NULL)
   2256      1.28       jmc 			DPRINTFN(1, ("fwohci_arrs_input: no listner\n"));
   2257      1.26     enami 	}
   2258      1.26     enami 	fwohci_buf_next(sc, fc);
   2259      1.26     enami 	OHCI_ASYNC_DMA_WRITE(sc, fc->fc_ctx,
   2260      1.26     enami 	    OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_WAKE);
   2261       1.3      onoe }
   2262       1.3      onoe 
   2263       1.3      onoe /*
   2264       1.3      onoe  * Isochronous Receive input frontend.
   2265       1.3      onoe  */
   2266       1.3      onoe static void
   2267      1.62      haya fwohci_as_input(struct fwohci_softc *sc, struct fwohci_ctx *fc)
   2268       1.3      onoe {
   2269       1.3      onoe 	int rcode, chan, tag;
   2270       1.3      onoe 	struct iovec *iov;
   2271       1.3      onoe 	struct fwohci_handler *fh;
   2272       1.3      onoe 	struct fwohci_pkt pkt;
   2273       1.3      onoe 
   2274      1.40      haya #if DOUBLEBUF
   2275      1.40      haya 	if (fc->fc_type == FWOHCI_CTX_ISO_MULTI) {
   2276      1.40      haya 		struct fwohci_buf *fb;
   2277      1.40      haya 		int i;
   2278      1.40      haya 		u_int32_t reg;
   2279      1.40      haya 
   2280      1.75       wiz 		/* stop DMA engine before read buffer */
   2281      1.40      haya 		reg = OHCI_SYNC_RX_DMA_READ(sc, fc->fc_ctx,
   2282      1.40      haya 		    OHCI_SUBREG_ContextControlClear);
   2283      1.40      haya 		DPRINTFN(5, ("ir_input %08x =>", reg));
   2284      1.40      haya 		if (reg & OHCI_CTXCTL_RUN) {
   2285      1.40      haya 			OHCI_SYNC_RX_DMA_WRITE(sc, fc->fc_ctx,
   2286      1.40      haya 			    OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
   2287      1.40      haya 		}
   2288      1.40      haya 		DPRINTFN(5, (" %08x\n", OHCI_SYNC_RX_DMA_READ(sc, fc->fc_ctx, OHCI_SUBREG_ContextControlClear)));
   2289      1.40      haya 
   2290      1.40      haya 		i = 0;
   2291      1.40      haya 		while ((reg = OHCI_SYNC_RX_DMA_READ(sc, fc->fc_ctx, OHCI_SUBREG_ContextControlSet)) & OHCI_CTXCTL_ACTIVE) {
   2292      1.40      haya 			delay(10);
   2293      1.40      haya 			if (++i > 10000) {
   2294      1.75       wiz 				printf("cannot stop DMA engine 0x%08x\n", reg);
   2295      1.40      haya 				return;
   2296      1.40      haya 			}
   2297      1.40      haya 		}
   2298      1.40      haya 
   2299      1.75       wiz 		/* rotate DMA buffer */
   2300      1.40      haya 		fb = TAILQ_FIRST(&fc->fc_buf2);
   2301      1.40      haya 		OHCI_SYNC_RX_DMA_WRITE(sc, fc->fc_ctx, OHCI_SUBREG_CommandPtr,
   2302      1.40      haya 		    fb->fb_daddr | 1);
   2303      1.75       wiz 		/* start DMA engine */
   2304      1.40      haya 		OHCI_SYNC_RX_DMA_WRITE(sc, fc->fc_ctx,
   2305      1.40      haya 		    OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_RUN);
   2306      1.40      haya 		OHCI_CSR_WRITE(sc, OHCI_REG_IsoRecvIntEventClear,
   2307      1.40      haya 		    (1 << fc->fc_ctx));
   2308      1.40      haya 	}
   2309      1.40      haya #endif
   2310      1.40      haya 
   2311      1.36      onoe 	while (fwohci_buf_input_ppb(sc, fc, &pkt)) {
   2312       1.3      onoe 		chan = (pkt.fp_hdr[0] & 0x00003f00) >> 8;
   2313       1.3      onoe 		tag  = (pkt.fp_hdr[0] & 0x0000c000) >> 14;
   2314      1.62      haya 		DPRINTFN(1, ("fwohci_as_input: hdr 0x%08x, tcode 0x%0x, hlen %d"
   2315      1.52       jmc 		    ", dlen %d\n", pkt.fp_hdr[0], pkt.fp_tcode, pkt.fp_hlen,
   2316      1.28       jmc 		    pkt.fp_dlen));
   2317      1.62      haya 		if (tag == IEEE1394_TAG_GASP &&
   2318      1.62      haya 		    fc->fc_type == FWOHCI_CTX_ISO_SINGLE) {
   2319       1.3      onoe 			/*
   2320       1.3      onoe 			 * The pkt with tag=3 is GASP format.
   2321       1.3      onoe 			 * Move GASP header to header part.
   2322       1.3      onoe 			 */
   2323       1.3      onoe 			if (pkt.fp_dlen < 8)
   2324       1.3      onoe 				continue;
   2325       1.3      onoe 			iov = pkt.fp_iov;
   2326       1.3      onoe 			/* assuming pkt per buffer mode */
   2327       1.9      onoe 			pkt.fp_hdr[1] = ntohl(((u_int32_t *)iov->iov_base)[0]);
   2328       1.9      onoe 			pkt.fp_hdr[2] = ntohl(((u_int32_t *)iov->iov_base)[1]);
   2329       1.3      onoe 			iov->iov_base = (caddr_t)iov->iov_base + 8;
   2330       1.3      onoe 			iov->iov_len -= 8;
   2331       1.3      onoe 			pkt.fp_hlen += 8;
   2332       1.3      onoe 			pkt.fp_dlen -= 8;
   2333       1.3      onoe 		}
   2334       1.3      onoe 		for (fh = LIST_FIRST(&fc->fc_handler); fh != NULL;
   2335       1.3      onoe 		    fh = LIST_NEXT(fh, fh_list)) {
   2336       1.3      onoe 			if (pkt.fp_tcode == fh->fh_tcode &&
   2337      1.62      haya 			    (chan == fh->fh_key1 ||
   2338      1.62      haya 				fh->fh_key1 == IEEE1394_ISO_CHANNEL_ANY) &&
   2339      1.62      haya 			    ((1 << tag) & fh->fh_key2) != 0) {
   2340       1.3      onoe 				rcode = (*fh->fh_handler)(sc, fh->fh_handarg,
   2341       1.3      onoe 				    &pkt);
   2342       1.3      onoe 				break;
   2343       1.3      onoe 			}
   2344       1.3      onoe 		}
   2345       1.3      onoe #ifdef FW_DEBUG
   2346      1.28       jmc 		if (fh == NULL) {
   2347      1.62      haya 			DPRINTFN(1, ("fwohci_as_input: no handler\n"));
   2348      1.28       jmc 		} else {
   2349      1.62      haya 			DPRINTFN(1, ("fwohci_as_input: rcode %d\n", rcode));
   2350       1.8      onoe 		}
   2351       1.3      onoe #endif
   2352       1.3      onoe 	}
   2353       1.3      onoe 	fwohci_buf_next(sc, fc);
   2354      1.40      haya 
   2355      1.40      haya 	if (fc->fc_type == FWOHCI_CTX_ISO_SINGLE) {
   2356      1.40      haya 		OHCI_SYNC_RX_DMA_WRITE(sc, fc->fc_ctx,
   2357      1.40      haya 		    OHCI_SUBREG_ContextControlSet,
   2358      1.40      haya 		    OHCI_CTXCTL_WAKE);
   2359      1.40      haya 	}
   2360       1.3      onoe }
   2361       1.3      onoe 
   2362       1.3      onoe /*
   2363       1.3      onoe  * Asynchronous Transmit common routine.
   2364       1.3      onoe  */
   2365       1.3      onoe static int
   2366       1.3      onoe fwohci_at_output(struct fwohci_softc *sc, struct fwohci_ctx *fc,
   2367       1.3      onoe     struct fwohci_pkt *pkt)
   2368       1.3      onoe {
   2369       1.9      onoe 	struct fwohci_buf *fb;
   2370       1.3      onoe 	struct fwohci_desc *fd;
   2371      1.26     enami 	struct mbuf *m, *m0;
   2372       1.9      onoe 	int i, ndesc, error, off, len;
   2373       1.3      onoe 	u_int32_t val;
   2374      1.28       jmc #ifdef FW_DEBUG
   2375      1.28       jmc 	struct iovec *iov;
   2376      1.60       jmc         int tlabel = (pkt->fp_hdr[0] & 0x0000fc00) >> 10;
   2377      1.28       jmc #endif
   2378      1.28       jmc 
   2379      1.36      onoe 	if ((sc->sc_nodeid & OHCI_NodeId_NodeNumber) == IEEE1394_BCAST_PHY_ID)
   2380       1.9      onoe 		/* We can't send anything during selfid duration */
   2381      1.26     enami 		return EAGAIN;
   2382      1.26     enami 
   2383       1.3      onoe #ifdef FW_DEBUG
   2384      1.60       jmc 	DPRINTFN(1, ("fwohci_at_output: tcode 0x%x, tlabel 0x%x hlen %d, "
   2385      1.60       jmc 	    "dlen %d", pkt->fp_tcode, tlabel, pkt->fp_hlen, pkt->fp_dlen));
   2386      1.28       jmc 	for (i = 0; i < pkt->fp_hlen/4; i++)
   2387      1.37      onoe 		DPRINTFN(2, ("%s%08x", i?" ":"\n    ", pkt->fp_hdr[i]));
   2388      1.28       jmc 	DPRINTFN(2, ("$"));
   2389      1.28       jmc 	for (ndesc = 0, iov = pkt->fp_iov;
   2390      1.28       jmc 	     ndesc < pkt->fp_uio.uio_iovcnt; ndesc++, iov++) {
   2391      1.28       jmc 		for (i = 0; i < iov->iov_len; i++)
   2392      1.37      onoe 			DPRINTFN(2, ("%s%02x", (i%32)?((i%4)?"":" "):"\n    ",
   2393      1.28       jmc 			    ((u_int8_t *)iov->iov_base)[i]));
   2394      1.28       jmc 		DPRINTFN(2, ("$"));
   2395       1.3      onoe 	}
   2396      1.28       jmc 	DPRINTFN(1, ("\n"));
   2397       1.3      onoe #endif
   2398       1.3      onoe 
   2399       1.9      onoe 	if ((m = pkt->fp_m) != NULL) {
   2400       1.9      onoe 		for (ndesc = 2; m != NULL; m = m->m_next)
   2401       1.9      onoe 			ndesc++;
   2402       1.9      onoe 		if (ndesc > OHCI_DESC_MAX) {
   2403       1.9      onoe 			m0 = NULL;
   2404       1.9      onoe 			ndesc = 2;
   2405       1.9      onoe 			for (off = 0; off < pkt->fp_dlen; off += len) {
   2406       1.9      onoe 				if (m0 == NULL) {
   2407       1.9      onoe 					MGETHDR(m0, M_DONTWAIT, MT_DATA);
   2408       1.9      onoe 					if (m0 != NULL)
   2409       1.9      onoe 						M_COPY_PKTHDR(m0, pkt->fp_m);
   2410       1.9      onoe 					m = m0;
   2411       1.9      onoe 				} else {
   2412       1.9      onoe 					MGET(m->m_next, M_DONTWAIT, MT_DATA);
   2413       1.9      onoe 					m = m->m_next;
   2414       1.9      onoe 				}
   2415       1.9      onoe 				if (m != NULL)
   2416       1.9      onoe 					MCLGET(m, M_DONTWAIT);
   2417       1.9      onoe 				if (m == NULL || (m->m_flags & M_EXT) == 0) {
   2418       1.9      onoe 					m_freem(m0);
   2419       1.9      onoe 					return ENOMEM;
   2420       1.9      onoe 				}
   2421       1.9      onoe 				len = pkt->fp_dlen - off;
   2422       1.9      onoe 				if (len > m->m_ext.ext_size)
   2423       1.9      onoe 					len = m->m_ext.ext_size;
   2424       1.9      onoe 				m_copydata(pkt->fp_m, off, len,
   2425       1.9      onoe 				    mtod(m, caddr_t));
   2426      1.15      onoe 				m->m_len = len;
   2427       1.9      onoe 				ndesc++;
   2428       1.9      onoe 			}
   2429       1.9      onoe 			m_freem(pkt->fp_m);
   2430       1.9      onoe 			pkt->fp_m = m0;
   2431       1.9      onoe 		}
   2432       1.9      onoe 	} else
   2433       1.9      onoe 		ndesc = 2 + pkt->fp_uio.uio_iovcnt;
   2434       1.9      onoe 
   2435       1.9      onoe 	if (ndesc > OHCI_DESC_MAX)
   2436       1.3      onoe 		return ENOBUFS;
   2437       1.3      onoe 
   2438      1.24       jmc 	fb = malloc(sizeof(*fb), M_DEVBUF, M_WAITOK);
   2439       1.9      onoe 	if (ndesc > 2) {
   2440      1.66       jmc 		if ((error = bus_dmamap_create(sc->sc_dmat, pkt->fp_dlen,
   2441      1.66       jmc 		    OHCI_DESC_MAX - 2, pkt->fp_dlen, 0, BUS_DMA_WAITOK,
   2442      1.66       jmc 		    &fb->fb_dmamap)) != 0) {
   2443       1.9      onoe 			fwohci_desc_put(sc, fb->fb_desc, ndesc);
   2444       1.9      onoe 			free(fb, M_DEVBUF);
   2445       1.9      onoe 			return error;
   2446       1.9      onoe 		}
   2447       1.9      onoe 
   2448       1.9      onoe 		if (pkt->fp_m != NULL)
   2449       1.9      onoe 			error = bus_dmamap_load_mbuf(sc->sc_dmat, fb->fb_dmamap,
   2450      1.24       jmc 			    pkt->fp_m, BUS_DMA_WAITOK);
   2451       1.9      onoe 		else
   2452       1.9      onoe 			error = bus_dmamap_load_uio(sc->sc_dmat, fb->fb_dmamap,
   2453      1.24       jmc 			    &pkt->fp_uio, BUS_DMA_WAITOK);
   2454       1.9      onoe 		if (error != 0) {
   2455      1.66       jmc 			DPRINTFN(1, ("Can't load DMA map: %d\n", error));
   2456       1.9      onoe 			bus_dmamap_destroy(sc->sc_dmat, fb->fb_dmamap);
   2457       1.9      onoe 			fwohci_desc_put(sc, fb->fb_desc, ndesc);
   2458       1.9      onoe 			free(fb, M_DEVBUF);
   2459       1.9      onoe 			return error;
   2460       1.3      onoe 		}
   2461      1.66       jmc 		ndesc = fb->fb_dmamap->dm_nsegs + 2;
   2462      1.66       jmc 
   2463       1.9      onoe 		bus_dmamap_sync(sc->sc_dmat, fb->fb_dmamap, 0, pkt->fp_dlen,
   2464       1.9      onoe 		    BUS_DMASYNC_PREWRITE);
   2465       1.3      onoe 	}
   2466       1.3      onoe 
   2467      1.66       jmc 	fb->fb_nseg = ndesc;
   2468      1.66       jmc 	fb->fb_desc = fwohci_desc_get(sc, ndesc);
   2469      1.66       jmc 	if (fb->fb_desc == NULL) {
   2470      1.66       jmc 		free(fb, M_DEVBUF);
   2471      1.66       jmc 		return ENOBUFS;
   2472      1.66       jmc 	}
   2473      1.66       jmc 	fb->fb_daddr = sc->sc_ddmamap->dm_segs[0].ds_addr +
   2474      1.66       jmc 	    ((caddr_t)fb->fb_desc - (caddr_t)sc->sc_desc);
   2475      1.66       jmc 	fb->fb_m = pkt->fp_m;
   2476      1.66       jmc 	fb->fb_callback = pkt->fp_callback;
   2477      1.66       jmc 	fb->fb_statuscb = pkt->fp_statuscb;
   2478      1.66       jmc 	fb->fb_statusarg = pkt->fp_statusarg;
   2479      1.66       jmc 
   2480       1.3      onoe 	fd = fb->fb_desc;
   2481       1.3      onoe 	fd->fd_flags = OHCI_DESC_IMMED;
   2482       1.3      onoe 	fd->fd_reqcount = pkt->fp_hlen;
   2483       1.3      onoe 	fd->fd_data = 0;
   2484       1.3      onoe 	fd->fd_branch = 0;
   2485       1.3      onoe 	fd->fd_status = 0;
   2486       1.3      onoe 	if (fc->fc_ctx == OHCI_CTX_ASYNC_TX_RESPONSE) {
   2487       1.3      onoe 		i = 3;				/* XXX: 3 sec */
   2488       1.3      onoe 		val = OHCI_CSR_READ(sc, OHCI_REG_IsochronousCycleTimer);
   2489       1.3      onoe 		fd->fd_timestamp = ((val >> 12) & 0x1fff) |
   2490       1.3      onoe 		    ((((val >> 25) + i) & 0x7) << 13);
   2491       1.3      onoe 	} else
   2492       1.3      onoe 		fd->fd_timestamp = 0;
   2493       1.9      onoe 	memcpy(fd + 1, pkt->fp_hdr, pkt->fp_hlen);
   2494       1.9      onoe 	for (i = 0; i < ndesc - 2; i++) {
   2495       1.9      onoe 		fd = fb->fb_desc + 2 + i;
   2496       1.3      onoe 		fd->fd_flags = 0;
   2497       1.9      onoe 		fd->fd_reqcount = fb->fb_dmamap->dm_segs[i].ds_len;
   2498       1.9      onoe 		fd->fd_data = fb->fb_dmamap->dm_segs[i].ds_addr;
   2499       1.3      onoe 		fd->fd_branch = 0;
   2500       1.3      onoe 		fd->fd_status = 0;
   2501       1.3      onoe 		fd->fd_timestamp = 0;
   2502       1.3      onoe 	}
   2503       1.3      onoe 	fd->fd_flags |= OHCI_DESC_LAST | OHCI_DESC_BRANCH;
   2504       1.3      onoe 	fd->fd_flags |= OHCI_DESC_INTR_ALWAYS;
   2505       1.3      onoe 
   2506       1.3      onoe #ifdef FW_DEBUG
   2507      1.28       jmc 	DPRINTFN(1, ("fwohci_at_output: desc %ld",
   2508      1.28       jmc 	    (long)(fb->fb_desc - sc->sc_desc)));
   2509      1.28       jmc 	for (i = 0; i < ndesc * 4; i++)
   2510      1.37      onoe 		DPRINTFN(2, ("%s%08x", i&7?" ":"\n    ",
   2511      1.28       jmc 		    ((u_int32_t *)fb->fb_desc)[i]));
   2512      1.28       jmc 	DPRINTFN(1, ("\n"));
   2513       1.3      onoe #endif
   2514       1.3      onoe 
   2515       1.3      onoe 	val = OHCI_ASYNC_DMA_READ(sc, fc->fc_ctx,
   2516       1.3      onoe 	    OHCI_SUBREG_ContextControlClear);
   2517       1.3      onoe 
   2518       1.3      onoe 	if (val & OHCI_CTXCTL_RUN) {
   2519       1.3      onoe 		if (fc->fc_branch == NULL) {
   2520       1.3      onoe 			OHCI_ASYNC_DMA_WRITE(sc, fc->fc_ctx,
   2521       1.3      onoe 			    OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
   2522       1.3      onoe 			goto run;
   2523       1.3      onoe 		}
   2524       1.3      onoe 		*fc->fc_branch = fb->fb_daddr | ndesc;
   2525       1.9      onoe 		OHCI_ASYNC_DMA_WRITE(sc, fc->fc_ctx,
   2526       1.9      onoe 		    OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_WAKE);
   2527       1.3      onoe 	} else {
   2528       1.3      onoe   run:
   2529       1.3      onoe 		OHCI_ASYNC_DMA_WRITE(sc, fc->fc_ctx,
   2530       1.3      onoe 		    OHCI_SUBREG_CommandPtr, fb->fb_daddr | ndesc);
   2531       1.3      onoe 		OHCI_ASYNC_DMA_WRITE(sc, fc->fc_ctx,
   2532       1.3      onoe 		    OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_RUN);
   2533       1.3      onoe 	}
   2534       1.3      onoe 	fc->fc_branch = &fd->fd_branch;
   2535       1.3      onoe 
   2536       1.9      onoe 	fc->fc_bufcnt++;
   2537       1.9      onoe 	TAILQ_INSERT_TAIL(&fc->fc_buf, fb, fb_list);
   2538      1.15      onoe 	pkt->fp_m = NULL;
   2539       1.3      onoe 	return 0;
   2540       1.3      onoe }
   2541       1.3      onoe 
   2542       1.3      onoe static void
   2543       1.9      onoe fwohci_at_done(struct fwohci_softc *sc, struct fwohci_ctx *fc, int force)
   2544       1.3      onoe {
   2545       1.9      onoe 	struct fwohci_buf *fb;
   2546       1.9      onoe 	struct fwohci_desc *fd;
   2547      1.29       jmc 	struct fwohci_pkt pkt;
   2548       1.9      onoe 	int i;
   2549       1.3      onoe 
   2550       1.9      onoe 	while ((fb = TAILQ_FIRST(&fc->fc_buf)) != NULL) {
   2551       1.9      onoe 		fd = fb->fb_desc;
   2552       1.3      onoe #ifdef FW_DEBUG
   2553      1.28       jmc 		DPRINTFN(1, ("fwohci_at_done: %sdesc %ld (%d)",
   2554      1.28       jmc 		    force ? "force " : "", (long)(fd - sc->sc_desc),
   2555      1.28       jmc 		    fb->fb_nseg));
   2556      1.28       jmc 		for (i = 0; i < fb->fb_nseg * 4; i++)
   2557      1.37      onoe 			DPRINTFN(2, ("%s%08x", i&7?" ":"\n    ",
   2558      1.28       jmc 			    ((u_int32_t *)fd)[i]));
   2559      1.28       jmc 		DPRINTFN(1, ("\n"));
   2560       1.3      onoe #endif
   2561       1.9      onoe 		if (fb->fb_nseg > 2)
   2562       1.9      onoe 			fd += fb->fb_nseg - 1;
   2563       1.9      onoe 		if (!force && !(fd->fd_status & OHCI_CTXCTL_ACTIVE))
   2564       1.3      onoe 			break;
   2565       1.9      onoe 		TAILQ_REMOVE(&fc->fc_buf, fb, fb_list);
   2566       1.9      onoe 		if (fc->fc_branch == &fd->fd_branch) {
   2567       1.9      onoe 			OHCI_ASYNC_DMA_WRITE(sc, fc->fc_ctx,
   2568       1.9      onoe 			    OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
   2569       1.9      onoe 			fc->fc_branch = NULL;
   2570       1.9      onoe 			for (i = 0; i < OHCI_LOOP; i++) {
   2571       1.9      onoe 				if (!(OHCI_ASYNC_DMA_READ(sc, fc->fc_ctx,
   2572       1.9      onoe 				    OHCI_SUBREG_ContextControlClear) &
   2573       1.9      onoe 				    OHCI_CTXCTL_ACTIVE))
   2574       1.9      onoe 					break;
   2575      1.36      onoe 				DELAY(10);
   2576       1.9      onoe 			}
   2577       1.3      onoe 		}
   2578      1.29       jmc 
   2579      1.29       jmc 		if (fb->fb_statuscb) {
   2580      1.29       jmc 			memset(&pkt, 0, sizeof(pkt));
   2581      1.29       jmc 			pkt.fp_status = fd->fd_status;
   2582      1.29       jmc 			memcpy(pkt.fp_hdr, fd + 1, sizeof(pkt.fp_hdr[0]));
   2583      1.29       jmc 
   2584      1.29       jmc 			/* Indicate this is just returning the status bits. */
   2585      1.29       jmc 			pkt.fp_tcode = -1;
   2586      1.29       jmc 			(*fb->fb_statuscb)(sc, fb->fb_statusarg, &pkt);
   2587      1.29       jmc 			fb->fb_statuscb = NULL;
   2588      1.29       jmc 			fb->fb_statusarg = NULL;
   2589      1.29       jmc 		}
   2590       1.9      onoe 		fwohci_desc_put(sc, fb->fb_desc, fb->fb_nseg);
   2591       1.9      onoe 		if (fb->fb_nseg > 2)
   2592       1.9      onoe 			bus_dmamap_destroy(sc->sc_dmat, fb->fb_dmamap);
   2593       1.9      onoe 		fc->fc_bufcnt--;
   2594      1.29       jmc 		if (fb->fb_callback) {
   2595       1.9      onoe 			(*fb->fb_callback)(sc->sc_sc1394.sc1394_if, fb->fb_m);
   2596       1.9      onoe 			fb->fb_callback = NULL;
   2597       1.9      onoe 		} else if (fb->fb_m != NULL)
   2598       1.9      onoe 			m_freem(fb->fb_m);
   2599       1.9      onoe 		free(fb, M_DEVBUF);
   2600       1.3      onoe 	}
   2601       1.3      onoe }
   2602       1.3      onoe 
   2603       1.3      onoe /*
   2604  1.78.2.2     skrll  * Asynchronous Transmit Response -- in response of request packet.
   2605       1.3      onoe  */
   2606       1.3      onoe static void
   2607       1.3      onoe fwohci_atrs_output(struct fwohci_softc *sc, int rcode, struct fwohci_pkt *req,
   2608       1.3      onoe     struct fwohci_pkt *res)
   2609       1.3      onoe {
   2610       1.3      onoe 
   2611      1.26     enami 	if (((*req->fp_trail & 0x001f0000) >> 16) !=
   2612      1.26     enami 	    OHCI_CTXCTL_EVENT_ACK_PENDING)
   2613      1.26     enami 		return;
   2614      1.26     enami 
   2615       1.3      onoe 	res->fp_hdr[0] = (req->fp_hdr[0] & 0x0000fc00) | 0x00000100;
   2616       1.3      onoe 	res->fp_hdr[1] = (req->fp_hdr[1] & 0xffff0000) | (rcode << 12);
   2617       1.3      onoe 	switch (req->fp_tcode) {
   2618       1.3      onoe 	case IEEE1394_TCODE_WRITE_REQ_QUAD:
   2619       1.3      onoe 	case IEEE1394_TCODE_WRITE_REQ_BLOCK:
   2620       1.3      onoe 		res->fp_tcode = IEEE1394_TCODE_WRITE_RESP;
   2621       1.3      onoe 		res->fp_hlen = 12;
   2622       1.3      onoe 		break;
   2623       1.3      onoe 	case IEEE1394_TCODE_READ_REQ_QUAD:
   2624       1.3      onoe 		res->fp_tcode = IEEE1394_TCODE_READ_RESP_QUAD;
   2625       1.3      onoe 		res->fp_hlen = 16;
   2626       1.3      onoe 		res->fp_dlen = 0;
   2627       1.9      onoe 		if (res->fp_uio.uio_iovcnt == 1 && res->fp_iov[0].iov_len == 4)
   2628       1.3      onoe 			res->fp_hdr[3] =
   2629       1.3      onoe 			    *(u_int32_t *)res->fp_iov[0].iov_base;
   2630       1.9      onoe 		res->fp_uio.uio_iovcnt = 0;
   2631       1.3      onoe 		break;
   2632       1.3      onoe 	case IEEE1394_TCODE_READ_REQ_BLOCK:
   2633       1.3      onoe 	case IEEE1394_TCODE_LOCK_REQ:
   2634       1.3      onoe 		if (req->fp_tcode == IEEE1394_TCODE_LOCK_REQ)
   2635       1.3      onoe 			res->fp_tcode = IEEE1394_TCODE_LOCK_RESP;
   2636       1.3      onoe 		else
   2637       1.3      onoe 			res->fp_tcode = IEEE1394_TCODE_READ_RESP_BLOCK;
   2638       1.3      onoe 		res->fp_hlen = 16;
   2639       1.9      onoe 		res->fp_dlen = res->fp_uio.uio_resid;
   2640       1.3      onoe 		res->fp_hdr[3] = res->fp_dlen << 16;
   2641       1.3      onoe 		break;
   2642       1.3      onoe 	}
   2643       1.3      onoe 	res->fp_hdr[0] |= (res->fp_tcode << 4);
   2644      1.26     enami 	fwohci_at_output(sc, sc->sc_ctx_atrs, res);
   2645       1.3      onoe }
   2646       1.3      onoe 
   2647       1.3      onoe /*
   2648       1.3      onoe  * APPLICATION LAYER SERVICES
   2649       1.3      onoe  */
   2650      1.16      onoe 
   2651      1.16      onoe /*
   2652      1.16      onoe  * Retrieve Global UID from GUID ROM
   2653      1.16      onoe  */
   2654      1.16      onoe static int
   2655      1.16      onoe fwohci_guidrom_init(struct fwohci_softc *sc)
   2656      1.16      onoe {
   2657      1.16      onoe 	int i, n, off;
   2658      1.16      onoe 	u_int32_t val1, val2;
   2659      1.16      onoe 
   2660      1.16      onoe 	/* Extract the Global UID
   2661      1.16      onoe 	 */
   2662      1.16      onoe 	val1 = OHCI_CSR_READ(sc, OHCI_REG_GUIDHi);
   2663      1.16      onoe 	val2 = OHCI_CSR_READ(sc, OHCI_REG_GUIDLo);
   2664      1.26     enami 
   2665      1.16      onoe 	if (val1 != 0 || val2 != 0) {
   2666      1.16      onoe 		sc->sc_sc1394.sc1394_guid[0] = (val1 >> 24) & 0xff;
   2667      1.16      onoe 		sc->sc_sc1394.sc1394_guid[1] = (val1 >> 16) & 0xff;
   2668      1.16      onoe 		sc->sc_sc1394.sc1394_guid[2] = (val1 >>  8) & 0xff;
   2669      1.16      onoe 		sc->sc_sc1394.sc1394_guid[3] = (val1 >>  0) & 0xff;
   2670      1.16      onoe 		sc->sc_sc1394.sc1394_guid[4] = (val2 >> 24) & 0xff;
   2671      1.16      onoe 		sc->sc_sc1394.sc1394_guid[5] = (val2 >> 16) & 0xff;
   2672      1.16      onoe 		sc->sc_sc1394.sc1394_guid[6] = (val2 >>  8) & 0xff;
   2673      1.16      onoe 		sc->sc_sc1394.sc1394_guid[7] = (val2 >>  0) & 0xff;
   2674      1.16      onoe 	} else {
   2675      1.16      onoe 		val1 = OHCI_CSR_READ(sc, OHCI_REG_Version);
   2676      1.16      onoe 		if ((val1 & OHCI_Version_GUID_ROM) == 0)
   2677      1.16      onoe 			return -1;
   2678      1.16      onoe 		OHCI_CSR_WRITE(sc, OHCI_REG_Guid_Rom, OHCI_Guid_AddrReset);
   2679      1.16      onoe 		for (i = 0; i < OHCI_LOOP; i++) {
   2680      1.16      onoe 			val1 = OHCI_CSR_READ(sc, OHCI_REG_Guid_Rom);
   2681      1.16      onoe 			if (!(val1 & OHCI_Guid_AddrReset))
   2682      1.16      onoe 				break;
   2683      1.36      onoe 			DELAY(10);
   2684      1.16      onoe 		}
   2685      1.18      onoe 		off = OHCI_BITVAL(val1, OHCI_Guid_MiniROM) + 4;
   2686      1.16      onoe 		val2 = 0;
   2687      1.16      onoe 		for (n = 0; n < off + sizeof(sc->sc_sc1394.sc1394_guid); n++) {
   2688      1.16      onoe 			OHCI_CSR_WRITE(sc, OHCI_REG_Guid_Rom,
   2689      1.16      onoe 			    OHCI_Guid_RdStart);
   2690      1.16      onoe 			for (i = 0; i < OHCI_LOOP; i++) {
   2691      1.16      onoe 				val1 = OHCI_CSR_READ(sc, OHCI_REG_Guid_Rom);
   2692      1.16      onoe 				if (!(val1 & OHCI_Guid_RdStart))
   2693      1.16      onoe 					break;
   2694      1.36      onoe 				DELAY(10);
   2695      1.16      onoe 			}
   2696      1.16      onoe 			if (n < off)
   2697      1.16      onoe 				continue;
   2698      1.18      onoe 			val1 = OHCI_BITVAL(val1, OHCI_Guid_RdData);
   2699      1.16      onoe 			sc->sc_sc1394.sc1394_guid[n - off] = val1;
   2700      1.16      onoe 			val2 |= val1;
   2701      1.16      onoe 		}
   2702      1.16      onoe 		if (val2 == 0)
   2703      1.16      onoe 			return -1;
   2704      1.16      onoe 	}
   2705      1.16      onoe 	return 0;
   2706      1.16      onoe }
   2707       1.3      onoe 
   2708       1.3      onoe /*
   2709       1.3      onoe  * Initialization for Configuration ROM (no DMA context)
   2710       1.3      onoe  */
   2711       1.3      onoe 
   2712       1.3      onoe #define	CFR_MAXUNIT		20
   2713       1.3      onoe 
   2714       1.3      onoe struct configromctx {
   2715       1.3      onoe 	u_int32_t	*ptr;
   2716       1.3      onoe 	int		curunit;
   2717       1.3      onoe 	struct {
   2718       1.3      onoe 		u_int32_t	*start;
   2719       1.3      onoe 		int		length;
   2720       1.3      onoe 		u_int32_t	*refer;
   2721       1.3      onoe 		int		refunit;
   2722       1.3      onoe 	} unit[CFR_MAXUNIT];
   2723       1.3      onoe };
   2724       1.3      onoe 
   2725       1.3      onoe #define	CFR_PUT_DATA4(cfr, d1, d2, d3, d4)				\
   2726       1.3      onoe 	(*(cfr)->ptr++ = (((d1)<<24) | ((d2)<<16) | ((d3)<<8) | (d4)))
   2727       1.3      onoe 
   2728       1.3      onoe #define	CFR_PUT_DATA1(cfr, d)	(*(cfr)->ptr++ = (d))
   2729       1.3      onoe 
   2730       1.3      onoe #define	CFR_PUT_VALUE(cfr, key, d)	(*(cfr)->ptr++ = ((key)<<24) | (d))
   2731       1.3      onoe 
   2732       1.3      onoe #define	CFR_PUT_CRC(cfr, n)						\
   2733       1.3      onoe 	(*(cfr)->unit[n].start = ((cfr)->unit[n].length << 16) |	\
   2734       1.3      onoe 	    fwohci_crc16((cfr)->unit[n].start + 1, (cfr)->unit[n].length))
   2735       1.3      onoe 
   2736       1.3      onoe #define	CFR_START_UNIT(cfr, n)						\
   2737       1.3      onoe do {									\
   2738       1.3      onoe 	if ((cfr)->unit[n].refer != NULL) {				\
   2739       1.3      onoe 		*(cfr)->unit[n].refer |=				\
   2740       1.3      onoe 		    (cfr)->ptr - (cfr)->unit[n].refer;			\
   2741       1.3      onoe 		CFR_PUT_CRC(cfr, (cfr)->unit[n].refunit);		\
   2742       1.3      onoe 	}								\
   2743       1.3      onoe 	(cfr)->curunit = (n);						\
   2744       1.3      onoe 	(cfr)->unit[n].start = (cfr)->ptr++;				\
   2745       1.3      onoe } while (0 /* CONSTCOND */)
   2746       1.3      onoe 
   2747       1.3      onoe #define	CFR_PUT_REFER(cfr, key, n)					\
   2748       1.3      onoe do {									\
   2749       1.3      onoe 	(cfr)->unit[n].refer = (cfr)->ptr;				\
   2750       1.3      onoe 	(cfr)->unit[n].refunit = (cfr)->curunit;			\
   2751       1.3      onoe 	*(cfr)->ptr++ = (key) << 24;					\
   2752       1.3      onoe } while (0 /* CONSTCOND */)
   2753       1.3      onoe 
   2754       1.3      onoe #define	CFR_END_UNIT(cfr)						\
   2755       1.3      onoe do {									\
   2756       1.3      onoe 	(cfr)->unit[(cfr)->curunit].length = (cfr)->ptr -		\
   2757       1.3      onoe 	    ((cfr)->unit[(cfr)->curunit].start + 1);			\
   2758       1.3      onoe 	CFR_PUT_CRC(cfr, (cfr)->curunit);				\
   2759       1.3      onoe } while (0 /* CONSTCOND */)
   2760       1.3      onoe 
   2761       1.3      onoe static u_int16_t
   2762       1.3      onoe fwohci_crc16(u_int32_t *ptr, int len)
   2763       1.3      onoe {
   2764       1.3      onoe 	int shift;
   2765       1.3      onoe 	u_int32_t crc, sum, data;
   2766       1.3      onoe 
   2767       1.3      onoe 	crc = 0;
   2768       1.3      onoe 	while (len-- > 0) {
   2769       1.3      onoe 		data = *ptr++;
   2770       1.3      onoe 		for (shift = 28; shift >= 0; shift -= 4) {
   2771       1.3      onoe 			sum = ((crc >> 12) ^ (data >> shift)) & 0x000f;
   2772       1.3      onoe 			crc = (crc << 4) ^ (sum << 12) ^ (sum << 5) ^ sum;
   2773       1.3      onoe 		}
   2774       1.3      onoe 		crc &= 0xffff;
   2775       1.3      onoe 	}
   2776       1.3      onoe 	return crc;
   2777       1.3      onoe }
   2778       1.3      onoe 
   2779       1.3      onoe static void
   2780       1.3      onoe fwohci_configrom_init(struct fwohci_softc *sc)
   2781       1.3      onoe {
   2782      1.29       jmc 	int i, val;
   2783       1.3      onoe 	struct fwohci_buf *fb;
   2784       1.3      onoe 	u_int32_t *hdr;
   2785       1.3      onoe 	struct configromctx cfr;
   2786       1.3      onoe 
   2787       1.3      onoe 	fb = &sc->sc_buf_cnfrom;
   2788       1.3      onoe 	memset(&cfr, 0, sizeof(cfr));
   2789       1.3      onoe 	cfr.ptr = hdr = (u_int32_t *)fb->fb_buf;
   2790       1.3      onoe 
   2791       1.3      onoe 	/* headers */
   2792       1.3      onoe 	CFR_START_UNIT(&cfr, 0);
   2793       1.3      onoe 	CFR_PUT_DATA1(&cfr, OHCI_CSR_READ(sc, OHCI_REG_BusId));
   2794       1.3      onoe 	CFR_PUT_DATA1(&cfr, OHCI_CSR_READ(sc, OHCI_REG_BusOptions));
   2795       1.3      onoe 	CFR_PUT_DATA1(&cfr, OHCI_CSR_READ(sc, OHCI_REG_GUIDHi));
   2796       1.3      onoe 	CFR_PUT_DATA1(&cfr, OHCI_CSR_READ(sc, OHCI_REG_GUIDLo));
   2797       1.3      onoe 	CFR_END_UNIT(&cfr);
   2798       1.3      onoe 	/* copy info_length from crc_length */
   2799       1.3      onoe 	*hdr |= (*hdr & 0x00ff0000) << 8;
   2800       1.3      onoe 	OHCI_CSR_WRITE(sc, OHCI_REG_ConfigROMhdr, *hdr);
   2801       1.3      onoe 
   2802       1.3      onoe 	/* root directory */
   2803       1.3      onoe 	CFR_START_UNIT(&cfr, 1);
   2804       1.3      onoe 	CFR_PUT_VALUE(&cfr, 0x03, 0x00005e);	/* vendor id */
   2805       1.3      onoe 	CFR_PUT_REFER(&cfr, 0x81, 2);		/* textual descriptor offset */
   2806       1.3      onoe 	CFR_PUT_VALUE(&cfr, 0x0c, 0x0083c0);	/* node capability */
   2807       1.3      onoe 						/* spt,64,fix,lst,drq */
   2808       1.3      onoe #ifdef INET
   2809       1.3      onoe 	CFR_PUT_REFER(&cfr, 0xd1, 3);		/* IPv4 unit directory */
   2810       1.3      onoe #endif /* INET */
   2811       1.3      onoe #ifdef INET6
   2812       1.3      onoe 	CFR_PUT_REFER(&cfr, 0xd1, 4);		/* IPv6 unit directory */
   2813       1.3      onoe #endif /* INET6 */
   2814       1.3      onoe 	CFR_END_UNIT(&cfr);
   2815       1.3      onoe 
   2816       1.3      onoe 	CFR_START_UNIT(&cfr, 2);
   2817       1.3      onoe 	CFR_PUT_VALUE(&cfr, 0, 0);		/* textual descriptor */
   2818       1.3      onoe 	CFR_PUT_DATA1(&cfr, 0);			/* minimal ASCII */
   2819       1.3      onoe 	CFR_PUT_DATA4(&cfr, 'N', 'e', 't', 'B');
   2820       1.3      onoe 	CFR_PUT_DATA4(&cfr, 'S', 'D', 0x00, 0x00);
   2821       1.3      onoe 	CFR_END_UNIT(&cfr);
   2822       1.3      onoe 
   2823       1.3      onoe #ifdef INET
   2824       1.3      onoe 	/* IPv4 unit directory */
   2825       1.3      onoe 	CFR_START_UNIT(&cfr, 3);
   2826       1.3      onoe 	CFR_PUT_VALUE(&cfr, 0x12, 0x00005e);	/* unit spec id */
   2827       1.3      onoe 	CFR_PUT_REFER(&cfr, 0x81, 6);		/* textual descriptor offset */
   2828       1.3      onoe 	CFR_PUT_VALUE(&cfr, 0x13, 0x000001);	/* unit sw version */
   2829       1.3      onoe 	CFR_PUT_REFER(&cfr, 0x81, 7);		/* textual descriptor offset */
   2830      1.53       jmc 	CFR_PUT_REFER(&cfr, 0x95, 8);		/* Unit location */
   2831       1.3      onoe 	CFR_END_UNIT(&cfr);
   2832       1.3      onoe 
   2833       1.3      onoe 	CFR_START_UNIT(&cfr, 6);
   2834       1.3      onoe 	CFR_PUT_VALUE(&cfr, 0, 0);		/* textual descriptor */
   2835       1.3      onoe 	CFR_PUT_DATA1(&cfr, 0);			/* minimal ASCII */
   2836       1.3      onoe 	CFR_PUT_DATA4(&cfr, 'I', 'A', 'N', 'A');
   2837       1.3      onoe 	CFR_END_UNIT(&cfr);
   2838       1.3      onoe 
   2839       1.3      onoe 	CFR_START_UNIT(&cfr, 7);
   2840       1.3      onoe 	CFR_PUT_VALUE(&cfr, 0, 0);		/* textual descriptor */
   2841       1.3      onoe 	CFR_PUT_DATA1(&cfr, 0);			/* minimal ASCII */
   2842       1.3      onoe 	CFR_PUT_DATA4(&cfr, 'I', 'P', 'v', '4');
   2843       1.3      onoe 	CFR_END_UNIT(&cfr);
   2844      1.53       jmc 
   2845      1.53       jmc 	CFR_START_UNIT(&cfr, 8);		/* Spec's valid addr range. */
   2846      1.53       jmc 	CFR_PUT_DATA1(&cfr, FW_FIFO_HI);
   2847      1.53       jmc 	CFR_PUT_DATA1(&cfr, (FW_FIFO_LO | 0x1));
   2848      1.53       jmc 	CFR_PUT_DATA1(&cfr, FW_FIFO_HI);
   2849      1.53       jmc 	CFR_PUT_DATA1(&cfr, FW_FIFO_LO);
   2850      1.53       jmc 	CFR_END_UNIT(&cfr);
   2851      1.53       jmc 
   2852       1.3      onoe #endif /* INET */
   2853       1.3      onoe 
   2854       1.3      onoe #ifdef INET6
   2855       1.3      onoe 	/* IPv6 unit directory */
   2856       1.3      onoe 	CFR_START_UNIT(&cfr, 4);
   2857       1.3      onoe 	CFR_PUT_VALUE(&cfr, 0x12, 0x00005e);	/* unit spec id */
   2858      1.53       jmc 	CFR_PUT_REFER(&cfr, 0x81, 9);		/* textual descriptor offset */
   2859       1.8      onoe 	CFR_PUT_VALUE(&cfr, 0x13, 0x000002);	/* unit sw version */
   2860       1.8      onoe 						/* XXX: TBA by IANA */
   2861      1.53       jmc 	CFR_PUT_REFER(&cfr, 0x81, 10);		/* textual descriptor offset */
   2862      1.53       jmc 	CFR_PUT_REFER(&cfr, 0x95, 11);		/* Unit location */
   2863       1.3      onoe 	CFR_END_UNIT(&cfr);
   2864       1.3      onoe 
   2865      1.53       jmc 	CFR_START_UNIT(&cfr, 9);
   2866       1.3      onoe 	CFR_PUT_VALUE(&cfr, 0, 0);		/* textual descriptor */
   2867       1.3      onoe 	CFR_PUT_DATA1(&cfr, 0);			/* minimal ASCII */
   2868       1.3      onoe 	CFR_PUT_DATA4(&cfr, 'I', 'A', 'N', 'A');
   2869       1.3      onoe 	CFR_END_UNIT(&cfr);
   2870       1.3      onoe 
   2871      1.53       jmc 	CFR_START_UNIT(&cfr, 10);
   2872       1.3      onoe 	CFR_PUT_VALUE(&cfr, 0, 0);		/* textual descriptor */
   2873       1.3      onoe 	CFR_PUT_DATA1(&cfr, 0);
   2874       1.3      onoe 	CFR_PUT_DATA4(&cfr, 'I', 'P', 'v', '6');
   2875       1.3      onoe 	CFR_END_UNIT(&cfr);
   2876      1.53       jmc 
   2877      1.53       jmc 	CFR_START_UNIT(&cfr, 11);		/* Spec's valid addr range. */
   2878      1.53       jmc 	CFR_PUT_DATA1(&cfr, FW_FIFO_HI);
   2879      1.53       jmc 	CFR_PUT_DATA1(&cfr, (FW_FIFO_LO | 0x1));
   2880      1.53       jmc 	CFR_PUT_DATA1(&cfr, FW_FIFO_HI);
   2881      1.53       jmc 	CFR_PUT_DATA1(&cfr, FW_FIFO_LO);
   2882      1.53       jmc 	CFR_END_UNIT(&cfr);
   2883      1.53       jmc 
   2884       1.3      onoe #endif /* INET6 */
   2885       1.3      onoe 
   2886      1.24       jmc 	fb->fb_off = cfr.ptr - hdr;
   2887       1.3      onoe #ifdef FW_DEBUG
   2888      1.53       jmc 	DPRINTF(("%s: Config ROM:", sc->sc_sc1394.sc1394_dev.dv_xname));
   2889      1.28       jmc 	for (i = 0; i < fb->fb_off; i++)
   2890      1.53       jmc 		DPRINTF(("%s%08x", i&7?" ":"\n    ", hdr[i]));
   2891      1.53       jmc 	DPRINTF(("\n"));
   2892       1.3      onoe #endif /* FW_DEBUG */
   2893       1.3      onoe 
   2894       1.3      onoe 	/*
   2895       1.3      onoe 	 * Make network byte order for DMA
   2896       1.3      onoe 	 */
   2897      1.24       jmc 	for (i = 0; i < fb->fb_off; i++)
   2898       1.8      onoe 		HTONL(hdr[i]);
   2899      1.26     enami 	bus_dmamap_sync(sc->sc_dmat, fb->fb_dmamap, 0,
   2900       1.3      onoe 	    (caddr_t)cfr.ptr - fb->fb_buf, BUS_DMASYNC_PREWRITE);
   2901       1.3      onoe 
   2902       1.3      onoe 	OHCI_CSR_WRITE(sc, OHCI_REG_ConfigROMmap,
   2903       1.3      onoe 	    fb->fb_dmamap->dm_segs[0].ds_addr);
   2904      1.24       jmc 
   2905      1.29       jmc 	/* This register is only valid on OHCI 1.1. */
   2906      1.29       jmc 	val = OHCI_CSR_READ(sc, OHCI_REG_Version);
   2907      1.29       jmc 	if ((OHCI_Version_GET_Version(val) == 1) &&
   2908      1.29       jmc 	    (OHCI_Version_GET_Revision(val) == 1))
   2909      1.29       jmc 		OHCI_CSR_WRITE(sc, OHCI_REG_HCControlSet,
   2910      1.29       jmc 		    OHCI_HCControl_BIBImageValid);
   2911      1.29       jmc 
   2912      1.67       jmc 	/* Only allow quad reads of the rom. */
   2913      1.26     enami 	for (i = 0; i < fb->fb_off; i++)
   2914      1.26     enami 		fwohci_handler_set(sc, IEEE1394_TCODE_READ_REQ_QUAD,
   2915      1.67       jmc 		    CSR_BASE_HI, CSR_BASE_LO + CSR_CONFIG_ROM + (i * 4), 0,
   2916      1.26     enami 		    fwohci_configrom_input, NULL);
   2917      1.24       jmc }
   2918      1.24       jmc 
   2919      1.24       jmc static int
   2920      1.24       jmc fwohci_configrom_input(struct fwohci_softc *sc, void *arg,
   2921      1.24       jmc     struct fwohci_pkt *pkt)
   2922      1.24       jmc {
   2923      1.24       jmc 	struct fwohci_pkt res;
   2924      1.24       jmc 	u_int32_t loc, *rom;
   2925      1.26     enami 
   2926      1.24       jmc 	/* This will be used as an array index so size accordingly. */
   2927      1.26     enami 	loc = pkt->fp_hdr[2] - (CSR_BASE_LO + CSR_CONFIG_ROM);
   2928      1.26     enami 	if ((loc & 0x03) != 0) {
   2929      1.24       jmc 		/* alignment error */
   2930      1.24       jmc 		return IEEE1394_RCODE_ADDRESS_ERROR;
   2931      1.24       jmc 	}
   2932      1.26     enami 	else
   2933      1.26     enami 		loc /= 4;
   2934      1.26     enami 	rom = (u_int32_t *)sc->sc_buf_cnfrom.fb_buf;
   2935      1.26     enami 
   2936      1.28       jmc 	DPRINTFN(1, ("fwohci_configrom_input: ConfigRom[0x%04x]: 0x%08x\n", loc,
   2937      1.28       jmc 	    ntohl(rom[loc])));
   2938      1.26     enami 
   2939      1.26     enami 	memset(&res, 0, sizeof(res));
   2940      1.26     enami 	res.fp_hdr[3] = rom[loc];
   2941      1.26     enami 	fwohci_atrs_output(sc, IEEE1394_RCODE_COMPLETE, pkt, &res);
   2942      1.26     enami 	return -1;
   2943       1.3      onoe }
   2944       1.3      onoe 
   2945       1.3      onoe /*
   2946       1.3      onoe  * SelfID buffer (no DMA context)
   2947       1.3      onoe  */
   2948       1.3      onoe static void
   2949       1.3      onoe fwohci_selfid_init(struct fwohci_softc *sc)
   2950       1.3      onoe {
   2951       1.3      onoe 	struct fwohci_buf *fb;
   2952       1.3      onoe 
   2953       1.3      onoe 	fb = &sc->sc_buf_selfid;
   2954      1.28       jmc #ifdef DIAGNOSTIC
   2955       1.7      onoe 	if ((fb->fb_dmamap->dm_segs[0].ds_addr & 0x7ff) != 0)
   2956      1.51       jmc 		panic("fwohci_selfid_init: not aligned: %ld (%ld) %p",
   2957      1.51       jmc 		    (unsigned long)fb->fb_dmamap->dm_segs[0].ds_addr,
   2958      1.28       jmc 		    (unsigned long)fb->fb_dmamap->dm_segs[0].ds_len, fb->fb_buf);
   2959       1.7      onoe #endif
   2960       1.9      onoe 	memset(fb->fb_buf, 0, fb->fb_dmamap->dm_segs[0].ds_len);
   2961       1.7      onoe 	bus_dmamap_sync(sc->sc_dmat, fb->fb_dmamap, 0,
   2962       1.7      onoe 	    fb->fb_dmamap->dm_segs[0].ds_len, BUS_DMASYNC_PREREAD);
   2963       1.3      onoe 
   2964       1.3      onoe 	OHCI_CSR_WRITE(sc, OHCI_REG_SelfIDBuffer,
   2965       1.3      onoe 	    fb->fb_dmamap->dm_segs[0].ds_addr);
   2966       1.3      onoe }
   2967       1.3      onoe 
   2968       1.7      onoe static int
   2969       1.3      onoe fwohci_selfid_input(struct fwohci_softc *sc)
   2970       1.3      onoe {
   2971       1.3      onoe 	int i;
   2972       1.7      onoe 	u_int32_t count, val, gen;
   2973       1.3      onoe 	u_int32_t *buf;
   2974       1.3      onoe 
   2975      1.20      onoe 	buf = (u_int32_t *)sc->sc_buf_selfid.fb_buf;
   2976       1.3      onoe 	val = OHCI_CSR_READ(sc, OHCI_REG_SelfIDCount);
   2977      1.20      onoe   again:
   2978       1.3      onoe 	if (val & OHCI_SelfID_Error) {
   2979       1.3      onoe 		printf("%s: SelfID Error\n", sc->sc_sc1394.sc1394_dev.dv_xname);
   2980       1.7      onoe 		return -1;
   2981       1.3      onoe 	}
   2982      1.18      onoe 	count = OHCI_BITVAL(val, OHCI_SelfID_Size);
   2983       1.3      onoe 
   2984       1.3      onoe 	bus_dmamap_sync(sc->sc_dmat, sc->sc_buf_selfid.fb_dmamap,
   2985       1.3      onoe 	    0, count << 2, BUS_DMASYNC_POSTREAD);
   2986      1.20      onoe 	gen = OHCI_BITVAL(buf[0], OHCI_SelfID_Gen);
   2987       1.3      onoe 
   2988       1.3      onoe #ifdef FW_DEBUG
   2989      1.28       jmc 	DPRINTFN(1, ("%s: SelfID: 0x%08x", sc->sc_sc1394.sc1394_dev.dv_xname,
   2990      1.28       jmc 	    val));
   2991      1.28       jmc 	for (i = 0; i < count; i++)
   2992      1.37      onoe 		DPRINTFN(2, ("%s%08x", i&7?" ":"\n    ", buf[i]));
   2993      1.28       jmc 	DPRINTFN(1, ("\n"));
   2994       1.3      onoe #endif /* FW_DEBUG */
   2995       1.3      onoe 
   2996      1.20      onoe 	for (i = 1; i < count; i += 2) {
   2997      1.20      onoe 		if (buf[i] != ~buf[i + 1])
   2998      1.20      onoe 			break;
   2999      1.20      onoe 		if (buf[i] & 0x00000001)
   3000      1.20      onoe 			continue;	/* more pkt */
   3001      1.20      onoe 		if (buf[i] & 0x00800000)
   3002      1.20      onoe 			continue;	/* external id */
   3003      1.20      onoe 		sc->sc_rootid = (buf[i] & 0x3f000000) >> 24;
   3004      1.20      onoe 		if ((buf[i] & 0x00400800) == 0x00400800)
   3005      1.20      onoe 			sc->sc_irmid = sc->sc_rootid;
   3006      1.20      onoe 	}
   3007      1.20      onoe 
   3008      1.20      onoe 	val = OHCI_CSR_READ(sc, OHCI_REG_SelfIDCount);
   3009      1.20      onoe 	if (OHCI_BITVAL(val, OHCI_SelfID_Gen) != gen) {
   3010      1.20      onoe 		if (OHCI_BITVAL(val, OHCI_SelfID_Gen) !=
   3011      1.20      onoe 		    OHCI_BITVAL(buf[0], OHCI_SelfID_Gen))
   3012      1.20      onoe 			goto again;
   3013      1.28       jmc 		DPRINTF(("%s: SelfID Gen mismatch (%d, %d)\n",
   3014      1.28       jmc 		    sc->sc_sc1394.sc1394_dev.dv_xname, gen,
   3015      1.28       jmc 		    OHCI_BITVAL(val, OHCI_SelfID_Gen)));
   3016      1.20      onoe 		return -1;
   3017      1.20      onoe 	}
   3018      1.20      onoe 	if (i != count) {
   3019      1.20      onoe 		printf("%s: SelfID corrupted (%d, 0x%08x, 0x%08x)\n",
   3020      1.20      onoe 		    sc->sc_sc1394.sc1394_dev.dv_xname, i, buf[i], buf[i + 1]);
   3021      1.20      onoe #if 1
   3022      1.20      onoe 		if (i == 1 && buf[i] == 0 && buf[i + 1] == 0) {
   3023      1.20      onoe 			/*
   3024      1.20      onoe 			 * XXX: CXD3222 sometimes fails to DMA
   3025      1.20      onoe 			 * selfid packet??
   3026      1.20      onoe 			 */
   3027      1.20      onoe 			sc->sc_rootid = (count - 1) / 2 - 1;
   3028      1.20      onoe 			sc->sc_irmid = sc->sc_rootid;
   3029      1.20      onoe 		} else
   3030      1.20      onoe #endif
   3031      1.20      onoe 		return -1;
   3032      1.20      onoe 	}
   3033      1.20      onoe 
   3034       1.7      onoe 	val = OHCI_CSR_READ(sc, OHCI_REG_NodeId);
   3035       1.7      onoe 	if ((val & OHCI_NodeId_IDValid) == 0) {
   3036       1.9      onoe 		sc->sc_nodeid = 0xffff;		/* invalid */
   3037       1.7      onoe 		printf("%s: nodeid is invalid\n",
   3038       1.7      onoe 		    sc->sc_sc1394.sc1394_dev.dv_xname);
   3039       1.7      onoe 		return -1;
   3040       1.7      onoe 	}
   3041       1.7      onoe 	sc->sc_nodeid = val & 0xffff;
   3042      1.64       jmc 	sc->sc_sc1394.sc1394_node_id = sc->sc_nodeid & OHCI_NodeId_NodeNumber;
   3043      1.28       jmc 
   3044      1.28       jmc 	DPRINTF(("%s: nodeid=0x%04x(%d), rootid=%d, irmid=%d\n",
   3045      1.28       jmc 	    sc->sc_sc1394.sc1394_dev.dv_xname, sc->sc_nodeid,
   3046      1.28       jmc 	    sc->sc_nodeid & OHCI_NodeId_NodeNumber, sc->sc_rootid,
   3047      1.28       jmc 	    sc->sc_irmid));
   3048       1.3      onoe 
   3049       1.3      onoe 	if ((sc->sc_nodeid & OHCI_NodeId_NodeNumber) > sc->sc_rootid)
   3050       1.7      onoe 		return -1;
   3051       1.3      onoe 
   3052       1.3      onoe 	if ((sc->sc_nodeid & OHCI_NodeId_NodeNumber) == sc->sc_rootid)
   3053       1.3      onoe 		OHCI_CSR_WRITE(sc, OHCI_REG_LinkControlSet,
   3054       1.3      onoe 		    OHCI_LinkControl_CycleMaster);
   3055       1.3      onoe 	else
   3056       1.3      onoe 		OHCI_CSR_WRITE(sc, OHCI_REG_LinkControlClear,
   3057       1.3      onoe 		    OHCI_LinkControl_CycleMaster);
   3058       1.7      onoe 	return 0;
   3059       1.3      onoe }
   3060       1.3      onoe 
   3061       1.3      onoe /*
   3062       1.3      onoe  * some CSRs are handled by driver.
   3063       1.3      onoe  */
   3064       1.3      onoe static void
   3065       1.3      onoe fwohci_csr_init(struct fwohci_softc *sc)
   3066       1.3      onoe {
   3067       1.3      onoe 	int i;
   3068       1.3      onoe 	static u_int32_t csr[] = {
   3069       1.3      onoe 	    CSR_STATE_CLEAR, CSR_STATE_SET, CSR_SB_CYCLE_TIME,
   3070       1.3      onoe 	    CSR_SB_BUS_TIME, CSR_SB_BUSY_TIMEOUT, CSR_SB_BUS_MANAGER_ID,
   3071       1.3      onoe 	    CSR_SB_CHANNEL_AVAILABLE_HI, CSR_SB_CHANNEL_AVAILABLE_LO,
   3072       1.3      onoe 	    CSR_SB_BROADCAST_CHANNEL
   3073       1.3      onoe 	};
   3074       1.3      onoe 
   3075       1.3      onoe 	for (i = 0; i < sizeof(csr) / sizeof(csr[0]); i++) {
   3076       1.3      onoe 		fwohci_handler_set(sc, IEEE1394_TCODE_WRITE_REQ_QUAD,
   3077      1.67       jmc 		    CSR_BASE_HI, CSR_BASE_LO + csr[i], 0, fwohci_csr_input,
   3078      1.67       jmc 		    NULL);
   3079       1.3      onoe 		fwohci_handler_set(sc, IEEE1394_TCODE_READ_REQ_QUAD,
   3080      1.67       jmc 		    CSR_BASE_HI, CSR_BASE_LO + csr[i], 0, fwohci_csr_input,
   3081      1.67       jmc 		    NULL);
   3082       1.3      onoe 	}
   3083       1.3      onoe 	sc->sc_csr[CSR_SB_BROADCAST_CHANNEL] = 31;	/*XXX*/
   3084       1.3      onoe }
   3085       1.3      onoe 
   3086       1.3      onoe static int
   3087       1.3      onoe fwohci_csr_input(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt)
   3088       1.3      onoe {
   3089       1.3      onoe 	struct fwohci_pkt res;
   3090       1.3      onoe 	u_int32_t reg;
   3091       1.3      onoe 
   3092       1.3      onoe 	/*
   3093       1.3      onoe 	 * XXX need to do special functionality other than just r/w...
   3094       1.3      onoe 	 */
   3095       1.3      onoe 	reg = pkt->fp_hdr[2] - CSR_BASE_LO;
   3096       1.3      onoe 
   3097       1.3      onoe 	if ((reg & 0x03) != 0) {
   3098       1.3      onoe 		/* alignment error */
   3099       1.3      onoe 		return IEEE1394_RCODE_ADDRESS_ERROR;
   3100       1.3      onoe 	}
   3101      1.28       jmc 	DPRINTFN(1, ("fwohci_csr_input: CSR[0x%04x]: 0x%08x", reg,
   3102      1.28       jmc 	    *(u_int32_t *)(&sc->sc_csr[reg])));
   3103       1.3      onoe 	if (pkt->fp_tcode == IEEE1394_TCODE_WRITE_REQ_QUAD) {
   3104      1.28       jmc 		DPRINTFN(1, (" -> 0x%08x\n",
   3105      1.28       jmc 		    ntohl(*(u_int32_t *)pkt->fp_iov[0].iov_base)));
   3106       1.3      onoe 		*(u_int32_t *)&sc->sc_csr[reg] =
   3107       1.3      onoe 		    ntohl(*(u_int32_t *)pkt->fp_iov[0].iov_base);
   3108       1.3      onoe 	} else {
   3109      1.28       jmc 		DPRINTFN(1, ("\n"));
   3110       1.3      onoe 		res.fp_hdr[3] = htonl(*(u_int32_t *)&sc->sc_csr[reg]);
   3111       1.3      onoe 		res.fp_iov[0].iov_base = &res.fp_hdr[3];
   3112       1.3      onoe 		res.fp_iov[0].iov_len = 4;
   3113       1.9      onoe 		res.fp_uio.uio_resid = 4;
   3114       1.9      onoe 		res.fp_uio.uio_iovcnt = 1;
   3115       1.3      onoe 		fwohci_atrs_output(sc, IEEE1394_RCODE_COMPLETE, pkt, &res);
   3116       1.3      onoe 		return -1;
   3117       1.3      onoe 	}
   3118       1.3      onoe 	return IEEE1394_RCODE_COMPLETE;
   3119       1.3      onoe }
   3120       1.3      onoe 
   3121       1.3      onoe /*
   3122       1.3      onoe  * Mapping between nodeid and unique ID (EUI-64).
   3123      1.24       jmc  *
   3124      1.24       jmc  * Track old mappings and simply update their devices with the new id's when
   3125      1.24       jmc  * they match an existing EUI. This allows proper renumeration of the bus.
   3126       1.3      onoe  */
   3127       1.3      onoe static void
   3128       1.3      onoe fwohci_uid_collect(struct fwohci_softc *sc)
   3129       1.3      onoe {
   3130       1.3      onoe 	int i;
   3131       1.3      onoe 	struct fwohci_uidtbl *fu;
   3132      1.24       jmc 	struct ieee1394_softc *iea;
   3133      1.24       jmc 
   3134      1.24       jmc 	LIST_FOREACH(iea, &sc->sc_nodelist, sc1394_node)
   3135      1.24       jmc 		iea->sc1394_node_id = 0xffff;
   3136       1.3      onoe 
   3137       1.3      onoe 	if (sc->sc_uidtbl != NULL)
   3138       1.3      onoe 		free(sc->sc_uidtbl, M_DEVBUF);
   3139      1.26     enami 	sc->sc_uidtbl = malloc(sizeof(*fu) * (sc->sc_rootid + 1), M_DEVBUF,
   3140      1.49   tsutsui 	    M_NOWAIT|M_ZERO);	/* XXX M_WAITOK requires locks */
   3141      1.36      onoe 	if (sc->sc_uidtbl == NULL)
   3142      1.36      onoe 		return;
   3143       1.3      onoe 
   3144       1.3      onoe 	for (i = 0, fu = sc->sc_uidtbl; i <= sc->sc_rootid; i++, fu++) {
   3145       1.3      onoe 		if (i == (sc->sc_nodeid & OHCI_NodeId_NodeNumber)) {
   3146       1.8      onoe 			memcpy(fu->fu_uid, sc->sc_sc1394.sc1394_guid, 8);
   3147       1.8      onoe 			fu->fu_valid = 3;
   3148      1.26     enami 
   3149      1.26     enami 			iea = (struct ieee1394_softc *)sc->sc_sc1394.sc1394_if;
   3150      1.26     enami 			if (iea) {
   3151      1.26     enami 				iea->sc1394_node_id = i;
   3152      1.28       jmc 				DPRINTF(("%s: Updating nodeid to %d\n",
   3153      1.28       jmc 				    iea->sc1394_dev.dv_xname,
   3154      1.28       jmc 				    iea->sc1394_node_id));
   3155      1.26     enami 			}
   3156      1.36      onoe 		} else {
   3157      1.36      onoe 			fu->fu_valid = 0;
   3158      1.36      onoe 			fwohci_uid_req(sc, i);
   3159       1.3      onoe 		}
   3160       1.3      onoe 	}
   3161      1.26     enami 	if (sc->sc_rootid == 0)
   3162      1.26     enami 		fwohci_check_nodes(sc);
   3163       1.3      onoe }
   3164       1.3      onoe 
   3165      1.36      onoe static void
   3166      1.36      onoe fwohci_uid_req(struct fwohci_softc *sc, int phyid)
   3167      1.36      onoe {
   3168      1.36      onoe 	struct fwohci_pkt pkt;
   3169      1.36      onoe 
   3170      1.36      onoe 	memset(&pkt, 0, sizeof(pkt));
   3171      1.36      onoe 	pkt.fp_tcode = IEEE1394_TCODE_READ_REQ_QUAD;
   3172      1.36      onoe 	pkt.fp_hlen = 12;
   3173      1.36      onoe 	pkt.fp_dlen = 0;
   3174      1.36      onoe 	pkt.fp_hdr[0] = 0x00000100 | (sc->sc_tlabel << 10) |
   3175      1.36      onoe 	    (pkt.fp_tcode << 4);
   3176      1.36      onoe 	pkt.fp_hdr[1] = ((0xffc0 | phyid) << 16) | CSR_BASE_HI;
   3177      1.36      onoe 	pkt.fp_hdr[2] = CSR_BASE_LO + CSR_CONFIG_ROM + 12;
   3178      1.36      onoe 	fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD, phyid,
   3179      1.67       jmc 	    sc->sc_tlabel, 0, fwohci_uid_input, (void *)0);
   3180      1.36      onoe 	sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f;
   3181      1.36      onoe 	fwohci_at_output(sc, sc->sc_ctx_atrq, &pkt);
   3182      1.36      onoe 
   3183      1.36      onoe 	pkt.fp_hdr[0] = 0x00000100 | (sc->sc_tlabel << 10) |
   3184      1.36      onoe 	    (pkt.fp_tcode << 4);
   3185      1.36      onoe 	pkt.fp_hdr[2] = CSR_BASE_LO + CSR_CONFIG_ROM + 16;
   3186      1.36      onoe 	fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD, phyid,
   3187      1.67       jmc 	    sc->sc_tlabel, 0, fwohci_uid_input, (void *)1);
   3188      1.36      onoe 	sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f;
   3189      1.36      onoe 	fwohci_at_output(sc, sc->sc_ctx_atrq, &pkt);
   3190      1.36      onoe }
   3191      1.36      onoe 
   3192       1.3      onoe static int
   3193       1.3      onoe fwohci_uid_input(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *res)
   3194       1.3      onoe {
   3195       1.8      onoe 	struct fwohci_uidtbl *fu;
   3196      1.24       jmc 	struct ieee1394_softc *iea;
   3197      1.26     enami 	struct ieee1394_attach_args fwa;
   3198      1.26     enami 	int i, n, done, rcode, found;
   3199      1.26     enami 
   3200      1.26     enami 	found = 0;
   3201      1.24       jmc 
   3202      1.26     enami 	n = (res->fp_hdr[1] >> 16) & OHCI_NodeId_NodeNumber;
   3203       1.8      onoe 	rcode = (res->fp_hdr[1] & 0x0000f000) >> 12;
   3204       1.8      onoe 	if (rcode != IEEE1394_RCODE_COMPLETE ||
   3205       1.8      onoe 	    sc->sc_uidtbl == NULL ||
   3206       1.8      onoe 	    n > sc->sc_rootid)
   3207       1.8      onoe 		return 0;
   3208       1.8      onoe 	fu = &sc->sc_uidtbl[n];
   3209       1.8      onoe 	if (arg == 0) {
   3210       1.8      onoe 		memcpy(fu->fu_uid, res->fp_iov[0].iov_base, 4);
   3211       1.8      onoe 		fu->fu_valid |= 0x1;
   3212       1.8      onoe 	} else {
   3213       1.8      onoe 		memcpy(fu->fu_uid + 4, res->fp_iov[0].iov_base, 4);
   3214       1.8      onoe 		fu->fu_valid |= 0x2;
   3215       1.8      onoe 	}
   3216       1.3      onoe #ifdef FW_DEBUG
   3217      1.28       jmc 	if (fu->fu_valid == 0x3)
   3218      1.28       jmc 		DPRINTFN(1, ("fwohci_uid_input: "
   3219       1.8      onoe 		    "Node %d, UID %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", n,
   3220       1.8      onoe 		    fu->fu_uid[0], fu->fu_uid[1], fu->fu_uid[2], fu->fu_uid[3],
   3221      1.28       jmc 		    fu->fu_uid[4], fu->fu_uid[5], fu->fu_uid[6], fu->fu_uid[7]));
   3222       1.3      onoe #endif
   3223      1.24       jmc 	if (fu->fu_valid == 0x3) {
   3224      1.26     enami 		LIST_FOREACH(iea, &sc->sc_nodelist, sc1394_node)
   3225      1.26     enami 			if (memcmp(iea->sc1394_guid, fu->fu_uid, 8) == 0) {
   3226      1.24       jmc 				found = 1;
   3227      1.24       jmc 				iea->sc1394_node_id = n;
   3228      1.28       jmc 				DPRINTF(("%s: Updating nodeid to %d\n",
   3229      1.28       jmc 				    iea->sc1394_dev.dv_xname,
   3230      1.28       jmc 				    iea->sc1394_node_id));
   3231      1.58       jmc 				if (iea->sc1394_callback.sc1394_reset)
   3232      1.58       jmc 					iea->sc1394_callback.sc1394_reset(iea,
   3233      1.58       jmc 					    iea->sc1394_callback.sc1394_resetarg);
   3234      1.24       jmc 				break;
   3235      1.24       jmc 			}
   3236      1.24       jmc 		if (!found) {
   3237      1.26     enami 			strcpy(fwa.name, "fwnode");
   3238      1.26     enami 			memcpy(fwa.uid, fu->fu_uid, 8);
   3239      1.24       jmc 			fwa.nodeid = n;
   3240      1.26     enami 			iea = (struct ieee1394_softc *)
   3241  1.78.2.3     skrll 			    config_found_sm_loc(&sc->sc_sc1394.sc1394_dev,
   3242  1.78.2.3     skrll 				"fwbus", NULL, &fwa,
   3243  1.78.2.3     skrll 				fwohci_print, fwohci_submatch);
   3244      1.27     enami 			if (iea != NULL)
   3245      1.27     enami 				LIST_INSERT_HEAD(&sc->sc_nodelist, iea,
   3246      1.27     enami 				    sc1394_node);
   3247      1.24       jmc 		}
   3248      1.24       jmc 	}
   3249      1.26     enami 	done = 1;
   3250      1.26     enami 
   3251      1.26     enami 	for (i = 0; i < sc->sc_rootid + 1; i++) {
   3252      1.26     enami 		fu = &sc->sc_uidtbl[i];
   3253      1.26     enami 		if (fu->fu_valid != 0x3) {
   3254      1.26     enami 			done = 0;
   3255      1.26     enami 			break;
   3256      1.26     enami 		}
   3257      1.26     enami 	}
   3258      1.26     enami 	if (done)
   3259      1.26     enami 		fwohci_check_nodes(sc);
   3260      1.26     enami 
   3261      1.26     enami 	return 0;
   3262      1.24       jmc }
   3263      1.24       jmc 
   3264      1.24       jmc static void
   3265      1.24       jmc fwohci_check_nodes(struct fwohci_softc *sc)
   3266      1.24       jmc {
   3267      1.26     enami 	struct device *detach = NULL;
   3268      1.26     enami 	struct ieee1394_softc *iea;
   3269      1.26     enami 
   3270      1.26     enami 	LIST_FOREACH(iea, &sc->sc_nodelist, sc1394_node) {
   3271      1.28       jmc 
   3272      1.26     enami 		/*
   3273      1.26     enami 		 * Have to defer detachment until the next
   3274      1.26     enami 		 * loop iteration since config_detach
   3275      1.26     enami 		 * free's the softc and the loop iterator
   3276      1.26     enami 		 * needs data from the softc to move
   3277      1.26     enami 		 * forward.
   3278      1.26     enami 		 */
   3279      1.26     enami 
   3280      1.26     enami 		if (detach) {
   3281      1.26     enami 			config_detach(detach, 0);
   3282      1.26     enami 			detach = NULL;
   3283      1.26     enami 		}
   3284      1.26     enami 		if (iea->sc1394_node_id == 0xffff) {
   3285      1.26     enami 			detach = (struct device *)iea;
   3286      1.26     enami 			LIST_REMOVE(iea, sc1394_node);
   3287      1.26     enami 		}
   3288      1.26     enami 	}
   3289      1.26     enami 	if (detach)
   3290      1.26     enami 		config_detach(detach, 0);
   3291       1.3      onoe }
   3292       1.3      onoe 
   3293       1.3      onoe static int
   3294       1.8      onoe fwohci_uid_lookup(struct fwohci_softc *sc, const u_int8_t *uid)
   3295       1.3      onoe {
   3296       1.3      onoe 	struct fwohci_uidtbl *fu;
   3297       1.3      onoe 	int n;
   3298       1.3      onoe 	static const u_int8_t bcast[] =
   3299       1.3      onoe 	    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
   3300       1.3      onoe 
   3301      1.26     enami 	fu = sc->sc_uidtbl;
   3302       1.3      onoe 	if (fu == NULL) {
   3303       1.8      onoe 		if (memcmp(uid, bcast, sizeof(bcast)) == 0)
   3304       1.8      onoe 			return IEEE1394_BCAST_PHY_ID;
   3305       1.3      onoe 		fwohci_uid_collect(sc); /* try to get */
   3306       1.3      onoe 		return -1;
   3307       1.3      onoe 	}
   3308      1.36      onoe 	for (n = 0; n <= sc->sc_rootid; n++, fu++) {
   3309       1.8      onoe 		if (fu->fu_valid == 0x3 && memcmp(fu->fu_uid, uid, 8) == 0)
   3310      1.36      onoe 			return n;
   3311      1.36      onoe 	}
   3312      1.36      onoe 	if (memcmp(uid, bcast, sizeof(bcast)) == 0)
   3313      1.36      onoe 		return IEEE1394_BCAST_PHY_ID;
   3314      1.36      onoe 	for (n = 0, fu = sc->sc_uidtbl; n <= sc->sc_rootid; n++, fu++) {
   3315      1.36      onoe 		if (fu->fu_valid != 0x3) {
   3316      1.36      onoe 			/*
   3317      1.36      onoe 			 * XXX: need timer before retransmission
   3318      1.36      onoe 			 */
   3319      1.36      onoe 			fwohci_uid_req(sc, n);
   3320      1.36      onoe 		}
   3321       1.3      onoe 	}
   3322      1.36      onoe 	return -1;
   3323       1.3      onoe }
   3324       1.3      onoe 
   3325       1.3      onoe /*
   3326       1.3      onoe  * functions to support network interface
   3327       1.3      onoe  */
   3328       1.3      onoe static int
   3329       1.3      onoe fwohci_if_inreg(struct device *self, u_int32_t offhi, u_int32_t offlo,
   3330       1.3      onoe     void (*handler)(struct device *, struct mbuf *))
   3331       1.3      onoe {
   3332       1.3      onoe 	struct fwohci_softc *sc = (struct fwohci_softc *)self;
   3333      1.26     enami 
   3334      1.67       jmc 	fwohci_handler_set(sc, IEEE1394_TCODE_WRITE_REQ_BLOCK, offhi, offlo, 0,
   3335      1.38      onoe 	    handler ? fwohci_if_input : NULL, handler);
   3336      1.26     enami 	fwohci_handler_set(sc, IEEE1394_TCODE_STREAM_DATA,
   3337      1.53       jmc 	    (sc->sc_csr[CSR_SB_BROADCAST_CHANNEL] & IEEE1394_ISOCH_MASK) |
   3338      1.53       jmc 	    OHCI_ASYNC_STREAM,
   3339      1.67       jmc 	    1 << IEEE1394_TAG_GASP, 0,
   3340      1.62      haya 	    handler ? fwohci_if_input : NULL, handler);
   3341       1.3      onoe 	return 0;
   3342       1.3      onoe }
   3343       1.3      onoe 
   3344       1.3      onoe static int
   3345       1.3      onoe fwohci_if_input(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt)
   3346       1.3      onoe {
   3347       1.4  jdolecek 	int n, len;
   3348       1.3      onoe 	struct mbuf *m;
   3349       1.3      onoe 	struct iovec *iov;
   3350       1.3      onoe 	void (*handler)(struct device *, struct mbuf *) = arg;
   3351       1.3      onoe 
   3352       1.3      onoe #ifdef FW_DEBUG
   3353      1.28       jmc 	int i;
   3354      1.28       jmc 	DPRINTFN(1, ("fwohci_if_input: tcode=0x%x, dlen=%d", pkt->fp_tcode,
   3355      1.28       jmc 	    pkt->fp_dlen));
   3356      1.28       jmc 	for (i = 0; i < pkt->fp_hlen/4; i++)
   3357      1.37      onoe 		DPRINTFN(2, ("%s%08x", i?" ":"\n    ", pkt->fp_hdr[i]));
   3358      1.28       jmc 	DPRINTFN(2, ("$"));
   3359      1.28       jmc 	for (n = 0, len = pkt->fp_dlen; len > 0; len -= i, n++){
   3360      1.28       jmc 		iov = &pkt->fp_iov[n];
   3361      1.28       jmc 		for (i = 0; i < iov->iov_len; i++)
   3362      1.37      onoe 			DPRINTFN(2, ("%s%02x", (i%32)?((i%4)?"":" "):"\n    ",
   3363      1.28       jmc 			    ((u_int8_t *)iov->iov_base)[i]));
   3364      1.28       jmc 		DPRINTFN(2, ("$"));
   3365       1.5      matt 	}
   3366      1.28       jmc 	DPRINTFN(1, ("\n"));
   3367       1.3      onoe #endif /* FW_DEBUG */
   3368       1.3      onoe 	len = pkt->fp_dlen;
   3369       1.3      onoe 	MGETHDR(m, M_DONTWAIT, MT_DATA);
   3370       1.3      onoe 	if (m == NULL)
   3371       1.3      onoe 		return IEEE1394_RCODE_COMPLETE;
   3372      1.15      onoe 	m->m_len = 16;
   3373       1.8      onoe 	if (len + m->m_len > MHLEN) {
   3374       1.3      onoe 		MCLGET(m, M_DONTWAIT);
   3375       1.3      onoe 		if ((m->m_flags & M_EXT) == 0) {
   3376       1.3      onoe 			m_freem(m);
   3377       1.3      onoe 			return IEEE1394_RCODE_COMPLETE;
   3378       1.3      onoe 		}
   3379       1.3      onoe 	}
   3380       1.8      onoe 	n = (pkt->fp_hdr[1] >> 16) & OHCI_NodeId_NodeNumber;
   3381      1.26     enami 	if (sc->sc_uidtbl == NULL || n > sc->sc_rootid ||
   3382       1.8      onoe 	    sc->sc_uidtbl[n].fu_valid != 0x3) {
   3383       1.8      onoe 		printf("%s: packet from unknown node: phy id %d\n",
   3384       1.8      onoe 		    sc->sc_sc1394.sc1394_dev.dv_xname, n);
   3385      1.26     enami 		m_freem(m);
   3386      1.36      onoe 		fwohci_uid_req(sc, n);
   3387       1.8      onoe 		return IEEE1394_RCODE_COMPLETE;
   3388       1.8      onoe 	}
   3389       1.8      onoe 	memcpy(mtod(m, caddr_t), sc->sc_uidtbl[n].fu_uid, 8);
   3390       1.8      onoe 	if (pkt->fp_tcode == IEEE1394_TCODE_STREAM_DATA) {
   3391       1.8      onoe 		m->m_flags |= M_BCAST;
   3392       1.8      onoe 		mtod(m, u_int32_t *)[2] = mtod(m, u_int32_t *)[3] = 0;
   3393       1.8      onoe 	} else {
   3394       1.8      onoe 		mtod(m, u_int32_t *)[2] = htonl(pkt->fp_hdr[1]);
   3395       1.8      onoe 		mtod(m, u_int32_t *)[3] = htonl(pkt->fp_hdr[2]);
   3396       1.8      onoe 	}
   3397       1.8      onoe 	mtod(m, u_int8_t *)[8] = n;	/*XXX: node id for debug */
   3398       1.8      onoe 	mtod(m, u_int8_t *)[9] =
   3399       1.8      onoe 	    (*pkt->fp_trail >> (16 + OHCI_CTXCTL_SPD_BITPOS)) &
   3400       1.8      onoe 	    ((1 << OHCI_CTXCTL_SPD_BITLEN) - 1);
   3401       1.8      onoe 
   3402       1.8      onoe 	m->m_pkthdr.rcvif = NULL;	/* set in child */
   3403       1.8      onoe 	m->m_pkthdr.len = len + m->m_len;
   3404       1.3      onoe 	/*
   3405       1.3      onoe 	 * We may use receive buffer by external mbuf instead of copy here.
   3406       1.3      onoe 	 * But asynchronous receive buffer must be operate in buffer fill
   3407       1.3      onoe 	 * mode, so that each receive buffer will shared by multiple mbufs.
   3408       1.3      onoe 	 * If upper layer doesn't free mbuf soon, e.g. application program
   3409       1.3      onoe 	 * is suspended, buffer must be reallocated.
   3410       1.3      onoe 	 * Isochronous buffer must be operate in packet buffer mode, and
   3411       1.3      onoe 	 * it is easy to map receive buffer to external mbuf.  But it is
   3412       1.3      onoe 	 * used for broadcast/multicast only, and is expected not so
   3413       1.3      onoe 	 * performance sensitive for now.
   3414       1.3      onoe 	 * XXX: The performance may be important for multicast case,
   3415       1.3      onoe 	 * so we should revisit here later.
   3416       1.3      onoe 	 *						-- onoe
   3417       1.3      onoe 	 */
   3418       1.3      onoe 	n = 0;
   3419       1.9      onoe 	iov = pkt->fp_uio.uio_iov;
   3420       1.3      onoe 	while (len > 0) {
   3421       1.3      onoe 		memcpy(mtod(m, caddr_t) + m->m_len, iov->iov_base,
   3422       1.3      onoe 		    iov->iov_len);
   3423      1.26     enami 		m->m_len += iov->iov_len;
   3424      1.26     enami 		len -= iov->iov_len;
   3425       1.3      onoe 		iov++;
   3426       1.3      onoe 	}
   3427       1.3      onoe 	(*handler)(sc->sc_sc1394.sc1394_if, m);
   3428       1.3      onoe 	return IEEE1394_RCODE_COMPLETE;
   3429       1.3      onoe }
   3430      1.40      haya 
   3431      1.40      haya static int
   3432      1.40      haya fwohci_if_input_iso(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt)
   3433      1.40      haya {
   3434      1.40      haya 	int n, len;
   3435      1.40      haya 	int chan, tag;
   3436      1.40      haya 	struct mbuf *m;
   3437      1.40      haya 	struct iovec *iov;
   3438      1.40      haya 	void (*handler)(struct device *, struct mbuf *) = arg;
   3439      1.41      onoe #ifdef FW_DEBUG
   3440      1.41      onoe 	int i;
   3441      1.41      onoe #endif
   3442      1.40      haya 
   3443      1.40      haya 	chan = (pkt->fp_hdr[0] & 0x00003f00) >> 8;
   3444      1.40      haya 	tag  = (pkt->fp_hdr[0] & 0x0000c000) >> 14;
   3445      1.40      haya #ifdef FW_DEBUG
   3446      1.41      onoe 	DPRINTFN(1, ("fwohci_if_input_iso: "
   3447      1.41      onoe 	    "tcode=0x%x, chan=%d, tag=%x, dlen=%d",
   3448      1.41      onoe 	    pkt->fp_tcode, chan, tag, pkt->fp_dlen));
   3449      1.41      onoe 	for (i = 0; i < pkt->fp_hlen/4; i++)
   3450      1.41      onoe 		DPRINTFN(2, ("%s%08x", i?" ":"\n\t", pkt->fp_hdr[i]));
   3451      1.41      onoe 	DPRINTFN(2, ("$"));
   3452      1.41      onoe 	for (n = 0, len = pkt->fp_dlen; len > 0; len -= i, n++){
   3453      1.41      onoe 		iov = &pkt->fp_iov[n];
   3454      1.41      onoe 		for (i = 0; i < iov->iov_len; i++)
   3455      1.41      onoe 			DPRINTFN(2, ("%s%02x",
   3456      1.41      onoe 			    (i%32)?((i%4)?"":" "):"\n\t",
   3457      1.41      onoe 			    ((u_int8_t *)iov->iov_base)[i]));
   3458      1.41      onoe 		DPRINTFN(2, ("$"));
   3459      1.40      haya 	}
   3460      1.41      onoe 	DPRINTFN(2, ("\n"));
   3461      1.40      haya #endif /* FW_DEBUG */
   3462      1.40      haya 	len = pkt->fp_dlen;
   3463      1.40      haya 	MGETHDR(m, M_DONTWAIT, MT_DATA);
   3464      1.40      haya 	if (m == NULL)
   3465      1.40      haya 		return IEEE1394_RCODE_COMPLETE;
   3466      1.40      haya 	m->m_len = 16;
   3467      1.40      haya 	if (m->m_len + len > MHLEN) {
   3468      1.40      haya 		MCLGET(m, M_DONTWAIT);
   3469      1.40      haya 		if ((m->m_flags & M_EXT) == 0) {
   3470      1.40      haya 			m_freem(m);
   3471      1.40      haya 			return IEEE1394_RCODE_COMPLETE;
   3472      1.40      haya 		}
   3473      1.40      haya 	}
   3474      1.40      haya 
   3475      1.40      haya 	m->m_flags |= M_BCAST;
   3476      1.40      haya 
   3477      1.40      haya 	if (tag == IEEE1394_TAG_GASP) {
   3478      1.40      haya 		n = (pkt->fp_hdr[1] >> 16) & OHCI_NodeId_NodeNumber;
   3479      1.40      haya 		if (sc->sc_uidtbl == NULL || n > sc->sc_rootid ||
   3480      1.40      haya 		    sc->sc_uidtbl[n].fu_valid != 0x3) {
   3481      1.40      haya 			printf("%s: packet from unknown node: phy id %d\n",
   3482      1.40      haya 			    sc->sc_sc1394.sc1394_dev.dv_xname, n);
   3483      1.40      haya 			m_freem(m);
   3484      1.40      haya 			return IEEE1394_RCODE_COMPLETE;
   3485      1.40      haya 		}
   3486      1.40      haya 		memcpy(mtod(m, caddr_t), sc->sc_uidtbl[n].fu_uid, 8);
   3487      1.40      haya 		mtod(m, u_int32_t *)[2] = htonl(pkt->fp_hdr[1]);
   3488      1.40      haya 		mtod(m, u_int32_t *)[3] = htonl(pkt->fp_hdr[2]);
   3489      1.40      haya 		mtod(m, u_int8_t *)[8] = n;	/*XXX: node id for debug */
   3490      1.40      haya 		mtod(m, u_int8_t *)[9] =
   3491      1.40      haya 		    (*pkt->fp_trail >> (16 + OHCI_CTXCTL_SPD_BITPOS)) &
   3492      1.40      haya 		    ((1 << OHCI_CTXCTL_SPD_BITLEN) - 1);
   3493      1.40      haya 	}
   3494      1.40      haya 	mtod(m, u_int8_t *)[14] = chan;
   3495      1.40      haya 	mtod(m, u_int8_t *)[15] = tag;
   3496      1.40      haya 
   3497      1.40      haya 
   3498      1.40      haya 	m->m_pkthdr.rcvif = NULL;	/* set in child */
   3499      1.40      haya 	m->m_pkthdr.len = len + m->m_len;
   3500      1.40      haya 	/*
   3501      1.40      haya 	 * We may use receive buffer by external mbuf instead of copy here.
   3502      1.40      haya 	 * But asynchronous receive buffer must be operate in buffer fill
   3503      1.40      haya 	 * mode, so that each receive buffer will shared by multiple mbufs.
   3504      1.40      haya 	 * If upper layer doesn't free mbuf soon, e.g. application program
   3505      1.40      haya 	 * is suspended, buffer must be reallocated.
   3506      1.40      haya 	 * Isochronous buffer must be operate in packet buffer mode, and
   3507      1.40      haya 	 * it is easy to map receive buffer to external mbuf.  But it is
   3508      1.40      haya 	 * used for broadcast/multicast only, and is expected not so
   3509      1.40      haya 	 * performance sensitive for now.
   3510      1.40      haya 	 * XXX: The performance may be important for multicast case,
   3511      1.40      haya 	 * so we should revisit here later.
   3512      1.40      haya 	 *						-- onoe
   3513      1.40      haya 	 */
   3514      1.40      haya 	n = 0;
   3515      1.40      haya 	iov = pkt->fp_uio.uio_iov;
   3516      1.40      haya 	while (len > 0) {
   3517      1.40      haya 		memcpy(mtod(m, caddr_t) + m->m_len, iov->iov_base,
   3518      1.40      haya 		    iov->iov_len);
   3519      1.40      haya 	        m->m_len += iov->iov_len;
   3520      1.40      haya 	        len -= iov->iov_len;
   3521      1.40      haya 		iov++;
   3522      1.40      haya 	}
   3523      1.40      haya 	(*handler)(sc->sc_sc1394.sc1394_if, m);
   3524      1.40      haya 	return IEEE1394_RCODE_COMPLETE;
   3525      1.40      haya }
   3526      1.40      haya 
   3527      1.40      haya 
   3528       1.3      onoe 
   3529       1.3      onoe static int
   3530       1.3      onoe fwohci_if_output(struct device *self, struct mbuf *m0,
   3531       1.3      onoe     void (*callback)(struct device *, struct mbuf *))
   3532       1.3      onoe {
   3533      1.26     enami 	struct fwohci_softc *sc = (struct fwohci_softc *)self;
   3534       1.3      onoe 	struct fwohci_pkt pkt;
   3535       1.3      onoe 	u_int8_t *p;
   3536  1.78.2.2     skrll 	int n = 0, error, spd, hdrlen, maxrec; /* XXX: gcc */
   3537      1.28       jmc #ifdef FW_DEBUG
   3538      1.28       jmc 	struct mbuf *m;
   3539      1.28       jmc #endif
   3540       1.8      onoe 
   3541       1.8      onoe 	p = mtod(m0, u_int8_t *);
   3542       1.9      onoe 	if (m0->m_flags & (M_BCAST | M_MCAST)) {
   3543       1.8      onoe 		spd = IEEE1394_SPD_S100;	/*XXX*/
   3544       1.8      onoe 		maxrec = 512;			/*XXX*/
   3545       1.8      onoe 		hdrlen = 8;
   3546       1.8      onoe 	} else {
   3547       1.8      onoe 		n = fwohci_uid_lookup(sc, p);
   3548       1.8      onoe 		if (n < 0) {
   3549       1.8      onoe 			printf("%s: nodeid unknown:"
   3550       1.8      onoe 			    " %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
   3551       1.8      onoe 			    sc->sc_sc1394.sc1394_dev.dv_xname,
   3552       1.8      onoe 			    p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
   3553       1.8      onoe 			error = EHOSTUNREACH;
   3554       1.8      onoe 			goto end;
   3555       1.8      onoe 		}
   3556       1.8      onoe 		if (n == IEEE1394_BCAST_PHY_ID) {
   3557      1.26     enami 			printf("%s: broadcast with !M_MCAST\n",
   3558       1.8      onoe 			    sc->sc_sc1394.sc1394_dev.dv_xname);
   3559       1.8      onoe #ifdef FW_DEBUG
   3560      1.28       jmc 			DPRINTFN(2, ("packet:"));
   3561      1.28       jmc 			for (m = m0; m != NULL; m = m->m_next) {
   3562      1.28       jmc 				for (n = 0; n < m->m_len; n++)
   3563      1.28       jmc 					DPRINTFN(2, ("%s%02x", (n%32)?
   3564      1.37      onoe 					    ((n%4)?"":" "):"\n    ",
   3565      1.28       jmc 					    mtod(m, u_int8_t *)[n]));
   3566      1.28       jmc 				DPRINTFN(2, ("$"));
   3567       1.8      onoe 			}
   3568      1.28       jmc 			DPRINTFN(2, ("\n"));
   3569       1.8      onoe #endif
   3570       1.8      onoe 			error = EHOSTUNREACH;
   3571       1.8      onoe 			goto end;
   3572       1.8      onoe 		}
   3573       1.8      onoe 		maxrec = 2 << p[8];
   3574       1.8      onoe 		spd = p[9];
   3575       1.8      onoe 		hdrlen = 0;
   3576       1.8      onoe 	}
   3577      1.26     enami 	if (spd > sc->sc_sc1394.sc1394_link_speed) {
   3578      1.28       jmc 		DPRINTF(("fwohci_if_output: spd (%d) is faster than %d\n",
   3579      1.28       jmc 		    spd, sc->sc_sc1394.sc1394_link_speed));
   3580       1.8      onoe 		spd = sc->sc_sc1394.sc1394_link_speed;
   3581       1.8      onoe 	}
   3582      1.26     enami 	if (maxrec > (512 << spd)) {
   3583      1.28       jmc 		DPRINTF(("fwohci_if_output: maxrec (%d) is larger for spd (%d)"
   3584      1.28       jmc 		    "\n", maxrec, spd));
   3585       1.8      onoe 		maxrec = 512 << spd;
   3586       1.8      onoe 	}
   3587       1.8      onoe 	while (maxrec > sc->sc_sc1394.sc1394_max_receive) {
   3588      1.28       jmc 		DPRINTF(("fwohci_if_output: maxrec (%d) is larger than"
   3589      1.28       jmc 		    " %d\n", maxrec, sc->sc_sc1394.sc1394_max_receive));
   3590       1.8      onoe 		maxrec >>= 1;
   3591       1.8      onoe 	}
   3592       1.8      onoe 	if (maxrec < 512) {
   3593      1.28       jmc 		DPRINTF(("fwohci_if_output: maxrec (%d) is smaller than "
   3594      1.28       jmc 		    "minimum\n", maxrec));
   3595       1.8      onoe 		maxrec = 512;
   3596       1.8      onoe 	}
   3597       1.8      onoe 
   3598       1.8      onoe 	m_adj(m0, 16 - hdrlen);
   3599       1.8      onoe 	if (m0->m_pkthdr.len > maxrec) {
   3600      1.28       jmc 		DPRINTF(("fwohci_if_output: packet too big: hdr %d, pktlen "
   3601      1.28       jmc 		    "%d, maxrec %d\n", hdrlen, m0->m_pkthdr.len, maxrec));
   3602       1.8      onoe 		error = E2BIG;	/*XXX*/
   3603       1.8      onoe 		goto end;
   3604       1.8      onoe 	}
   3605       1.3      onoe 
   3606       1.3      onoe 	memset(&pkt, 0, sizeof(pkt));
   3607       1.9      onoe 	pkt.fp_uio.uio_iov = pkt.fp_iov;
   3608       1.9      onoe 	pkt.fp_uio.uio_segflg = UIO_SYSSPACE;
   3609       1.9      onoe 	pkt.fp_uio.uio_rw = UIO_WRITE;
   3610       1.9      onoe 	if (m0->m_flags & (M_BCAST | M_MCAST)) {
   3611       1.3      onoe 		/* construct GASP header */
   3612       1.3      onoe 		p = mtod(m0, u_int8_t *);
   3613       1.3      onoe 		p[0] = sc->sc_nodeid >> 8;
   3614       1.3      onoe 		p[1] = sc->sc_nodeid & 0xff;
   3615       1.3      onoe 		p[2] = 0x00; p[3] = 0x00; p[4] = 0x5e;
   3616       1.3      onoe 		p[5] = 0x00; p[6] = 0x00; p[7] = 0x01;
   3617       1.3      onoe 		pkt.fp_tcode = IEEE1394_TCODE_STREAM_DATA;
   3618       1.3      onoe 		pkt.fp_hlen = 8;
   3619       1.8      onoe 		pkt.fp_hdr[0] = (spd << 16) | (IEEE1394_TAG_GASP << 14) |
   3620       1.3      onoe 		    ((sc->sc_csr[CSR_SB_BROADCAST_CHANNEL] &
   3621       1.3      onoe 		    OHCI_NodeId_NodeNumber) << 8);
   3622       1.3      onoe 		pkt.fp_hdr[1] = m0->m_pkthdr.len << 16;
   3623       1.3      onoe 	} else {
   3624       1.3      onoe 		pkt.fp_tcode = IEEE1394_TCODE_WRITE_REQ_BLOCK;
   3625       1.3      onoe 		pkt.fp_hlen = 16;
   3626       1.3      onoe 		pkt.fp_hdr[0] = 0x00800100 | (sc->sc_tlabel << 10) |
   3627       1.8      onoe 		    (spd << 16);
   3628       1.3      onoe 		pkt.fp_hdr[1] =
   3629       1.3      onoe 		    (((sc->sc_nodeid & OHCI_NodeId_BusNumber) | n) << 16) |
   3630       1.3      onoe 		    (p[10] << 8) | p[11];
   3631       1.3      onoe 		pkt.fp_hdr[2] = (p[12]<<24) | (p[13]<<16) | (p[14]<<8) | p[15];
   3632       1.3      onoe 		pkt.fp_hdr[3] = m0->m_pkthdr.len << 16;
   3633       1.3      onoe 		sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f;
   3634       1.3      onoe 	}
   3635       1.3      onoe 	pkt.fp_hdr[0] |= (pkt.fp_tcode << 4);
   3636       1.3      onoe 	pkt.fp_dlen = m0->m_pkthdr.len;
   3637       1.3      onoe 	pkt.fp_m = m0;
   3638       1.3      onoe 	pkt.fp_callback = callback;
   3639       1.3      onoe 	error = fwohci_at_output(sc, sc->sc_ctx_atrq, &pkt);
   3640       1.9      onoe 	m0 = pkt.fp_m;
   3641       1.3      onoe   end:
   3642      1.15      onoe 	if (m0 != NULL) {
   3643       1.3      onoe 		if (callback)
   3644       1.3      onoe 			(*callback)(sc->sc_sc1394.sc1394_if, m0);
   3645       1.3      onoe 		else
   3646       1.3      onoe 			m_freem(m0);
   3647       1.3      onoe 	}
   3648       1.3      onoe 	return error;
   3649      1.24       jmc }
   3650      1.24       jmc 
   3651      1.24       jmc /*
   3652      1.24       jmc  * High level routines to provide abstraction to attaching layers to
   3653      1.24       jmc  * send/receive data.
   3654      1.24       jmc  */
   3655      1.24       jmc 
   3656      1.31       jmc /*
   3657      1.31       jmc  * These break down into 4 routines as follows:
   3658      1.31       jmc  *
   3659      1.31       jmc  * int fwohci_read(struct ieee1394_abuf *)
   3660      1.31       jmc  *
   3661      1.31       jmc  * This routine will attempt to read a region from the requested node.
   3662      1.31       jmc  * A callback must be provided which will be called when either the completed
   3663      1.31       jmc  * read is done or an unrecoverable error occurs. This is mainly a convenience
   3664      1.54       jmc  * routine since it will encapsulate retrying a region as quadlet vs. block
   3665      1.54       jmc  * reads and recombining all the returned data. This could also be done with a
   3666      1.54       jmc  * series of write/inreg's for each packet sent.
   3667      1.31       jmc  *
   3668      1.31       jmc  * int fwohci_write(struct ieee1394_abuf *)
   3669      1.31       jmc  *
   3670      1.31       jmc  * The work horse main entry point for putting packets on the bus. This is the
   3671      1.31       jmc  * generalized interface for fwnode/etc code to put packets out onto the bus.
   3672      1.54       jmc  * It accepts all standard ieee1394 tcodes (XXX: only a few today) and
   3673      1.54       jmc  * optionally will callback via a func pointer to the calling code with the
   3674      1.54       jmc  * resulting ACK code from the packet. If the ACK code is to be ignored (i.e.
   3675      1.54       jmc  * no cb) then the write routine will take care of free'ing the abuf since the
   3676      1.54       jmc  * fwnode/etc code won't have any knowledge of when to do this. This allows for
   3677      1.54       jmc  * simple one-off packets to be sent from the upper-level code without worrying
   3678      1.54       jmc  * about a callback for cleanup.
   3679      1.31       jmc  *
   3680      1.31       jmc  * int fwohci_inreg(struct ieee1394_abuf *, int)
   3681      1.31       jmc  *
   3682      1.31       jmc  * This is very simple. It evals the abuf passed in and registers an internal
   3683      1.31       jmc  * handler as the callback for packets received for that operation.
   3684      1.31       jmc  * The integer argument specifies whether on a block read/write operation to
   3685      1.31       jmc  * allow sub-regions to be read/written (in block form) as well.
   3686      1.31       jmc  *
   3687      1.31       jmc  * XXX: This whole structure needs to be redone as a list of regions and
   3688      1.31       jmc  * operations allowed on those regions.
   3689      1.31       jmc  *
   3690      1.31       jmc  * int fwohci_unreg(struct ieee1394_abuf *, int)
   3691      1.31       jmc  *
   3692      1.31       jmc  * This simply unregisters the respective callback done via inreg for items
   3693      1.31       jmc  * which only need to register an area for a one-time operation (like a status
   3694      1.31       jmc  * buffer a remote node will write to when the current operation is done). The
   3695      1.31       jmc  * int argument specifies the same behavior as inreg, except in reverse (i.e.
   3696      1.31       jmc  * it unregisters).
   3697      1.31       jmc  */
   3698      1.31       jmc 
   3699      1.24       jmc static int
   3700      1.29       jmc fwohci_read(struct ieee1394_abuf *ab)
   3701      1.24       jmc {
   3702      1.26     enami 	struct fwohci_pkt pkt;
   3703      1.29       jmc 	struct ieee1394_softc *sc = ab->ab_req;
   3704      1.26     enami 	struct fwohci_softc *psc =
   3705      1.26     enami 	    (struct fwohci_softc *)sc->sc1394_dev.dv_parent;
   3706      1.31       jmc 	struct fwohci_cb *fcb;
   3707      1.26     enami 	u_int32_t high, lo;
   3708      1.26     enami 	int rv, tcode;
   3709      1.26     enami 
   3710      1.31       jmc 	/* Have to have a callback when reading. */
   3711      1.31       jmc 	if (ab->ab_cb == NULL)
   3712      1.31       jmc 		return -1;
   3713      1.31       jmc 
   3714      1.31       jmc 	fcb = malloc(sizeof(struct fwohci_cb), M_DEVBUF, M_WAITOK);
   3715      1.31       jmc 	fcb->ab = ab;
   3716      1.31       jmc 	fcb->count = 0;
   3717      1.31       jmc 	fcb->abuf_valid = 1;
   3718      1.31       jmc 
   3719      1.59   thorpej 	high = ((ab->ab_addr & 0x0000ffff00000000ULL) >> 32);
   3720      1.59   thorpej 	lo = (ab->ab_addr & 0x00000000ffffffffULL);
   3721      1.26     enami 
   3722      1.24       jmc 	memset(&pkt, 0, sizeof(pkt));
   3723      1.29       jmc 	pkt.fp_hdr[1] = ((0xffc0 | ab->ab_req->sc1394_node_id) << 16) | high;
   3724      1.26     enami 	pkt.fp_hdr[2] = lo;
   3725      1.26     enami 	pkt.fp_dlen = 0;
   3726      1.26     enami 
   3727      1.26     enami 	if (ab->ab_length == 4) {
   3728      1.26     enami 		pkt.fp_tcode = IEEE1394_TCODE_READ_REQ_QUAD;
   3729      1.26     enami 		tcode = IEEE1394_TCODE_READ_RESP_QUAD;
   3730      1.26     enami 		pkt.fp_hlen = 12;
   3731      1.26     enami 	} else {
   3732      1.26     enami 		pkt.fp_tcode = IEEE1394_TCODE_READ_REQ_BLOCK;
   3733      1.26     enami 		pkt.fp_hlen = 16;
   3734      1.26     enami 		tcode = IEEE1394_TCODE_READ_RESP_BLOCK;
   3735      1.26     enami 		pkt.fp_hdr[3] = (ab->ab_length << 16);
   3736      1.26     enami 	}
   3737      1.26     enami 	pkt.fp_hdr[0] = 0x00000100 | (sc->sc1394_link_speed << 16) |
   3738      1.26     enami 	    (psc->sc_tlabel << 10) | (pkt.fp_tcode << 4);
   3739      1.26     enami 
   3740      1.31       jmc 	pkt.fp_statusarg = fcb;
   3741      1.31       jmc 	pkt.fp_statuscb = fwohci_read_resp;
   3742      1.29       jmc 
   3743      1.29       jmc 	rv = fwohci_handler_set(psc, tcode, ab->ab_req->sc1394_node_id,
   3744      1.67       jmc 	    psc->sc_tlabel, 0, fwohci_read_resp, fcb);
   3745      1.26     enami 	if (rv)
   3746      1.26     enami 		return rv;
   3747      1.31       jmc 	rv = fwohci_at_output(psc, psc->sc_ctx_atrq, &pkt);
   3748      1.31       jmc 	if (rv)
   3749      1.31       jmc 		fwohci_handler_set(psc, tcode, ab->ab_req->sc1394_node_id,
   3750      1.67       jmc 		    psc->sc_tlabel, 0, NULL, NULL);
   3751      1.26     enami 	psc->sc_tlabel = (psc->sc_tlabel + 1) & 0x3f;
   3752      1.31       jmc 	fcb->count = 1;
   3753      1.26     enami 	return rv;
   3754      1.24       jmc }
   3755      1.24       jmc 
   3756      1.24       jmc static int
   3757      1.29       jmc fwohci_write(struct ieee1394_abuf *ab)
   3758      1.24       jmc {
   3759      1.26     enami 	struct fwohci_pkt pkt;
   3760      1.29       jmc 	struct ieee1394_softc *sc = ab->ab_req;
   3761      1.26     enami 	struct fwohci_softc *psc =
   3762      1.26     enami 	    (struct fwohci_softc *)sc->sc1394_dev.dv_parent;
   3763      1.26     enami 	u_int32_t high, lo;
   3764      1.26     enami 	int rv;
   3765      1.26     enami 
   3766      1.65       jmc 	if (ab->ab_tcode == IEEE1394_TCODE_WRITE_REQ_BLOCK) {
   3767      1.65       jmc 		if (ab->ab_length > IEEE1394_MAX_REC(sc->sc1394_max_receive)) {
   3768      1.65       jmc 			DPRINTF(("Packet too large: %d\n", ab->ab_length));
   3769      1.65       jmc 			return E2BIG;
   3770      1.65       jmc 		}
   3771      1.65       jmc 	}
   3772      1.65       jmc 
   3773      1.65       jmc 	if (ab->ab_length >
   3774      1.65       jmc 	    IEEE1394_MAX_ASYNCH_FOR_SPEED(sc->sc1394_link_speed)) {
   3775      1.28       jmc 		DPRINTF(("Packet too large: %d\n", ab->ab_length));
   3776      1.26     enami 		return E2BIG;
   3777      1.26     enami 	}
   3778      1.24       jmc 
   3779      1.51       jmc 	if (ab->ab_data && ab->ab_uio)
   3780      1.57    provos 		panic("Can't call with uio and data set");
   3781      1.51       jmc 	if ((ab->ab_data == NULL) && (ab->ab_uio == NULL))
   3782      1.57    provos 		panic("One of either ab_data or ab_uio must be set");
   3783      1.51       jmc 
   3784      1.26     enami 	memset(&pkt, 0, sizeof(pkt));
   3785      1.26     enami 
   3786      1.26     enami 	pkt.fp_tcode = ab->ab_tcode;
   3787      1.51       jmc 	if (ab->ab_data) {
   3788      1.51       jmc 		pkt.fp_uio.uio_iov = pkt.fp_iov;
   3789      1.51       jmc 		pkt.fp_uio.uio_segflg = UIO_SYSSPACE;
   3790      1.51       jmc 		pkt.fp_uio.uio_rw = UIO_WRITE;
   3791      1.51       jmc 	} else
   3792      1.51       jmc 		memcpy(&pkt.fp_uio, ab->ab_uio, sizeof(struct uio));
   3793      1.51       jmc 
   3794      1.31       jmc 	pkt.fp_statusarg = ab;
   3795      1.31       jmc 	pkt.fp_statuscb = fwohci_write_ack;
   3796      1.31       jmc 
   3797      1.24       jmc 	switch (ab->ab_tcode) {
   3798      1.26     enami 	case IEEE1394_TCODE_WRITE_RESP:
   3799      1.26     enami 		pkt.fp_hlen = 12;
   3800      1.26     enami 	case IEEE1394_TCODE_READ_RESP_QUAD:
   3801      1.26     enami 	case IEEE1394_TCODE_READ_RESP_BLOCK:
   3802      1.26     enami 		if (!pkt.fp_hlen)
   3803      1.26     enami 			pkt.fp_hlen = 16;
   3804      1.26     enami 		high = ab->ab_retlen;
   3805      1.26     enami 		ab->ab_retlen = 0;
   3806      1.26     enami 		lo = 0;
   3807      1.26     enami 		pkt.fp_hdr[0] = 0x00000100 | (sc->sc1394_link_speed << 16) |
   3808      1.26     enami 		    (ab->ab_tlabel << 10) | (pkt.fp_tcode << 4);
   3809      1.26     enami 		break;
   3810      1.26     enami 	default:
   3811      1.26     enami 		pkt.fp_hlen = 16;
   3812      1.59   thorpej 		high = ((ab->ab_addr & 0x0000ffff00000000ULL) >> 32);
   3813      1.59   thorpej 		lo = (ab->ab_addr & 0x00000000ffffffffULL);
   3814      1.26     enami 		pkt.fp_hdr[0] = 0x00000100 | (sc->sc1394_link_speed << 16) |
   3815      1.26     enami 		    (psc->sc_tlabel << 10) | (pkt.fp_tcode << 4);
   3816      1.58       jmc 		psc->sc_tlabel = (psc->sc_tlabel + 1) & 0x3f;
   3817      1.26     enami 		break;
   3818      1.26     enami 	}
   3819      1.26     enami 
   3820      1.29       jmc 	pkt.fp_hdr[1] = ((0xffc0 | ab->ab_req->sc1394_node_id) << 16) | high;
   3821      1.26     enami 	pkt.fp_hdr[2] = lo;
   3822      1.26     enami 	if (pkt.fp_hlen == 16) {
   3823      1.26     enami 		if (ab->ab_length == 4) {
   3824      1.26     enami 			pkt.fp_hdr[3] = ab->ab_data[0];
   3825      1.26     enami 			pkt.fp_dlen = 0;
   3826      1.26     enami 		}  else {
   3827      1.26     enami 			pkt.fp_hdr[3] = (ab->ab_length << 16);
   3828      1.26     enami 			pkt.fp_dlen = ab->ab_length;
   3829      1.51       jmc 			if (ab->ab_data) {
   3830      1.51       jmc 				pkt.fp_uio.uio_iovcnt = 1;
   3831      1.51       jmc 				pkt.fp_uio.uio_resid = ab->ab_length;
   3832      1.51       jmc 				pkt.fp_iov[0].iov_base = ab->ab_data;
   3833      1.51       jmc 				pkt.fp_iov[0].iov_len = ab->ab_length;
   3834      1.51       jmc 			}
   3835      1.26     enami 		}
   3836      1.26     enami 	}
   3837      1.26     enami 	switch (ab->ab_tcode) {
   3838      1.26     enami 	case IEEE1394_TCODE_WRITE_RESP:
   3839      1.26     enami 	case IEEE1394_TCODE_READ_RESP_QUAD:
   3840      1.26     enami 	case IEEE1394_TCODE_READ_RESP_BLOCK:
   3841      1.26     enami 		rv = fwohci_at_output(psc, psc->sc_ctx_atrs, &pkt);
   3842      1.26     enami 		break;
   3843      1.26     enami 	default:
   3844      1.26     enami 		rv = fwohci_at_output(psc, psc->sc_ctx_atrq, &pkt);
   3845      1.26     enami 		break;
   3846      1.26     enami 	}
   3847      1.26     enami 	return rv;
   3848      1.24       jmc }
   3849      1.24       jmc 
   3850      1.24       jmc static int
   3851      1.31       jmc fwohci_read_resp(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt)
   3852      1.24       jmc {
   3853      1.31       jmc 	struct fwohci_cb *fcb = arg;
   3854      1.31       jmc 	struct ieee1394_abuf *ab = fcb->ab;
   3855      1.26     enami 	struct fwohci_pkt newpkt;
   3856      1.26     enami 	u_int32_t *cur, high, lo;
   3857      1.31       jmc 	int i, tcode, rcode, status, rv;
   3858      1.29       jmc 
   3859      1.26     enami 	/*
   3860      1.31       jmc 	 * Both the ACK handling and normal response callbacks are handled here.
   3861      1.31       jmc 	 * The main reason for this is the various error conditions that can
   3862      1.31       jmc 	 * occur trying to block read some areas and the ways that gets reported
   3863      1.31       jmc 	 * back to calling station. This is a variety of ACK codes, responses,
   3864      1.31       jmc 	 * etc which makes it much more difficult to process if both aren't
   3865      1.31       jmc 	 * handled here.
   3866      1.26     enami 	 */
   3867      1.31       jmc 
   3868      1.29       jmc 	/* Check for status packet. */
   3869      1.29       jmc 
   3870      1.29       jmc 	if (pkt->fp_tcode == -1) {
   3871      1.29       jmc 		status = pkt->fp_status & OHCI_DESC_STATUS_ACK_MASK;
   3872      1.31       jmc 		rcode = -1;
   3873      1.31       jmc 		tcode = (pkt->fp_hdr[0] >> 4) & 0xf;
   3874      1.31       jmc 		if ((status != OHCI_CTXCTL_EVENT_ACK_COMPLETE) &&
   3875      1.31       jmc 		    (status != OHCI_CTXCTL_EVENT_ACK_PENDING))
   3876      1.53       jmc 			DPRINTFN(2, ("Got status packet: 0x%02x\n",
   3877      1.31       jmc 			    (unsigned int)status));
   3878      1.31       jmc 		fcb->count--;
   3879      1.29       jmc 
   3880      1.31       jmc 		/*
   3881      1.31       jmc 		 * Got all the ack's back and the buffer is invalid (i.e. the
   3882      1.31       jmc 		 * callback has been called. Clean up.
   3883      1.31       jmc 		 */
   3884      1.31       jmc 
   3885      1.31       jmc 		if (fcb->abuf_valid == 0) {
   3886      1.31       jmc 			if (fcb->count == 0)
   3887      1.31       jmc 				free(fcb, M_DEVBUF);
   3888      1.29       jmc 			return IEEE1394_RCODE_COMPLETE;
   3889      1.29       jmc 		}
   3890      1.31       jmc 	} else {
   3891      1.31       jmc 		status = -1;
   3892      1.31       jmc 		tcode = pkt->fp_tcode;
   3893      1.29       jmc 		rcode = (pkt->fp_hdr[1] & 0x0000f000) >> 12;
   3894      1.31       jmc 	}
   3895      1.26     enami 
   3896      1.29       jmc 	/*
   3897      1.29       jmc 	 * Some area's (like the config rom want to be read as quadlets only.
   3898      1.29       jmc 	 *
   3899      1.29       jmc 	 * The current ideas to try are:
   3900      1.29       jmc 	 *
   3901      1.31       jmc 	 * Got an ACK_TYPE_ERROR on a block read.
   3902      1.29       jmc 	 *
   3903      1.31       jmc 	 * Got either RCODE_TYPE or RCODE_ADDRESS errors in a block read
   3904      1.31       jmc 	 * response.
   3905      1.29       jmc 	 *
   3906      1.31       jmc 	 * In all cases construct a new packet for a quadlet read and let
   3907      1.29       jmc 	 * mutli_resp handle the iteration over the space.
   3908      1.29       jmc 	 */
   3909      1.29       jmc 
   3910      1.29       jmc 	if (((status == OHCI_CTXCTL_EVENT_ACK_TYPE_ERROR) &&
   3911      1.31       jmc 	     (tcode == IEEE1394_TCODE_READ_REQ_BLOCK)) ||
   3912      1.29       jmc 	    (((rcode == IEEE1394_RCODE_TYPE_ERROR) ||
   3913      1.31       jmc 	     (rcode == IEEE1394_RCODE_ADDRESS_ERROR)) &&
   3914      1.31       jmc 	      (tcode == IEEE1394_TCODE_READ_RESP_BLOCK))) {
   3915      1.26     enami 
   3916      1.26     enami 		/* Read the area in quadlet chunks (internally track this). */
   3917      1.26     enami 
   3918      1.26     enami 		memset(&newpkt, 0, sizeof(newpkt));
   3919      1.26     enami 
   3920      1.59   thorpej 		high = ((ab->ab_addr & 0x0000ffff00000000ULL) >> 32);
   3921      1.59   thorpej 		lo = (ab->ab_addr & 0x00000000ffffffffULL);
   3922      1.26     enami 
   3923      1.26     enami 		newpkt.fp_tcode = IEEE1394_TCODE_READ_REQ_QUAD;
   3924      1.26     enami 		newpkt.fp_hlen = 12;
   3925      1.26     enami 		newpkt.fp_dlen = 0;
   3926      1.26     enami 		newpkt.fp_hdr[1] =
   3927      1.29       jmc 		    ((0xffc0 | ab->ab_req->sc1394_node_id) << 16) | high;
   3928      1.26     enami 		newpkt.fp_hdr[2] = lo;
   3929      1.26     enami 		newpkt.fp_hdr[0] = 0x00000100 | (sc->sc_tlabel << 10) |
   3930      1.26     enami 		    (newpkt.fp_tcode << 4);
   3931      1.26     enami 
   3932      1.26     enami 		rv = fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD,
   3933      1.67       jmc 		    ab->ab_req->sc1394_node_id, sc->sc_tlabel, 0,
   3934      1.31       jmc 		    fwohci_read_multi_resp, fcb);
   3935      1.31       jmc 		if (rv) {
   3936      1.31       jmc 			(*ab->ab_cb)(ab, -1);
   3937      1.31       jmc 			goto cleanup;
   3938      1.31       jmc 		}
   3939      1.31       jmc 		newpkt.fp_statusarg = fcb;
   3940      1.31       jmc 		newpkt.fp_statuscb = fwohci_read_resp;
   3941      1.31       jmc 		rv = fwohci_at_output(sc, sc->sc_ctx_atrq, &newpkt);
   3942      1.31       jmc 		if (rv) {
   3943      1.31       jmc 			fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD,
   3944      1.67       jmc 			    ab->ab_req->sc1394_node_id, sc->sc_tlabel, 0, NULL,
   3945      1.31       jmc 			    NULL);
   3946      1.31       jmc 			(*ab->ab_cb)(ab, -1);
   3947      1.31       jmc 			goto cleanup;
   3948      1.31       jmc 		}
   3949      1.31       jmc 		fcb->count++;
   3950      1.26     enami 		sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f;
   3951      1.31       jmc 		return IEEE1394_RCODE_COMPLETE;
   3952      1.31       jmc 	} else if ((rcode != -1) || ((status != -1) &&
   3953      1.31       jmc 	    (status != OHCI_CTXCTL_EVENT_ACK_COMPLETE) &&
   3954      1.31       jmc 	    (status != OHCI_CTXCTL_EVENT_ACK_PENDING))) {
   3955      1.26     enami 
   3956      1.26     enami 		/*
   3957      1.26     enami 		 * Recombine all the iov data into 1 chunk for higher
   3958      1.26     enami 		 * level code.
   3959      1.26     enami 		 */
   3960      1.26     enami 
   3961      1.31       jmc 		if (rcode != -1) {
   3962      1.31       jmc 			cur = ab->ab_data;
   3963      1.31       jmc 			for (i = 0; i < pkt->fp_uio.uio_iovcnt; i++) {
   3964      1.31       jmc 				/*
   3965      1.31       jmc 				 * Make sure and don't exceed the buffer
   3966      1.31       jmc 				 * allocated for return.
   3967      1.31       jmc 				 */
   3968      1.31       jmc 				if ((ab->ab_retlen + pkt->fp_iov[i].iov_len) >
   3969      1.31       jmc 				    ab->ab_length) {
   3970      1.31       jmc 					memcpy(cur, pkt->fp_iov[i].iov_base,
   3971      1.31       jmc 					    (ab->ab_length - ab->ab_retlen));
   3972      1.31       jmc 					ab->ab_retlen = ab->ab_length;
   3973      1.31       jmc 					break;
   3974      1.31       jmc 				}
   3975      1.26     enami 				memcpy(cur, pkt->fp_iov[i].iov_base,
   3976      1.31       jmc 				    pkt->fp_iov[i].iov_len);
   3977      1.31       jmc 				cur += pkt->fp_iov[i].iov_len;
   3978      1.31       jmc 				ab->ab_retlen += pkt->fp_iov[i].iov_len;
   3979      1.26     enami 			}
   3980      1.26     enami 		}
   3981      1.31       jmc 		if (status != -1)
   3982      1.31       jmc 			/* XXX: Need a complete tlabel interface. */
   3983      1.31       jmc 			for (i = 0; i < 64; i++)
   3984      1.31       jmc 				fwohci_handler_set(sc,
   3985      1.31       jmc 				    IEEE1394_TCODE_READ_RESP_QUAD,
   3986      1.67       jmc 				    ab->ab_req->sc1394_node_id, i, 0, NULL,
   3987      1.67       jmc 				    NULL);
   3988      1.26     enami 		(*ab->ab_cb)(ab, rcode);
   3989      1.31       jmc 		goto cleanup;
   3990      1.31       jmc 	} else
   3991      1.31       jmc 		/* Good ack packet. */
   3992      1.31       jmc 		return IEEE1394_RCODE_COMPLETE;
   3993      1.31       jmc 
   3994      1.31       jmc 	/* Can't get here unless ab->ab_cb has been called. */
   3995      1.31       jmc 
   3996      1.31       jmc  cleanup:
   3997      1.31       jmc 	fcb->abuf_valid = 0;
   3998      1.31       jmc 	if (fcb->count == 0)
   3999      1.31       jmc 		free(fcb, M_DEVBUF);
   4000      1.24       jmc 	return IEEE1394_RCODE_COMPLETE;
   4001      1.24       jmc }
   4002      1.24       jmc 
   4003      1.24       jmc static int
   4004      1.31       jmc fwohci_read_multi_resp(struct fwohci_softc *sc, void *arg,
   4005      1.31       jmc     struct fwohci_pkt *pkt)
   4006      1.24       jmc {
   4007      1.31       jmc 	struct fwohci_cb *fcb = arg;
   4008      1.31       jmc 	struct ieee1394_abuf *ab = fcb->ab;
   4009      1.26     enami 	struct fwohci_pkt newpkt;
   4010      1.26     enami 	u_int32_t high, lo;
   4011      1.26     enami 	int rcode, rv;
   4012      1.26     enami 
   4013      1.26     enami 	/*
   4014      1.26     enami 	 * Bad return codes from the wire, just return what's already in the
   4015      1.26     enami 	 * buf.
   4016      1.26     enami 	 */
   4017      1.26     enami 
   4018      1.31       jmc 	/* Make sure a response packet didn't arrive after a bad ACK. */
   4019      1.31       jmc 	if (fcb->abuf_valid == 0)
   4020      1.31       jmc 		return IEEE1394_RCODE_COMPLETE;
   4021      1.31       jmc 
   4022      1.26     enami 	rcode = (pkt->fp_hdr[1] & 0x0000f000) >> 12;
   4023      1.26     enami 
   4024      1.26     enami 	if (rcode) {
   4025      1.26     enami 		(*ab->ab_cb)(ab, rcode);
   4026      1.31       jmc 		goto cleanup;
   4027      1.26     enami 	}
   4028      1.26     enami 
   4029      1.26     enami 	if ((ab->ab_retlen + pkt->fp_iov[0].iov_len) > ab->ab_length) {
   4030      1.26     enami 		memcpy(((char *)ab->ab_data + ab->ab_retlen),
   4031      1.26     enami 		    pkt->fp_iov[0].iov_base, (ab->ab_length - ab->ab_retlen));
   4032      1.26     enami 		ab->ab_retlen = ab->ab_length;
   4033      1.26     enami 	} else {
   4034      1.26     enami 		memcpy(((char *)ab->ab_data + ab->ab_retlen),
   4035      1.26     enami 		    pkt->fp_iov[0].iov_base, 4);
   4036      1.26     enami 		ab->ab_retlen += 4;
   4037      1.26     enami 	}
   4038      1.26     enami 	/* Still more, loop and read 4 more bytes. */
   4039      1.26     enami 	if (ab->ab_retlen < ab->ab_length) {
   4040      1.26     enami 		memset(&newpkt, 0, sizeof(newpkt));
   4041      1.26     enami 
   4042      1.59   thorpej 		high = ((ab->ab_addr & 0x0000ffff00000000ULL) >> 32);
   4043      1.59   thorpej 		lo = (ab->ab_addr & 0x00000000ffffffffULL) + ab->ab_retlen;
   4044      1.26     enami 
   4045      1.26     enami 		newpkt.fp_tcode = IEEE1394_TCODE_READ_REQ_QUAD;
   4046      1.26     enami 		newpkt.fp_hlen = 12;
   4047      1.26     enami 		newpkt.fp_dlen = 0;
   4048      1.26     enami 		newpkt.fp_hdr[1] =
   4049      1.29       jmc 		    ((0xffc0 | ab->ab_req->sc1394_node_id) << 16) | high;
   4050      1.26     enami 		newpkt.fp_hdr[2] = lo;
   4051      1.26     enami 		newpkt.fp_hdr[0] = 0x00000100 | (sc->sc_tlabel << 10) |
   4052      1.26     enami 		    (newpkt.fp_tcode << 4);
   4053      1.26     enami 
   4054      1.31       jmc 		newpkt.fp_statusarg = fcb;
   4055      1.31       jmc 		newpkt.fp_statuscb = fwohci_read_resp;
   4056      1.31       jmc 
   4057      1.26     enami 		/*
   4058      1.26     enami 		 * Bad return code.  Just give up and return what's
   4059      1.26     enami 		 * come in now.
   4060      1.26     enami 		 */
   4061      1.26     enami 		rv = fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD,
   4062      1.67       jmc 		    ab->ab_req->sc1394_node_id, sc->sc_tlabel, 0,
   4063      1.31       jmc 		    fwohci_read_multi_resp, fcb);
   4064      1.31       jmc 		if (rv)
   4065      1.31       jmc 			(*ab->ab_cb)(ab, -1);
   4066      1.31       jmc 		else {
   4067      1.31       jmc 			rv = fwohci_at_output(sc, sc->sc_ctx_atrq, &newpkt);
   4068      1.31       jmc 			if (rv) {
   4069      1.31       jmc 				fwohci_handler_set(sc,
   4070      1.31       jmc 				    IEEE1394_TCODE_READ_RESP_QUAD,
   4071      1.31       jmc 				    ab->ab_req->sc1394_node_id, sc->sc_tlabel,
   4072      1.67       jmc 				    0, NULL, NULL);
   4073      1.31       jmc 				(*ab->ab_cb)(ab, -1);
   4074      1.31       jmc 			} else {
   4075      1.31       jmc 				sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f;
   4076      1.31       jmc 				fcb->count++;
   4077      1.31       jmc 				return IEEE1394_RCODE_COMPLETE;
   4078      1.31       jmc 			}
   4079      1.26     enami 		}
   4080      1.31       jmc 	} else
   4081      1.31       jmc 		(*ab->ab_cb)(ab, IEEE1394_RCODE_COMPLETE);
   4082      1.31       jmc 
   4083      1.31       jmc  cleanup:
   4084      1.31       jmc 	/* Can't get here unless ab_cb has been called. */
   4085      1.31       jmc 	fcb->abuf_valid = 0;
   4086      1.31       jmc 	if (fcb->count == 0)
   4087      1.31       jmc 		free(fcb, M_DEVBUF);
   4088      1.31       jmc 	return IEEE1394_RCODE_COMPLETE;
   4089      1.31       jmc }
   4090      1.31       jmc 
   4091      1.31       jmc static int
   4092      1.31       jmc fwohci_write_ack(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt)
   4093      1.31       jmc {
   4094      1.31       jmc 	struct ieee1394_abuf *ab = arg;
   4095      1.31       jmc 	u_int16_t status;
   4096      1.31       jmc 
   4097      1.31       jmc 
   4098      1.31       jmc 	status = pkt->fp_status & OHCI_DESC_STATUS_ACK_MASK;
   4099      1.31       jmc 	if ((status != OHCI_CTXCTL_EVENT_ACK_COMPLETE) &&
   4100      1.31       jmc 	    (status != OHCI_CTXCTL_EVENT_ACK_PENDING))
   4101      1.31       jmc 		DPRINTF(("Got status packet: 0x%02x\n",
   4102      1.31       jmc 		    (unsigned int)status));
   4103      1.31       jmc 
   4104      1.31       jmc 	/* No callback means this level should free the buffers. */
   4105      1.31       jmc 	if (ab->ab_cb)
   4106      1.31       jmc 		(*ab->ab_cb)(ab, status);
   4107      1.31       jmc 	else {
   4108      1.31       jmc 		if (ab->ab_data)
   4109      1.31       jmc 			free(ab->ab_data, M_1394DATA);
   4110      1.31       jmc 		free(ab, M_1394DATA);
   4111      1.31       jmc 	}
   4112      1.26     enami 	return IEEE1394_RCODE_COMPLETE;
   4113      1.24       jmc }
   4114      1.24       jmc 
   4115      1.24       jmc static int
   4116      1.24       jmc fwohci_inreg(struct ieee1394_abuf *ab, int allow)
   4117      1.24       jmc {
   4118      1.29       jmc 	struct ieee1394_softc *sc = ab->ab_req;
   4119      1.26     enami 	struct fwohci_softc *psc =
   4120      1.26     enami 	    (struct fwohci_softc *)sc->sc1394_dev.dv_parent;
   4121      1.26     enami 	u_int32_t high, lo;
   4122      1.67       jmc 	int rv;
   4123      1.26     enami 
   4124      1.59   thorpej 	high = ((ab->ab_addr & 0x0000ffff00000000ULL) >> 32);
   4125      1.59   thorpej 	lo = (ab->ab_addr & 0x00000000ffffffffULL);
   4126      1.26     enami 
   4127      1.31       jmc 	rv = 0;
   4128      1.26     enami 	switch (ab->ab_tcode) {
   4129      1.26     enami 	case IEEE1394_TCODE_READ_REQ_QUAD:
   4130      1.26     enami 	case IEEE1394_TCODE_WRITE_REQ_QUAD:
   4131      1.31       jmc 		if (ab->ab_cb)
   4132      1.67       jmc 			rv = fwohci_handler_set(psc, ab->ab_tcode, high, lo, 0,
   4133      1.31       jmc 			    fwohci_parse_input, ab);
   4134      1.31       jmc 		else
   4135      1.67       jmc 			fwohci_handler_set(psc, ab->ab_tcode, high, lo, 0, NULL,
   4136      1.31       jmc 			    NULL);
   4137      1.26     enami 		break;
   4138      1.26     enami 	case IEEE1394_TCODE_READ_REQ_BLOCK:
   4139      1.26     enami 	case IEEE1394_TCODE_WRITE_REQ_BLOCK:
   4140      1.26     enami 		if (allow) {
   4141      1.67       jmc 			if (ab->ab_cb) {
   4142      1.67       jmc 				rv = fwohci_handler_set(psc, ab->ab_tcode,
   4143      1.67       jmc 				    high, lo, ab->ab_length,
   4144      1.67       jmc 				    fwohci_parse_input, ab);
   4145      1.67       jmc 				if (rv)
   4146      1.67       jmc 					fwohci_handler_set(psc, ab->ab_tcode,
   4147      1.67       jmc 					    high, lo, ab->ab_length, NULL,
   4148      1.67       jmc 					    NULL);
   4149      1.58       jmc                                 ab->ab_subok = 1;
   4150      1.67       jmc 			} else
   4151      1.67       jmc 				fwohci_handler_set(psc, ab->ab_tcode, high, lo,
   4152      1.67       jmc 				    ab->ab_length, NULL, NULL);
   4153      1.31       jmc 		} else {
   4154      1.31       jmc 			if (ab->ab_cb)
   4155      1.31       jmc 				rv = fwohci_handler_set(psc, ab->ab_tcode, high,
   4156      1.67       jmc 				    lo, 0, fwohci_parse_input, ab);
   4157      1.31       jmc 			else
   4158      1.31       jmc 				fwohci_handler_set(psc, ab->ab_tcode, high, lo,
   4159      1.67       jmc 				    0, NULL, NULL);
   4160      1.31       jmc 		}
   4161      1.26     enami 		break;
   4162      1.26     enami 	default:
   4163      1.28       jmc 		DPRINTF(("Invalid registration tcode: %d\n", ab->ab_tcode));
   4164      1.26     enami 		return -1;
   4165      1.26     enami 		break;
   4166      1.26     enami 	}
   4167      1.26     enami 	return rv;
   4168      1.24       jmc }
   4169      1.24       jmc 
   4170      1.24       jmc static int
   4171      1.51       jmc fwohci_unreg(struct ieee1394_abuf *ab, int allow)
   4172      1.51       jmc {
   4173      1.51       jmc 	void *save;
   4174      1.51       jmc 	int rv;
   4175      1.51       jmc 
   4176      1.51       jmc 	save = ab->ab_cb;
   4177      1.51       jmc 	ab->ab_cb = NULL;
   4178      1.51       jmc 	rv = fwohci_inreg(ab, allow);
   4179      1.51       jmc 	ab->ab_cb = save;
   4180      1.51       jmc 	return rv;
   4181      1.51       jmc }
   4182      1.51       jmc 
   4183      1.51       jmc static int
   4184      1.24       jmc fwohci_parse_input(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt)
   4185      1.24       jmc {
   4186      1.26     enami 	struct ieee1394_abuf *ab = (struct ieee1394_abuf *)arg;
   4187      1.51       jmc 	u_int64_t addr;
   4188      1.61       jmc 	u_int8_t *cur;
   4189      1.60       jmc 	int i, count, ret;
   4190      1.26     enami 
   4191      1.26     enami 	ab->ab_tcode = (pkt->fp_hdr[0] >> 4) & 0xf;
   4192      1.26     enami 	ab->ab_tlabel = (pkt->fp_hdr[0] >> 10) & 0x3f;
   4193      1.51       jmc 	addr = (((u_int64_t)(pkt->fp_hdr[1] & 0xffff) << 32) | pkt->fp_hdr[2]);
   4194      1.26     enami 
   4195      1.58       jmc 	/* Make sure it's always 0 in case this gets reused multiple times. */
   4196      1.58       jmc 	ab->ab_retlen = 0;
   4197      1.58       jmc 
   4198      1.26     enami 	switch (ab->ab_tcode) {
   4199      1.26     enami 	case IEEE1394_TCODE_READ_REQ_QUAD:
   4200      1.26     enami 		ab->ab_retlen = 4;
   4201      1.60       jmc 		/* Response's (if required) will come from callback code */
   4202      1.60       jmc 		ret = -1;
   4203      1.26     enami 		break;
   4204      1.26     enami 	case IEEE1394_TCODE_READ_REQ_BLOCK:
   4205      1.26     enami 		ab->ab_retlen = (pkt->fp_hdr[3] >> 16) & 0xffff;
   4206      1.58       jmc 		if (ab->ab_subok) {
   4207      1.51       jmc 			if ((addr + ab->ab_retlen) >
   4208      1.51       jmc 			    (ab->ab_addr + ab->ab_length))
   4209      1.26     enami 				return IEEE1394_RCODE_ADDRESS_ERROR;
   4210      1.26     enami 		} else
   4211      1.26     enami 			if (ab->ab_retlen != ab->ab_length)
   4212      1.26     enami 				return IEEE1394_RCODE_ADDRESS_ERROR;
   4213      1.60       jmc 		/* Response's (if required) will come from callback code */
   4214      1.60       jmc 		ret = -1;
   4215      1.26     enami 		break;
   4216      1.26     enami 	case IEEE1394_TCODE_WRITE_REQ_QUAD:
   4217      1.26     enami 		ab->ab_retlen = 4;
   4218      1.58       jmc 		/* Fall through. */
   4219      1.58       jmc 
   4220      1.26     enami 	case IEEE1394_TCODE_WRITE_REQ_BLOCK:
   4221      1.26     enami 		if (!ab->ab_retlen)
   4222      1.26     enami 			ab->ab_retlen = (pkt->fp_hdr[3] >> 16) & 0xffff;
   4223      1.58       jmc 		if (ab->ab_subok) {
   4224      1.51       jmc 			if ((addr + ab->ab_retlen) >
   4225      1.51       jmc 			    (ab->ab_addr + ab->ab_length))
   4226      1.26     enami 				return IEEE1394_RCODE_ADDRESS_ERROR;
   4227      1.26     enami 		} else
   4228      1.67       jmc 			if (ab->ab_retlen > ab->ab_length)
   4229      1.26     enami 				return IEEE1394_RCODE_ADDRESS_ERROR;
   4230      1.26     enami 
   4231      1.26     enami 		if (ab->ab_tcode == IEEE1394_TCODE_WRITE_REQ_QUAD)
   4232      1.26     enami 			ab->ab_data[0] = pkt->fp_hdr[3];
   4233      1.26     enami 		else {
   4234      1.26     enami 			count = 0;
   4235      1.67       jmc 			cur = (u_int8_t *)ab->ab_data + (addr - ab->ab_addr);
   4236      1.26     enami 			for (i = 0; i < pkt->fp_uio.uio_iovcnt; i++) {
   4237      1.26     enami 				memcpy(cur, pkt->fp_iov[i].iov_base,
   4238      1.26     enami 				    pkt->fp_iov[i].iov_len);
   4239      1.26     enami 				cur += pkt->fp_iov[i].iov_len;
   4240      1.26     enami 				count += pkt->fp_iov[i].iov_len;
   4241      1.26     enami 			}
   4242      1.26     enami 			if (ab->ab_retlen != count)
   4243      1.26     enami 				panic("Packet claims %d length "
   4244      1.26     enami 				    "but only %d bytes returned\n",
   4245      1.26     enami 				    ab->ab_retlen, count);
   4246      1.26     enami 		}
   4247      1.60       jmc 		ret = IEEE1394_RCODE_COMPLETE;
   4248      1.26     enami 		break;
   4249      1.26     enami 	default:
   4250      1.57    provos 		panic("Got a callback for a tcode that wasn't requested: %d",
   4251      1.26     enami 		    ab->ab_tcode);
   4252      1.26     enami 		break;
   4253      1.26     enami 	}
   4254      1.67       jmc 	if (ab->ab_cb) {
   4255      1.67       jmc 		ab->ab_retaddr = addr;
   4256      1.67       jmc 		ab->ab_cb(ab, IEEE1394_RCODE_COMPLETE);
   4257      1.67       jmc 	}
   4258      1.60       jmc 	return ret;
   4259      1.30       jmc }
   4260      1.30       jmc 
   4261      1.30       jmc static int
   4262  1.78.2.3     skrll fwohci_submatch(struct device *parent, struct cfdata *cf,
   4263  1.78.2.3     skrll 		const locdesc_t *ldesc, void *aux)
   4264      1.30       jmc {
   4265      1.30       jmc 	struct ieee1394_attach_args *fwa = aux;
   4266      1.30       jmc 
   4267      1.30       jmc 	/* Both halves must be filled in for a match. */
   4268      1.30       jmc 	if ((cf->fwbuscf_idhi == FWBUS_UNK_IDHI &&
   4269      1.30       jmc 	    cf->fwbuscf_idlo == FWBUS_UNK_IDLO) ||
   4270      1.30       jmc 	    (cf->fwbuscf_idhi == ntohl(*((u_int32_t *)&fwa->uid[0])) &&
   4271      1.30       jmc 	    cf->fwbuscf_idlo == ntohl(*((u_int32_t *)&fwa->uid[4]))))
   4272      1.56   thorpej 		return (config_match(parent, cf, aux));
   4273      1.30       jmc 	return 0;
   4274      1.47    ichiro }
   4275      1.47    ichiro 
   4276      1.47    ichiro int
   4277      1.47    ichiro fwohci_detach(struct fwohci_softc *sc, int flags)
   4278      1.47    ichiro {
   4279      1.47    ichiro 	int rv = 0;
   4280      1.47    ichiro 
   4281      1.47    ichiro 	if (sc->sc_sc1394.sc1394_if != NULL)
   4282      1.47    ichiro 		rv = config_detach(sc->sc_sc1394.sc1394_if, flags);
   4283      1.47    ichiro 	if (rv != 0)
   4284      1.47    ichiro 		return (rv);
   4285      1.47    ichiro 
   4286      1.47    ichiro 	callout_stop(&sc->sc_selfid_callout);
   4287      1.47    ichiro 
   4288      1.47    ichiro 	if (sc->sc_powerhook != NULL)
   4289      1.47    ichiro 		powerhook_disestablish(sc->sc_powerhook);
   4290      1.47    ichiro 	if (sc->sc_shutdownhook != NULL)
   4291      1.47    ichiro 		shutdownhook_disestablish(sc->sc_shutdownhook);
   4292      1.47    ichiro 
   4293      1.47    ichiro 	return (rv);
   4294      1.47    ichiro }
   4295      1.47    ichiro 
   4296      1.47    ichiro int
   4297      1.47    ichiro fwohci_activate(struct device *self, enum devact act)
   4298      1.47    ichiro {
   4299      1.47    ichiro 	struct fwohci_softc *sc = (struct fwohci_softc *)self;
   4300      1.47    ichiro 	int s, rv = 0;
   4301      1.47    ichiro 
   4302      1.47    ichiro 	s = splhigh();
   4303      1.47    ichiro 	switch (act) {
   4304      1.47    ichiro 	case DVACT_ACTIVATE:
   4305      1.47    ichiro 		rv = EOPNOTSUPP;
   4306      1.47    ichiro 		break;
   4307      1.47    ichiro 
   4308      1.47    ichiro 	case DVACT_DEACTIVATE:
   4309      1.47    ichiro 		if (sc->sc_sc1394.sc1394_if != NULL)
   4310      1.47    ichiro 	                rv = config_deactivate(sc->sc_sc1394.sc1394_if);
   4311      1.47    ichiro 		break;
   4312      1.47    ichiro 	}
   4313      1.47    ichiro 	splx(s);
   4314      1.47    ichiro 
   4315      1.47    ichiro 	return (rv);
   4316       1.1      matt }
   4317      1.33      onoe 
   4318      1.33      onoe #ifdef FW_DEBUG
   4319      1.33      onoe static void
   4320      1.33      onoe fwohci_show_intr(struct fwohci_softc *sc, u_int32_t intmask)
   4321      1.33      onoe {
   4322      1.33      onoe 
   4323      1.33      onoe 	printf("%s: intmask=0x%08x:", sc->sc_sc1394.sc1394_dev.dv_xname,
   4324      1.33      onoe 	    intmask);
   4325      1.33      onoe 	if (intmask & OHCI_Int_CycleTooLong)
   4326      1.33      onoe 		printf(" CycleTooLong");
   4327      1.33      onoe 	if (intmask & OHCI_Int_UnrecoverableError)
   4328      1.33      onoe 		printf(" UnrecoverableError");
   4329      1.33      onoe 	if (intmask & OHCI_Int_CycleInconsistent)
   4330      1.33      onoe 		printf(" CycleInconsistent");
   4331      1.33      onoe 	if (intmask & OHCI_Int_BusReset)
   4332      1.33      onoe 		printf(" BusReset");
   4333      1.33      onoe 	if (intmask & OHCI_Int_SelfIDComplete)
   4334      1.33      onoe 		printf(" SelfIDComplete");
   4335      1.33      onoe 	if (intmask & OHCI_Int_LockRespErr)
   4336      1.33      onoe 		printf(" LockRespErr");
   4337      1.33      onoe 	if (intmask & OHCI_Int_PostedWriteErr)
   4338      1.33      onoe 		printf(" PostedWriteErr");
   4339      1.33      onoe 	if (intmask & OHCI_Int_ReqTxComplete)
   4340      1.33      onoe 		printf(" ReqTxComplete(0x%04x)",
   4341      1.33      onoe 		    OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_TX_REQUEST,
   4342      1.33      onoe 		    OHCI_SUBREG_ContextControlClear));
   4343      1.33      onoe 	if (intmask & OHCI_Int_RespTxComplete)
   4344      1.33      onoe 		printf(" RespTxComplete(0x%04x)",
   4345      1.33      onoe 		    OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_TX_RESPONSE,
   4346      1.33      onoe 		    OHCI_SUBREG_ContextControlClear));
   4347      1.33      onoe 	if (intmask & OHCI_Int_ARRS)
   4348      1.33      onoe 		printf(" ARRS(0x%04x)",
   4349      1.33      onoe 		    OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_RX_RESPONSE,
   4350      1.33      onoe 		    OHCI_SUBREG_ContextControlClear));
   4351      1.33      onoe 	if (intmask & OHCI_Int_ARRQ)
   4352      1.33      onoe 		printf(" ARRQ(0x%04x)",
   4353      1.33      onoe 		    OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_RX_REQUEST,
   4354      1.33      onoe 		    OHCI_SUBREG_ContextControlClear));
   4355      1.33      onoe 	if (intmask & OHCI_Int_IsochRx)
   4356      1.33      onoe 		printf(" IsochRx(0x%08x)",
   4357      1.33      onoe 		    OHCI_CSR_READ(sc, OHCI_REG_IsoRecvIntEventClear));
   4358      1.33      onoe 	if (intmask & OHCI_Int_IsochTx)
   4359      1.33      onoe 		printf(" IsochTx(0x%08x)",
   4360      1.33      onoe 		    OHCI_CSR_READ(sc, OHCI_REG_IsoXmitIntEventClear));
   4361      1.33      onoe 	if (intmask & OHCI_Int_RQPkt)
   4362      1.33      onoe 		printf(" RQPkt(0x%04x)",
   4363      1.33      onoe 		    OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_RX_REQUEST,
   4364      1.33      onoe 		    OHCI_SUBREG_ContextControlClear));
   4365      1.33      onoe 	if (intmask & OHCI_Int_RSPkt)
   4366      1.33      onoe 		printf(" RSPkt(0x%04x)",
   4367      1.33      onoe 		    OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_RX_RESPONSE,
   4368      1.33      onoe 		    OHCI_SUBREG_ContextControlClear));
   4369      1.33      onoe 	printf("\n");
   4370      1.33      onoe }
   4371      1.33      onoe 
   4372      1.33      onoe static void
   4373      1.33      onoe fwohci_show_phypkt(struct fwohci_softc *sc, u_int32_t val)
   4374      1.33      onoe {
   4375      1.33      onoe 	u_int8_t key, phyid;
   4376      1.33      onoe 
   4377      1.33      onoe 	key = (val & 0xc0000000) >> 30;
   4378      1.33      onoe 	phyid = (val & 0x3f000000) >> 24;
   4379      1.33      onoe 	printf("%s: PHY packet from %d: ",
   4380      1.33      onoe 	    sc->sc_sc1394.sc1394_dev.dv_xname, phyid);
   4381      1.33      onoe 	switch (key) {
   4382      1.33      onoe 	case 0:
   4383      1.33      onoe 		printf("PHY Config:");
   4384      1.33      onoe 		if (val & 0x00800000)
   4385      1.33      onoe 			printf(" ForceRoot");
   4386      1.33      onoe 		if (val & 0x00400000)
   4387      1.33      onoe 			printf(" Gap=%x", (val & 0x003f0000) >> 16);
   4388      1.33      onoe 		printf("\n");
   4389      1.33      onoe 		break;
   4390      1.33      onoe 	case 1:
   4391      1.33      onoe 		printf("Link-on\n");
   4392      1.33      onoe 		break;
   4393      1.33      onoe 	case 2:
   4394      1.33      onoe 		printf("SelfID:");
   4395      1.33      onoe 		if (val & 0x00800000) {
   4396      1.33      onoe 			printf(" #%d", (val & 0x00700000) >> 20);
   4397      1.33      onoe 		} else {
   4398      1.33      onoe 			if (val & 0x00400000)
   4399      1.33      onoe 				printf(" LinkActive");
   4400      1.33      onoe 			printf(" Gap=%x", (val & 0x003f0000) >> 16);
   4401      1.33      onoe 			printf(" Spd=S%d", 100 << ((val & 0x0000c000) >> 14));
   4402      1.33      onoe 			if (val & 0x00000800)
   4403      1.33      onoe 				printf(" Cont");
   4404      1.33      onoe 			if (val & 0x00000002)
   4405      1.33      onoe 				printf(" InitiateBusReset");
   4406      1.33      onoe 		}
   4407      1.33      onoe 		if (val & 0x00000001)
   4408      1.33      onoe 			printf(" +");
   4409      1.33      onoe 		printf("\n");
   4410      1.33      onoe 		break;
   4411      1.33      onoe 	default:
   4412      1.33      onoe 		printf("unknown: 0x%08x\n", val);
   4413      1.33      onoe 		break;
   4414      1.33      onoe 	}
   4415      1.33      onoe }
   4416      1.33      onoe #endif /* FW_DEBUG */
   4417      1.62      haya 
   4418      1.62      haya #if 0
   4419      1.62      haya void fwohci_dumpreg(struct ieee1394_softc *, struct fwiso_regdump *);
   4420      1.62      haya 
   4421      1.62      haya void
   4422      1.62      haya fwohci_dumpreg(struct ieee1394_softc *isc, struct fwiso_regdump *fr)
   4423      1.62      haya {
   4424      1.62      haya 	struct fwohci_softc *sc = (struct fwohci_softc *)isc;
   4425      1.62      haya #if 0
   4426      1.62      haya 	u_int32_t val;
   4427      1.62      haya 
   4428      1.62      haya 	printf("%s: dump reg\n", isc->sc1394_dev.dv_xname);
   4429      1.62      haya 	printf("\tNodeID reg 0x%08x\n",
   4430      1.62      haya 	    OHCI_CSR_READ(sc, OHCI_REG_NodeId));
   4431      1.62      haya 	val = OHCI_CSR_READ(sc, OHCI_REG_IsochronousCycleTimer);
   4432      1.62      haya 	printf("\tIsoCounter 0x%08x, %d %d %d", val,
   4433      1.62      haya 	    (val >> 25) & 0xfe, (val >> 12) & 0x1fff, val & 0xfff);
   4434      1.62      haya 	val = OHCI_CSR_READ(sc, OHCI_REG_IntMaskSet);
   4435      1.62      haya 	printf(" IntMask    0x%08x, %s\n", val,
   4436      1.62      haya 	    val & OHCI_Int_IsochTx ? "isoTx" : "");
   4437      1.62      haya 
   4438      1.62      haya 	val = OHCI_SYNC_TX_DMA_READ(sc, 0, OHCI_SUBREG_ContextControlSet);
   4439      1.62      haya 	printf("\tIT_CommandPtr 0x%08x ContextCtrl 0x%08x%s%s%s%s\n",
   4440      1.62      haya 	    OHCI_SYNC_TX_DMA_READ(sc, 0, OHCI_SUBREG_CommandPtr),
   4441      1.62      haya 	    val,
   4442      1.62      haya 	    val & OHCI_CTXCTL_RUN ? " run" : "",
   4443      1.62      haya 	    val & OHCI_CTXCTL_WAKE ? " wake" : "",
   4444      1.62      haya 	    val & OHCI_CTXCTL_DEAD ? " dead" : "",
   4445      1.62      haya 	    val & OHCI_CTXCTL_ACTIVE ? " active" : "");
   4446      1.62      haya #endif
   4447      1.62      haya 
   4448      1.62      haya 	fr->fr_nodeid = OHCI_CSR_READ(sc, OHCI_REG_NodeId);
   4449      1.62      haya 	fr->fr_isocounter = OHCI_CSR_READ(sc, OHCI_REG_IsochronousCycleTimer);
   4450      1.62      haya 	fr->fr_intmask = OHCI_CSR_READ(sc, OHCI_REG_IntMaskSet);
   4451      1.62      haya 	fr->fr_it0_commandptr = OHCI_SYNC_TX_DMA_READ(sc, 0, OHCI_SUBREG_CommandPtr);
   4452      1.62      haya 	fr->fr_it0_contextctrl = OHCI_SYNC_TX_DMA_READ(sc, 0, OHCI_SUBREG_ContextControlSet);
   4453      1.62      haya 
   4454      1.62      haya 
   4455      1.62      haya }
   4456      1.62      haya #endif
   4457      1.62      haya 
   4458      1.62      haya 
   4459      1.62      haya u_int16_t
   4460      1.62      haya fwohci_cycletimer(struct fwohci_softc *sc)
   4461      1.62      haya {
   4462      1.62      haya 	u_int32_t reg;
   4463      1.62      haya 
   4464      1.62      haya 	reg = OHCI_CSR_READ(sc, OHCI_REG_IsochronousCycleTimer);
   4465      1.62      haya 
   4466      1.62      haya 	return (reg >> 12)&0xffff;
   4467      1.62      haya }
   4468      1.62      haya 
   4469      1.62      haya 
   4470      1.62      haya u_int16_t
   4471      1.62      haya fwohci_it_cycletimer(ieee1394_it_tag_t it)
   4472      1.62      haya {
   4473      1.62      haya 	struct fwohci_it_ctx *itc = (struct fwohci_it_ctx *)it;
   4474      1.62      haya 
   4475      1.62      haya 	return fwohci_cycletimer(itc->itc_sc);
   4476      1.62      haya }
   4477      1.62      haya 
   4478      1.62      haya 
   4479      1.62      haya 
   4480      1.62      haya 
   4481      1.62      haya 
   4482      1.62      haya /*
   4483      1.62      haya  * return value: if positive value, number of DMA buffer segments.  If
   4484      1.62      haya  * negative value, error happens.  Never zero.
   4485      1.62      haya  */
   4486      1.62      haya static int
   4487      1.62      haya fwohci_misc_dmabuf_alloc(bus_dma_tag_t dmat, int dsize, int segno,
   4488      1.62      haya     bus_dma_segment_t *segp, bus_dmamap_t *dmapp, void **mapp,
   4489      1.62      haya     const char *xname)
   4490      1.62      haya {
   4491      1.62      haya 	int nsegs;
   4492      1.62      haya 	int error;
   4493      1.62      haya 
   4494      1.62      haya 	printf("fwohci_misc_desc_alloc: dsize %d segno %d\n", dsize, segno);
   4495      1.62      haya 
   4496      1.62      haya 	if ((error = bus_dmamem_alloc(dmat, dsize, PAGE_SIZE, 0,
   4497      1.62      haya 	    segp, segno, &nsegs, 0)) != 0) {
   4498      1.62      haya 		printf("%s: unable to allocate descriptor buffer, error = %d\n",
   4499      1.62      haya 		    xname, error);
   4500      1.62      haya 		goto fail_0;
   4501      1.62      haya 	}
   4502      1.62      haya 
   4503      1.62      haya 	DPRINTF(("fwohci_misc_desc_alloc: %d segment[s]\n", nsegs));
   4504      1.62      haya 
   4505      1.62      haya 	if ((error = bus_dmamem_map(dmat, segp, nsegs, dsize, (caddr_t *)mapp,
   4506      1.62      haya 	    BUS_DMA_COHERENT | BUS_DMA_WAITOK)) != 0) {
   4507      1.62      haya 		printf("%s: unable to map descriptor buffer, error = %d\n",
   4508      1.62      haya 		    xname, error);
   4509      1.62      haya 		goto fail_1;
   4510      1.62      haya 	}
   4511      1.62      haya 
   4512      1.62      haya 	DPRINTF(("fwohci_misc_desc_alloc: %s map ok\n", xname));
   4513      1.62      haya 
   4514      1.62      haya #ifdef FWOHCI_DEBUG
   4515      1.62      haya 	{
   4516      1.62      haya 		int loop;
   4517      1.62      haya 
   4518      1.62      haya 		for (loop = 0; loop < nsegs; ++loop) {
   4519      1.62      haya 			printf("\t%.2d: 0x%lx - 0x%lx\n", loop,
   4520      1.62      haya 			    (long)segp[loop].ds_addr,
   4521      1.62      haya 			    (long)segp[loop].ds_addr + segp[loop].ds_len - 1);
   4522      1.62      haya 		}
   4523      1.62      haya 	}
   4524      1.62      haya #endif /* FWOHCI_DEBUG */
   4525      1.62      haya 
   4526      1.62      haya 	if ((error = bus_dmamap_create(dmat, dsize, nsegs, dsize,
   4527      1.62      haya 	    0, BUS_DMA_WAITOK, dmapp)) != 0) {
   4528      1.62      haya 		printf("%s: unable to create descriptor buffer DMA map, "
   4529      1.62      haya 		    "error = %d\n", xname, error);
   4530      1.62      haya 		goto fail_2;
   4531      1.62      haya 	}
   4532      1.62      haya 
   4533      1.62      haya 	DPRINTF(("fwohci_misc_dmabuf_alloc: bus_dmamem_create success\n"));
   4534      1.62      haya 
   4535      1.62      haya 	if ((error = bus_dmamap_load(dmat, *dmapp, *mapp, dsize, NULL,
   4536      1.62      haya 	    BUS_DMA_WAITOK)) != 0) {
   4537      1.62      haya 		printf("%s: unable to load descriptor buffer DMA map, "
   4538      1.62      haya 		    "error = %d\n", xname, error);
   4539      1.62      haya 		goto fail_3;
   4540      1.62      haya 	}
   4541      1.62      haya 
   4542      1.62      haya 	DPRINTF(("fwohci_it_desc_alloc: bus_dmamem_load success\n"));
   4543      1.62      haya 
   4544      1.62      haya 	return nsegs;
   4545      1.62      haya 
   4546      1.62      haya   fail_3:
   4547      1.62      haya 	bus_dmamap_destroy(dmat, *dmapp);
   4548      1.62      haya   fail_2:
   4549      1.62      haya 	bus_dmamem_unmap(dmat, *mapp, dsize);
   4550      1.62      haya   fail_1:
   4551      1.62      haya 	bus_dmamem_free(dmat, segp, nsegs);
   4552      1.62      haya   fail_0:
   4553      1.62      haya 	return error;
   4554      1.62      haya }
   4555      1.62      haya 
   4556      1.62      haya 
   4557      1.62      haya static void
   4558      1.62      haya fwohci_misc_dmabuf_free(bus_dma_tag_t dmat, int dsize, int nsegs,
   4559      1.62      haya     bus_dma_segment_t *segp, bus_dmamap_t *dmapp, caddr_t map)
   4560      1.62      haya {
   4561      1.62      haya 	bus_dmamap_destroy(dmat, *dmapp);
   4562      1.62      haya 	bus_dmamem_unmap(dmat, map, dsize);
   4563      1.62      haya 	bus_dmamem_free(dmat, segp, nsegs);
   4564      1.62      haya }
   4565      1.62      haya 
   4566      1.62      haya 
   4567      1.62      haya 
   4568      1.62      haya 
   4569      1.62      haya /*
   4570      1.62      haya  * Isochronous receive service
   4571      1.62      haya  */
   4572      1.62      haya 
   4573      1.62      haya /*
   4574      1.62      haya  * static struct fwohci_ir_ctx *
   4575      1.62      haya  * fwohci_ir_ctx_construct(struct fwohci_softc *sc, int no, int ch, int tagbm,
   4576      1.62      haya  *			   int bufnum, int maxsize, int flags)
   4577      1.62      haya  */
   4578      1.62      haya static struct fwohci_ir_ctx *
   4579      1.62      haya fwohci_ir_ctx_construct(struct fwohci_softc *sc, int no, int ch, int tagbm,
   4580      1.62      haya     int bufnum, int maxsize, int flags)
   4581      1.62      haya {
   4582      1.62      haya 	struct fwohci_ir_ctx *irc;
   4583      1.62      haya 	int i;
   4584      1.62      haya 
   4585      1.62      haya 	printf("fwohci_ir_construct(%s, %d, %d, %x, %d, %d\n",
   4586      1.62      haya 	    sc->sc_sc1394.sc1394_dev.dv_xname, no, ch, tagbm, bufnum, maxsize);
   4587      1.62      haya 
   4588      1.62      haya 	if ((irc = malloc(sizeof(*irc), M_DEVBUF, M_WAITOK|M_ZERO)) == NULL) {
   4589      1.62      haya 		return NULL;
   4590      1.62      haya 	}
   4591      1.62      haya 
   4592      1.62      haya 	irc->irc_sc = sc;
   4593      1.62      haya 
   4594      1.62      haya 	irc->irc_num = no;
   4595      1.62      haya 	irc->irc_status = 0;
   4596      1.62      haya 
   4597      1.62      haya 	irc->irc_channel = ch;
   4598      1.62      haya 	irc->irc_tagbm = tagbm;
   4599      1.62      haya 
   4600      1.62      haya 	irc->irc_desc_num = bufnum;
   4601      1.62      haya 
   4602      1.62      haya 	irc->irc_flags = flags;
   4603      1.62      haya 
   4604      1.62      haya 	/* add header */
   4605      1.62      haya 	maxsize += 8;
   4606      1.62      haya 	/* rounding up */
   4607      1.62      haya 	for (i = 32; i < maxsize; i <<= 1);
   4608      1.62      haya 	printf("fwohci_ir_ctx_construct: maxsize %d => %d\n",
   4609      1.62      haya 	    maxsize, i);
   4610      1.62      haya 
   4611      1.62      haya 	maxsize = i;
   4612      1.62      haya 
   4613      1.62      haya 	irc->irc_maxsize = maxsize;
   4614      1.62      haya 	irc->irc_buf_totalsize = bufnum * maxsize;
   4615      1.62      haya 
   4616      1.62      haya 	if (fwohci_ir_buf_setup(irc)) {
   4617      1.62      haya 		/* cannot alloc descriptor */
   4618      1.62      haya 		return NULL;
   4619      1.62      haya 	}
   4620      1.62      haya 
   4621      1.62      haya 	irc->irc_readtop = irc->irc_desc_map;
   4622      1.62      haya 	irc->irc_writeend = irc->irc_desc_map + irc->irc_desc_num - 1;
   4623      1.62      haya 	irc->irc_savedbranch = irc->irc_writeend->fd_branch;
   4624      1.62      haya 	irc->irc_writeend->fd_branch = 0;
   4625      1.62      haya 	/* sync */
   4626      1.62      haya 
   4627      1.62      haya 	if (fwohci_ir_stop(irc) || fwohci_ir_init(irc)) {
   4628      1.62      haya 		return NULL;
   4629      1.62      haya 	}
   4630      1.62      haya 
   4631      1.62      haya 	irc->irc_status |= IRC_STATUS_READY;
   4632      1.62      haya 
   4633      1.62      haya 	return irc;
   4634      1.62      haya }
   4635      1.62      haya 
   4636      1.62      haya 
   4637      1.62      haya 
   4638      1.62      haya /*
   4639      1.62      haya  * static void fwohci_ir_ctx_destruct(struct fwohci_ir_ctx *irc)
   4640      1.62      haya  *
   4641      1.62      haya  *	This function release all DMA buffers and itself.
   4642      1.62      haya  */
   4643      1.62      haya static void
   4644      1.62      haya fwohci_ir_ctx_destruct(struct fwohci_ir_ctx *irc)
   4645      1.62      haya {
   4646      1.62      haya 	fwohci_misc_dmabuf_free(irc->irc_sc->sc_dmat, irc->irc_buf_totalsize,
   4647      1.62      haya 	    irc->irc_buf_nsegs, irc->irc_buf_segs,
   4648      1.62      haya 	    &irc->irc_buf_dmamap, (caddr_t)irc->irc_buf);
   4649      1.62      haya 	fwohci_misc_dmabuf_free(irc->irc_sc->sc_dmat,
   4650      1.62      haya 	    irc->irc_desc_size,
   4651      1.62      haya 	    irc->irc_desc_nsegs, &irc->irc_desc_seg,
   4652      1.62      haya 	    &irc->irc_desc_dmamap, (caddr_t)irc->irc_desc_map);
   4653      1.62      haya 
   4654      1.62      haya 	free(irc, M_DEVBUF);
   4655      1.62      haya }
   4656      1.62      haya 
   4657      1.62      haya 
   4658      1.62      haya 
   4659      1.62      haya 
   4660      1.62      haya /*
   4661      1.62      haya  * static int fwohci_ir_buf_setup(struct fwohci_ir_ctx *irc)
   4662      1.62      haya  *
   4663      1.62      haya  *	Allocates descriptors for context DMA dedicated for
   4664      1.62      haya  *	isochronous receive.
   4665      1.62      haya  *
   4666      1.62      haya  *	This function returns 0 (zero) if it succeeds.  Otherwise,
   4667      1.62      haya  *	return negative value.
   4668      1.62      haya  */
   4669      1.62      haya static int
   4670      1.62      haya fwohci_ir_buf_setup(struct fwohci_ir_ctx *irc)
   4671      1.62      haya {
   4672      1.62      haya 	int nsegs;
   4673      1.62      haya 	struct fwohci_desc *fd;
   4674      1.62      haya 	u_int32_t branch;
   4675      1.62      haya 	int bufno = 0;		/* DMA segment */
   4676      1.62      haya 	bus_size_t bufused = 0;	/* offset in a DMA segment */
   4677      1.62      haya 
   4678      1.62      haya 	irc->irc_desc_size = irc->irc_desc_num * sizeof(struct fwohci_desc);
   4679      1.62      haya 
   4680      1.62      haya 	nsegs = fwohci_misc_dmabuf_alloc(irc->irc_sc->sc_dmat,
   4681      1.62      haya 	    irc->irc_desc_size, 1, &irc->irc_desc_seg, &irc->irc_desc_dmamap,
   4682      1.62      haya 	    (void **)&irc->irc_desc_map,
   4683      1.62      haya 	    irc->irc_sc->sc_sc1394.sc1394_dev.dv_xname);
   4684      1.62      haya 
   4685      1.62      haya 	if (nsegs < 0) {
   4686      1.62      haya 		printf("fwohci_ir_buf_alloc: cannot get descriptor\n");
   4687      1.62      haya 		return -1;
   4688      1.62      haya 	}
   4689      1.62      haya 	irc->irc_desc_nsegs = nsegs;
   4690      1.62      haya 
   4691      1.62      haya 	nsegs = fwohci_misc_dmabuf_alloc(irc->irc_sc->sc_dmat,
   4692      1.62      haya 	    irc->irc_buf_totalsize, 16, irc->irc_buf_segs,
   4693      1.62      haya 	    &irc->irc_buf_dmamap, (void **)&irc->irc_buf,
   4694      1.62      haya 	    irc->irc_sc->sc_sc1394.sc1394_dev.dv_xname);
   4695      1.62      haya 
   4696      1.62      haya 	if (nsegs < 0) {
   4697      1.62      haya 		printf("fwohci_ir_buf_alloc: cannot get DMA buffer\n");
   4698      1.62      haya 		fwohci_misc_dmabuf_free(irc->irc_sc->sc_dmat,
   4699      1.62      haya 		    irc->irc_desc_size,
   4700      1.62      haya 		    irc->irc_desc_nsegs, &irc->irc_desc_seg,
   4701      1.62      haya 		    &irc->irc_desc_dmamap, (caddr_t)irc->irc_desc_map);
   4702      1.62      haya 		return -1;
   4703      1.62      haya 	}
   4704      1.62      haya 	irc->irc_buf_nsegs = nsegs;
   4705      1.62      haya 
   4706      1.62      haya 	branch = irc->irc_desc_dmamap->dm_segs[0].ds_addr
   4707      1.62      haya 	    + sizeof(struct fwohci_desc);
   4708      1.62      haya 	bufno = 0;
   4709      1.62      haya 	bufused = 0;
   4710      1.62      haya 
   4711      1.62      haya 	for (fd = irc->irc_desc_map;
   4712      1.62      haya 	     fd < irc->irc_desc_map + irc->irc_desc_num; ++fd) {
   4713      1.62      haya 		fd->fd_flags = OHCI_DESC_INPUT | OHCI_DESC_LAST
   4714      1.62      haya 		    | OHCI_DESC_STATUS | OHCI_DESC_BRANCH;
   4715      1.62      haya 		if (irc->irc_flags & IEEE1394_IR_SHORTDELAY) {
   4716      1.62      haya 			fd->fd_flags |= OHCI_DESC_INTR_ALWAYS;
   4717      1.62      haya 		}
   4718      1.62      haya #if 0
   4719      1.62      haya 		if  ((fd - irc->irc_desc_map) % 64 == 0) {
   4720      1.62      haya 			fd->fd_flags |= OHCI_DESC_INTR_ALWAYS;
   4721      1.62      haya 		}
   4722      1.62      haya #endif
   4723      1.62      haya 		fd->fd_reqcount = irc->irc_maxsize;
   4724      1.62      haya 		fd->fd_status = fd->fd_rescount = 0;
   4725      1.62      haya 
   4726      1.62      haya 		fd->fd_branch = branch | 0x01;
   4727      1.62      haya 		branch += sizeof(struct fwohci_desc);
   4728      1.62      haya 
   4729      1.62      haya 		/* physical addr to data? */
   4730      1.62      haya 		fd->fd_data =
   4731      1.62      haya 		    (u_int32_t)((irc->irc_buf_segs[bufno].ds_addr + bufused));
   4732      1.62      haya 		bufused += irc->irc_maxsize;
   4733      1.62      haya 		if (bufused > irc->irc_buf_segs[bufno].ds_len) {
   4734      1.62      haya 			bufused = 0;
   4735      1.62      haya 			if (++bufno == irc->irc_buf_nsegs) {
   4736      1.62      haya 				/* fail */
   4737      1.62      haya 				printf("fwohci_ir_buf_setup fail\n");
   4738      1.62      haya 
   4739      1.62      haya 				fwohci_misc_dmabuf_free(irc->irc_sc->sc_dmat,
   4740      1.62      haya 				    irc->irc_desc_size,
   4741      1.62      haya 				    irc->irc_desc_nsegs, &irc->irc_desc_seg,
   4742      1.62      haya 				    &irc->irc_desc_dmamap,
   4743      1.62      haya 				    (caddr_t)irc->irc_desc_map);
   4744      1.62      haya 				fwohci_misc_dmabuf_free(irc->irc_sc->sc_dmat,
   4745      1.62      haya 				    irc->irc_buf_totalsize,
   4746      1.62      haya 				    irc->irc_buf_nsegs, irc->irc_buf_segs,
   4747      1.62      haya 				    &irc->irc_buf_dmamap,
   4748      1.62      haya 				    (caddr_t)irc->irc_buf);
   4749      1.62      haya 				return -1;
   4750      1.62      haya 			}
   4751      1.62      haya 		}
   4752      1.62      haya 
   4753      1.62      haya #ifdef FWOHCI_DEBUG
   4754      1.62      haya 		if (fd < irc->irc_desc_map + 4
   4755      1.62      haya 		    || (fd > irc->irc_desc_map + irc->irc_desc_num - 4)) {
   4756      1.62      haya 			printf("fwohci_ir_buf_setup: desc %d %p buf %08x"
   4757      1.62      haya 			    " size %d branch %08x\n",
   4758      1.62      haya 			    fd - irc->irc_desc_map, fd, fd->fd_data,
   4759      1.62      haya 			    fd->fd_reqcount, fd->fd_branch);
   4760      1.62      haya 		}
   4761      1.62      haya #endif /* FWOHCI_DEBUG */
   4762      1.62      haya 	}
   4763      1.62      haya 
   4764      1.62      haya 	--fd;
   4765      1.62      haya 	fd->fd_branch = irc->irc_desc_dmamap->dm_segs[0].ds_addr | 1;
   4766      1.62      haya 	DPRINTF(("fwohci_ir_buf_setup: desc %d %p buf %08x size %d branch %08x\n",
   4767      1.74  christos 	    (int)(fd - irc->irc_desc_map), fd, fd->fd_data, fd->fd_reqcount,
   4768      1.62      haya 	    fd->fd_branch));
   4769      1.62      haya 
   4770      1.62      haya 	return 0;
   4771      1.62      haya }
   4772      1.62      haya 
   4773      1.62      haya 
   4774      1.62      haya 
   4775      1.62      haya /*
   4776      1.62      haya  * static void fwohci_ir_init(struct fwohci_ir_ctx *irc)
   4777      1.62      haya  *
   4778      1.62      haya  *	This function initialise DMA engine.
   4779      1.62      haya  */
   4780      1.62      haya static int
   4781      1.62      haya fwohci_ir_init(struct fwohci_ir_ctx *irc)
   4782      1.62      haya {
   4783      1.62      haya 	struct fwohci_softc *sc = irc->irc_sc;
   4784      1.62      haya 	int n = irc->irc_num;
   4785      1.62      haya 	u_int32_t ctxmatch;
   4786      1.62      haya 
   4787      1.62      haya 	ctxmatch = irc->irc_channel & IEEE1394_ISO_CHANNEL_MASK;
   4788      1.62      haya 
   4789      1.62      haya 	if (irc->irc_channel & IEEE1394_ISO_CHANNEL_ANY) {
   4790      1.62      haya 		OHCI_SYNC_RX_DMA_WRITE(sc, n,
   4791      1.62      haya 		    OHCI_SUBREG_ContextControlSet,
   4792      1.62      haya 		    OHCI_CTXCTL_RX_MULTI_CHAN_MODE);
   4793      1.62      haya 
   4794      1.62      haya 		/* Receive all the isochronous channels */
   4795      1.62      haya 		OHCI_CSR_WRITE(sc, OHCI_REG_IRMultiChanMaskHiSet, 0xffffffff);
   4796      1.62      haya 		OHCI_CSR_WRITE(sc, OHCI_REG_IRMultiChanMaskLoSet, 0xffffffff);
   4797      1.62      haya 		ctxmatch = 0;
   4798      1.62      haya 	}
   4799      1.62      haya 
   4800      1.62      haya 	ctxmatch |= ((irc->irc_tagbm & 0x0f) << OHCI_CTXMATCH_TAG_BITPOS);
   4801      1.62      haya 	OHCI_SYNC_RX_DMA_WRITE(sc, n, OHCI_SUBREG_ContextMatch, ctxmatch);
   4802      1.62      haya 
   4803      1.62      haya 	OHCI_SYNC_RX_DMA_WRITE(sc, n, OHCI_SUBREG_ContextControlClear,
   4804      1.62      haya 	    OHCI_CTXCTL_RX_BUFFER_FILL | OHCI_CTXCTL_RX_CYCLE_MATCH_ENABLE);
   4805      1.62      haya 	OHCI_SYNC_RX_DMA_WRITE(sc, n, OHCI_SUBREG_ContextControlSet,
   4806      1.62      haya 	    OHCI_CTXCTL_RX_ISOCH_HEADER);
   4807      1.62      haya 
   4808      1.62      haya 	printf("fwohci_ir_init\n");
   4809      1.62      haya 
   4810      1.62      haya 	return 0;
   4811      1.62      haya }
   4812      1.62      haya 
   4813      1.62      haya 
   4814      1.62      haya /*
   4815      1.62      haya  * static int fwohci_ir_start(struct fwohci_ir_ctx *irc)
   4816      1.62      haya  *
   4817      1.62      haya  *	This function starts DMA engine.  This function must call
   4818      1.62      haya  *	after fwohci_ir_init() and active bit of context control
   4819      1.62      haya  *	register negated.  This function will not check it.
   4820      1.62      haya  */
   4821      1.62      haya static int
   4822      1.62      haya fwohci_ir_start(struct fwohci_ir_ctx *irc)
   4823      1.62      haya {
   4824      1.62      haya 	struct fwohci_softc *sc = irc->irc_sc;
   4825      1.62      haya 	int startidx = irc->irc_readtop - irc->irc_desc_map;
   4826      1.62      haya 	u_int32_t startaddr;
   4827      1.62      haya 
   4828      1.62      haya 	startaddr = irc->irc_desc_dmamap->dm_segs[0].ds_addr
   4829      1.62      haya 	    + sizeof(struct fwohci_desc)*startidx;
   4830      1.62      haya 
   4831      1.62      haya 	OHCI_SYNC_RX_DMA_WRITE(sc, irc->irc_num, OHCI_SUBREG_CommandPtr,
   4832      1.62      haya 	    startaddr | 1);
   4833      1.62      haya 	OHCI_CSR_WRITE(sc, OHCI_REG_IsoRecvIntEventClear,
   4834      1.62      haya 		    (1 << irc->irc_num));
   4835      1.62      haya 	OHCI_SYNC_RX_DMA_WRITE(sc, irc->irc_num,
   4836      1.62      haya 	    OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_RUN);
   4837      1.62      haya 
   4838      1.62      haya 	printf("fwohci_ir_start: CmdPtr %08x Ctx %08x startidx %d\n",
   4839      1.62      haya 	    OHCI_SYNC_RX_DMA_READ(sc, irc->irc_num, OHCI_SUBREG_CommandPtr),
   4840      1.62      haya 	    OHCI_SYNC_RX_DMA_READ(sc, irc->irc_num, OHCI_SUBREG_ContextControlSet),
   4841      1.62      haya 	    startidx);
   4842      1.62      haya 
   4843      1.62      haya 	irc->irc_status &= ~IRC_STATUS_READY;
   4844      1.62      haya 	irc->irc_status |= IRC_STATUS_RUN;
   4845      1.62      haya 
   4846      1.62      haya 	if ((irc->irc_flags & IEEE1394_IR_TRIGGER_CIP_SYNC) == 0) {
   4847      1.62      haya 		irc->irc_status |= IRC_STATUS_RECEIVE;
   4848      1.62      haya 	}
   4849      1.62      haya 
   4850      1.62      haya 	return 0;
   4851      1.62      haya }
   4852      1.62      haya 
   4853      1.62      haya 
   4854      1.62      haya 
   4855      1.62      haya /*
   4856      1.62      haya  * static int fwohci_ir_stop(struct fwohci_ir_ctx *irc)
   4857      1.62      haya  *
   4858      1.62      haya  *	This function stops DMA engine.
   4859      1.62      haya  */
   4860      1.62      haya static int
   4861      1.62      haya fwohci_ir_stop(struct fwohci_ir_ctx *irc)
   4862      1.62      haya {
   4863      1.62      haya 	struct fwohci_softc *sc = irc->irc_sc;
   4864      1.62      haya 	int i;
   4865      1.62      haya 
   4866      1.62      haya 	printf("fwohci_ir_stop\n");
   4867      1.62      haya 
   4868      1.62      haya 	OHCI_SYNC_RX_DMA_WRITE(sc, irc->irc_num,
   4869      1.62      haya 	    OHCI_SUBREG_ContextControlClear,
   4870      1.62      haya 	    OHCI_CTXCTL_RUN | OHCI_CTXCTL_DEAD);
   4871      1.62      haya 
   4872      1.62      haya 	i = 0;
   4873      1.62      haya 	while (OHCI_SYNC_RX_DMA_READ(sc, irc->irc_num,
   4874      1.62      haya 	    OHCI_SUBREG_ContextControlSet) & OHCI_CTXCTL_ACTIVE) {
   4875      1.62      haya #if 0
   4876      1.62      haya 		u_int32_t reg = OHCI_SYNC_RX_DMA_READ(sc, irc->irc_num,
   4877      1.62      haya 		    OHCI_SUBREG_ContextControlClear);
   4878      1.62      haya 
   4879      1.62      haya 		printf("%s: %d intr IR_CommandPtr 0x%08x "
   4880      1.62      haya 		    "ContextCtrl 0x%08x%s%s%s%s\n",
   4881      1.62      haya 		    sc->sc_sc1394.sc1394_dev.dv_xname, i,
   4882      1.62      haya 		    OHCI_SYNC_RX_DMA_READ(sc, irc->irc_num,
   4883      1.62      haya 			OHCI_SUBREG_CommandPtr),
   4884      1.62      haya 		    reg,
   4885      1.62      haya 		    reg & OHCI_CTXCTL_RUN ? " run" : "",
   4886      1.62      haya 		    reg & OHCI_CTXCTL_WAKE ? " wake" : "",
   4887      1.62      haya 		    reg & OHCI_CTXCTL_DEAD ? " dead" : "",
   4888      1.62      haya 		    reg & OHCI_CTXCTL_ACTIVE ? " active" : "");
   4889      1.62      haya #endif
   4890      1.62      haya 		if (i > 20) {
   4891      1.62      haya 			printf("fwohci_ir_stop: %s does not stop\n",
   4892      1.62      haya 			    sc->sc_sc1394.sc1394_dev.dv_xname);
   4893      1.62      haya 			return 1;
   4894      1.62      haya 		}
   4895      1.62      haya 		DELAY(10);
   4896      1.62      haya 	}
   4897      1.62      haya 
   4898      1.62      haya 	irc->irc_status &= ~IRC_STATUS_RUN;
   4899      1.62      haya 
   4900      1.62      haya 	return 0;
   4901      1.62      haya }
   4902      1.62      haya 
   4903      1.62      haya 
   4904      1.62      haya 
   4905      1.62      haya 
   4906      1.62      haya 
   4907      1.62      haya 
   4908      1.62      haya static void
   4909      1.62      haya fwohci_ir_intr(struct fwohci_softc *sc, struct fwohci_ir_ctx *irc)
   4910      1.62      haya {
   4911      1.62      haya 	const char *xname = sc->sc_sc1394.sc1394_dev.dv_xname;
   4912      1.62      haya 	u_int32_t cmd, ctx;
   4913      1.62      haya 	int idx;
   4914      1.62      haya 	struct fwohci_desc *fd;
   4915      1.62      haya 
   4916      1.62      haya 	sc->sc_isocnt.ev_count++;
   4917      1.62      haya 
   4918      1.62      haya 	if (!(irc->irc_status & IRC_STATUS_RUN)) {
   4919      1.62      haya 		printf("fwohci_ir_intr: not running\n");
   4920      1.62      haya 		return;
   4921      1.62      haya 	}
   4922      1.62      haya 
   4923      1.62      haya 	bus_dmamap_sync(sc->sc_dmat, irc->irc_desc_dmamap,
   4924      1.62      haya 	    0, irc->irc_desc_size, BUS_DMASYNC_PREREAD);
   4925      1.62      haya 
   4926      1.62      haya 	ctx = OHCI_SYNC_RX_DMA_READ(sc, irc->irc_num,
   4927      1.62      haya 	    OHCI_SUBREG_ContextControlSet);
   4928      1.62      haya 
   4929      1.62      haya 	cmd = OHCI_SYNC_RX_DMA_READ(sc, irc->irc_num,
   4930      1.62      haya 	    OHCI_SUBREG_CommandPtr);
   4931      1.62      haya 
   4932      1.62      haya #define OHCI_CTXCTL_RUNNING (OHCI_CTXCTL_RUN|OHCI_CTXCTL_ACTIVE)
   4933      1.62      haya #define OHCI_CTXCTL_RUNNING_MASK (OHCI_CTXCTL_RUNNING|OHCI_CTXCTL_DEAD)
   4934      1.62      haya 
   4935      1.62      haya 	idx = (cmd & 0xfffffff8) - (u_int32_t)irc->irc_desc_dmamap->dm_segs[0].ds_addr;
   4936      1.62      haya 	idx /= sizeof(struct fwohci_desc);
   4937      1.62      haya 
   4938      1.62      haya 	if ((ctx & OHCI_CTXCTL_RUNNING_MASK) == OHCI_CTXCTL_RUNNING) {
   4939      1.62      haya 		if (irc->irc_waitchan != NULL) {
   4940      1.62      haya 			DPRINTF(("fwohci_ir_intr: wakeup "
   4941      1.62      haya 			    "ctx %d CmdPtr %08x Ctxctl %08x idx %d\n",
   4942      1.62      haya 			    irc->irc_num, cmd, ctx, idx));
   4943      1.62      haya #ifdef FWOHCI_WAIT_DEBUG
   4944      1.62      haya 			irc->irc_cycle[1] = fwohci_cycletimer(irc->irc_sc);
   4945      1.62      haya #endif
   4946      1.62      haya 			wakeup((void *)irc->irc_waitchan);
   4947      1.62      haya 		}
   4948      1.62      haya 		selwakeup(&irc->irc_sel);
   4949      1.62      haya 		return;
   4950      1.62      haya 	}
   4951      1.62      haya 
   4952      1.62      haya 	fd = irc->irc_desc_map + idx;
   4953      1.62      haya 
   4954      1.62      haya 	printf("fwohci_ir_intr: %s error "
   4955      1.62      haya 	    "ctx %d CmdPtr %08x Ctxctl %08x idx %d\n", xname,
   4956      1.62      haya 	    irc->irc_num, cmd, ctx, idx);
   4957      1.62      haya 	printf("\tfd flag %x branch %x stat %x rescnt %x total pkt %d\n",
   4958      1.62      haya 	    fd->fd_flags, fd->fd_branch, fd->fd_status,fd->fd_rescount,
   4959      1.62      haya 	    irc->irc_pktcount);
   4960      1.62      haya }
   4961      1.62      haya 
   4962      1.62      haya 
   4963      1.62      haya 
   4964      1.62      haya 
   4965      1.62      haya /*
   4966      1.62      haya  * static int fwohci_ir_ctx_packetnum(struct fwohci_ir_ctx *irc)
   4967      1.62      haya  *
   4968      1.62      haya  *	This function obtains the lenth of descriptors with data.
   4969      1.62      haya  */
   4970      1.62      haya static int
   4971      1.62      haya fwohci_ir_ctx_packetnum(struct fwohci_ir_ctx *irc)
   4972      1.62      haya {
   4973      1.62      haya 	struct fwohci_desc *fd = irc->irc_readtop;
   4974      1.62      haya 	int i = 0;
   4975      1.62      haya 
   4976      1.62      haya 	/* XXX SYNC */
   4977      1.62      haya 	while (fd->fd_status != 0) {
   4978      1.62      haya 		if (fd == irc->irc_readtop && i > 0) {
   4979      1.62      haya 			printf("descriptor filled %d at %d\n", i,
   4980      1.62      haya 			    irc->irc_pktcount);
   4981      1.62      haya #ifdef FWOHCI_WAIT_DEBUG
   4982      1.62      haya 			irc->irc_cycle[2] = fwohci_cycletimer(irc->irc_sc);
   4983      1.62      haya 			printf("cycletimer %d:%d %d:%d %d:%d\n",
   4984      1.62      haya 			    irc->irc_cycle[0]>>13, irc->irc_cycle[0]&0x1fff,
   4985      1.62      haya 			    irc->irc_cycle[1]>>13, irc->irc_cycle[1]&0x1fff,
   4986      1.62      haya 			    irc->irc_cycle[2]>>13, irc->irc_cycle[2]&0x1fff);
   4987      1.62      haya #endif
   4988      1.62      haya 
   4989      1.62      haya 			break;
   4990      1.62      haya 		}
   4991      1.62      haya 
   4992      1.62      haya 		++i;
   4993      1.62      haya 		++fd;
   4994      1.62      haya 		if (fd == irc->irc_desc_map + irc->irc_desc_num) {
   4995      1.62      haya 			fd = irc->irc_desc_map;
   4996      1.62      haya 		}
   4997      1.62      haya 
   4998      1.62      haya 	}
   4999      1.62      haya 
   5000      1.62      haya 	return i;
   5001      1.62      haya }
   5002      1.62      haya 
   5003      1.62      haya 
   5004      1.62      haya 
   5005      1.62      haya 
   5006      1.62      haya /*
   5007      1.62      haya  * int fwohci_ir_read(struct device *dev, ieee1394_ir_tag_t tag,
   5008      1.62      haya  *		      struct uio *uio, int headoffs, int flags)
   5009      1.62      haya  *
   5010      1.62      haya  *	This function reads data from fwohci's isochronous receive
   5011      1.62      haya  *	buffer.
   5012      1.62      haya  */
   5013      1.62      haya int
   5014      1.62      haya fwohci_ir_read(struct device *dev, ieee1394_ir_tag_t tag, struct uio *uio,
   5015      1.62      haya     int headoffs, int flags)
   5016      1.62      haya {
   5017      1.62      haya 	struct fwohci_ir_ctx *irc = (struct fwohci_ir_ctx *)tag;
   5018      1.62      haya 	int packetnum;
   5019      1.62      haya 	int copylen, hdrshim, fwisohdrsiz;
   5020  1.78.2.2     skrll 	struct fwohci_desc *fd, *fdprev = NULL;	/* XXX fdprev use is suspect */
   5021      1.62      haya 	u_int8_t *data;
   5022      1.62      haya 	int status = 0;
   5023      1.62      haya 	u_int32_t tmpbranch;
   5024      1.62      haya 	int pktcount_prev = irc->irc_pktcount;
   5025      1.62      haya #ifdef FW_DEBUG
   5026      1.62      haya 	int totalread = 0;
   5027      1.62      haya #endif
   5028      1.62      haya 
   5029      1.62      haya 	if (irc->irc_status & IRC_STATUS_READY) {
   5030      1.62      haya 		printf("fwohci_ir_read: starting iso read engine\n");
   5031      1.62      haya 		fwohci_ir_start(irc);
   5032      1.62      haya 	}
   5033      1.62      haya 
   5034      1.62      haya 	packetnum = fwohci_ir_ctx_packetnum(irc);
   5035      1.62      haya 
   5036      1.74  christos 	DPRINTF(("fwohci_ir_read resid %lu DMA buf %d\n",
   5037      1.74  christos 	    (unsigned long)uio->uio_resid, packetnum));
   5038      1.62      haya 
   5039      1.62      haya 	if (packetnum == 0) {
   5040      1.62      haya 		return EAGAIN;
   5041      1.62      haya 	}
   5042      1.62      haya 
   5043      1.62      haya #ifdef USEDRAIN
   5044      1.62      haya 	if (packetnum > irc->irc_desc_num - irc->irc_desc_num/4) {
   5045      1.62      haya 		packetnum -= fwohci_ir_ctx_drain(irc);
   5046      1.62      haya 		if (irc->irc_pktcount != 0) {
   5047      1.62      haya 			printf("fwohci_ir_read overrun %d\n",
   5048      1.62      haya 			    irc->irc_pktcount);
   5049      1.62      haya 		}
   5050      1.62      haya 	}
   5051      1.62      haya #endif /* USEDRAIN */
   5052      1.62      haya 
   5053      1.62      haya 	fd = irc->irc_readtop;
   5054      1.62      haya 
   5055      1.62      haya #if 0
   5056      1.62      haya 	if ((irc->irc_status & IRC_STATUS_RECEIVE) == 0
   5057      1.62      haya 	    && irc->irc_flags & IEEE1394_IR_TRIGGER_CIP_SYNC) {
   5058      1.62      haya 		unsigned int s;
   5059      1.62      haya 		int i = 0;
   5060      1.62      haya 
   5061      1.62      haya 		fdprev = fd;
   5062      1.62      haya 		while (fd->fd_status != 0) {
   5063      1.62      haya 			s = data[14] << 8;
   5064      1.62      haya 			s |= data[15];
   5065      1.62      haya 
   5066      1.62      haya 			if (s != 0x0000ffffu) {
   5067      1.62      haya 				DPRINTF(("find header %x at %d\n",
   5068      1.62      haya 				    s, irc->irc_pktcount));
   5069      1.62      haya 				irc->irc_status |= IRC_STATUS_RECEIVE;
   5070      1.62      haya 				break;
   5071      1.62      haya 			}
   5072      1.62      haya 
   5073      1.62      haya 			fd->fd_rescount = 0;
   5074      1.62      haya 			fd->fd_status = 0;
   5075      1.62      haya 
   5076      1.62      haya 			fdprev = fd;
   5077      1.62      haya 			if (++fd == irc->irc_desc_map + irc->irc_desc_num) {
   5078      1.62      haya 				fd = irc->irc_desc_map;
   5079      1.62      haya 				data = irc->irc_buf;
   5080      1.62      haya 			}
   5081      1.62      haya 			++i;
   5082      1.62      haya 		}
   5083      1.62      haya 
   5084      1.62      haya 		/* XXX SYNC */
   5085      1.62      haya 		if (i > 0) {
   5086      1.62      haya 			tmpbranch = fdprev->fd_branch;
   5087      1.62      haya 			fdprev->fd_branch = 0;
   5088      1.62      haya 			irc->irc_writeend->fd_branch = irc->irc_savedbranch;
   5089      1.62      haya 			irc->irc_writeend = fdprev;
   5090      1.62      haya 			irc->irc_savedbranch = tmpbranch;
   5091      1.62      haya 		}
   5092      1.62      haya 		/* XXX SYNC */
   5093      1.62      haya 
   5094      1.62      haya 		if (fd->fd_status == 0) {
   5095      1.62      haya 			return EAGAIN;
   5096      1.62      haya 		}
   5097      1.62      haya 	}
   5098      1.62      haya #endif
   5099      1.62      haya 
   5100      1.62      haya 	hdrshim = 8;
   5101      1.62      haya 	fwisohdrsiz = 0;
   5102      1.62      haya 	data = irc->irc_buf + (fd - irc->irc_desc_map) * irc->irc_maxsize;
   5103      1.62      haya 	if (irc->irc_flags & IEEE1394_IR_NEEDHEADER) {
   5104      1.62      haya 		fwisohdrsiz = sizeof(struct fwiso_header);
   5105      1.62      haya 	}
   5106      1.62      haya 
   5107      1.62      haya 	while (fd->fd_status != 0 &&
   5108      1.62      haya 	    (copylen = fd->fd_reqcount - fd->fd_rescount - hdrshim - headoffs)
   5109      1.76      haya 	    + fwisohdrsiz <= uio->uio_resid) {
   5110      1.62      haya 
   5111      1.62      haya 		DPRINTF(("pkt %04x:%04x uiomove %p, %d\n",
   5112      1.62      haya 		    fd->fd_status, fd->fd_rescount,
   5113      1.62      haya 		    (void *)(data + 8 + headoffs), copylen));
   5114      1.62      haya 		if ((irc->irc_status & IRC_STATUS_RECEIVE) == 0) {
   5115      1.62      haya 			DPRINTF(("[%d]", copylen));
   5116      1.62      haya 			if (irc->irc_pktcount > 1000) {
   5117      1.62      haya 				printf("no header found\n");
   5118      1.62      haya 				status = EIO;
   5119      1.62      haya 				break; /* XXX */
   5120      1.62      haya 			}
   5121      1.62      haya 		} else {
   5122      1.62      haya 			DPRINTF(("<%d>", copylen));
   5123      1.62      haya 		}
   5124      1.62      haya 
   5125      1.62      haya 		if ((irc->irc_status & IRC_STATUS_RECEIVE) == 0
   5126      1.62      haya 		    && irc->irc_flags & IEEE1394_IR_TRIGGER_CIP_SYNC
   5127      1.62      haya 		    && copylen > 0) {
   5128      1.62      haya 			unsigned int s;
   5129      1.62      haya 
   5130      1.62      haya 			s = data[14] << 8;
   5131      1.62      haya 			s |= data[15];
   5132      1.62      haya 
   5133      1.62      haya 			if (s != 0x0000ffffu) {
   5134      1.62      haya 				DPRINTF(("find header %x at %d\n",
   5135      1.62      haya 				    s, irc->irc_pktcount));
   5136      1.62      haya 				irc->irc_status |= IRC_STATUS_RECEIVE;
   5137      1.62      haya 			}
   5138      1.62      haya 		}
   5139      1.62      haya 
   5140      1.62      haya 		if (irc->irc_status & IRC_STATUS_RECEIVE) {
   5141      1.62      haya 			if (copylen > 0) {
   5142      1.62      haya 				if (irc->irc_flags & IEEE1394_IR_NEEDHEADER) {
   5143      1.62      haya 					struct fwiso_header fh;
   5144      1.62      haya 
   5145      1.62      haya 					fh.fh_timestamp = htonl((*(u_int32_t *)data) & 0xffff);
   5146      1.62      haya 					fh.fh_speed = htonl((fd->fd_status >> 5)& 0x00000007);
   5147      1.62      haya 					fh.fh_capture_size = htonl(copylen + 4);
   5148      1.62      haya 					fh.fh_iso_header = htonl(*(u_int32_t *)(data + 4));
   5149      1.62      haya 					status = uiomove((void *)&fh,
   5150      1.62      haya 					    sizeof(fh), uio);
   5151      1.62      haya 					if (status != 0) {
   5152      1.62      haya 						/* An error happens */
   5153      1.62      haya 						printf("uio error in hdr\n");
   5154      1.62      haya 						break;
   5155      1.62      haya 					}
   5156      1.62      haya 				}
   5157      1.62      haya 				status = uiomove((void *)(data + 8 + headoffs),
   5158      1.62      haya 				    copylen, uio);
   5159      1.62      haya 				if (status != 0) {
   5160      1.62      haya 					/* An error happens */
   5161      1.62      haya 					printf("uio error\n");
   5162      1.62      haya 					break;
   5163      1.62      haya 				}
   5164      1.62      haya #ifdef FW_DEBUG
   5165      1.62      haya 				totalread += copylen;
   5166      1.62      haya #endif
   5167      1.62      haya 			}
   5168      1.62      haya 		}
   5169      1.62      haya 
   5170      1.62      haya 		fd->fd_rescount = 0;
   5171      1.62      haya 		fd->fd_status = 0;
   5172      1.62      haya 
   5173      1.62      haya #if 0
   5174      1.62      haya 		/* advance writeend pointer and fill branch */
   5175      1.62      haya 
   5176      1.62      haya 		tmpbranch = fd->fd_branch;
   5177      1.62      haya 		fd->fd_branch = 0;
   5178      1.62      haya 		irc->irc_writeend->fd_branch = irc->irc_savedbranch;
   5179      1.62      haya 		irc->irc_writeend = fd;
   5180      1.62      haya 		irc->irc_savedbranch = tmpbranch;
   5181      1.62      haya #endif
   5182      1.62      haya 		fdprev = fd;
   5183      1.62      haya 
   5184      1.62      haya 		data += irc->irc_maxsize;
   5185      1.62      haya 		if (++fd == irc->irc_desc_map + irc->irc_desc_num) {
   5186      1.62      haya 			fd = irc->irc_desc_map;
   5187      1.62      haya 			data = irc->irc_buf;
   5188      1.62      haya 		}
   5189      1.62      haya 		++irc->irc_pktcount;
   5190      1.62      haya 	}
   5191      1.62      haya 
   5192      1.62      haya #if 1
   5193      1.62      haya 	if (irc->irc_pktcount != pktcount_prev) {
   5194      1.62      haya 		/* XXX SYNC */
   5195      1.62      haya 		tmpbranch = fdprev->fd_branch;
   5196      1.62      haya 		fdprev->fd_branch = 0;
   5197      1.62      haya 		irc->irc_writeend->fd_branch = irc->irc_savedbranch;
   5198      1.62      haya 		irc->irc_writeend = fdprev;
   5199      1.62      haya 		irc->irc_savedbranch = tmpbranch;
   5200      1.62      haya 		/* XXX SYNC */
   5201      1.62      haya 	}
   5202      1.62      haya #endif
   5203      1.62      haya 
   5204      1.62      haya 	if (!(OHCI_SYNC_RX_DMA_READ(irc->irc_sc, irc->irc_num,
   5205      1.62      haya 	    OHCI_SUBREG_ContextControlClear) & OHCI_CTXCTL_ACTIVE)) {
   5206      1.62      haya 		/* do wake */
   5207      1.62      haya 		OHCI_SYNC_RX_DMA_WRITE(irc->irc_sc, irc->irc_num,
   5208      1.62      haya 		    OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_WAKE);
   5209      1.62      haya 	}
   5210      1.62      haya 
   5211      1.62      haya 	if (packetnum > irc->irc_maxqueuelen) {
   5212      1.62      haya 		irc->irc_maxqueuelen = packetnum;
   5213      1.62      haya 		irc->irc_maxqueuepos = irc->irc_pktcount;
   5214      1.62      haya 	}
   5215      1.62      haya 
   5216      1.62      haya 	if (irc->irc_pktcount == pktcount_prev) {
   5217      1.62      haya #if 0
   5218      1.62      haya 		printf("fwohci_ir_read: process 0 packet, total %d\n",
   5219      1.62      haya 		    irc->irc_pktcount);
   5220      1.62      haya 		if (++pktfail > 30) {
   5221      1.62      haya 			return 0;
   5222      1.62      haya 		}
   5223      1.62      haya #endif
   5224      1.62      haya 		return EAGAIN;
   5225      1.62      haya 	}
   5226      1.62      haya 
   5227      1.62      haya 	irc->irc_readtop = fd;
   5228      1.62      haya 
   5229      1.62      haya 	DPRINTF(("fwochi_ir_read: process %d packet, total %d\n",
   5230      1.62      haya 	    totalread, irc->irc_pktcount));
   5231      1.62      haya 
   5232      1.62      haya 	return status;
   5233      1.62      haya }
   5234      1.62      haya 
   5235      1.62      haya 
   5236      1.62      haya 
   5237      1.62      haya 
   5238      1.62      haya /*
   5239      1.62      haya  * int fwohci_ir_wait(struct device *dev, ieee1394_ir_tag_t tag,
   5240      1.62      haya  *		      void *wchan, char *name)
   5241      1.62      haya  *
   5242      1.62      haya  *	This function waits till new data comes.
   5243      1.62      haya  */
   5244      1.62      haya int
   5245      1.62      haya fwohci_ir_wait(struct device *dev, ieee1394_ir_tag_t tag, void *wchan, char *name)
   5246      1.62      haya {
   5247      1.62      haya 	struct fwohci_ir_ctx *irc = (struct fwohci_ir_ctx *)tag;
   5248      1.62      haya 	struct fwohci_desc *fd;
   5249      1.62      haya 	int pktnum;
   5250      1.62      haya 	int stat;
   5251      1.62      haya 
   5252      1.62      haya 	if ((pktnum = fwohci_ir_ctx_packetnum(irc)) > 4) {
   5253      1.62      haya 		DPRINTF(("fwohci_ir_wait enough data %d\n", pktnum));
   5254      1.62      haya 		return 0;
   5255      1.62      haya 	}
   5256      1.62      haya 
   5257      1.62      haya 	fd = irc->irc_readtop + 32;
   5258      1.62      haya 	if (fd >= irc->irc_desc_map + irc->irc_desc_num) {
   5259      1.62      haya 		fd -= irc->irc_desc_num;
   5260      1.62      haya 	}
   5261      1.62      haya 
   5262      1.62      haya 	irc->irc_waitchan = wchan;
   5263      1.62      haya 	if ((irc->irc_flags & IEEE1394_IR_SHORTDELAY) == 0) {
   5264      1.62      haya 		fd->fd_flags |= OHCI_DESC_INTR_ALWAYS;
   5265      1.62      haya 		DPRINTF(("fwohci_ir_wait stops %d set intr %d\n",
   5266      1.74  christos 		    (int)(irc->irc_readtop - irc->irc_desc_map),
   5267      1.74  christos 		    (int)(fd - irc->irc_desc_map)));
   5268      1.62      haya 		/* XXX SYNC */
   5269      1.62      haya 	}
   5270      1.62      haya 
   5271      1.62      haya #ifdef FWOHCI_WAIT_DEBUG
   5272      1.62      haya 	irc->irc_cycle[0] = fwohci_cycletimer(irc->irc_sc);
   5273      1.62      haya #endif
   5274      1.62      haya 
   5275      1.62      haya 	irc->irc_status |= IRC_STATUS_SLEEPING;
   5276      1.62      haya 	if ((stat = tsleep(wchan, PCATCH|PRIBIO, name, hz*10)) != 0) {
   5277      1.62      haya 		irc->irc_waitchan = NULL;
   5278      1.62      haya 		fd->fd_flags &= ~OHCI_DESC_INTR_ALWAYS;
   5279      1.62      haya 		if (stat == EWOULDBLOCK) {
   5280      1.62      haya 			printf("fwohci_ir_wait: timeout\n");
   5281      1.62      haya 			return EIO;
   5282      1.62      haya 		} else {
   5283      1.62      haya 			return EINTR;
   5284      1.62      haya 		}
   5285      1.62      haya 	}
   5286      1.62      haya 
   5287      1.62      haya 	irc->irc_waitchan = NULL;
   5288      1.62      haya 	if ((irc->irc_flags & IEEE1394_IR_SHORTDELAY) == 0) {
   5289      1.62      haya 		fd->fd_flags &= ~OHCI_DESC_INTR_ALWAYS;
   5290      1.62      haya 		/* XXX SYNC */
   5291      1.62      haya 	}
   5292      1.62      haya 
   5293      1.62      haya 	DPRINTF(("fwohci_ir_wait: wakeup\n"));
   5294      1.62      haya 
   5295      1.62      haya 	return 0;
   5296      1.62      haya }
   5297      1.62      haya 
   5298      1.62      haya 
   5299      1.62      haya 
   5300      1.62      haya 
   5301      1.62      haya /*
   5302      1.62      haya  * int fwohci_ir_select(struct device *dev, ieee1394_ir_tag_t tag,
   5303  1.78.2.4     skrll  *			   struct lwp *l)
   5304      1.62      haya  *
   5305      1.62      haya  *	This function returns the number of packets in queue.
   5306      1.62      haya  */
   5307      1.62      haya int
   5308  1.78.2.4     skrll fwohci_ir_select(struct device *dev, ieee1394_ir_tag_t tag, struct lwp *l)
   5309      1.62      haya {
   5310      1.62      haya 	struct fwohci_ir_ctx *irc = (struct fwohci_ir_ctx *)tag;
   5311      1.62      haya 	int pktnum;
   5312      1.62      haya 
   5313      1.62      haya 	if (irc->irc_status & IRC_STATUS_READY) {
   5314      1.62      haya 		printf("fwohci_ir_select: starting iso read engine\n");
   5315      1.62      haya 		fwohci_ir_start(irc);
   5316      1.62      haya 	}
   5317      1.62      haya 
   5318      1.62      haya 	if ((pktnum = fwohci_ir_ctx_packetnum(irc)) == 0) {
   5319  1.78.2.4     skrll 		selrecord(l, &irc->irc_sel);
   5320      1.62      haya 	}
   5321      1.62      haya 
   5322      1.62      haya 	return pktnum;
   5323      1.62      haya }
   5324      1.62      haya 
   5325      1.62      haya 
   5326      1.62      haya 
   5327      1.62      haya #ifdef USEDRAIN
   5328      1.62      haya /*
   5329      1.62      haya  * int fwohci_ir_ctx_drain(struct fwohci_ir_ctx *irc)
   5330      1.62      haya  *
   5331      1.62      haya  *	This function will drain all the packets in receive DMA
   5332      1.62      haya  *	buffer.
   5333      1.62      haya  */
   5334      1.62      haya static int
   5335      1.62      haya fwohci_ir_ctx_drain(struct fwohci_ir_ctx *irc)
   5336      1.62      haya {
   5337      1.62      haya 	struct fwohci_desc *fd = irc->irc_readtop;
   5338      1.62      haya 	u_int32_t reg;
   5339      1.62      haya 	int count = 0;
   5340      1.62      haya 
   5341      1.62      haya 	reg = OHCI_SYNC_RX_DMA_READ(irc->irc_sc, irc->irc_num,
   5342      1.62      haya 	    OHCI_SUBREG_ContextControlClear);
   5343      1.62      haya 
   5344      1.62      haya 	printf("fwohci_ir_ctx_drain ctx%s%s%s%s\n",
   5345      1.62      haya 	    reg & OHCI_CTXCTL_RUN ? " run" : "",
   5346      1.62      haya 	    reg & OHCI_CTXCTL_WAKE ? " wake" : "",
   5347      1.62      haya 	    reg & OHCI_CTXCTL_DEAD ? " dead" : "",
   5348      1.62      haya 	    reg & OHCI_CTXCTL_ACTIVE ? " active" : "");
   5349      1.62      haya 
   5350      1.62      haya 	if ((reg & OHCI_CTXCTL_RUNNING_MASK) == OHCI_CTXCTL_RUN) {
   5351      1.62      haya 		/* DMA engine is stopped */
   5352      1.62      haya 		u_int32_t startadr;
   5353      1.62      haya 
   5354      1.62      haya 		for (fd = irc->irc_desc_map;
   5355      1.62      haya 		     fd < irc->irc_desc_map + irc->irc_desc_num;
   5356      1.62      haya 		     ++fd) {
   5357      1.62      haya 			fd->fd_status = 0;
   5358      1.62      haya 		}
   5359      1.62      haya 
   5360      1.62      haya 		/* Restore branch addr of the last descriptor */
   5361      1.62      haya 		irc->irc_writeend->fd_branch = irc->irc_savedbranch;
   5362      1.62      haya 
   5363      1.62      haya 		irc->irc_readtop = irc->irc_desc_map;
   5364      1.62      haya 		irc->irc_writeend = irc->irc_desc_map + irc->irc_desc_num - 1;
   5365      1.62      haya 		irc->irc_savedbranch = irc->irc_writeend->fd_branch;
   5366      1.62      haya 		irc->irc_writeend->fd_branch = 0;
   5367      1.62      haya 
   5368      1.62      haya 		count = irc->irc_desc_num;
   5369      1.62      haya 
   5370      1.62      haya 		OHCI_SYNC_RX_DMA_WRITE(irc->irc_sc, irc->irc_num,
   5371      1.62      haya 		    OHCI_SUBREG_ContextControlClear,
   5372      1.62      haya 		    OHCI_CTXCTL_RUN | OHCI_CTXCTL_DEAD);
   5373      1.62      haya 
   5374      1.62      haya 		startadr = (u_int32_t)irc->irc_desc_dmamap->dm_segs[0].ds_addr;
   5375      1.62      haya 
   5376      1.62      haya 		printf("fwohci_ir_ctx_drain: remove %d pkts\n", count);
   5377      1.62      haya 
   5378      1.62      haya 		OHCI_SYNC_RX_DMA_WRITE(irc->irc_sc, irc->irc_num,
   5379      1.62      haya 		    OHCI_SUBREG_CommandPtr, startadr | 1);
   5380      1.62      haya 
   5381      1.62      haya 		OHCI_SYNC_RX_DMA_WRITE(irc->irc_sc, irc->irc_num,
   5382      1.62      haya 		    OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_RUN);
   5383      1.62      haya 	} else {
   5384      1.62      haya 		const int removecount = irc->irc_desc_num/2;
   5385      1.62      haya 		u_int32_t tmpbranch;
   5386      1.62      haya 
   5387      1.62      haya 		for (count = 0; count < removecount; ++count) {
   5388      1.62      haya 			if (fd->fd_status == 0) {
   5389      1.62      haya 				break;
   5390      1.62      haya 			}
   5391      1.62      haya 
   5392      1.62      haya 			fd->fd_status = 0;
   5393      1.62      haya 
   5394      1.62      haya 			tmpbranch = fd->fd_branch;
   5395      1.62      haya 			fd->fd_branch = 0;
   5396      1.62      haya 			irc->irc_writeend->fd_branch = irc->irc_savedbranch;
   5397      1.62      haya 			irc->irc_writeend = fd;
   5398      1.62      haya 			irc->irc_savedbranch = tmpbranch;
   5399      1.62      haya 
   5400      1.62      haya 			if (++fd == irc->irc_desc_map + irc->irc_desc_num) {
   5401      1.62      haya 				fd = irc->irc_desc_map;
   5402      1.62      haya 			}
   5403      1.62      haya 			++count;
   5404      1.62      haya 		}
   5405      1.62      haya 
   5406      1.62      haya 		printf("fwohci_ir_ctx_drain: remove %d pkts\n", count);
   5407      1.62      haya 	}
   5408      1.62      haya 
   5409      1.62      haya 	return count;
   5410      1.62      haya }
   5411      1.62      haya #endif /* USEDRAIN */
   5412      1.62      haya 
   5413      1.62      haya 
   5414      1.62      haya 
   5415      1.62      haya 
   5416      1.62      haya 
   5417      1.62      haya 
   5418      1.62      haya 
   5419      1.62      haya 
   5420      1.62      haya 
   5421      1.62      haya /*
   5422      1.62      haya  * service routines for isochronous transmit
   5423      1.62      haya  */
   5424      1.62      haya 
   5425      1.62      haya 
   5426      1.62      haya struct fwohci_it_ctx *
   5427      1.62      haya fwohci_it_ctx_construct(struct fwohci_softc *sc, int no, int ch, int tag, int maxsize)
   5428      1.62      haya {
   5429      1.62      haya 	struct fwohci_it_ctx *itc;
   5430      1.62      haya 	size_t dmastrsize;
   5431      1.62      haya 	struct fwohci_it_dmabuf *dmastr;
   5432      1.62      haya 	struct fwohci_desc *desc;
   5433      1.62      haya 	bus_addr_t descphys;
   5434      1.62      haya 	int nodesc;
   5435      1.62      haya 	int i, j;
   5436      1.62      haya 
   5437      1.62      haya 	if ((itc = malloc(sizeof(*itc), M_DEVBUF, M_NOWAIT|M_ZERO)) == NULL) {
   5438      1.62      haya 		return itc;
   5439      1.62      haya 	}
   5440      1.62      haya 
   5441      1.62      haya 	itc->itc_num = no;
   5442      1.62      haya 	itc->itc_flags = 0;
   5443      1.62      haya 	itc->itc_sc = sc;
   5444      1.62      haya 	itc->itc_bufnum = FWOHCI_IT_BUFNUM;
   5445      1.62      haya 
   5446      1.62      haya 	itc->itc_channel = ch;
   5447      1.62      haya 	itc->itc_tag = tag;
   5448      1.62      haya 	itc->itc_speed = OHCI_CTXCTL_SPD_100; /* XXX */
   5449      1.62      haya 
   5450      1.62      haya 	itc->itc_outpkt = 0;
   5451      1.62      haya 
   5452      1.62      haya 	itc->itc_maxsize = maxsize;
   5453      1.62      haya 
   5454      1.62      haya 	dmastrsize = sizeof(struct fwohci_it_dmabuf)*itc->itc_bufnum;
   5455      1.62      haya 
   5456      1.62      haya 	if ((dmastr = malloc(dmastrsize, M_DEVBUF, M_NOWAIT|M_ZERO)) == NULL) {
   5457      1.62      haya 		goto error_1;
   5458      1.62      haya 	}
   5459      1.62      haya 	itc->itc_buf = dmastr;
   5460      1.62      haya 
   5461      1.62      haya 	/*
   5462      1.62      haya 	 * Get memory for descriptors.  One buffer will have 256
   5463      1.62      haya 	 * packet entry and 1 trailing descriptor for writing scratch.
   5464      1.62      haya 	 * 4-byte space for scratch.
   5465      1.62      haya 	 */
   5466      1.62      haya 	itc->itc_descsize = (256*3 + 1)*itc->itc_bufnum;
   5467      1.62      haya 
   5468      1.62      haya 	if (fwohci_it_desc_alloc(itc)) {
   5469      1.62      haya 		printf("%s: cannot get enough memory for descriptor\n",
   5470      1.62      haya 		    sc->sc_sc1394.sc1394_dev.dv_xname);
   5471      1.62      haya 		goto error_2;
   5472      1.62      haya 	}
   5473      1.62      haya 
   5474      1.62      haya 	/* prepare DMA buffer */
   5475      1.62      haya 	nodesc = itc->itc_descsize/itc->itc_bufnum;
   5476      1.62      haya 	desc = (struct fwohci_desc *)itc->itc_descmap;
   5477      1.62      haya 	descphys = itc->itc_dseg.ds_addr;
   5478      1.62      haya 
   5479      1.62      haya 	for (i = 0; i < itc->itc_bufnum; ++i) {
   5480      1.62      haya 
   5481      1.62      haya 		if (fwohci_itd_construct(itc, &dmastr[i], i, desc,
   5482      1.62      haya 		    descphys, nodesc,
   5483      1.62      haya 		    itc->itc_maxsize, itc->itc_scratch_paddr)) {
   5484      1.62      haya 			goto error_3;
   5485      1.62      haya 		}
   5486      1.62      haya 		desc += nodesc;
   5487      1.62      haya 		descphys += sizeof(struct fwohci_desc)*nodesc;
   5488      1.62      haya 	}
   5489      1.62      haya 
   5490      1.62      haya #if 1
   5491      1.62      haya 	itc->itc_buf_start = itc->itc_buf;
   5492      1.62      haya 	itc->itc_buf_end = itc->itc_buf;
   5493      1.62      haya 	itc->itc_buf_linkend = itc->itc_buf;
   5494      1.62      haya #else
   5495      1.62      haya 	itc->itc_bufidx_start = 0;
   5496      1.62      haya 	itc->itc_bufidx_end = 0;
   5497      1.62      haya 	itc->itc_bufidx_linkend = 0;
   5498      1.62      haya #endif
   5499      1.62      haya 	itc->itc_buf_cnt = 0;
   5500      1.62      haya 	itc->itc_waitchan = NULL;
   5501      1.62      haya 	*itc->itc_scratch = 0xffffffff;
   5502      1.62      haya 
   5503      1.62      haya 	return itc;
   5504      1.62      haya 
   5505      1.62      haya  error_3:
   5506      1.62      haya 	for (j = 0; j < i; ++j) {
   5507      1.62      haya 		fwohci_itd_destruct(&dmastr[j]);
   5508      1.62      haya 	}
   5509      1.62      haya 	fwohci_it_desc_free(itc);
   5510      1.62      haya  error_2:
   5511      1.62      haya 	free(itc->itc_buf, M_DEVBUF);
   5512      1.62      haya  error_1:
   5513      1.62      haya 	free(itc, M_DEVBUF);
   5514      1.62      haya 
   5515      1.62      haya 	return NULL;
   5516      1.62      haya }
   5517      1.62      haya 
   5518      1.62      haya 
   5519      1.62      haya 
   5520      1.62      haya void
   5521      1.62      haya fwohci_it_ctx_destruct(struct fwohci_it_ctx *itc)
   5522      1.62      haya {
   5523      1.62      haya 	int i;
   5524      1.62      haya 
   5525      1.62      haya 	for (i = 0; i < itc->itc_bufnum; ++i) {
   5526      1.62      haya 		fwohci_itd_destruct(&itc->itc_buf[i]);
   5527      1.62      haya 	}
   5528      1.62      haya 
   5529      1.62      haya 	fwohci_it_desc_free(itc);
   5530      1.62      haya 	free(itc, M_DEVBUF);
   5531      1.62      haya }
   5532      1.62      haya 
   5533      1.62      haya 
   5534      1.62      haya /*
   5535      1.62      haya  * static int fwohci_it_desc_alloc(struct fwohci_it_ctx *itc)
   5536      1.62      haya  *
   5537      1.62      haya  *	Allocates descriptors for context DMA dedicated for
   5538      1.62      haya  *	isochronous transmit.
   5539      1.62      haya  *
   5540      1.62      haya  *	This function returns 0 (zero) if it succeeds.  Otherwise,
   5541      1.62      haya  *	return negative value.
   5542      1.62      haya  */
   5543      1.62      haya static int
   5544      1.62      haya fwohci_it_desc_alloc(struct fwohci_it_ctx *itc)
   5545      1.62      haya {
   5546      1.62      haya 	bus_dma_tag_t dmat = itc->itc_sc->sc_dmat;
   5547      1.62      haya 	const char *xname = itc->itc_sc->sc_sc1394.sc1394_dev.dv_xname;
   5548      1.62      haya 	int error, dsize;
   5549      1.62      haya 
   5550      1.62      haya 	/* add for scratch */
   5551      1.62      haya 	itc->itc_descsize++;
   5552      1.62      haya 
   5553      1.62      haya 	/* rounding up to 256 */
   5554      1.62      haya 	if ((itc->itc_descsize & 0x0ff) != 0) {
   5555      1.62      haya 		itc->itc_descsize =
   5556      1.62      haya 		    (itc->itc_descsize & ~0x0ff) + 0x100;
   5557      1.62      haya 	}
   5558      1.62      haya 	/* remove for scratch */
   5559      1.62      haya 
   5560      1.62      haya 	itc->itc_descsize--;
   5561      1.62      haya 	printf("%s: fwohci_it_desc_alloc will allocate %d descs\n",
   5562      1.62      haya 	    xname, itc->itc_descsize);
   5563      1.62      haya 
   5564      1.62      haya 	/*
   5565      1.62      haya 	 * allocate descriptor buffer
   5566      1.62      haya 	 */
   5567      1.62      haya 	dsize = sizeof(struct fwohci_desc) * itc->itc_descsize;
   5568      1.62      haya 
   5569      1.62      haya 	printf("%s: fwohci_it_desc_alloc: descriptor %d, dsize %d\n",
   5570      1.62      haya 	    xname, itc->itc_descsize, dsize);
   5571      1.62      haya 
   5572      1.62      haya 	if ((error = bus_dmamem_alloc(dmat, dsize, PAGE_SIZE, 0,
   5573      1.62      haya 	    &itc->itc_dseg, 1, &itc->itc_dnsegs, 0)) != 0) {
   5574      1.62      haya 		printf("%s: unable to allocate descriptor buffer, error = %d\n",
   5575      1.62      haya 		    xname, error);
   5576      1.62      haya 		goto fail_0;
   5577      1.62      haya 	}
   5578      1.62      haya 
   5579      1.62      haya 	printf("fwohci_it_desc_alloc: %d segment[s]\n", itc->itc_dnsegs);
   5580      1.62      haya 
   5581      1.62      haya 	if ((error = bus_dmamem_map(dmat, &itc->itc_dseg,
   5582      1.62      haya 	    itc->itc_dnsegs, dsize, (caddr_t *)&itc->itc_descmap,
   5583      1.62      haya 	    BUS_DMA_COHERENT | BUS_DMA_WAITOK)) != 0) {
   5584      1.62      haya 		printf("%s: unable to map descriptor buffer, error = %d\n",
   5585      1.62      haya 		    xname, error);
   5586      1.62      haya 		goto fail_1;
   5587      1.62      haya 	}
   5588      1.62      haya 
   5589      1.62      haya 	printf("fwohci_it_desc_alloc: bus_dmamem_map success dseg %lx:%lx\n",
   5590      1.62      haya 	    (long)itc->itc_dseg.ds_addr, (long)itc->itc_dseg.ds_len);
   5591      1.62      haya 
   5592      1.62      haya 	if ((error = bus_dmamap_create(dmat, dsize, itc->itc_dnsegs,
   5593      1.62      haya 	    dsize, 0, BUS_DMA_WAITOK, &itc->itc_ddmamap)) != 0) {
   5594      1.62      haya 		printf("%s: unable to create descriptor buffer DMA map, "
   5595      1.62      haya 		    "error = %d\n", xname, error);
   5596      1.62      haya 		goto fail_2;
   5597      1.62      haya 	}
   5598      1.62      haya 
   5599      1.62      haya 	printf("fwohci_it_desc_alloc: bus_dmamem_create success\n");
   5600      1.62      haya 
   5601      1.62      haya 	{
   5602      1.62      haya 		int loop;
   5603      1.62      haya 
   5604      1.62      haya 		for (loop = 0; loop < itc->itc_ddmamap->dm_nsegs; ++loop) {
   5605      1.62      haya 			printf("\t%.2d: 0x%lx - 0x%lx\n", loop,
   5606      1.62      haya 			    (long)itc->itc_ddmamap->dm_segs[loop].ds_addr,
   5607      1.62      haya 			    (long)itc->itc_ddmamap->dm_segs[loop].ds_addr +
   5608      1.62      haya 			    (long)itc->itc_ddmamap->dm_segs[loop].ds_len - 1);
   5609      1.62      haya 		}
   5610      1.62      haya 	}
   5611      1.62      haya 
   5612      1.62      haya 	if ((error = bus_dmamap_load(dmat, itc->itc_ddmamap,
   5613      1.62      haya 	    itc->itc_descmap, dsize, NULL, BUS_DMA_WAITOK)) != 0) {
   5614      1.62      haya 		printf("%s: unable to load descriptor buffer DMA map, "
   5615      1.62      haya 		    "error = %d\n", xname, error);
   5616      1.62      haya 		goto fail_3;
   5617      1.62      haya 	}
   5618      1.62      haya 
   5619      1.62      haya 	printf("%s: fwohci_it_desc_alloc: get DMA memory phys:0x%08x vm:%p\n",
   5620      1.62      haya 	    xname, (int)itc->itc_ddmamap->dm_segs[0].ds_addr, itc->itc_descmap);
   5621      1.62      haya 
   5622      1.62      haya 	itc->itc_scratch = (u_int32_t *)(itc->itc_descmap
   5623      1.62      haya 	    + (sizeof(struct fwohci_desc))*itc->itc_descsize);
   5624      1.62      haya 	itc->itc_scratch_paddr =
   5625      1.62      haya 	    itc->itc_ddmamap->dm_segs[0].ds_addr
   5626      1.62      haya 	    + (sizeof(struct fwohci_desc))*itc->itc_descsize;
   5627      1.62      haya 
   5628      1.62      haya 	printf("%s: scratch %p, 0x%x\n", xname, itc->itc_scratch,
   5629      1.62      haya 	    (int)itc->itc_scratch_paddr);
   5630      1.62      haya 
   5631      1.62      haya 	/* itc->itc_scratch_paddr = vtophys(itc->itc_scratch); */
   5632      1.62      haya 
   5633      1.62      haya 	return 0;
   5634      1.62      haya 
   5635      1.62      haya   fail_3:
   5636      1.62      haya 	bus_dmamap_destroy(dmat, itc->itc_ddmamap);
   5637      1.62      haya   fail_2:
   5638      1.62      haya 	bus_dmamem_unmap(dmat, (caddr_t)itc->itc_descmap, dsize);
   5639      1.62      haya   fail_1:
   5640      1.62      haya 	bus_dmamem_free(dmat, &itc->itc_dseg, itc->itc_dnsegs);
   5641      1.62      haya   fail_0:
   5642      1.62      haya 	itc->itc_dnsegs = 0;
   5643      1.62      haya 	itc->itc_descmap = NULL;
   5644      1.62      haya 	return error;
   5645      1.62      haya }
   5646      1.62      haya 
   5647      1.62      haya 
   5648      1.62      haya static void
   5649      1.62      haya fwohci_it_desc_free(struct fwohci_it_ctx *itc)
   5650      1.62      haya {
   5651      1.62      haya 	bus_dma_tag_t dmat = itc->itc_sc->sc_dmat;
   5652      1.62      haya 	int dsize = sizeof(struct fwohci_desc) * itc->itc_descsize + 4;
   5653      1.62      haya 
   5654      1.62      haya 	bus_dmamap_destroy(dmat, itc->itc_ddmamap);
   5655      1.62      haya 	bus_dmamem_unmap(dmat, (caddr_t)itc->itc_descmap, dsize);
   5656      1.62      haya 	bus_dmamem_free(dmat, &itc->itc_dseg, itc->itc_dnsegs);
   5657      1.62      haya 
   5658      1.62      haya 	itc->itc_dnsegs = 0;
   5659      1.62      haya 	itc->itc_descmap = NULL;
   5660      1.62      haya }
   5661      1.62      haya 
   5662      1.62      haya 
   5663      1.62      haya 
   5664      1.62      haya /*
   5665      1.62      haya  * int fwohci_it_ctx_writedata(ieee1394_it_tag_t it, int ndata,
   5666      1.62      haya  *		struct ieee1394_it_datalist *itdata, int flags)
   5667      1.62      haya  *
   5668      1.62      haya  *	This function will write packet data to DMA buffer in the
   5669      1.62      haya  *	context.  This function will parse ieee1394_it_datalist
   5670      1.62      haya  *	command and fill DMA buffer.  This function will return the
   5671      1.62      haya  *	number of written packets, or error code if the return value
   5672      1.62      haya  *	is negative.
   5673      1.62      haya  *
   5674      1.62      haya  *	When this funtion returns positive value but smaller than
   5675      1.62      haya  *	ndata, it reaches at the ent of DMA buffer.
   5676      1.62      haya  */
   5677      1.62      haya int
   5678      1.62      haya fwohci_it_ctx_writedata(ieee1394_it_tag_t it, int ndata,
   5679      1.62      haya     struct ieee1394_it_datalist *itdata, int flags)
   5680      1.62      haya {
   5681      1.62      haya 	struct fwohci_it_ctx *itc = (struct fwohci_it_ctx *)it;
   5682      1.62      haya 	int rv;
   5683      1.62      haya 	int writepkt = 0;
   5684      1.62      haya 	struct fwohci_it_dmabuf *itd;
   5685      1.62      haya 	int i = 0;
   5686      1.62      haya 
   5687      1.62      haya 	itd = itc->itc_buf_end;
   5688      1.62      haya 
   5689      1.62      haya 	while (ndata > 0) {
   5690      1.62      haya 		int s;
   5691      1.62      haya 
   5692      1.62      haya 		if (fwohci_itd_isfull(itd) || fwohci_itd_islocked(itd)) {
   5693      1.62      haya 			if (itc->itc_buf_cnt == itc->itc_bufnum) {
   5694      1.62      haya 				/* no space to write */
   5695      1.62      haya 				printf("sleeping: start linkend end %d %d %d "
   5696      1.62      haya 				    "bufcnt %d\n",
   5697      1.62      haya 				    itc->itc_buf_start->itd_num,
   5698      1.62      haya 				    itc->itc_buf_linkend->itd_num,
   5699      1.62      haya 				    itc->itc_buf_end->itd_num,
   5700      1.62      haya 				    itc->itc_buf_cnt);
   5701      1.62      haya 
   5702      1.62      haya 				itc->itc_waitchan = itc;
   5703      1.62      haya 				if (tsleep((void *)itc->itc_waitchan,
   5704      1.62      haya 				    PCATCH, "fwohci it", 0) == EWOULDBLOCK) {
   5705      1.62      haya 					itc->itc_waitchan = NULL;
   5706      1.62      haya 					printf("fwohci0 signal\n");
   5707      1.62      haya 					break;
   5708      1.62      haya 				}
   5709      1.62      haya 				printf("waking:   start linkend end %d %d %d\n",
   5710      1.62      haya 				    itc->itc_buf_start->itd_num,
   5711      1.62      haya 				    itc->itc_buf_linkend->itd_num,
   5712      1.62      haya 				    itc->itc_buf_end->itd_num);
   5713      1.62      haya 
   5714      1.62      haya 				itc->itc_waitchan = itc;
   5715      1.62      haya 				i = 0;
   5716      1.62      haya 			} else {
   5717      1.62      haya 				/*
   5718      1.62      haya 				 * Use next buffer.  This DMA buffer is full
   5719      1.62      haya 				 * or locked.
   5720      1.62      haya 				 */
   5721      1.62      haya 				INC_BUF(itc, itd);
   5722      1.62      haya 			}
   5723      1.62      haya 		}
   5724      1.62      haya 
   5725      1.62      haya 		if (++i > 10) {
   5726      1.62      haya 			panic("why loop so much %d", itc->itc_buf_cnt);
   5727      1.62      haya 			break;
   5728      1.62      haya 		}
   5729      1.62      haya 
   5730      1.62      haya 		s = splbio();
   5731      1.62      haya 
   5732      1.62      haya 		if (fwohci_itd_hasdata(itd) == 0) {
   5733      1.62      haya 			++itc->itc_buf_cnt;
   5734      1.62      haya 			DPRINTF(("<buf cnt %d>\n", itc->itc_buf_cnt));
   5735      1.62      haya 		}
   5736      1.62      haya 
   5737      1.62      haya 		rv = fwohci_itd_writedata(itd, ndata, itdata);
   5738      1.62      haya 		DPRINTF(("fwohci_it_ctx_writedata: buf %d ndata %d rv %d\n",
   5739      1.62      haya 		    itd->itd_num, ndata, rv));
   5740      1.62      haya 
   5741      1.62      haya 		if (itc->itc_buf_start == itc->itc_buf_linkend
   5742      1.62      haya 		    && (itc->itc_flags & ITC_FLAGS_RUN) != 0) {
   5743      1.62      haya 
   5744      1.62      haya #ifdef DEBUG_USERADD
   5745      1.62      haya 			printf("fwohci_it_ctx_writedata: emergency!\n");
   5746      1.62      haya #endif
   5747      1.62      haya 			if (itc->itc_buf_linkend != itc->itc_buf_end
   5748      1.62      haya 			    && fwohci_itd_hasdata(itc->itc_buf_end)) {
   5749      1.62      haya 				struct fwohci_it_dmabuf *itdn = itc->itc_buf_linkend;
   5750      1.62      haya 
   5751      1.62      haya 				INC_BUF(itc, itdn);
   5752      1.62      haya 				printf("connecting %d after %d\n",
   5753      1.62      haya 				    itdn->itd_num,
   5754      1.62      haya 				    itc->itc_buf_linkend->itd_num);
   5755      1.62      haya 				if (fwohci_itd_link(itc->itc_buf_linkend, itdn)) {
   5756      1.62      haya 					printf("fwohci_it_ctx_writedata:"
   5757      1.62      haya 					    " cannot link correctly\n");
   5758      1.71       jmc 					splx(s);
   5759      1.62      haya 					return -1;
   5760      1.62      haya 				}
   5761      1.62      haya 				itc->itc_buf_linkend = itdn;
   5762      1.62      haya 			}
   5763      1.62      haya 		}
   5764      1.62      haya 
   5765      1.62      haya 		splx(s);
   5766      1.62      haya 
   5767      1.62      haya 		if (rv < 0) {
   5768      1.62      haya 			/* some errors happend */
   5769      1.62      haya 			break;
   5770      1.62      haya 		}
   5771      1.62      haya 
   5772      1.62      haya 		writepkt += rv;
   5773      1.62      haya 		ndata -= rv;
   5774      1.62      haya 		itdata += rv;
   5775      1.62      haya 		itc->itc_buf_end = itd;
   5776      1.62      haya 	}
   5777      1.62      haya 
   5778      1.62      haya 	/* Start DMA engine if stopped */
   5779      1.62      haya 	if ((itc->itc_flags & ITC_FLAGS_RUN) == 0) {
   5780      1.62      haya 		if (itc->itc_buf_cnt > itc->itc_bufnum - 1 || flags) {
   5781      1.62      haya 			/* run */
   5782      1.62      haya 			printf("fwohci_itc_ctl_writedata: DMA engine start\n");
   5783      1.62      haya 			fwohci_it_ctx_run(itc);
   5784      1.62      haya 		}
   5785      1.62      haya 	}
   5786      1.62      haya 
   5787      1.62      haya 	return writepkt;
   5788      1.62      haya }
   5789      1.62      haya 
   5790      1.62      haya 
   5791      1.62      haya 
   5792      1.62      haya static void
   5793      1.62      haya fwohci_it_ctx_run(struct fwohci_it_ctx *itc)
   5794      1.62      haya {
   5795      1.62      haya 	struct fwohci_softc *sc = itc->itc_sc;
   5796      1.62      haya 	int ctx = itc->itc_num;
   5797      1.62      haya 	struct fwohci_it_dmabuf *itd
   5798      1.62      haya 	    = (struct fwohci_it_dmabuf *)itc->itc_buf_start;
   5799      1.62      haya 	u_int32_t reg;
   5800      1.62      haya 	int i;
   5801      1.62      haya 
   5802      1.62      haya 	if (itc->itc_flags & ITC_FLAGS_RUN) {
   5803      1.62      haya 		return;
   5804      1.62      haya 	}
   5805      1.62      haya 	itc->itc_flags |= ITC_FLAGS_RUN;
   5806      1.62      haya 
   5807      1.62      haya 	/*
   5808      1.62      haya 	 * dirty, but I can't imagine better place to save branch addr
   5809      1.62      haya 	 * of top DMA buffer and substitute 0 to it.
   5810      1.62      haya 	 */
   5811      1.62      haya 	itd->itd_savedbranch = itd->itd_lastdesc->fd_branch;
   5812      1.62      haya 	itd->itd_lastdesc->fd_branch = 0;
   5813      1.62      haya 
   5814      1.62      haya 	if (itc->itc_buf_cnt > 1) {
   5815      1.62      haya 		struct fwohci_it_dmabuf *itdn = itd;
   5816      1.62      haya 
   5817      1.62      haya #if 0
   5818      1.62      haya 		INC_BUF(itc, itdn);
   5819      1.62      haya 
   5820      1.62      haya 		if (fwohci_itd_link(itd, itdn)) {
   5821      1.62      haya 			printf("fwohci_it_ctx_run: cannot link correctly\n");
   5822      1.62      haya 			return;
   5823      1.62      haya 		}
   5824      1.62      haya 		itc->itc_buf_linkend = itdn;
   5825      1.62      haya #else
   5826      1.62      haya 		for (;;) {
   5827      1.62      haya 			INC_BUF(itc, itdn);
   5828      1.62      haya 
   5829      1.62      haya 			if (itdn == itc->itc_buf_end) {
   5830      1.62      haya 				break;
   5831      1.62      haya 			}
   5832      1.62      haya 			if (fwohci_itd_link(itd, itdn)) {
   5833      1.62      haya 				printf("fwohci_it_ctx_run: cannot link\n");
   5834      1.62      haya 				return;
   5835      1.62      haya 			}
   5836      1.62      haya 			itd = itdn;
   5837      1.62      haya 		}
   5838      1.62      haya 		itc->itc_buf_linkend = itd;
   5839      1.62      haya #endif
   5840      1.62      haya 	} else {
   5841      1.62      haya 		itd->itd_lastdesc->fd_flags |= OHCI_DESC_INTR_ALWAYS;
   5842      1.62      haya 		itc->itc_buf_linkend = itc->itc_buf_end;
   5843      1.62      haya 		itc->itc_buf_end->itd_flags |= ITD_FLAGS_LOCK;
   5844      1.62      haya 
   5845      1.62      haya 		/* sanity check */
   5846      1.62      haya 		if (itc->itc_buf_end != itc->itc_buf_start) {
   5847      1.62      haya 			printf("buf start & end differs %p %p\n",
   5848      1.62      haya 			    itc->itc_buf_end, itc->itc_buf_start);
   5849      1.62      haya 		}
   5850      1.62      haya #if 0
   5851      1.62      haya 		{
   5852      1.62      haya 			u_int32_t *fdp;
   5853      1.62      haya 			u_int32_t adr;
   5854      1.62      haya 			int i;
   5855      1.62      haya 
   5856      1.62      haya 			printf("fwohci_it_ctx_run: itc_buf_cnt 1, DMA buf %d\n",
   5857      1.62      haya 			    itd->itd_num);
   5858      1.62      haya 			printf(" last desc %p npacket %d, %d 0x%04x%04x",
   5859      1.62      haya 			    itd->itd_lastdesc, itd->itd_npacket,
   5860      1.62      haya 			    (itd->itd_lastdesc - itd->itd_desc)/3,
   5861      1.62      haya 			    itd->itd_lastdesc->fd_flags,
   5862      1.62      haya 			    itd->itd_lastdesc->fd_reqcount);
   5863      1.62      haya 			fdp = (u_int32_t *)itd->itd_desc;
   5864      1.62      haya 			adr = (u_int32_t)itd->itd_desc_phys; /* XXX */
   5865      1.62      haya 
   5866      1.62      haya 			for (i = 0; i < 7*4; ++i) {
   5867      1.62      haya 				if (i % 4 == 0) {
   5868      1.62      haya 					printf("\n%x:", adr + 4*i);
   5869      1.62      haya 				}
   5870      1.62      haya 				printf(" %08x", fdp[i]);
   5871      1.62      haya 			}
   5872      1.62      haya 
   5873      1.62      haya 			if (itd->itd_npacket > 4) {
   5874      1.62      haya 				printf("\n...");
   5875      1.62      haya 				i = (itd->itd_npacket - 2)*12 + 4;
   5876      1.62      haya 			} else {
   5877      1.62      haya 				i = 2*12 + 4;
   5878      1.62      haya 			}
   5879      1.62      haya 			for (;i < itd->itd_npacket*12 + 4; ++i) {
   5880      1.62      haya 				if (i % 4 == 0) {
   5881      1.62      haya 					printf("\n%x:", adr + 4*i);
   5882      1.62      haya 				}
   5883      1.62      haya 				printf(" %08x", fdp[i]);
   5884      1.62      haya 			}
   5885      1.62      haya 			printf("\n");
   5886      1.62      haya 		}
   5887      1.62      haya #endif
   5888      1.62      haya 	}
   5889      1.62      haya 	{
   5890      1.62      haya 		struct fwohci_desc *fd;
   5891      1.62      haya 
   5892      1.62      haya 		printf("fwohci_it_ctx_run: link start linkend end %d %d %d\n",
   5893      1.62      haya 		    itc->itc_buf_start->itd_num,
   5894      1.62      haya 		    itc->itc_buf_linkend->itd_num,
   5895      1.62      haya 		    itc->itc_buf_end->itd_num);
   5896      1.62      haya 
   5897      1.62      haya 		fd = itc->itc_buf_start->itd_desc;
   5898      1.62      haya 		if ((fd->fd_flags & 0xff00) != OHCI_DESC_STORE_VALUE) {
   5899      1.62      haya 			printf("fwohci_it_ctx_run: start buf not with STORE\n");
   5900      1.62      haya 		}
   5901      1.62      haya 		fd += 3;
   5902      1.62      haya 		if ((fd->fd_flags & OHCI_DESC_INTR_ALWAYS) == 0) {
   5903      1.62      haya 			printf("fwohci_it_ctx_run: start buf does not have intr\n");
   5904      1.62      haya 		}
   5905      1.62      haya 
   5906      1.62      haya 		fd = itc->itc_buf_linkend->itd_desc;
   5907      1.62      haya 		if ((fd->fd_flags & 0xff00) != OHCI_DESC_STORE_VALUE) {
   5908      1.62      haya 			printf("fwohci_it_ctx_run: linkend buf not with STORE\n");
   5909      1.62      haya 		}
   5910      1.62      haya 		fd += 3;
   5911      1.62      haya 		if ((fd->fd_flags & OHCI_DESC_INTR_ALWAYS) == 0) {
   5912      1.62      haya 			printf("fwohci_it_ctx_run: linkend buf does not have intr\n");
   5913      1.62      haya 		}
   5914      1.62      haya 	}
   5915      1.62      haya 
   5916      1.62      haya 	*itc->itc_scratch = 0xffffffff;
   5917      1.62      haya 
   5918      1.62      haya 	OHCI_SYNC_TX_DMA_WRITE(sc, ctx, OHCI_SUBREG_ContextControlClear,
   5919      1.62      haya 	    0xffff0000);
   5920      1.62      haya 	reg = OHCI_SYNC_TX_DMA_READ(sc, ctx, OHCI_SUBREG_ContextControlSet);
   5921      1.62      haya 
   5922      1.62      haya 	printf("fwohci_it_ctx_run start for ctx %d\n", ctx);
   5923      1.62      haya 	printf("%s: bfr IT_CommandPtr 0x%08x ContextCtrl 0x%08x%s%s%s%s\n",
   5924      1.62      haya 	    sc->sc_sc1394.sc1394_dev.dv_xname,
   5925      1.62      haya 	    OHCI_SYNC_TX_DMA_READ(sc, ctx, OHCI_SUBREG_CommandPtr),
   5926      1.62      haya 	    reg,
   5927      1.62      haya 	    reg & OHCI_CTXCTL_RUN ? " run" : "",
   5928      1.62      haya 	    reg & OHCI_CTXCTL_WAKE ? " wake" : "",
   5929      1.62      haya 	    reg & OHCI_CTXCTL_DEAD ? " dead" : "",
   5930      1.62      haya 	    reg & OHCI_CTXCTL_ACTIVE ? " active" : "");
   5931      1.62      haya 
   5932      1.62      haya 	OHCI_SYNC_TX_DMA_WRITE(sc, ctx, OHCI_SUBREG_ContextControlClear,
   5933      1.62      haya 	    OHCI_CTXCTL_RUN);
   5934      1.62      haya 
   5935      1.62      haya 	reg = OHCI_SYNC_TX_DMA_READ(sc, ctx, OHCI_SUBREG_ContextControlSet);
   5936      1.62      haya 	i = 0;
   5937      1.62      haya 	while (reg & (OHCI_CTXCTL_ACTIVE | OHCI_CTXCTL_RUN)) {
   5938      1.62      haya 		delay(100);
   5939      1.62      haya 		if (++i > 1000) {
   5940      1.62      haya 			printf("%s: cannot stop iso transmit engine\n",
   5941      1.62      haya 			    sc->sc_sc1394.sc1394_dev.dv_xname);
   5942      1.62      haya 			break;
   5943      1.62      haya 		}
   5944      1.62      haya 		reg = OHCI_SYNC_TX_DMA_READ(sc, ctx,
   5945      1.62      haya 		    OHCI_SUBREG_ContextControlSet);
   5946      1.62      haya 	}
   5947      1.62      haya 
   5948      1.62      haya 	printf("%s: itm IT_CommandPtr 0x%08x ContextCtrl 0x%08x%s%s%s%s\n",
   5949      1.62      haya 	    sc->sc_sc1394.sc1394_dev.dv_xname,
   5950      1.62      haya 	    OHCI_SYNC_TX_DMA_READ(sc, ctx, OHCI_SUBREG_CommandPtr),
   5951      1.62      haya 	    reg,
   5952      1.62      haya 	    reg & OHCI_CTXCTL_RUN ? " run" : "",
   5953      1.62      haya 	    reg & OHCI_CTXCTL_WAKE ? " wake" : "",
   5954      1.62      haya 	    reg & OHCI_CTXCTL_DEAD ? " dead" : "",
   5955      1.62      haya 	    reg & OHCI_CTXCTL_ACTIVE ? " active" : "");
   5956      1.62      haya 
   5957      1.62      haya 	printf("%s: writing CommandPtr to 0x%08x\n",
   5958      1.62      haya 	    sc->sc_sc1394.sc1394_dev.dv_xname,
   5959      1.62      haya 	    (int)itc->itc_buf_start->itd_desc_phys);
   5960      1.62      haya 	OHCI_SYNC_TX_DMA_WRITE(sc, ctx, OHCI_SUBREG_CommandPtr,
   5961      1.62      haya 	    fwohci_itd_list_head(itc->itc_buf_start) | 4);
   5962      1.62      haya 
   5963      1.62      haya 	OHCI_SYNC_TX_DMA_WRITE(sc, ctx, OHCI_SUBREG_ContextControlSet,
   5964      1.62      haya 	    OHCI_CTXCTL_RUN | OHCI_CTXCTL_WAKE);
   5965      1.62      haya 
   5966      1.62      haya 	reg = OHCI_SYNC_TX_DMA_READ(sc, ctx, OHCI_SUBREG_ContextControlSet);
   5967      1.62      haya 
   5968      1.62      haya 	printf("%s: aft IT_CommandPtr 0x%08x ContextCtrl 0x%08x%s%s%s%s\n",
   5969      1.62      haya 	    sc->sc_sc1394.sc1394_dev.dv_xname,
   5970      1.62      haya 	    OHCI_SYNC_TX_DMA_READ(sc, ctx, OHCI_SUBREG_CommandPtr),
   5971      1.62      haya 	    reg,
   5972      1.62      haya 	    reg & OHCI_CTXCTL_RUN ? " run" : "",
   5973      1.62      haya 	    reg & OHCI_CTXCTL_WAKE ? " wake" : "",
   5974      1.62      haya 	    reg & OHCI_CTXCTL_DEAD ? " dead" : "",
   5975      1.62      haya 	    reg & OHCI_CTXCTL_ACTIVE ? " active" : "");
   5976      1.62      haya }
   5977      1.62      haya 
   5978      1.62      haya 
   5979      1.62      haya 
   5980      1.62      haya int
   5981      1.62      haya fwohci_it_ctx_flush(ieee1394_it_tag_t it)
   5982      1.62      haya {
   5983      1.62      haya 	struct fwohci_it_ctx *itc = (struct fwohci_it_ctx *)it;
   5984      1.62      haya 	int rv = 0;
   5985      1.62      haya 
   5986      1.62      haya 	if ((itc->itc_flags & ITC_FLAGS_RUN) == 0
   5987      1.62      haya 	    && itc->itc_buf_cnt > 0) {
   5988      1.62      haya 		printf("fwohci_it_ctx_flush: %s flushing\n",
   5989      1.62      haya 		    itc->itc_sc->sc_sc1394.sc1394_dev.dv_xname);
   5990      1.62      haya 
   5991      1.62      haya 		fwohci_it_ctx_run(itc);
   5992      1.62      haya 		rv = 1;
   5993      1.62      haya 	}
   5994      1.62      haya 
   5995      1.62      haya 	return rv;
   5996      1.62      haya }
   5997      1.62      haya 
   5998      1.62      haya 
   5999      1.62      haya /*
   6000      1.62      haya  * static void fwohci_it_intr(struct fwohci_softc *sc,
   6001      1.62      haya  *			      struct fwochi_it_ctx *itc)
   6002      1.62      haya  *
   6003      1.62      haya  *	This function is the interrupt handler for isochronous
   6004      1.62      haya  *	transmit interrupt.  This function will 1) unlink used
   6005      1.62      haya  *	(already transmitted) buffers, 2) link new filled buffers, if
   6006      1.75       wiz  *	necessary and 3) say some free DMA buffers exist to
   6007      1.62      haya  *	fwiso_write()
   6008      1.62      haya  */
   6009      1.62      haya static void
   6010      1.62      haya fwohci_it_intr(struct fwohci_softc *sc, struct fwohci_it_ctx *itc)
   6011      1.62      haya {
   6012      1.62      haya 	struct fwohci_it_dmabuf *itd, *newstartbuf;
   6013      1.62      haya 	u_int16_t scratchval;
   6014      1.62      haya 	u_int32_t reg;
   6015      1.62      haya 
   6016      1.62      haya 	reg = OHCI_SYNC_TX_DMA_READ(sc, itc->itc_num,
   6017      1.62      haya 	    OHCI_SUBREG_ContextControlSet);
   6018      1.62      haya 
   6019      1.62      haya 	/* print out debug info */
   6020      1.62      haya #ifdef FW_DEBUG
   6021      1.62      haya 	printf("fwohci_it_intr: CTX %d\n", itc->itc_num);
   6022      1.62      haya 
   6023      1.62      haya 	printf("fwohci_it_intr: %s: IT_CommandPtr 0x%08x "
   6024      1.62      haya 	    "ContextCtrl 0x%08x%s%s%s%s\n",
   6025      1.62      haya 	    sc->sc_sc1394.sc1394_dev.dv_xname,
   6026      1.62      haya 	    OHCI_SYNC_TX_DMA_READ(sc, itc->itc_num, OHCI_SUBREG_CommandPtr),
   6027      1.62      haya 	    reg,
   6028      1.62      haya 	    reg & OHCI_CTXCTL_RUN ? " run" : "",
   6029      1.62      haya 	    reg & OHCI_CTXCTL_WAKE ? " wake" : "",
   6030      1.62      haya 	    reg & OHCI_CTXCTL_DEAD ? " dead" : "",
   6031      1.62      haya 	    reg & OHCI_CTXCTL_ACTIVE ? " active" : "");
   6032      1.62      haya 	printf("fwohci_it_intr: %s: scratch %x start %d end %d valid %d\n",
   6033      1.62      haya 	    sc->sc_sc1394.sc1394_dev.dv_xname, *itc->itc_scratch,
   6034      1.62      haya 	    itc->itc_buf_start->itd_num, itc->itc_buf_end->itd_num,
   6035      1.62      haya 	    itc->itc_buf_cnt);
   6036      1.62      haya 	{
   6037      1.62      haya 		u_int32_t reg
   6038      1.62      haya 		    = OHCI_CSR_READ(sc, OHCI_REG_IsochronousCycleTimer);
   6039      1.62      haya 		printf("\t\tIsoCounter 0x%08x, %d %d %d\n", reg,
   6040      1.62      haya 		    (reg >> 25) & 0xfe, (reg >> 12) & 0x1fff, reg & 0xfff);
   6041      1.62      haya 	}
   6042      1.62      haya #endif /* FW_DEBUG */
   6043      1.62      haya 	/* end print out debug info */
   6044      1.62      haya 
   6045      1.62      haya 	scratchval = (*itc->itc_scratch) & 0x0000ffff;
   6046      1.62      haya 	*itc->itc_scratch = 0xffffffff;
   6047      1.62      haya 
   6048      1.62      haya 	if ((reg & OHCI_CTXCTL_ACTIVE) == 0 && scratchval != 0xffff) {
   6049      1.62      haya 		/* DMA engine has been stopped */
   6050      1.62      haya 		printf("DMA engine stopped\n");
   6051      1.62      haya 		printf("fwohci_it_intr: %s: IT_CommandPtr 0x%08x "
   6052      1.62      haya 		    "ContextCtrl 0x%08x%s%s%s%s\n",
   6053      1.62      haya 		    sc->sc_sc1394.sc1394_dev.dv_xname,
   6054      1.62      haya 		    OHCI_SYNC_TX_DMA_READ(sc, itc->itc_num, OHCI_SUBREG_CommandPtr),
   6055      1.62      haya 		    reg,
   6056      1.62      haya 		    reg & OHCI_CTXCTL_RUN ? " run" : "",
   6057      1.62      haya 		    reg & OHCI_CTXCTL_WAKE ? " wake" : "",
   6058      1.62      haya 		    reg & OHCI_CTXCTL_DEAD ? " dead" : "",
   6059      1.62      haya 		    reg & OHCI_CTXCTL_ACTIVE ? " active" : "");
   6060      1.62      haya 		printf("fwohci_it_intr: %s: scratch %x start %d end %d valid %d\n",
   6061      1.62      haya 		    sc->sc_sc1394.sc1394_dev.dv_xname, *itc->itc_scratch,
   6062      1.62      haya 		    itc->itc_buf_start->itd_num, itc->itc_buf_end->itd_num,
   6063      1.62      haya 		    itc->itc_buf_cnt);
   6064      1.62      haya 		{
   6065      1.62      haya 			u_int32_t reg
   6066      1.62      haya 			    = OHCI_CSR_READ(sc, OHCI_REG_IsochronousCycleTimer);
   6067      1.62      haya 			printf("\t\tIsoCounter 0x%08x, %d %d %d\n", reg,
   6068      1.62      haya 			    (reg >> 25) & 0xfe, (reg >> 12) & 0x1fff, reg & 0xfff);
   6069      1.62      haya 		}
   6070      1.62      haya 		printf("\t\tbranch of lastdesc 0x%08x\n",
   6071      1.62      haya 		    itc->itc_buf_start->itd_lastdesc->fd_branch);
   6072      1.62      haya 
   6073      1.62      haya 		scratchval = 0xffff;
   6074      1.62      haya 		itc->itc_flags &= ~ITC_FLAGS_RUN;
   6075      1.62      haya 	}
   6076      1.62      haya 
   6077      1.62      haya 	/* unlink old buffers */
   6078      1.62      haya 	if (scratchval != 0xffff) {
   6079      1.62      haya 		/* normal path */
   6080      1.62      haya 		newstartbuf = &itc->itc_buf[scratchval];
   6081      1.62      haya 	} else {
   6082      1.62      haya 		/* DMA engine stopped */
   6083      1.62      haya 		newstartbuf = itc->itc_buf_linkend;
   6084      1.62      haya 		INC_BUF(itc, newstartbuf);
   6085      1.62      haya 	}
   6086      1.62      haya 
   6087      1.62      haya 	itd = (struct fwohci_it_dmabuf *)itc->itc_buf_start;
   6088      1.62      haya 	itc->itc_buf_start = newstartbuf;
   6089      1.62      haya 	while (itd != newstartbuf) {
   6090      1.62      haya 		itc->itc_outpkt += itd->itd_npacket;
   6091      1.62      haya 		fwohci_itd_unlink(itd);
   6092      1.62      haya 		INC_BUF(itc, itd);
   6093      1.62      haya 		--itc->itc_buf_cnt;
   6094      1.62      haya 		DPRINTF(("<buf cnt %d>\n", itc->itc_buf_cnt));
   6095      1.62      haya 	}
   6096      1.62      haya 
   6097      1.62      haya #ifdef DEBUG_USERADD
   6098      1.62      haya 	if (scratchval != 0xffff) {
   6099      1.62      haya 		printf("fwohci0: intr start %d dataend %d %d\n", scratchval,
   6100      1.62      haya 		    itc->itc_buf_end->itd_num, itc->itc_outpkt);
   6101      1.62      haya 	}
   6102      1.62      haya #endif
   6103      1.62      haya 
   6104      1.62      haya 	if (scratchval == 0xffff) {
   6105      1.62      haya 		/* no data supplied */
   6106      1.62      haya 		printf("fwohci_it_intr: no it data.  output total %d\n",
   6107      1.62      haya 		    itc->itc_outpkt);
   6108      1.62      haya 
   6109      1.62      haya 		if (itc->itc_buf_cnt > 0) {
   6110      1.62      haya 			printf("fwohci_it_intr: it DMA stops "
   6111      1.62      haya 			    "w/ valid databuf %d buf %d data %d"
   6112      1.62      haya 			    " intr reg 0x%08x\n",
   6113      1.62      haya 			    itc->itc_buf_cnt,
   6114      1.62      haya 			    itc->itc_buf_end->itd_num,
   6115      1.62      haya 			    fwohci_itd_hasdata(itc->itc_buf_end),
   6116      1.62      haya 			    OHCI_CSR_READ(sc, OHCI_REG_IntEventSet));
   6117      1.62      haya 		} else {
   6118      1.62      haya 			/* All the data gone */
   6119      1.62      haya 			itc->itc_buf_start
   6120      1.62      haya 			    = itc->itc_buf_end
   6121      1.62      haya 			    = itc->itc_buf_linkend
   6122      1.62      haya 			    = &itc->itc_buf[0];
   6123      1.62      haya 			printf("fwohci_it_intr: all packets gone\n");
   6124      1.62      haya 		}
   6125      1.62      haya 
   6126      1.62      haya 		itc->itc_flags &= ~ITC_FLAGS_RUN;
   6127      1.62      haya 
   6128      1.62      haya 		OHCI_SYNC_TX_DMA_WRITE(sc, itc->itc_num,
   6129      1.62      haya 		    OHCI_SUBREG_ContextControlClear, 0xffffffff);
   6130      1.62      haya 		OHCI_SYNC_TX_DMA_WRITE(sc, itc->itc_num,
   6131      1.62      haya 		    OHCI_SUBREG_CommandPtr, 0);
   6132      1.62      haya 		OHCI_SYNC_TX_DMA_WRITE(sc, itc->itc_num,
   6133      1.62      haya 		    OHCI_SUBREG_ContextControlClear, 0x1f);
   6134      1.62      haya 
   6135      1.62      haya 		/* send message */
   6136      1.62      haya 		if (itc->itc_waitchan != NULL) {
   6137      1.62      haya 			wakeup((void *)itc->itc_waitchan);
   6138      1.62      haya 		}
   6139      1.62      haya 
   6140      1.62      haya 		return;
   6141      1.62      haya 	}
   6142      1.62      haya 
   6143      1.62      haya #if 0
   6144      1.62      haya 	/* unlink old buffers */
   6145      1.62      haya 	newstartbuf = &itc->itc_buf[scratchval];
   6146      1.62      haya 
   6147      1.62      haya 	itd = (struct fwohci_it_dmabuf *)itc->itc_buf_start;
   6148      1.62      haya 	itc->itc_buf_start = newstartbuf;
   6149      1.62      haya 	while (itd != newstartbuf) {
   6150      1.62      haya 		itc->itc_outpkt += itd->itd_npacket;
   6151      1.62      haya 		fwohci_itd_unlink(itd);
   6152      1.62      haya 		INC_BUF(itc, itd);
   6153      1.62      haya 		--itc->itc_buf_cnt;
   6154      1.62      haya 		DPRINTF(("<buf cnt %d>\n", itc->itc_buf_cnt));
   6155      1.62      haya 	}
   6156      1.62      haya #endif
   6157      1.62      haya 
   6158      1.62      haya 	/* sanity check */
   6159      1.62      haya 	{
   6160      1.62      haya 		int startidx, endidx, linkendidx;
   6161      1.62      haya 
   6162      1.62      haya 		startidx = itc->itc_buf_start->itd_num;
   6163      1.62      haya 		endidx = itc->itc_buf_end->itd_num;
   6164      1.62      haya 		linkendidx = itc->itc_buf_linkend->itd_num;
   6165      1.62      haya 
   6166      1.62      haya 		if (startidx < endidx) {
   6167      1.62      haya 			if (linkendidx < startidx
   6168      1.62      haya 			    || endidx < linkendidx) {
   6169      1.62      haya 				printf("funny, linkend is not between start "
   6170      1.62      haya 				    "and end [%d, %d]: %d\n",
   6171      1.62      haya 				    startidx, endidx, linkendidx);
   6172      1.62      haya 			}
   6173      1.62      haya 		} else if (startidx > endidx) {
   6174      1.62      haya 			if (linkendidx < startidx
   6175      1.62      haya 			    && endidx < linkendidx) {
   6176      1.62      haya 				printf("funny, linkend is not between start "
   6177      1.62      haya 				    "and end [%d, %d]: %d\n",
   6178      1.62      haya 				    startidx, endidx, linkendidx);
   6179      1.62      haya 			}
   6180      1.62      haya 		} else {
   6181      1.62      haya 			if (linkendidx != startidx) {
   6182      1.62      haya 				printf("funny, linkend is not between start "
   6183      1.62      haya 				    "and end [%d, %d]: %d\n",
   6184      1.62      haya 				    startidx, endidx, linkendidx);
   6185      1.62      haya 			}
   6186      1.62      haya 
   6187      1.62      haya 		}
   6188      1.62      haya 	}
   6189      1.62      haya 
   6190      1.62      haya 	/* link if some valid DMA buffers exist */
   6191      1.62      haya 	if (itc->itc_buf_cnt > 1
   6192      1.62      haya 	    && itc->itc_buf_linkend != itc->itc_buf_end) {
   6193      1.62      haya 		struct fwohci_it_dmabuf *itdprev;
   6194      1.62      haya 		int i;
   6195      1.62      haya 
   6196      1.62      haya 		DPRINTF(("CTX %d: start linkend dataend bufs %d, %d, %d, %d\n",
   6197      1.62      haya 		    itc->itc_num,
   6198      1.62      haya 		    itc->itc_buf_start->itd_num,
   6199      1.62      haya 		    itc->itc_buf_linkend->itd_num,
   6200      1.62      haya 		    itc->itc_buf_end->itd_num,
   6201      1.62      haya 		    itc->itc_buf_cnt));
   6202      1.62      haya 
   6203      1.62      haya 		itd = itdprev = itc->itc_buf_linkend;
   6204      1.62      haya 		INC_BUF(itc, itd);
   6205      1.62      haya 
   6206      1.62      haya #if 0
   6207      1.62      haya 		if (fwohci_itd_isfilled(itd) || itc->itc_buf_cnt == 2) {
   6208      1.62      haya 			while (itdprev != itc->itc_buf_end) {
   6209      1.62      haya 
   6210      1.62      haya 				if (fwohci_itd_link(itdprev, itd)) {
   6211      1.62      haya 					break;
   6212      1.62      haya 				}
   6213      1.62      haya 
   6214      1.62      haya 				itdprev = itd;
   6215      1.62      haya 				INC_BUF(itc, itd);
   6216      1.62      haya 			}
   6217      1.62      haya 			itc->itc_buf_linkend = itdprev;
   6218      1.62      haya 		}
   6219      1.62      haya #endif
   6220      1.62      haya 		i = 0;
   6221      1.62      haya 		while (itdprev != itc->itc_buf_end) {
   6222      1.62      haya 			if (!fwohci_itd_isfilled(itd) && itc->itc_buf_cnt > 2) {
   6223      1.62      haya 				break;
   6224      1.62      haya 			}
   6225      1.62      haya 
   6226      1.62      haya 			if (fwohci_itd_link(itdprev, itd)) {
   6227      1.62      haya 				break;
   6228      1.62      haya 			}
   6229      1.62      haya 
   6230      1.62      haya 			itdprev = itd;
   6231      1.62      haya 			INC_BUF(itc, itd);
   6232      1.62      haya 
   6233      1.62      haya 			itc->itc_buf_linkend = itdprev;
   6234      1.62      haya 			++i;
   6235      1.62      haya 		}
   6236      1.62      haya 
   6237      1.62      haya 		if (i > 0) {
   6238      1.62      haya 			DPRINTF(("CTX %d: start linkend dataend bufs %d, %d, %d, %d\n",
   6239      1.62      haya 			    itc->itc_num,
   6240      1.62      haya 			    itc->itc_buf_start->itd_num,
   6241      1.62      haya 			    itc->itc_buf_linkend->itd_num,
   6242      1.62      haya 			    itc->itc_buf_end->itd_num,
   6243      1.62      haya 			    itc->itc_buf_cnt));
   6244      1.62      haya 		}
   6245      1.62      haya 	} else {
   6246      1.62      haya 		struct fwohci_it_dmabuf *le;
   6247      1.62      haya 
   6248      1.62      haya 		le = itc->itc_buf_linkend;
   6249      1.62      haya 
   6250      1.62      haya 		printf("CTX %d: start linkend dataend bufs %d, %d, %d, %d no buffer added\n",
   6251      1.62      haya 			    itc->itc_num,
   6252      1.62      haya 			    itc->itc_buf_start->itd_num,
   6253      1.62      haya 			    itc->itc_buf_linkend->itd_num,
   6254      1.62      haya 			    itc->itc_buf_end->itd_num,
   6255      1.62      haya 			    itc->itc_buf_cnt);
   6256      1.62      haya 		printf("\tlast descriptor %s %04x %08x\n",
   6257      1.62      haya 		    le->itd_lastdesc->fd_flags & OHCI_DESC_INTR_ALWAYS ? "intr" : "",
   6258      1.62      haya 		    le->itd_lastdesc->fd_flags,
   6259      1.62      haya 		    le->itd_lastdesc->fd_branch);
   6260      1.62      haya 	}
   6261      1.62      haya 
   6262      1.62      haya 	/* send message */
   6263      1.62      haya 	if (itc->itc_waitchan != NULL) {
   6264      1.62      haya 		/*  */
   6265      1.62      haya 		wakeup((void *)itc->itc_waitchan);
   6266      1.62      haya 	}
   6267      1.62      haya }
   6268      1.62      haya 
   6269      1.62      haya 
   6270      1.62      haya 
   6271      1.62      haya /*
   6272      1.62      haya  * int fwohci_itd_construct(struct fwohci_it_ctx *itc,
   6273      1.62      haya  *			    struct fwohci_it_dmabuf *itd, int num,
   6274      1.62      haya  *			    struct fwohci_desc *desc, bus_addr_t phys,
   6275      1.62      haya  *			    int descsize, int maxsize, paddr_t scratch)
   6276      1.62      haya  *
   6277      1.62      haya  *
   6278      1.62      haya  *
   6279      1.62      haya  */
   6280      1.62      haya int
   6281      1.62      haya fwohci_itd_construct(struct fwohci_it_ctx *itc, struct fwohci_it_dmabuf *itd,
   6282      1.62      haya     int num, struct fwohci_desc *desc, bus_addr_t phys, int descsize,
   6283      1.62      haya     int maxsize, paddr_t scratch)
   6284      1.62      haya {
   6285      1.62      haya 	const char *xname = itc->itc_sc->sc_sc1394.sc1394_dev.dv_xname;
   6286      1.62      haya 	struct fwohci_desc *fd;
   6287      1.62      haya 	struct fwohci_desc *descend;
   6288      1.62      haya 	int npkt;
   6289      1.62      haya 	int bufno = 0;		/* DMA segment */
   6290      1.62      haya 	bus_size_t bufused = 0;	/* offset in a DMA segment */
   6291      1.62      haya 	int roundsize;
   6292      1.62      haya 	int tag = itc->itc_tag;
   6293      1.62      haya 	int ch = itc->itc_channel;
   6294      1.62      haya 
   6295      1.62      haya 	itd->itd_ctx = itc;
   6296      1.62      haya 	itd->itd_num = num;
   6297      1.62      haya 
   6298      1.62      haya 	if (descsize > 1024*3) {
   6299      1.62      haya 		printf("%s: fwohci_itd_construct[%d] descsize %d too big\n",
   6300      1.62      haya 		    xname, num, descsize);
   6301      1.62      haya 		return -1;
   6302      1.62      haya 	}
   6303      1.62      haya 
   6304      1.62      haya 	itd->itd_desc = desc;
   6305      1.62      haya 	itd->itd_descsize = descsize;
   6306      1.62      haya 	itd->itd_desc_phys = phys;
   6307      1.62      haya 
   6308      1.62      haya 	itd->itd_lastdesc = desc;
   6309      1.62      haya 	itd->itd_npacket = 0;
   6310      1.62      haya 
   6311      1.62      haya 	printf("%s: fwohci_itd_construct[%d] desc %p descsize %d, maxsize %d\n",
   6312      1.62      haya 	    xname, itd->itd_num, itd->itd_desc, itd->itd_descsize, maxsize);
   6313      1.62      haya 
   6314      1.62      haya 	if (descsize < 4) {
   6315      1.62      haya 		/* too small descriptor array.  at least 4 */
   6316      1.62      haya 		return -1;
   6317      1.62      haya 	}
   6318      1.62      haya 
   6319      1.62      haya 	/* count up how many packet can handle */
   6320      1.62      haya 	itd->itd_maxpacket = (descsize - 1)/3;
   6321      1.62      haya 
   6322      1.62      haya 	/* rounding up to power of 2. minimum 16 */
   6323      1.62      haya 	roundsize = 16;
   6324      1.62      haya 	for (roundsize = 16; roundsize < maxsize; roundsize <<= 1);
   6325      1.62      haya 	itd->itd_maxsize = roundsize;
   6326      1.62      haya 
   6327      1.63       agc 	printf("\t\tdesc%d [%x, %lx]\n", itd->itd_num,
   6328      1.62      haya 	    (u_int32_t)phys,
   6329      1.63       agc 	    (unsigned long)((u_int32_t)phys
   6330      1.63       agc 	    + (itd->itd_maxpacket*3 + 1)*sizeof(struct fwohci_desc)));
   6331      1.62      haya 	printf("%s: fwohci_itd_construct[%d] npkt %d maxsize round up to %d\n",
   6332      1.62      haya 	    xname, itd->itd_num, itd->itd_maxpacket, itd->itd_maxsize);
   6333      1.62      haya 
   6334      1.62      haya 	/* obtain DMA buffer */
   6335      1.62      haya 	if (fwohci_itd_dmabuf_alloc(itd)) {
   6336      1.62      haya 		/* cannot allocate memory for DMA buffer */
   6337      1.62      haya 		return -1;
   6338      1.62      haya 	}
   6339      1.62      haya 
   6340      1.62      haya 	/*
   6341      1.62      haya 	 * make descriptor chain
   6342      1.62      haya 	 *
   6343      1.62      haya 	 * First descriptor group has a STORE_VALUE, OUTPUT_IMMEDIATE
   6344      1.62      haya 	 * and OUTPUT_LAST descriptors Second and after that, a
   6345      1.62      haya 	 * descriptor group has an OUTPUT_IMMEDIATE and an OUTPUT_LAST
   6346      1.62      haya 	 * descriptor.
   6347      1.62      haya 	 */
   6348      1.62      haya 	descend = desc + descsize;
   6349      1.62      haya 
   6350      1.62      haya 	/* set store value descriptor for 1st descriptor group */
   6351      1.62      haya 	desc->fd_flags = OHCI_DESC_STORE_VALUE;
   6352      1.62      haya 	desc->fd_reqcount = num; /* write number of DMA buffer class */
   6353      1.62      haya 	desc->fd_data = scratch; /* at physical memory 'scratch' */
   6354      1.62      haya 	desc->fd_branch = 0;
   6355      1.62      haya 	desc->fd_status = desc->fd_rescount = 0;
   6356      1.62      haya 
   6357      1.62      haya 	itd->itd_store = desc;
   6358      1.62      haya 	itd->itd_store_phys = phys;
   6359      1.62      haya 
   6360      1.62      haya 	++desc;
   6361      1.62      haya 	phys += 16;
   6362      1.62      haya 
   6363      1.62      haya 	npkt = 0;
   6364      1.62      haya 	/* make OUTPUT_DESC chain for packets */
   6365      1.62      haya 	for (fd = desc; fd + 2 < descend; fd += 3, ++npkt) {
   6366      1.62      haya 		struct fwohci_desc *fi = fd;
   6367      1.62      haya 		struct fwohci_desc *fl = fd + 2;
   6368      1.62      haya 		u_int32_t *fi_data = (u_int32_t *)(fd + 1);
   6369      1.62      haya 
   6370      1.62      haya #if 0
   6371      1.62      haya 		if (npkt > itd->itd_maxpacket - 3) {
   6372      1.62      haya 			printf("%s: %3d fi fl %p %p\n", xname, npkt, fi,fl);
   6373      1.62      haya 		}
   6374      1.62      haya #endif
   6375      1.62      haya 
   6376      1.62      haya 		fi->fd_reqcount = 8; /* data size for OHCI command */
   6377      1.62      haya 		fi->fd_flags = OHCI_DESC_IMMED;
   6378      1.62      haya 		fi->fd_data = 0;
   6379      1.62      haya 		fi->fd_branch = 0; /* branch for error */
   6380      1.62      haya 		fi->fd_status = fi->fd_rescount = 0;
   6381      1.62      haya 
   6382      1.62      haya 		/* channel and tag is unchanged */
   6383      1.62      haya 		*fi_data = OHCI_ITHEADER_VAL(TAG, tag) |
   6384      1.62      haya 		    OHCI_ITHEADER_VAL(CHAN, ch) |
   6385      1.62      haya 		    OHCI_ITHEADER_VAL(TCODE, IEEE1394_TCODE_STREAM_DATA);
   6386      1.62      haya 		*++fi_data = 0;
   6387      1.62      haya 		*++fi_data = 0;
   6388      1.62      haya 		*++fi_data = 0;
   6389      1.62      haya 
   6390      1.62      haya 		fl->fd_flags = OHCI_DESC_OUTPUT | OHCI_DESC_LAST |
   6391      1.62      haya 		    OHCI_DESC_BRANCH;
   6392      1.62      haya 		fl->fd_branch =
   6393      1.62      haya 		    (phys + sizeof(struct fwohci_desc)*(npkt + 1)*3) | 0x03;
   6394      1.62      haya 		fl->fd_status = fl->fd_rescount = 0;
   6395      1.62      haya 
   6396      1.62      haya #ifdef FW_DEBUG
   6397      1.62      haya 		if (npkt > itd->itd_maxpacket - 3) {
   6398      1.62      haya 			DPRINTF(("%s: %3d fi fl fl branch %p %p 0x%x\n",
   6399      1.62      haya 			    xname, npkt, fi, fl, (int)fl->fd_branch));
   6400      1.62      haya 		}
   6401      1.62      haya #endif
   6402      1.62      haya 
   6403      1.62      haya 		/* physical addr to data? */
   6404      1.62      haya 		fl->fd_data =
   6405      1.62      haya 		    (u_int32_t)((itd->itd_seg[bufno].ds_addr + bufused));
   6406      1.62      haya 		bufused += itd->itd_maxsize;
   6407      1.62      haya 		if (bufused > itd->itd_seg[bufno].ds_len) {
   6408      1.62      haya 			bufused = 0;
   6409      1.62      haya 			if (++bufno == itd->itd_nsegs) {
   6410      1.62      haya 				/* fail */
   6411      1.62      haya 				break;
   6412      1.62      haya 			}
   6413      1.62      haya 		}
   6414      1.62      haya 	}
   6415      1.62      haya 
   6416      1.62      haya #if 0
   6417      1.62      haya 	if (itd->itd_num == 0) {
   6418      1.62      haya 		u_int32_t *fdp;
   6419      1.62      haya 		u_int32_t adr;
   6420      1.62      haya 		int i = 0;
   6421      1.62      haya 
   6422      1.62      haya 		fdp = (u_int32_t *)itd->itd_desc;
   6423      1.62      haya 		adr = (u_int32_t)itd->itd_desc_phys; /* XXX */
   6424      1.62      haya 
   6425      1.62      haya 		printf("fwohci_itd_construct: audit DMA desc chain. %d\n",
   6426      1.62      haya 		    itd->itd_maxpacket);
   6427      1.62      haya 		for (i = 0; i < itd->itd_maxpacket*12 + 4; ++i) {
   6428      1.62      haya 			if (i % 4 == 0) {
   6429      1.62      haya 				printf("\n%x:", adr + 4*i);
   6430      1.62      haya 			}
   6431      1.62      haya 			printf(" %08x", fdp[i]);
   6432      1.62      haya 		}
   6433      1.62      haya 		printf("\n");
   6434      1.62      haya 
   6435      1.62      haya 	}
   6436      1.62      haya #endif
   6437      1.62      haya 	/* last branch should be 0 */
   6438      1.62      haya 	--fd;
   6439      1.62      haya 	fd->fd_branch = 0;
   6440      1.62      haya 
   6441      1.62      haya 	printf("%s: pkt %d %d maxdesc %p\n",
   6442      1.62      haya 	    xname, npkt, itd->itd_maxpacket, descend);
   6443      1.62      haya 
   6444      1.62      haya 	return 0;
   6445      1.62      haya }
   6446      1.62      haya 
   6447      1.62      haya void
   6448      1.62      haya fwohci_itd_destruct(struct fwohci_it_dmabuf *itd)
   6449      1.62      haya {
   6450      1.62      haya 	const char *xname = itd->itd_ctx->itc_sc->sc_sc1394.sc1394_dev.dv_xname;
   6451      1.62      haya 
   6452      1.62      haya 	printf("%s: fwohci_itd_destruct %d\n", xname, itd->itd_num);
   6453      1.62      haya 
   6454      1.62      haya 	fwohci_itd_dmabuf_free(itd);
   6455      1.62      haya }
   6456      1.62      haya 
   6457      1.62      haya 
   6458      1.62      haya /*
   6459      1.62      haya  * static int fwohci_itd_dmabuf_alloc(struct fwohci_it_dmabuf *itd)
   6460      1.62      haya  *
   6461      1.62      haya  *	This function allocates DMA memory for fwohci_it_dmabuf.  This
   6462      1.62      haya  *	function will return 0 when it succeeds and return non-zero
   6463      1.62      haya  *	value when it fails.
   6464      1.62      haya  */
   6465      1.62      haya static int
   6466      1.62      haya fwohci_itd_dmabuf_alloc(struct fwohci_it_dmabuf *itd)
   6467      1.62      haya {
   6468      1.62      haya 	const char *xname = itd->itd_ctx->itc_sc->sc_sc1394.sc1394_dev.dv_xname;
   6469      1.62      haya 	bus_dma_tag_t dmat = itd->itd_ctx->itc_sc->sc_dmat;
   6470      1.62      haya 
   6471      1.62      haya 	int dmasize = itd->itd_maxsize * itd->itd_maxpacket;
   6472      1.62      haya 	int error;
   6473      1.62      haya 
   6474      1.62      haya 	DPRINTF(("%s: fwohci_itd_dmabuf_alloc[%d] dmasize %d maxpkt %d\n",
   6475      1.62      haya 	    xname, itd->itd_num, dmasize, itd->itd_maxpacket));
   6476      1.62      haya 
   6477      1.62      haya 	if ((error = bus_dmamem_alloc(dmat, dmasize, PAGE_SIZE, 0,
   6478      1.62      haya 	    itd->itd_seg, FWOHCI_MAX_ITDATASEG, &itd->itd_nsegs, 0)) != 0) {
   6479      1.62      haya 		printf("%s: unable to allocate data buffer, error = %d\n",
   6480      1.62      haya 		    xname, error);
   6481      1.62      haya 		goto fail_0;
   6482      1.62      haya 	}
   6483      1.62      haya 
   6484      1.62      haya 	/* checking memory range */
   6485      1.62      haya #ifdef FW_DEBUG
   6486      1.62      haya 	{
   6487      1.62      haya 		int loop;
   6488      1.62      haya 
   6489      1.62      haya 		for (loop = 0; loop < itd->itd_nsegs; ++loop) {
   6490      1.62      haya 			DPRINTF(("\t%.2d: 0x%lx - 0x%lx\n", loop,
   6491      1.62      haya 			    (long)itd->itd_seg[loop].ds_addr,
   6492      1.62      haya 			    (long)itd->itd_seg[loop].ds_addr
   6493      1.62      haya 			    + (long)itd->itd_seg[loop].ds_len - 1));
   6494      1.62      haya 		}
   6495      1.62      haya 	}
   6496      1.62      haya #endif
   6497      1.62      haya 
   6498      1.62      haya 	if ((error = bus_dmamem_map(dmat, itd->itd_seg, itd->itd_nsegs,
   6499      1.62      haya 	    dmasize, (caddr_t *)&itd->itd_buf,
   6500      1.62      haya 	    BUS_DMA_COHERENT | BUS_DMA_WAITOK)) != 0) {
   6501      1.62      haya 		printf("%s: unable to map data buffer, error = %d\n",
   6502      1.62      haya 		    xname, error);
   6503      1.62      haya 		goto fail_1;
   6504      1.62      haya 	}
   6505      1.62      haya 
   6506      1.62      haya 	DPRINTF(("fwohci_it_data_alloc[%d]: bus_dmamem_map addr %p\n",
   6507      1.62      haya 	    itd->itd_num, itd->itd_buf));
   6508      1.62      haya 
   6509      1.62      haya 	if ((error = bus_dmamap_create(dmat, /*chunklen*/dmasize,
   6510      1.62      haya 	    itd->itd_nsegs, dmasize, 0, BUS_DMA_WAITOK,
   6511      1.62      haya 	    &itd->itd_dmamap)) != 0) {
   6512      1.62      haya 		printf("%s: unable to create data buffer DMA map, "
   6513      1.62      haya 		    "error = %d\n", xname, error);
   6514      1.62      haya 		goto fail_2;
   6515      1.62      haya 	}
   6516      1.62      haya 
   6517      1.62      haya 	DPRINTF(("fwohci_it_data_alloc: bus_dmamem_create\n"));
   6518      1.62      haya 
   6519      1.62      haya 	if ((error = bus_dmamap_load(dmat, itd->itd_dmamap,
   6520      1.62      haya 	    itd->itd_buf, dmasize, NULL, BUS_DMA_WAITOK)) != 0) {
   6521      1.62      haya 		printf("%s: unable to load data buffer DMA map, error = %d\n",
   6522      1.62      haya 		    xname, error);
   6523      1.62      haya 		goto fail_3;
   6524      1.62      haya 	}
   6525      1.62      haya 
   6526      1.62      haya 	DPRINTF(("fwohci_itd_dmabuf_alloc: load DMA memory vm %p\n",
   6527      1.62      haya 	    itd->itd_buf));
   6528      1.62      haya 	DPRINTF(("\tmapsize %ld nsegs %d\n",
   6529      1.62      haya 	    (long)itd->itd_dmamap->dm_mapsize, itd->itd_dmamap->dm_nsegs));
   6530      1.62      haya 
   6531      1.62      haya #ifdef FW_DEBUG
   6532      1.62      haya 	{
   6533      1.62      haya 		int loop;
   6534      1.62      haya 
   6535      1.62      haya 		for (loop = 0; loop < itd->itd_dmamap->dm_nsegs; ++loop) {
   6536      1.62      haya 			DPRINTF(("\t%.2d: 0x%lx - 0x%lx\n", loop,
   6537      1.62      haya 			    (long)itd->itd_dmamap->dm_segs[loop].ds_addr,
   6538      1.62      haya 			    (long)itd->itd_dmamap->dm_segs[loop].ds_addr +
   6539      1.62      haya 			    (long)itd->itd_dmamap->dm_segs[loop].ds_len - 1));
   6540      1.62      haya 		}
   6541      1.62      haya 	}
   6542      1.62      haya #endif
   6543      1.62      haya 
   6544      1.62      haya 	return 0;
   6545      1.62      haya 
   6546      1.62      haya   fail_3:
   6547      1.62      haya 	bus_dmamap_destroy(dmat, itd->itd_dmamap);
   6548      1.62      haya   fail_2:
   6549      1.62      haya 	bus_dmamem_unmap(dmat, (caddr_t)itd->itd_buf, dmasize);
   6550      1.62      haya   fail_1:
   6551      1.62      haya 	bus_dmamem_free(dmat, itd->itd_seg, itd->itd_nsegs);
   6552      1.62      haya   fail_0:
   6553      1.62      haya 	itd->itd_nsegs = 0;
   6554      1.62      haya 	itd->itd_maxpacket = 0;
   6555      1.62      haya 	return error;
   6556      1.62      haya }
   6557      1.62      haya 
   6558      1.62      haya /*
   6559      1.62      haya  * static void fwohci_itd_dmabuf_free(struct fwohci_it_dmabuf *itd)
   6560      1.62      haya  *
   6561      1.62      haya  *	This function will release memory resource allocated by
   6562      1.62      haya  *	fwohci_itd_dmabuf_alloc().
   6563      1.62      haya  */
   6564      1.62      haya static void
   6565      1.62      haya fwohci_itd_dmabuf_free(struct fwohci_it_dmabuf *itd)
   6566      1.62      haya {
   6567      1.62      haya 	bus_dma_tag_t dmat = itd->itd_ctx->itc_sc->sc_dmat;
   6568      1.62      haya 	int dmasize = itd->itd_maxsize * itd->itd_maxpacket;
   6569      1.62      haya 
   6570      1.62      haya 	bus_dmamap_destroy(dmat, itd->itd_dmamap);
   6571      1.62      haya 	bus_dmamem_unmap(dmat, (caddr_t)itd->itd_buf, dmasize);
   6572      1.62      haya 	bus_dmamem_free(dmat, itd->itd_seg, itd->itd_nsegs);
   6573      1.62      haya 
   6574      1.62      haya 	itd->itd_nsegs = 0;
   6575      1.62      haya 	itd->itd_maxpacket = 0;
   6576      1.62      haya }
   6577      1.62      haya 
   6578      1.62      haya 
   6579      1.62      haya 
   6580      1.62      haya /*
   6581      1.62      haya  * int fwohci_itd_link(struct fwohci_it_dmabuf *itd,
   6582      1.62      haya  *		struct fwohci_it_dmabuf *itdc)
   6583      1.62      haya  *
   6584      1.62      haya  *	This function will concatinate two descriptor chains in dmabuf
   6585      1.62      haya  *	itd and itdc.  The descriptor link in itdc follows one in itd.
   6586      1.62      haya  *	This function will move interrrupt packet from the end of itd
   6587      1.62      haya  *	to the top of itdc.
   6588      1.62      haya  *
   6589      1.62      haya  *	This function will return 0 whel this funcion suceeds.  If an
   6590      1.62      haya  *	error happens, return a negative value.
   6591      1.62      haya  */
   6592      1.62      haya int
   6593      1.62      haya fwohci_itd_link(struct fwohci_it_dmabuf *itd, struct fwohci_it_dmabuf *itdc)
   6594      1.62      haya {
   6595      1.62      haya 	struct fwohci_desc *fd1, *fdc;
   6596      1.62      haya 
   6597      1.62      haya 	if (itdc->itd_lastdesc == itdc->itd_desc) {
   6598      1.62      haya 		/* no valid data */
   6599      1.62      haya 		printf("fwohci_itd_link: no data\n");
   6600      1.62      haya 		return -1;
   6601      1.62      haya 	}
   6602      1.62      haya 
   6603      1.62      haya 	if (itdc->itd_flags & ITD_FLAGS_LOCK) {
   6604      1.62      haya 		/* used already */
   6605      1.62      haya 		printf("fwohci_itd_link: link locked\n");
   6606      1.62      haya 		return -1;
   6607      1.62      haya 	}
   6608      1.62      haya 	itdc->itd_flags |= ITD_FLAGS_LOCK;
   6609      1.62      haya 	/* for the first one */
   6610      1.62      haya 	itd->itd_flags |= ITD_FLAGS_LOCK;
   6611      1.62      haya 
   6612      1.62      haya 	DPRINTF(("linking %d after %d: add %d pkts\n",
   6613      1.62      haya 	    itdc->itd_num, itd->itd_num, itdc->itd_npacket));
   6614      1.62      haya 
   6615      1.62      haya 	/* XXX: should sync cache */
   6616      1.62      haya 
   6617      1.62      haya 	fd1 = itd->itd_lastdesc;
   6618      1.62      haya 	fdc = itdc->itd_desc + 3; /* OUTPUT_LAST in the first descriptor */
   6619      1.62      haya 
   6620      1.62      haya 	/* sanity check */
   6621      1.62      haya #define OUTPUT_LAST_DESC (OHCI_DESC_OUTPUT | OHCI_DESC_LAST | OHCI_DESC_BRANCH)
   6622      1.62      haya 	if ((fd1->fd_flags & OUTPUT_LAST_DESC) != OUTPUT_LAST_DESC) {
   6623      1.62      haya 		printf("funny! not OUTPUT_LAST descriptor %p\n", fd1);
   6624      1.62      haya 	}
   6625      1.62      haya 	if (itd->itd_lastdesc - itd->itd_desc != 3 * itd->itd_npacket) {
   6626      1.63       agc 		printf("funny! packet number inconsistency %ld <=> %ld\n",
   6627      1.63       agc 		    (long)(itd->itd_lastdesc - itd->itd_desc),
   6628      1.63       agc 		    (long)(3*itd->itd_npacket));
   6629      1.62      haya 	}
   6630      1.62      haya 
   6631      1.62      haya 	fd1->fd_flags &= ~OHCI_DESC_INTR_ALWAYS;
   6632      1.62      haya 	fdc->fd_flags |= OHCI_DESC_INTR_ALWAYS;
   6633      1.62      haya 	fd1->fd_branch = itdc->itd_desc_phys | 4;
   6634      1.62      haya 
   6635      1.62      haya 	itdc->itd_lastdesc->fd_flags |= OHCI_DESC_INTR_ALWAYS;
   6636      1.62      haya 	/* save branch addr of lastdesc and substitute 0 to it */
   6637      1.62      haya 	itdc->itd_savedbranch = itdc->itd_lastdesc->fd_branch;
   6638      1.62      haya 	itdc->itd_lastdesc->fd_branch = 0;
   6639      1.62      haya 
   6640      1.62      haya 	DPRINTF(("%s: link (%d %d), add pkt %d/%d branch 0x%x next saved 0x%x\n",
   6641      1.62      haya 	    itd->itd_ctx->itc_sc->sc_sc1394.sc1394_dev.dv_xname,
   6642      1.62      haya 	    itd->itd_num, itdc->itd_num,
   6643      1.62      haya 	    itdc->itd_npacket, itdc->itd_maxpacket,
   6644      1.62      haya 	    (int)fd1->fd_branch, (int)itdc->itd_savedbranch));
   6645      1.62      haya 
   6646      1.62      haya 	/* XXX: should sync cache */
   6647      1.62      haya 
   6648      1.62      haya 	return 0;
   6649      1.62      haya }
   6650      1.62      haya 
   6651      1.62      haya 
   6652      1.62      haya /*
   6653      1.62      haya  * int fwohci_itd_unlink(struct fwohci_it_dmabuf *itd)
   6654      1.62      haya  *
   6655      1.62      haya  *	This function will unlink the descriptor chain from valid link
   6656      1.62      haya  *	of descriptors.  The target descriptor is specified by the
   6657      1.62      haya  *	arguent.
   6658      1.62      haya  */
   6659      1.62      haya int
   6660      1.62      haya fwohci_itd_unlink(struct fwohci_it_dmabuf *itd)
   6661      1.62      haya {
   6662      1.62      haya 	struct fwohci_desc *fd;
   6663      1.62      haya 
   6664      1.62      haya 	/* XXX: should sync cache */
   6665      1.62      haya 
   6666      1.62      haya 	fd = itd->itd_lastdesc;
   6667      1.62      haya 
   6668      1.62      haya 	fd->fd_branch = itd->itd_savedbranch;
   6669      1.62      haya 	DPRINTF(("%s: unlink buf %d branch restored 0x%x\n",
   6670      1.62      haya 	    itd->itd_ctx->itc_sc->sc_sc1394.sc1394_dev.dv_xname,
   6671      1.62      haya 	    itd->itd_num, (int)fd->fd_branch));
   6672      1.62      haya 
   6673      1.62      haya 	fd->fd_flags &= ~OHCI_DESC_INTR_ALWAYS;
   6674      1.62      haya 	itd->itd_lastdesc = itd->itd_desc;
   6675      1.62      haya 
   6676      1.62      haya 	fd = itd->itd_desc + 3;	/* 1st OUTPUT_LAST */
   6677      1.62      haya 	fd->fd_flags &= ~OHCI_DESC_INTR_ALWAYS;
   6678      1.62      haya 
   6679      1.62      haya 	/* XXX: should sync cache */
   6680      1.62      haya 
   6681      1.62      haya 	itd->itd_npacket = 0;
   6682      1.62      haya 	itd->itd_lastdesc = itd->itd_desc;
   6683      1.62      haya 	itd->itd_flags &= ~ITD_FLAGS_LOCK;
   6684      1.62      haya 
   6685      1.62      haya 	return 0;
   6686      1.62      haya }
   6687      1.62      haya 
   6688      1.62      haya 
   6689      1.62      haya /*
   6690      1.62      haya  * static int fwohci_itd_writedata(struct fwohci_it_dmabuf *, int ndata,
   6691      1.62      haya  *			struct ieee1394_it_datalist *);
   6692      1.62      haya  *
   6693      1.62      haya  *	This function will return the number of written data, or
   6694      1.62      haya  *	negative value if an error happens
   6695      1.62      haya  */
   6696      1.62      haya int
   6697      1.62      haya fwohci_itd_writedata(struct fwohci_it_dmabuf *itd, int ndata,
   6698      1.62      haya     struct ieee1394_it_datalist *itdata)
   6699      1.62      haya {
   6700      1.62      haya 	int writepkt;
   6701      1.62      haya 	int i;
   6702      1.62      haya 	u_int8_t *p;
   6703      1.62      haya 	struct fwohci_desc *fd;
   6704      1.62      haya 	u_int32_t *fd_idata;
   6705      1.62      haya 	const int dspace =
   6706      1.62      haya 	    itd->itd_maxpacket - itd->itd_npacket < ndata ?
   6707      1.62      haya 	    itd->itd_maxpacket - itd->itd_npacket : ndata;
   6708      1.62      haya 
   6709      1.62      haya 	if (itd->itd_flags & ITD_FLAGS_LOCK || dspace == 0) {
   6710      1.62      haya 		/* it is locked: cannot write anything */
   6711      1.62      haya 		if (itd->itd_flags & ITD_FLAGS_LOCK) {
   6712      1.62      haya 			DPRINTF(("fwohci_itd_writedata: buf %d lock flag %s,"
   6713      1.62      haya 			    " dspace %d\n",
   6714      1.62      haya 			    itd->itd_num,
   6715      1.62      haya 			    itd->itd_flags & ITD_FLAGS_LOCK ? "ON" : "OFF",
   6716      1.62      haya 			    dspace));
   6717      1.62      haya 			return 0;	/* not an error */
   6718      1.62      haya 		}
   6719      1.62      haya 	}
   6720      1.62      haya 
   6721      1.62      haya 	/* sanity check */
   6722      1.62      haya 	if (itd->itd_maxpacket < itd->itd_npacket) {
   6723      1.62      haya 		printf("fwohci_itd_writedata: funny! # pkt > maxpkt"
   6724      1.62      haya 			"%d %d\n", itd->itd_npacket, itd->itd_maxpacket);
   6725      1.62      haya 	}
   6726      1.62      haya 
   6727      1.62      haya 	p = itd->itd_buf + itd->itd_maxsize * itd->itd_npacket;
   6728      1.62      haya 	fd = itd->itd_lastdesc;
   6729      1.62      haya 
   6730      1.62      haya 	DPRINTF(("fwohci_itd_writedata(%d[%p], %d, 0x%p) invoked:\n",
   6731      1.62      haya 	    itd->itd_num, itd, ndata, itdata));
   6732      1.62      haya 
   6733      1.62      haya 	for (writepkt = 0; writepkt < dspace; ++writepkt) {
   6734      1.62      haya 		u_int8_t *p1 = p;
   6735      1.62      haya 		int cpysize;
   6736      1.62      haya 		int totalsize = 0;
   6737      1.62      haya 
   6738      1.62      haya 		DPRINTF(("writing %d ", writepkt));
   6739      1.62      haya 
   6740      1.62      haya 		for (i = 0; i < 4; ++i) {
   6741      1.62      haya 			switch (itdata->it_cmd[i]&IEEE1394_IT_CMD_MASK) {
   6742      1.62      haya 			case IEEE1394_IT_CMD_IMMED:
   6743      1.62      haya 				memcpy(p1, &itdata->it_u[i].id_data, 8);
   6744      1.62      haya 				p1 += 8;
   6745      1.62      haya 				totalsize += 8;
   6746      1.62      haya 				break;
   6747      1.62      haya 			case IEEE1394_IT_CMD_PTR:
   6748      1.62      haya 				cpysize = itdata->it_cmd[i]&IEEE1394_IT_CMD_SIZE;
   6749      1.62      haya 				DPRINTF(("fwohci_itd_writedata: cpy %d %p\n",
   6750      1.62      haya 				    cpysize, itdata->it_u[i].id_addr));
   6751      1.62      haya 				if (totalsize + cpysize > itd->itd_maxsize) {
   6752      1.62      haya 					/* error: too big size */
   6753      1.62      haya 					break;
   6754      1.62      haya 				}
   6755      1.62      haya 				memcpy(p1, itdata->it_u[i].id_addr, cpysize);
   6756      1.62      haya 				totalsize += cpysize;
   6757      1.62      haya 				break;
   6758      1.62      haya 			case IEEE1394_IT_CMD_NOP:
   6759      1.62      haya 				break;
   6760      1.62      haya 			default:
   6761      1.62      haya 				/* unknown command */
   6762      1.62      haya 				break;
   6763      1.62      haya 			}
   6764      1.62      haya 		}
   6765      1.62      haya 
   6766      1.62      haya 		/* only for DV test */
   6767      1.62      haya 		if (totalsize != 488) {
   6768      1.62      haya 			printf("error: totalsize %d at %d\n",
   6769      1.62      haya 			    totalsize, writepkt);
   6770      1.62      haya 		}
   6771      1.62      haya 
   6772      1.62      haya 		DPRINTF(("totalsize %d ", totalsize));
   6773      1.62      haya 
   6774      1.62      haya 		/* fill iso command in OUTPUT_IMMED descriptor */
   6775      1.62      haya 
   6776      1.62      haya 		/* XXX: sync cache */
   6777      1.62      haya 		fd += 2;	/* next to first descriptor */
   6778      1.62      haya 		fd_idata = (u_int32_t *)fd;
   6779      1.62      haya 
   6780      1.62      haya 		/*
   6781      1.62      haya 		 * Umm, should tag, channel and tcode be written
   6782      1.62      haya 		 * previously in itd_construct?
   6783      1.62      haya 		 */
   6784      1.62      haya #if 0
   6785      1.62      haya 		*fd_idata = OHCI_ITHEADER_VAL(TAG, tag) |
   6786      1.62      haya 		    OHCI_ITHEADER_VAL(CHAN, ch) |
   6787      1.62      haya 		    OHCI_ITHEADER_VAL(TCODE, IEEE1394_TCODE_STREAM_DATA);
   6788      1.62      haya #endif
   6789      1.62      haya 		*++fd_idata = totalsize << 16;
   6790      1.62      haya 
   6791      1.62      haya 		/* fill data in OUTPUT_LAST descriptor */
   6792      1.62      haya 		++fd;
   6793      1.62      haya 		/* intr check... */
   6794      1.62      haya 		if (fd->fd_flags & OHCI_DESC_INTR_ALWAYS) {
   6795      1.63       agc 			printf("uncleared INTR flag in desc %ld\n",
   6796      1.63       agc 			    (long)(fd - itd->itd_desc - 1)/3);
   6797      1.62      haya 		}
   6798      1.62      haya 		fd->fd_flags &= ~OHCI_DESC_INTR_ALWAYS;
   6799      1.62      haya 
   6800      1.62      haya 		if ((fd - itd->itd_desc - 1)/3 != itd->itd_maxpacket - 1) {
   6801      1.62      haya 			u_int32_t bcal;
   6802      1.62      haya 
   6803      1.62      haya 			bcal = (fd - itd->itd_desc + 1)*sizeof(struct fwohci_desc) + (u_int32_t)itd->itd_desc_phys;
   6804      1.62      haya 			if (bcal != (fd->fd_branch & 0xfffffff0)) {
   6805      1.62      haya 
   6806      1.63       agc 				printf("uum, branch differ at %d, %x %x %ld/%d\n",
   6807      1.62      haya 				    itd->itd_num,
   6808      1.62      haya 				    bcal,
   6809      1.62      haya 				    fd->fd_branch,
   6810      1.63       agc 				    (long)((fd - itd->itd_desc - 1)/3),
   6811      1.62      haya 				    itd->itd_maxpacket);
   6812      1.62      haya 			}
   6813      1.62      haya 		} else {
   6814      1.62      haya 			/* the last pcaket */
   6815      1.62      haya 			if (fd->fd_branch != 0) {
   6816      1.63       agc 				printf("uum, branch differ at %d, %x %x %ld/%d\n",
   6817      1.62      haya 				    itd->itd_num,
   6818      1.62      haya 				    0,
   6819      1.62      haya 				    fd->fd_branch,
   6820      1.63       agc 				    (long)((fd - itd->itd_desc - 1)/3),
   6821      1.62      haya 				    itd->itd_maxpacket);
   6822      1.62      haya 			}
   6823      1.62      haya 		}
   6824      1.62      haya 
   6825      1.62      haya 		/* sanity check */
   6826      1.62      haya 		if (fd->fd_flags != OUTPUT_LAST_DESC) {
   6827      1.62      haya 			printf("fwohci_itd_writedata: dmabuf %d desc inconsistent %d\n",
   6828      1.62      haya 			    itd->itd_num, writepkt + itd->itd_npacket);
   6829      1.62      haya 			break;
   6830      1.62      haya 		}
   6831      1.62      haya 		fd->fd_reqcount = totalsize;
   6832      1.62      haya 		/* XXX: sync cache */
   6833      1.62      haya 
   6834      1.62      haya 		++itdata;
   6835      1.62      haya 		p += itd->itd_maxsize;
   6836      1.62      haya 	}
   6837      1.62      haya 
   6838      1.62      haya 	DPRINTF(("loop start %d, %d times %d\n",
   6839      1.62      haya 	    itd->itd_npacket, dspace, writepkt));
   6840      1.62      haya 
   6841      1.62      haya 	itd->itd_npacket += writepkt;
   6842      1.62      haya 	itd->itd_lastdesc = fd;
   6843      1.62      haya 
   6844      1.62      haya 	return writepkt;
   6845      1.62      haya }
   6846      1.62      haya 
   6847      1.62      haya 
   6848      1.62      haya 
   6849      1.62      haya 
   6850      1.62      haya 
   6851      1.62      haya int
   6852      1.62      haya fwohci_itd_isfilled(struct fwohci_it_dmabuf *itd)
   6853      1.62      haya {
   6854      1.62      haya 
   6855      1.62      haya 	return itd->itd_npacket*2 > itd->itd_maxpacket ? 1 : 0;
   6856      1.62      haya }
   6857