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

Cache object: e4a4ea22e14dd7eb63cbff9f3476b890


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