The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ieee1394/fwohci.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: c1a06a21dad353f7099c3baa75f3cab7


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.