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

Cache object: c899e9fd229f00c7591c67ee8fe76612


[ 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.