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

Cache object: 25dec65ddf5c720c8ad60b85d8b51ce6


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