13c60ba66SKatsushi Kobayashi /* 277ee030bSHidetoshi Shimokawa * Copyright (c) 2003 Hidetoshi Shimokawa 33c60ba66SKatsushi Kobayashi * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa 43c60ba66SKatsushi Kobayashi * All rights reserved. 53c60ba66SKatsushi Kobayashi * 63c60ba66SKatsushi Kobayashi * Redistribution and use in source and binary forms, with or without 73c60ba66SKatsushi Kobayashi * modification, are permitted provided that the following conditions 83c60ba66SKatsushi Kobayashi * are met: 93c60ba66SKatsushi Kobayashi * 1. Redistributions of source code must retain the above copyright 103c60ba66SKatsushi Kobayashi * notice, this list of conditions and the following disclaimer. 113c60ba66SKatsushi Kobayashi * 2. Redistributions in binary form must reproduce the above copyright 123c60ba66SKatsushi Kobayashi * notice, this list of conditions and the following disclaimer in the 133c60ba66SKatsushi Kobayashi * documentation and/or other materials provided with the distribution. 143c60ba66SKatsushi Kobayashi * 3. All advertising materials mentioning features or use of this software 153c60ba66SKatsushi Kobayashi * must display the acknowledgement as bellow: 163c60ba66SKatsushi Kobayashi * 178da326fdSHidetoshi Shimokawa * This product includes software developed by K. Kobayashi and H. Shimokawa 183c60ba66SKatsushi Kobayashi * 193c60ba66SKatsushi Kobayashi * 4. The name of the author may not be used to endorse or promote products 203c60ba66SKatsushi Kobayashi * derived from this software without specific prior written permission. 213c60ba66SKatsushi Kobayashi * 223c60ba66SKatsushi Kobayashi * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 233c60ba66SKatsushi Kobayashi * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 243c60ba66SKatsushi Kobayashi * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 253c60ba66SKatsushi Kobayashi * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 263c60ba66SKatsushi Kobayashi * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 273c60ba66SKatsushi Kobayashi * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 283c60ba66SKatsushi Kobayashi * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 293c60ba66SKatsushi Kobayashi * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 303c60ba66SKatsushi Kobayashi * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 313c60ba66SKatsushi Kobayashi * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 323c60ba66SKatsushi Kobayashi * POSSIBILITY OF SUCH DAMAGE. 333c60ba66SKatsushi Kobayashi * 343c60ba66SKatsushi Kobayashi * $FreeBSD$ 353c60ba66SKatsushi Kobayashi * 363c60ba66SKatsushi Kobayashi */ 378da326fdSHidetoshi Shimokawa 383c60ba66SKatsushi Kobayashi #define ATRQ_CH 0 393c60ba66SKatsushi Kobayashi #define ATRS_CH 1 403c60ba66SKatsushi Kobayashi #define ARRQ_CH 2 413c60ba66SKatsushi Kobayashi #define ARRS_CH 3 423c60ba66SKatsushi Kobayashi #define ITX_CH 4 433c60ba66SKatsushi Kobayashi #define IRX_CH 0x24 443c60ba66SKatsushi Kobayashi 453c60ba66SKatsushi Kobayashi #include <sys/param.h> 463c60ba66SKatsushi Kobayashi #include <sys/systm.h> 473c60ba66SKatsushi Kobayashi #include <sys/mbuf.h> 483c60ba66SKatsushi Kobayashi #include <sys/malloc.h> 493c60ba66SKatsushi Kobayashi #include <sys/sockio.h> 503c60ba66SKatsushi Kobayashi #include <sys/bus.h> 513c60ba66SKatsushi Kobayashi #include <sys/kernel.h> 523c60ba66SKatsushi Kobayashi #include <sys/conf.h> 5377ee030bSHidetoshi Shimokawa #include <sys/endian.h> 543c60ba66SKatsushi Kobayashi 553c60ba66SKatsushi Kobayashi #include <machine/bus.h> 563c60ba66SKatsushi Kobayashi 5710d3ed64SHidetoshi Shimokawa #if defined(__DragonFly__) || __FreeBSD_version < 500000 58170e7a20SHidetoshi Shimokawa #include <machine/clock.h> /* for DELAY() */ 59170e7a20SHidetoshi Shimokawa #endif 60170e7a20SHidetoshi Shimokawa 6110d3ed64SHidetoshi Shimokawa #ifdef __DragonFly__ 6210d3ed64SHidetoshi Shimokawa #include "firewire.h" 6310d3ed64SHidetoshi Shimokawa #include "firewirereg.h" 6410d3ed64SHidetoshi Shimokawa #include "fwdma.h" 6510d3ed64SHidetoshi Shimokawa #include "fwohcireg.h" 6610d3ed64SHidetoshi Shimokawa #include "fwohcivar.h" 6710d3ed64SHidetoshi Shimokawa #include "firewire_phy.h" 6810d3ed64SHidetoshi Shimokawa #else 693c60ba66SKatsushi Kobayashi #include <dev/firewire/firewire.h> 703c60ba66SKatsushi Kobayashi #include <dev/firewire/firewirereg.h> 7177ee030bSHidetoshi Shimokawa #include <dev/firewire/fwdma.h> 723c60ba66SKatsushi Kobayashi #include <dev/firewire/fwohcireg.h> 733c60ba66SKatsushi Kobayashi #include <dev/firewire/fwohcivar.h> 743c60ba66SKatsushi Kobayashi #include <dev/firewire/firewire_phy.h> 7510d3ed64SHidetoshi Shimokawa #endif 763c60ba66SKatsushi Kobayashi 773c60ba66SKatsushi Kobayashi #undef OHCI_DEBUG 788da326fdSHidetoshi Shimokawa 793c60ba66SKatsushi Kobayashi static char dbcode[16][0x10]={"OUTM", "OUTL","INPM","INPL", 803c60ba66SKatsushi Kobayashi "STOR","LOAD","NOP ","STOP",}; 8177ee030bSHidetoshi Shimokawa 823c60ba66SKatsushi Kobayashi static char dbkey[8][0x10]={"ST0", "ST1","ST2","ST3", 833c60ba66SKatsushi Kobayashi "UNDEF","REG","SYS","DEV"}; 8477ee030bSHidetoshi Shimokawa static char dbcond[4][0x10]={"NEV","C=1", "C=0", "ALL"}; 853c60ba66SKatsushi Kobayashi char fwohcicode[32][0x20]={ 863c60ba66SKatsushi Kobayashi "No stat","Undef","long","miss Ack err", 873c60ba66SKatsushi Kobayashi "underrun","overrun","desc err", "data read err", 883c60ba66SKatsushi Kobayashi "data write err","bus reset","timeout","tcode err", 893c60ba66SKatsushi Kobayashi "Undef","Undef","unknown event","flushed", 903c60ba66SKatsushi Kobayashi "Undef","ack complete","ack pend","Undef", 913c60ba66SKatsushi Kobayashi "ack busy_X","ack busy_A","ack busy_B","Undef", 923c60ba66SKatsushi Kobayashi "Undef","Undef","Undef","ack tardy", 933c60ba66SKatsushi Kobayashi "Undef","ack data_err","ack type_err",""}; 9477ee030bSHidetoshi Shimokawa 950bc666e0SHidetoshi Shimokawa #define MAX_SPEED 3 9648087829SHidetoshi Shimokawa extern char *linkspeed[]; 9703161bbcSDoug Rabson uint32_t tagbit[4] = { 1 << 28, 1 << 29, 1 << 30, 1 << 31}; 983c60ba66SKatsushi Kobayashi 993c60ba66SKatsushi Kobayashi static struct tcode_info tinfo[] = { 1003c60ba66SKatsushi Kobayashi /* hdr_len block flag*/ 1013c60ba66SKatsushi Kobayashi /* 0 WREQQ */ {16, FWTI_REQ | FWTI_TLABEL}, 1023c60ba66SKatsushi Kobayashi /* 1 WREQB */ {16, FWTI_REQ | FWTI_TLABEL | FWTI_BLOCK_ASY}, 1033c60ba66SKatsushi Kobayashi /* 2 WRES */ {12, FWTI_RES}, 1043c60ba66SKatsushi Kobayashi /* 3 XXX */ { 0, 0}, 1053c60ba66SKatsushi Kobayashi /* 4 RREQQ */ {12, FWTI_REQ | FWTI_TLABEL}, 1063c60ba66SKatsushi Kobayashi /* 5 RREQB */ {16, FWTI_REQ | FWTI_TLABEL}, 1073c60ba66SKatsushi Kobayashi /* 6 RRESQ */ {16, FWTI_RES}, 1083c60ba66SKatsushi Kobayashi /* 7 RRESB */ {16, FWTI_RES | FWTI_BLOCK_ASY}, 1093c60ba66SKatsushi Kobayashi /* 8 CYCS */ { 0, 0}, 1103c60ba66SKatsushi Kobayashi /* 9 LREQ */ {16, FWTI_REQ | FWTI_TLABEL | FWTI_BLOCK_ASY}, 1113c60ba66SKatsushi Kobayashi /* a STREAM */ { 4, FWTI_REQ | FWTI_BLOCK_STR}, 1123c60ba66SKatsushi Kobayashi /* b LRES */ {16, FWTI_RES | FWTI_BLOCK_ASY}, 1133c60ba66SKatsushi Kobayashi /* c XXX */ { 0, 0}, 1143c60ba66SKatsushi Kobayashi /* d XXX */ { 0, 0}, 1153c60ba66SKatsushi Kobayashi /* e PHY */ {12, FWTI_REQ}, 1163c60ba66SKatsushi Kobayashi /* f XXX */ { 0, 0} 1173c60ba66SKatsushi Kobayashi }; 1183c60ba66SKatsushi Kobayashi 1193c60ba66SKatsushi Kobayashi #define OHCI_WRITE_SIGMASK 0xffff0000 1203c60ba66SKatsushi Kobayashi #define OHCI_READ_SIGMASK 0xffff0000 1213c60ba66SKatsushi Kobayashi 1223c60ba66SKatsushi Kobayashi #define OWRITE(sc, r, x) bus_space_write_4((sc)->bst, (sc)->bsh, (r), (x)) 1233c60ba66SKatsushi Kobayashi #define OREAD(sc, r) bus_space_read_4((sc)->bst, (sc)->bsh, (r)) 1243c60ba66SKatsushi Kobayashi 125d09a5d6fSHidetoshi Shimokawa static void fwohci_ibr (struct firewire_comm *); 126d09a5d6fSHidetoshi Shimokawa static void fwohci_db_init (struct fwohci_softc *, struct fwohci_dbch *); 127d09a5d6fSHidetoshi Shimokawa static void fwohci_db_free (struct fwohci_dbch *); 128d09a5d6fSHidetoshi Shimokawa static void fwohci_arcv (struct fwohci_softc *, struct fwohci_dbch *, int); 129d09a5d6fSHidetoshi Shimokawa static void fwohci_txd (struct fwohci_softc *, struct fwohci_dbch *); 130d09a5d6fSHidetoshi Shimokawa static void fwohci_start_atq (struct firewire_comm *); 131d09a5d6fSHidetoshi Shimokawa static void fwohci_start_ats (struct firewire_comm *); 132d09a5d6fSHidetoshi Shimokawa static void fwohci_start (struct fwohci_softc *, struct fwohci_dbch *); 13303161bbcSDoug Rabson static uint32_t fwphy_wrdata ( struct fwohci_softc *, uint32_t, uint32_t); 13403161bbcSDoug Rabson static uint32_t fwphy_rddata ( struct fwohci_softc *, uint32_t); 135d09a5d6fSHidetoshi Shimokawa static int fwohci_rx_enable (struct fwohci_softc *, struct fwohci_dbch *); 136d09a5d6fSHidetoshi Shimokawa static int fwohci_tx_enable (struct fwohci_softc *, struct fwohci_dbch *); 137d09a5d6fSHidetoshi Shimokawa static int fwohci_irx_enable (struct firewire_comm *, int); 138d09a5d6fSHidetoshi Shimokawa static int fwohci_irx_disable (struct firewire_comm *, int); 13977ee030bSHidetoshi Shimokawa #if BYTE_ORDER == BIG_ENDIAN 14003161bbcSDoug Rabson static void fwohci_irx_post (struct firewire_comm *, uint32_t *); 14177ee030bSHidetoshi Shimokawa #endif 142d09a5d6fSHidetoshi Shimokawa static int fwohci_itxbuf_enable (struct firewire_comm *, int); 143d09a5d6fSHidetoshi Shimokawa static int fwohci_itx_disable (struct firewire_comm *, int); 144d09a5d6fSHidetoshi Shimokawa static void fwohci_timeout (void *); 145d09a5d6fSHidetoshi Shimokawa static void fwohci_set_intr (struct firewire_comm *, int); 14677ee030bSHidetoshi Shimokawa 147d09a5d6fSHidetoshi Shimokawa static int fwohci_add_rx_buf (struct fwohci_dbch *, struct fwohcidb_tr *, int, struct fwdma_alloc *); 148d09a5d6fSHidetoshi Shimokawa static int fwohci_add_tx_buf (struct fwohci_dbch *, struct fwohcidb_tr *, int); 14903161bbcSDoug Rabson static void dump_db (struct fwohci_softc *, uint32_t); 15003161bbcSDoug Rabson static void print_db (struct fwohcidb_tr *, struct fwohcidb *, uint32_t , uint32_t); 15103161bbcSDoug Rabson static void dump_dma (struct fwohci_softc *, uint32_t); 15203161bbcSDoug Rabson static uint32_t fwohci_cyctimer (struct firewire_comm *); 153d09a5d6fSHidetoshi Shimokawa static void fwohci_rbuf_update (struct fwohci_softc *, int); 154d09a5d6fSHidetoshi Shimokawa static void fwohci_tbuf_update (struct fwohci_softc *, int); 155d09a5d6fSHidetoshi Shimokawa void fwohci_txbufdb (struct fwohci_softc *, int , struct fw_bulkxfer *); 15677ee030bSHidetoshi Shimokawa #if FWOHCI_TASKQUEUE 15777ee030bSHidetoshi Shimokawa static void fwohci_complete(void *, int); 15877ee030bSHidetoshi Shimokawa #endif 1593c60ba66SKatsushi Kobayashi 1603c60ba66SKatsushi Kobayashi /* 1613c60ba66SKatsushi Kobayashi * memory allocated for DMA programs 1623c60ba66SKatsushi Kobayashi */ 1633c60ba66SKatsushi Kobayashi #define DMA_PROG_ALLOC (8 * PAGE_SIZE) 1643c60ba66SKatsushi Kobayashi 1653c60ba66SKatsushi Kobayashi #define NDB FWMAXQUEUE 1663c60ba66SKatsushi Kobayashi 1673c60ba66SKatsushi Kobayashi #define OHCI_VERSION 0x00 16873aa55baSHidetoshi Shimokawa #define OHCI_ATRETRY 0x08 1693c60ba66SKatsushi Kobayashi #define OHCI_CROMHDR 0x18 1703c60ba66SKatsushi Kobayashi #define OHCI_BUS_OPT 0x20 1713c60ba66SKatsushi Kobayashi #define OHCI_BUSIRMC (1 << 31) 1723c60ba66SKatsushi Kobayashi #define OHCI_BUSCMC (1 << 30) 1733c60ba66SKatsushi Kobayashi #define OHCI_BUSISC (1 << 29) 1743c60ba66SKatsushi Kobayashi #define OHCI_BUSBMC (1 << 28) 1753c60ba66SKatsushi Kobayashi #define OHCI_BUSPMC (1 << 27) 1763c60ba66SKatsushi Kobayashi #define OHCI_BUSFNC OHCI_BUSIRMC | OHCI_BUSCMC | OHCI_BUSISC |\ 1773c60ba66SKatsushi Kobayashi OHCI_BUSBMC | OHCI_BUSPMC 1783c60ba66SKatsushi Kobayashi 1793c60ba66SKatsushi Kobayashi #define OHCI_EUID_HI 0x24 1803c60ba66SKatsushi Kobayashi #define OHCI_EUID_LO 0x28 1813c60ba66SKatsushi Kobayashi 1823c60ba66SKatsushi Kobayashi #define OHCI_CROMPTR 0x34 1833c60ba66SKatsushi Kobayashi #define OHCI_HCCCTL 0x50 1843c60ba66SKatsushi Kobayashi #define OHCI_HCCCTLCLR 0x54 1853c60ba66SKatsushi Kobayashi #define OHCI_AREQHI 0x100 1863c60ba66SKatsushi Kobayashi #define OHCI_AREQHICLR 0x104 1873c60ba66SKatsushi Kobayashi #define OHCI_AREQLO 0x108 1883c60ba66SKatsushi Kobayashi #define OHCI_AREQLOCLR 0x10c 1893c60ba66SKatsushi Kobayashi #define OHCI_PREQHI 0x110 1903c60ba66SKatsushi Kobayashi #define OHCI_PREQHICLR 0x114 1913c60ba66SKatsushi Kobayashi #define OHCI_PREQLO 0x118 1923c60ba66SKatsushi Kobayashi #define OHCI_PREQLOCLR 0x11c 1933c60ba66SKatsushi Kobayashi #define OHCI_PREQUPPER 0x120 1943c60ba66SKatsushi Kobayashi 1953c60ba66SKatsushi Kobayashi #define OHCI_SID_BUF 0x64 1963c60ba66SKatsushi Kobayashi #define OHCI_SID_CNT 0x68 19777ee030bSHidetoshi Shimokawa #define OHCI_SID_ERR (1 << 31) 1983c60ba66SKatsushi Kobayashi #define OHCI_SID_CNT_MASK 0xffc 1993c60ba66SKatsushi Kobayashi 2003c60ba66SKatsushi Kobayashi #define OHCI_IT_STAT 0x90 2013c60ba66SKatsushi Kobayashi #define OHCI_IT_STATCLR 0x94 2023c60ba66SKatsushi Kobayashi #define OHCI_IT_MASK 0x98 2033c60ba66SKatsushi Kobayashi #define OHCI_IT_MASKCLR 0x9c 2043c60ba66SKatsushi Kobayashi 2053c60ba66SKatsushi Kobayashi #define OHCI_IR_STAT 0xa0 2063c60ba66SKatsushi Kobayashi #define OHCI_IR_STATCLR 0xa4 2073c60ba66SKatsushi Kobayashi #define OHCI_IR_MASK 0xa8 2083c60ba66SKatsushi Kobayashi #define OHCI_IR_MASKCLR 0xac 2093c60ba66SKatsushi Kobayashi 2103c60ba66SKatsushi Kobayashi #define OHCI_LNKCTL 0xe0 2113c60ba66SKatsushi Kobayashi #define OHCI_LNKCTLCLR 0xe4 2123c60ba66SKatsushi Kobayashi 2133c60ba66SKatsushi Kobayashi #define OHCI_PHYACCESS 0xec 2143c60ba66SKatsushi Kobayashi #define OHCI_CYCLETIMER 0xf0 2153c60ba66SKatsushi Kobayashi 2163c60ba66SKatsushi Kobayashi #define OHCI_DMACTL(off) (off) 2173c60ba66SKatsushi Kobayashi #define OHCI_DMACTLCLR(off) (off + 4) 2183c60ba66SKatsushi Kobayashi #define OHCI_DMACMD(off) (off + 0xc) 2193c60ba66SKatsushi Kobayashi #define OHCI_DMAMATCH(off) (off + 0x10) 2203c60ba66SKatsushi Kobayashi 2213c60ba66SKatsushi Kobayashi #define OHCI_ATQOFF 0x180 2223c60ba66SKatsushi Kobayashi #define OHCI_ATQCTL OHCI_ATQOFF 2233c60ba66SKatsushi Kobayashi #define OHCI_ATQCTLCLR (OHCI_ATQOFF + 4) 2243c60ba66SKatsushi Kobayashi #define OHCI_ATQCMD (OHCI_ATQOFF + 0xc) 2253c60ba66SKatsushi Kobayashi #define OHCI_ATQMATCH (OHCI_ATQOFF + 0x10) 2263c60ba66SKatsushi Kobayashi 2273c60ba66SKatsushi Kobayashi #define OHCI_ATSOFF 0x1a0 2283c60ba66SKatsushi Kobayashi #define OHCI_ATSCTL OHCI_ATSOFF 2293c60ba66SKatsushi Kobayashi #define OHCI_ATSCTLCLR (OHCI_ATSOFF + 4) 2303c60ba66SKatsushi Kobayashi #define OHCI_ATSCMD (OHCI_ATSOFF + 0xc) 2313c60ba66SKatsushi Kobayashi #define OHCI_ATSMATCH (OHCI_ATSOFF + 0x10) 2323c60ba66SKatsushi Kobayashi 2333c60ba66SKatsushi Kobayashi #define OHCI_ARQOFF 0x1c0 2343c60ba66SKatsushi Kobayashi #define OHCI_ARQCTL OHCI_ARQOFF 2353c60ba66SKatsushi Kobayashi #define OHCI_ARQCTLCLR (OHCI_ARQOFF + 4) 2363c60ba66SKatsushi Kobayashi #define OHCI_ARQCMD (OHCI_ARQOFF + 0xc) 2373c60ba66SKatsushi Kobayashi #define OHCI_ARQMATCH (OHCI_ARQOFF + 0x10) 2383c60ba66SKatsushi Kobayashi 2393c60ba66SKatsushi Kobayashi #define OHCI_ARSOFF 0x1e0 2403c60ba66SKatsushi Kobayashi #define OHCI_ARSCTL OHCI_ARSOFF 2413c60ba66SKatsushi Kobayashi #define OHCI_ARSCTLCLR (OHCI_ARSOFF + 4) 2423c60ba66SKatsushi Kobayashi #define OHCI_ARSCMD (OHCI_ARSOFF + 0xc) 2433c60ba66SKatsushi Kobayashi #define OHCI_ARSMATCH (OHCI_ARSOFF + 0x10) 2443c60ba66SKatsushi Kobayashi 2453c60ba66SKatsushi Kobayashi #define OHCI_ITOFF(CH) (0x200 + 0x10 * (CH)) 2463c60ba66SKatsushi Kobayashi #define OHCI_ITCTL(CH) (OHCI_ITOFF(CH)) 2473c60ba66SKatsushi Kobayashi #define OHCI_ITCTLCLR(CH) (OHCI_ITOFF(CH) + 4) 2483c60ba66SKatsushi Kobayashi #define OHCI_ITCMD(CH) (OHCI_ITOFF(CH) + 0xc) 2493c60ba66SKatsushi Kobayashi 2503c60ba66SKatsushi Kobayashi #define OHCI_IROFF(CH) (0x400 + 0x20 * (CH)) 2513c60ba66SKatsushi Kobayashi #define OHCI_IRCTL(CH) (OHCI_IROFF(CH)) 2523c60ba66SKatsushi Kobayashi #define OHCI_IRCTLCLR(CH) (OHCI_IROFF(CH) + 4) 2533c60ba66SKatsushi Kobayashi #define OHCI_IRCMD(CH) (OHCI_IROFF(CH) + 0xc) 2543c60ba66SKatsushi Kobayashi #define OHCI_IRMATCH(CH) (OHCI_IROFF(CH) + 0x10) 2553c60ba66SKatsushi Kobayashi 2563c60ba66SKatsushi Kobayashi d_ioctl_t fwohci_ioctl; 2573c60ba66SKatsushi Kobayashi 2583c60ba66SKatsushi Kobayashi /* 2593c60ba66SKatsushi Kobayashi * Communication with PHY device 2603c60ba66SKatsushi Kobayashi */ 26103161bbcSDoug Rabson static uint32_t 26203161bbcSDoug Rabson fwphy_wrdata( struct fwohci_softc *sc, uint32_t addr, uint32_t data) 2633c60ba66SKatsushi Kobayashi { 26403161bbcSDoug Rabson uint32_t fun; 2653c60ba66SKatsushi Kobayashi 2663c60ba66SKatsushi Kobayashi addr &= 0xf; 2673c60ba66SKatsushi Kobayashi data &= 0xff; 2683c60ba66SKatsushi Kobayashi 2693c60ba66SKatsushi Kobayashi fun = (PHYDEV_WRCMD | (addr << PHYDEV_REGADDR) | (data << PHYDEV_WRDATA)); 2703c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_PHYACCESS, fun); 2713c60ba66SKatsushi Kobayashi DELAY(100); 2723c60ba66SKatsushi Kobayashi 2733c60ba66SKatsushi Kobayashi return(fwphy_rddata( sc, addr)); 2743c60ba66SKatsushi Kobayashi } 2753c60ba66SKatsushi Kobayashi 27603161bbcSDoug Rabson static uint32_t 2773c60ba66SKatsushi Kobayashi fwohci_set_bus_manager(struct firewire_comm *fc, u_int node) 2783c60ba66SKatsushi Kobayashi { 2793c60ba66SKatsushi Kobayashi struct fwohci_softc *sc = (struct fwohci_softc *)fc; 2803c60ba66SKatsushi Kobayashi int i; 28103161bbcSDoug Rabson uint32_t bm; 2823c60ba66SKatsushi Kobayashi 2833c60ba66SKatsushi Kobayashi #define OHCI_CSR_DATA 0x0c 2843c60ba66SKatsushi Kobayashi #define OHCI_CSR_COMP 0x10 2853c60ba66SKatsushi Kobayashi #define OHCI_CSR_CONT 0x14 2863c60ba66SKatsushi Kobayashi #define OHCI_BUS_MANAGER_ID 0 2873c60ba66SKatsushi Kobayashi 2883c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_CSR_DATA, node); 2893c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_CSR_COMP, 0x3f); 2903c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_CSR_CONT, OHCI_BUS_MANAGER_ID); 2913c60ba66SKatsushi Kobayashi for (i = 0; !(OREAD(sc, OHCI_CSR_CONT) & (1<<31)) && (i < 1000); i++) 2924ed65ce9SHidetoshi Shimokawa DELAY(10); 2933c60ba66SKatsushi Kobayashi bm = OREAD(sc, OHCI_CSR_DATA); 29417c3d42cSHidetoshi Shimokawa if((bm & 0x3f) == 0x3f) 2953c60ba66SKatsushi Kobayashi bm = node; 29617c3d42cSHidetoshi Shimokawa if (bootverbose) 29717c3d42cSHidetoshi Shimokawa device_printf(sc->fc.dev, 29817c3d42cSHidetoshi Shimokawa "fw_set_bus_manager: %d->%d (loop=%d)\n", bm, node, i); 2993c60ba66SKatsushi Kobayashi 3003c60ba66SKatsushi Kobayashi return(bm); 3013c60ba66SKatsushi Kobayashi } 3023c60ba66SKatsushi Kobayashi 30303161bbcSDoug Rabson static uint32_t 304c572b810SHidetoshi Shimokawa fwphy_rddata(struct fwohci_softc *sc, u_int addr) 3053c60ba66SKatsushi Kobayashi { 30603161bbcSDoug Rabson uint32_t fun, stat; 307e4b13179SHidetoshi Shimokawa u_int i, retry = 0; 3083c60ba66SKatsushi Kobayashi 3093c60ba66SKatsushi Kobayashi addr &= 0xf; 310e4b13179SHidetoshi Shimokawa #define MAX_RETRY 100 311e4b13179SHidetoshi Shimokawa again: 312e4b13179SHidetoshi Shimokawa OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_REG_FAIL); 3133c60ba66SKatsushi Kobayashi fun = PHYDEV_RDCMD | (addr << PHYDEV_REGADDR); 3143c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_PHYACCESS, fun); 315e4b13179SHidetoshi Shimokawa for ( i = 0 ; i < MAX_RETRY ; i ++ ){ 3163c60ba66SKatsushi Kobayashi fun = OREAD(sc, OHCI_PHYACCESS); 3173c60ba66SKatsushi Kobayashi if ((fun & PHYDEV_RDCMD) == 0 && (fun & PHYDEV_RDDONE) != 0) 3183c60ba66SKatsushi Kobayashi break; 3194ed65ce9SHidetoshi Shimokawa DELAY(100); 3203c60ba66SKatsushi Kobayashi } 321e4b13179SHidetoshi Shimokawa if(i >= MAX_RETRY) { 3224ed65ce9SHidetoshi Shimokawa if (bootverbose) 3234ed65ce9SHidetoshi Shimokawa device_printf(sc->fc.dev, "phy read failed(1).\n"); 3241f2361f8SHidetoshi Shimokawa if (++retry < MAX_RETRY) { 3254ed65ce9SHidetoshi Shimokawa DELAY(100); 3261f2361f8SHidetoshi Shimokawa goto again; 3271f2361f8SHidetoshi Shimokawa } 328e4b13179SHidetoshi Shimokawa } 329e4b13179SHidetoshi Shimokawa /* Make sure that SCLK is started */ 330e4b13179SHidetoshi Shimokawa stat = OREAD(sc, FWOHCI_INTSTAT); 331e4b13179SHidetoshi Shimokawa if ((stat & OHCI_INT_REG_FAIL) != 0 || 332e4b13179SHidetoshi Shimokawa ((fun >> PHYDEV_REGADDR) & 0xf) != addr) { 3334ed65ce9SHidetoshi Shimokawa if (bootverbose) 3344ed65ce9SHidetoshi Shimokawa device_printf(sc->fc.dev, "phy read failed(2).\n"); 335e4b13179SHidetoshi Shimokawa if (++retry < MAX_RETRY) { 3364ed65ce9SHidetoshi Shimokawa DELAY(100); 337e4b13179SHidetoshi Shimokawa goto again; 338e4b13179SHidetoshi Shimokawa } 339e4b13179SHidetoshi Shimokawa } 340e4b13179SHidetoshi Shimokawa if (bootverbose || retry >= MAX_RETRY) 341e4b13179SHidetoshi Shimokawa device_printf(sc->fc.dev, 342f9c8c31dSHidetoshi Shimokawa "fwphy_rddata: 0x%x loop=%d, retry=%d\n", addr, i, retry); 343e4b13179SHidetoshi Shimokawa #undef MAX_RETRY 3443c60ba66SKatsushi Kobayashi return((fun >> PHYDEV_RDDATA )& 0xff); 3453c60ba66SKatsushi Kobayashi } 3463c60ba66SKatsushi Kobayashi /* Device specific ioctl. */ 3473c60ba66SKatsushi Kobayashi int 3483c60ba66SKatsushi Kobayashi fwohci_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td) 3493c60ba66SKatsushi Kobayashi { 3503c60ba66SKatsushi Kobayashi struct firewire_softc *sc; 3513c60ba66SKatsushi Kobayashi struct fwohci_softc *fc; 3523c60ba66SKatsushi Kobayashi int unit = DEV2UNIT(dev); 3533c60ba66SKatsushi Kobayashi int err = 0; 3543c60ba66SKatsushi Kobayashi struct fw_reg_req_t *reg = (struct fw_reg_req_t *) data; 35503161bbcSDoug Rabson uint32_t *dmach = (uint32_t *) data; 3563c60ba66SKatsushi Kobayashi 3573c60ba66SKatsushi Kobayashi sc = devclass_get_softc(firewire_devclass, unit); 3583c60ba66SKatsushi Kobayashi if(sc == NULL){ 3593c60ba66SKatsushi Kobayashi return(EINVAL); 3603c60ba66SKatsushi Kobayashi } 3613c60ba66SKatsushi Kobayashi fc = (struct fwohci_softc *)sc->fc; 3623c60ba66SKatsushi Kobayashi 3633c60ba66SKatsushi Kobayashi if (!data) 3643c60ba66SKatsushi Kobayashi return(EINVAL); 3653c60ba66SKatsushi Kobayashi 3663c60ba66SKatsushi Kobayashi switch (cmd) { 3673c60ba66SKatsushi Kobayashi case FWOHCI_WRREG: 3683c60ba66SKatsushi Kobayashi #define OHCI_MAX_REG 0x800 3693c60ba66SKatsushi Kobayashi if(reg->addr <= OHCI_MAX_REG){ 3703c60ba66SKatsushi Kobayashi OWRITE(fc, reg->addr, reg->data); 3713c60ba66SKatsushi Kobayashi reg->data = OREAD(fc, reg->addr); 3723c60ba66SKatsushi Kobayashi }else{ 3733c60ba66SKatsushi Kobayashi err = EINVAL; 3743c60ba66SKatsushi Kobayashi } 3753c60ba66SKatsushi Kobayashi break; 3763c60ba66SKatsushi Kobayashi case FWOHCI_RDREG: 3773c60ba66SKatsushi Kobayashi if(reg->addr <= OHCI_MAX_REG){ 3783c60ba66SKatsushi Kobayashi reg->data = OREAD(fc, reg->addr); 3793c60ba66SKatsushi Kobayashi }else{ 3803c60ba66SKatsushi Kobayashi err = EINVAL; 3813c60ba66SKatsushi Kobayashi } 3823c60ba66SKatsushi Kobayashi break; 3833c60ba66SKatsushi Kobayashi /* Read DMA descriptors for debug */ 3843c60ba66SKatsushi Kobayashi case DUMPDMA: 3853c60ba66SKatsushi Kobayashi if(*dmach <= OHCI_MAX_DMA_CH ){ 3863c60ba66SKatsushi Kobayashi dump_dma(fc, *dmach); 3873c60ba66SKatsushi Kobayashi dump_db(fc, *dmach); 3883c60ba66SKatsushi Kobayashi }else{ 3893c60ba66SKatsushi Kobayashi err = EINVAL; 3903c60ba66SKatsushi Kobayashi } 3913c60ba66SKatsushi Kobayashi break; 392f9c8c31dSHidetoshi Shimokawa /* Read/Write Phy registers */ 393f9c8c31dSHidetoshi Shimokawa #define OHCI_MAX_PHY_REG 0xf 394f9c8c31dSHidetoshi Shimokawa case FWOHCI_RDPHYREG: 395f9c8c31dSHidetoshi Shimokawa if (reg->addr <= OHCI_MAX_PHY_REG) 396f9c8c31dSHidetoshi Shimokawa reg->data = fwphy_rddata(fc, reg->addr); 397f9c8c31dSHidetoshi Shimokawa else 398f9c8c31dSHidetoshi Shimokawa err = EINVAL; 399f9c8c31dSHidetoshi Shimokawa break; 400f9c8c31dSHidetoshi Shimokawa case FWOHCI_WRPHYREG: 401f9c8c31dSHidetoshi Shimokawa if (reg->addr <= OHCI_MAX_PHY_REG) 402f9c8c31dSHidetoshi Shimokawa reg->data = fwphy_wrdata(fc, reg->addr, reg->data); 403f9c8c31dSHidetoshi Shimokawa else 404f9c8c31dSHidetoshi Shimokawa err = EINVAL; 405f9c8c31dSHidetoshi Shimokawa break; 4063c60ba66SKatsushi Kobayashi default: 407f9c8c31dSHidetoshi Shimokawa err = EINVAL; 4083c60ba66SKatsushi Kobayashi break; 4093c60ba66SKatsushi Kobayashi } 4103c60ba66SKatsushi Kobayashi return err; 4113c60ba66SKatsushi Kobayashi } 412c572b810SHidetoshi Shimokawa 413d0fd7bc6SHidetoshi Shimokawa static int 414d0fd7bc6SHidetoshi Shimokawa fwohci_probe_phy(struct fwohci_softc *sc, device_t dev) 4153c60ba66SKatsushi Kobayashi { 41603161bbcSDoug Rabson uint32_t reg, reg2; 417d0fd7bc6SHidetoshi Shimokawa int e1394a = 1; 418d0fd7bc6SHidetoshi Shimokawa /* 419d0fd7bc6SHidetoshi Shimokawa * probe PHY parameters 420d0fd7bc6SHidetoshi Shimokawa * 0. to prove PHY version, whether compliance of 1394a. 421d0fd7bc6SHidetoshi Shimokawa * 1. to probe maximum speed supported by the PHY and 422d0fd7bc6SHidetoshi Shimokawa * number of port supported by core-logic. 423d0fd7bc6SHidetoshi Shimokawa * It is not actually available port on your PC . 424d0fd7bc6SHidetoshi Shimokawa */ 425d0fd7bc6SHidetoshi Shimokawa OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LPS); 426d0fd7bc6SHidetoshi Shimokawa reg = fwphy_rddata(sc, FW_PHY_SPD_REG); 427d0fd7bc6SHidetoshi Shimokawa 428d0fd7bc6SHidetoshi Shimokawa if((reg >> 5) != 7 ){ 429d0fd7bc6SHidetoshi Shimokawa sc->fc.mode &= ~FWPHYASYST; 430d0fd7bc6SHidetoshi Shimokawa sc->fc.nport = reg & FW_PHY_NP; 431d0fd7bc6SHidetoshi Shimokawa sc->fc.speed = reg & FW_PHY_SPD >> 6; 432d0fd7bc6SHidetoshi Shimokawa if (sc->fc.speed > MAX_SPEED) { 433d0fd7bc6SHidetoshi Shimokawa device_printf(dev, "invalid speed %d (fixed to %d).\n", 434d0fd7bc6SHidetoshi Shimokawa sc->fc.speed, MAX_SPEED); 435d0fd7bc6SHidetoshi Shimokawa sc->fc.speed = MAX_SPEED; 436d0fd7bc6SHidetoshi Shimokawa } 437d0fd7bc6SHidetoshi Shimokawa device_printf(dev, 43894b6f028SHidetoshi Shimokawa "Phy 1394 only %s, %d ports.\n", 43994b6f028SHidetoshi Shimokawa linkspeed[sc->fc.speed], sc->fc.nport); 440d0fd7bc6SHidetoshi Shimokawa }else{ 441d0fd7bc6SHidetoshi Shimokawa reg2 = fwphy_rddata(sc, FW_PHY_ESPD_REG); 442d0fd7bc6SHidetoshi Shimokawa sc->fc.mode |= FWPHYASYST; 443d0fd7bc6SHidetoshi Shimokawa sc->fc.nport = reg & FW_PHY_NP; 444d0fd7bc6SHidetoshi Shimokawa sc->fc.speed = (reg2 & FW_PHY_ESPD) >> 5; 445d0fd7bc6SHidetoshi Shimokawa if (sc->fc.speed > MAX_SPEED) { 446d0fd7bc6SHidetoshi Shimokawa device_printf(dev, "invalid speed %d (fixed to %d).\n", 447d0fd7bc6SHidetoshi Shimokawa sc->fc.speed, MAX_SPEED); 448d0fd7bc6SHidetoshi Shimokawa sc->fc.speed = MAX_SPEED; 449d0fd7bc6SHidetoshi Shimokawa } 450d0fd7bc6SHidetoshi Shimokawa device_printf(dev, 45194b6f028SHidetoshi Shimokawa "Phy 1394a available %s, %d ports.\n", 45294b6f028SHidetoshi Shimokawa linkspeed[sc->fc.speed], sc->fc.nport); 453d0fd7bc6SHidetoshi Shimokawa 454d0fd7bc6SHidetoshi Shimokawa /* check programPhyEnable */ 455d0fd7bc6SHidetoshi Shimokawa reg2 = fwphy_rddata(sc, 5); 456d0fd7bc6SHidetoshi Shimokawa #if 0 457d0fd7bc6SHidetoshi Shimokawa if (e1394a && (OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_PRPHY)) { 458d0fd7bc6SHidetoshi Shimokawa #else /* XXX force to enable 1394a */ 459d0fd7bc6SHidetoshi Shimokawa if (e1394a) { 460d0fd7bc6SHidetoshi Shimokawa #endif 461d0fd7bc6SHidetoshi Shimokawa if (bootverbose) 462d0fd7bc6SHidetoshi Shimokawa device_printf(dev, 463d0fd7bc6SHidetoshi Shimokawa "Enable 1394a Enhancements\n"); 464d0fd7bc6SHidetoshi Shimokawa /* enable EAA EMC */ 465d0fd7bc6SHidetoshi Shimokawa reg2 |= 0x03; 466d0fd7bc6SHidetoshi Shimokawa /* set aPhyEnhanceEnable */ 467d0fd7bc6SHidetoshi Shimokawa OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_PHYEN); 468d0fd7bc6SHidetoshi Shimokawa OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_PRPHY); 469d0fd7bc6SHidetoshi Shimokawa } else { 470d0fd7bc6SHidetoshi Shimokawa /* for safe */ 471d0fd7bc6SHidetoshi Shimokawa reg2 &= ~0x83; 472d0fd7bc6SHidetoshi Shimokawa } 473d0fd7bc6SHidetoshi Shimokawa reg2 = fwphy_wrdata(sc, 5, reg2); 474d0fd7bc6SHidetoshi Shimokawa } 475d0fd7bc6SHidetoshi Shimokawa 476d0fd7bc6SHidetoshi Shimokawa reg = fwphy_rddata(sc, FW_PHY_SPD_REG); 477d0fd7bc6SHidetoshi Shimokawa if((reg >> 5) == 7 ){ 478d0fd7bc6SHidetoshi Shimokawa reg = fwphy_rddata(sc, 4); 479d0fd7bc6SHidetoshi Shimokawa reg |= 1 << 6; 480d0fd7bc6SHidetoshi Shimokawa fwphy_wrdata(sc, 4, reg); 481d0fd7bc6SHidetoshi Shimokawa reg = fwphy_rddata(sc, 4); 482d0fd7bc6SHidetoshi Shimokawa } 483d0fd7bc6SHidetoshi Shimokawa return 0; 484d0fd7bc6SHidetoshi Shimokawa } 485d0fd7bc6SHidetoshi Shimokawa 486d0fd7bc6SHidetoshi Shimokawa 487d0fd7bc6SHidetoshi Shimokawa void 488d0fd7bc6SHidetoshi Shimokawa fwohci_reset(struct fwohci_softc *sc, device_t dev) 489d0fd7bc6SHidetoshi Shimokawa { 49094b6f028SHidetoshi Shimokawa int i, max_rec, speed; 49103161bbcSDoug Rabson uint32_t reg, reg2; 4923c60ba66SKatsushi Kobayashi struct fwohcidb_tr *db_tr; 493d0fd7bc6SHidetoshi Shimokawa 49495a24954SDoug Rabson /* Disable interrupts */ 495d0fd7bc6SHidetoshi Shimokawa OWRITE(sc, FWOHCI_INTMASKCLR, ~0); 496d0fd7bc6SHidetoshi Shimokawa 49795a24954SDoug Rabson /* Now stopping all DMA channels */ 498d0fd7bc6SHidetoshi Shimokawa OWRITE(sc, OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN); 499d0fd7bc6SHidetoshi Shimokawa OWRITE(sc, OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN); 500d0fd7bc6SHidetoshi Shimokawa OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN); 501d0fd7bc6SHidetoshi Shimokawa OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN); 502d0fd7bc6SHidetoshi Shimokawa 503d0fd7bc6SHidetoshi Shimokawa OWRITE(sc, OHCI_IR_MASKCLR, ~0); 504d0fd7bc6SHidetoshi Shimokawa for( i = 0 ; i < sc->fc.nisodma ; i ++ ){ 505d0fd7bc6SHidetoshi Shimokawa OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN); 506d0fd7bc6SHidetoshi Shimokawa OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN); 507d0fd7bc6SHidetoshi Shimokawa } 508d0fd7bc6SHidetoshi Shimokawa 509d0fd7bc6SHidetoshi Shimokawa /* FLUSH FIFO and reset Transmitter/Reciever */ 510d0fd7bc6SHidetoshi Shimokawa OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_RESET); 511d0fd7bc6SHidetoshi Shimokawa if (bootverbose) 512d0fd7bc6SHidetoshi Shimokawa device_printf(dev, "resetting OHCI..."); 513d0fd7bc6SHidetoshi Shimokawa i = 0; 514d0fd7bc6SHidetoshi Shimokawa while(OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_RESET) { 515d0fd7bc6SHidetoshi Shimokawa if (i++ > 100) break; 516d0fd7bc6SHidetoshi Shimokawa DELAY(1000); 517d0fd7bc6SHidetoshi Shimokawa } 518d0fd7bc6SHidetoshi Shimokawa if (bootverbose) 519d0fd7bc6SHidetoshi Shimokawa printf("done (loop=%d)\n", i); 520d0fd7bc6SHidetoshi Shimokawa 52194b6f028SHidetoshi Shimokawa /* Probe phy */ 52294b6f028SHidetoshi Shimokawa fwohci_probe_phy(sc, dev); 52394b6f028SHidetoshi Shimokawa 52494b6f028SHidetoshi Shimokawa /* Probe link */ 525d0fd7bc6SHidetoshi Shimokawa reg = OREAD(sc, OHCI_BUS_OPT); 526d0fd7bc6SHidetoshi Shimokawa reg2 = reg | OHCI_BUSFNC; 52794b6f028SHidetoshi Shimokawa max_rec = (reg & 0x0000f000) >> 12; 52894b6f028SHidetoshi Shimokawa speed = (reg & 0x00000007); 52994b6f028SHidetoshi Shimokawa device_printf(dev, "Link %s, max_rec %d bytes.\n", 53094b6f028SHidetoshi Shimokawa linkspeed[speed], MAXREC(max_rec)); 53194b6f028SHidetoshi Shimokawa /* XXX fix max_rec */ 53294b6f028SHidetoshi Shimokawa sc->fc.maxrec = sc->fc.speed + 8; 53394b6f028SHidetoshi Shimokawa if (max_rec != sc->fc.maxrec) { 53494b6f028SHidetoshi Shimokawa reg2 = (reg2 & 0xffff0fff) | (sc->fc.maxrec << 12); 53594b6f028SHidetoshi Shimokawa device_printf(dev, "max_rec %d -> %d\n", 53694b6f028SHidetoshi Shimokawa MAXREC(max_rec), MAXREC(sc->fc.maxrec)); 53794b6f028SHidetoshi Shimokawa } 538d0fd7bc6SHidetoshi Shimokawa if (bootverbose) 539d0fd7bc6SHidetoshi Shimokawa device_printf(dev, "BUS_OPT 0x%x -> 0x%x\n", reg, reg2); 540d0fd7bc6SHidetoshi Shimokawa OWRITE(sc, OHCI_BUS_OPT, reg2); 541d0fd7bc6SHidetoshi Shimokawa 54294b6f028SHidetoshi Shimokawa /* Initialize registers */ 543d0fd7bc6SHidetoshi Shimokawa OWRITE(sc, OHCI_CROMHDR, sc->fc.config_rom[0]); 54477ee030bSHidetoshi Shimokawa OWRITE(sc, OHCI_CROMPTR, sc->crom_dma.bus_addr); 545d0fd7bc6SHidetoshi Shimokawa OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_BIGEND); 546d0fd7bc6SHidetoshi Shimokawa OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_POSTWR); 54777ee030bSHidetoshi Shimokawa OWRITE(sc, OHCI_SID_BUF, sc->sid_dma.bus_addr); 548d0fd7bc6SHidetoshi Shimokawa OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_SID); 5499339321dSHidetoshi Shimokawa 55094b6f028SHidetoshi Shimokawa /* Enable link */ 55194b6f028SHidetoshi Shimokawa OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LINKEN); 55294b6f028SHidetoshi Shimokawa 55394b6f028SHidetoshi Shimokawa /* Force to start async RX DMA */ 5549339321dSHidetoshi Shimokawa sc->arrq.xferq.flag &= ~FWXFERQ_RUNNING; 5559339321dSHidetoshi Shimokawa sc->arrs.xferq.flag &= ~FWXFERQ_RUNNING; 556d0fd7bc6SHidetoshi Shimokawa fwohci_rx_enable(sc, &sc->arrq); 557d0fd7bc6SHidetoshi Shimokawa fwohci_rx_enable(sc, &sc->arrs); 558d0fd7bc6SHidetoshi Shimokawa 55994b6f028SHidetoshi Shimokawa /* Initialize async TX */ 56094b6f028SHidetoshi Shimokawa OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD); 56194b6f028SHidetoshi Shimokawa OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD); 562630529adSHidetoshi Shimokawa 56394b6f028SHidetoshi Shimokawa /* AT Retries */ 56494b6f028SHidetoshi Shimokawa OWRITE(sc, FWOHCI_RETRY, 56594b6f028SHidetoshi Shimokawa /* CycleLimit PhyRespRetries ATRespRetries ATReqRetries */ 56694b6f028SHidetoshi Shimokawa (0xffff << 16 ) | (0x0f << 8) | (0x0f << 4) | 0x0f) ; 567630529adSHidetoshi Shimokawa 568630529adSHidetoshi Shimokawa sc->atrq.top = STAILQ_FIRST(&sc->atrq.db_trq); 569630529adSHidetoshi Shimokawa sc->atrs.top = STAILQ_FIRST(&sc->atrs.db_trq); 570630529adSHidetoshi Shimokawa sc->atrq.bottom = sc->atrq.top; 571630529adSHidetoshi Shimokawa sc->atrs.bottom = sc->atrs.top; 572630529adSHidetoshi Shimokawa 573d0fd7bc6SHidetoshi Shimokawa for( i = 0, db_tr = sc->atrq.top; i < sc->atrq.ndb ; 574d0fd7bc6SHidetoshi Shimokawa i ++, db_tr = STAILQ_NEXT(db_tr, link)){ 575d0fd7bc6SHidetoshi Shimokawa db_tr->xfer = NULL; 576d0fd7bc6SHidetoshi Shimokawa } 577d0fd7bc6SHidetoshi Shimokawa for( i = 0, db_tr = sc->atrs.top; i < sc->atrs.ndb ; 578d0fd7bc6SHidetoshi Shimokawa i ++, db_tr = STAILQ_NEXT(db_tr, link)){ 579d0fd7bc6SHidetoshi Shimokawa db_tr->xfer = NULL; 580d0fd7bc6SHidetoshi Shimokawa } 581d0fd7bc6SHidetoshi Shimokawa 58294b6f028SHidetoshi Shimokawa 58395a24954SDoug Rabson /* Enable interrupts */ 584d0fd7bc6SHidetoshi Shimokawa OWRITE(sc, FWOHCI_INTMASK, 585d0fd7bc6SHidetoshi Shimokawa OHCI_INT_ERR | OHCI_INT_PHY_SID 586d0fd7bc6SHidetoshi Shimokawa | OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS 587d0fd7bc6SHidetoshi Shimokawa | OHCI_INT_DMA_PRRQ | OHCI_INT_DMA_PRRS 588d0fd7bc6SHidetoshi Shimokawa | OHCI_INT_PHY_BUS_R | OHCI_INT_PW_ERR); 589d0fd7bc6SHidetoshi Shimokawa fwohci_set_intr(&sc->fc, 1); 590d0fd7bc6SHidetoshi Shimokawa 591d0fd7bc6SHidetoshi Shimokawa } 592d0fd7bc6SHidetoshi Shimokawa 593d0fd7bc6SHidetoshi Shimokawa int 594d0fd7bc6SHidetoshi Shimokawa fwohci_init(struct fwohci_softc *sc, device_t dev) 595d0fd7bc6SHidetoshi Shimokawa { 596ff04511eSHidetoshi Shimokawa int i, mver; 59703161bbcSDoug Rabson uint32_t reg; 59803161bbcSDoug Rabson uint8_t ui[8]; 5993c60ba66SKatsushi Kobayashi 60077ee030bSHidetoshi Shimokawa #if FWOHCI_TASKQUEUE 60177ee030bSHidetoshi Shimokawa TASK_INIT(&sc->fwohci_task_complete, 0, fwohci_complete, sc); 60277ee030bSHidetoshi Shimokawa #endif 60377ee030bSHidetoshi Shimokawa 604ff04511eSHidetoshi Shimokawa /* OHCI version */ 6053c60ba66SKatsushi Kobayashi reg = OREAD(sc, OHCI_VERSION); 606ff04511eSHidetoshi Shimokawa mver = (reg >> 16) & 0xff; 6073c60ba66SKatsushi Kobayashi device_printf(dev, "OHCI version %x.%x (ROM=%d)\n", 608ff04511eSHidetoshi Shimokawa mver, reg & 0xff, (reg>>24) & 1); 609ff04511eSHidetoshi Shimokawa if (mver < 1 || mver > 9) { 61018349893SHidetoshi Shimokawa device_printf(dev, "invalid OHCI version\n"); 61118349893SHidetoshi Shimokawa return (ENXIO); 61218349893SHidetoshi Shimokawa } 61318349893SHidetoshi Shimokawa 61495a24954SDoug Rabson /* Available Isochronous DMA channel probe */ 6157054e848SHidetoshi Shimokawa OWRITE(sc, OHCI_IT_MASK, 0xffffffff); 6167054e848SHidetoshi Shimokawa OWRITE(sc, OHCI_IR_MASK, 0xffffffff); 6177054e848SHidetoshi Shimokawa reg = OREAD(sc, OHCI_IT_MASK) & OREAD(sc, OHCI_IR_MASK); 6187054e848SHidetoshi Shimokawa OWRITE(sc, OHCI_IT_MASKCLR, 0xffffffff); 6197054e848SHidetoshi Shimokawa OWRITE(sc, OHCI_IR_MASKCLR, 0xffffffff); 6207054e848SHidetoshi Shimokawa for (i = 0; i < 0x20; i++) 6217054e848SHidetoshi Shimokawa if ((reg & (1 << i)) == 0) 6227054e848SHidetoshi Shimokawa break; 6233c60ba66SKatsushi Kobayashi sc->fc.nisodma = i; 62495a24954SDoug Rabson device_printf(dev, "No. of Isochronous channels is %d.\n", i); 625f40a2915SHidetoshi Shimokawa if (i == 0) 626f40a2915SHidetoshi Shimokawa return (ENXIO); 6273c60ba66SKatsushi Kobayashi 6283c60ba66SKatsushi Kobayashi sc->fc.arq = &sc->arrq.xferq; 6293c60ba66SKatsushi Kobayashi sc->fc.ars = &sc->arrs.xferq; 6303c60ba66SKatsushi Kobayashi sc->fc.atq = &sc->atrq.xferq; 6313c60ba66SKatsushi Kobayashi sc->fc.ats = &sc->atrs.xferq; 6323c60ba66SKatsushi Kobayashi 63377ee030bSHidetoshi Shimokawa sc->arrq.xferq.psize = roundup2(FWPMAX_S400, PAGE_SIZE); 63477ee030bSHidetoshi Shimokawa sc->arrs.xferq.psize = roundup2(FWPMAX_S400, PAGE_SIZE); 63577ee030bSHidetoshi Shimokawa sc->atrq.xferq.psize = roundup2(FWPMAX_S400, PAGE_SIZE); 63677ee030bSHidetoshi Shimokawa sc->atrs.xferq.psize = roundup2(FWPMAX_S400, PAGE_SIZE); 63777ee030bSHidetoshi Shimokawa 6383c60ba66SKatsushi Kobayashi sc->arrq.xferq.start = NULL; 6393c60ba66SKatsushi Kobayashi sc->arrs.xferq.start = NULL; 6403c60ba66SKatsushi Kobayashi sc->atrq.xferq.start = fwohci_start_atq; 6413c60ba66SKatsushi Kobayashi sc->atrs.xferq.start = fwohci_start_ats; 6423c60ba66SKatsushi Kobayashi 64377ee030bSHidetoshi Shimokawa sc->arrq.xferq.buf = NULL; 64477ee030bSHidetoshi Shimokawa sc->arrs.xferq.buf = NULL; 64577ee030bSHidetoshi Shimokawa sc->atrq.xferq.buf = NULL; 64677ee030bSHidetoshi Shimokawa sc->atrs.xferq.buf = NULL; 6473c60ba66SKatsushi Kobayashi 6486cada79aSHidetoshi Shimokawa sc->arrq.xferq.dmach = -1; 6496cada79aSHidetoshi Shimokawa sc->arrs.xferq.dmach = -1; 6506cada79aSHidetoshi Shimokawa sc->atrq.xferq.dmach = -1; 6516cada79aSHidetoshi Shimokawa sc->atrs.xferq.dmach = -1; 6526cada79aSHidetoshi Shimokawa 6533c60ba66SKatsushi Kobayashi sc->arrq.ndesc = 1; 6543c60ba66SKatsushi Kobayashi sc->arrs.ndesc = 1; 655645394e6SHidetoshi Shimokawa sc->atrq.ndesc = 8; /* equal to maximum of mbuf chains */ 656645394e6SHidetoshi Shimokawa sc->atrs.ndesc = 2; 6573c60ba66SKatsushi Kobayashi 6583c60ba66SKatsushi Kobayashi sc->arrq.ndb = NDB; 6593c60ba66SKatsushi Kobayashi sc->arrs.ndb = NDB / 2; 6603c60ba66SKatsushi Kobayashi sc->atrq.ndb = NDB; 6613c60ba66SKatsushi Kobayashi sc->atrs.ndb = NDB / 2; 6623c60ba66SKatsushi Kobayashi 6633c60ba66SKatsushi Kobayashi for( i = 0 ; i < sc->fc.nisodma ; i ++ ){ 6643c60ba66SKatsushi Kobayashi sc->fc.it[i] = &sc->it[i].xferq; 6653c60ba66SKatsushi Kobayashi sc->fc.ir[i] = &sc->ir[i].xferq; 6666cada79aSHidetoshi Shimokawa sc->it[i].xferq.dmach = i; 6676cada79aSHidetoshi Shimokawa sc->ir[i].xferq.dmach = i; 6683c60ba66SKatsushi Kobayashi sc->it[i].ndb = 0; 6693c60ba66SKatsushi Kobayashi sc->ir[i].ndb = 0; 6703c60ba66SKatsushi Kobayashi } 6713c60ba66SKatsushi Kobayashi 6723c60ba66SKatsushi Kobayashi sc->fc.tcode = tinfo; 67377ee030bSHidetoshi Shimokawa sc->fc.dev = dev; 6743c60ba66SKatsushi Kobayashi 67577ee030bSHidetoshi Shimokawa sc->fc.config_rom = fwdma_malloc(&sc->fc, CROMSIZE, CROMSIZE, 67677ee030bSHidetoshi Shimokawa &sc->crom_dma, BUS_DMA_WAITOK); 67777ee030bSHidetoshi Shimokawa if(sc->fc.config_rom == NULL){ 67877ee030bSHidetoshi Shimokawa device_printf(dev, "config_rom alloc failed."); 6793c60ba66SKatsushi Kobayashi return ENOMEM; 6803c60ba66SKatsushi Kobayashi } 6813c60ba66SKatsushi Kobayashi 6820bc666e0SHidetoshi Shimokawa #if 0 6830bc666e0SHidetoshi Shimokawa bzero(&sc->fc.config_rom[0], CROMSIZE); 6843c60ba66SKatsushi Kobayashi sc->fc.config_rom[1] = 0x31333934; 6853c60ba66SKatsushi Kobayashi sc->fc.config_rom[2] = 0xf000a002; 6863c60ba66SKatsushi Kobayashi sc->fc.config_rom[3] = OREAD(sc, OHCI_EUID_HI); 6873c60ba66SKatsushi Kobayashi sc->fc.config_rom[4] = OREAD(sc, OHCI_EUID_LO); 6883c60ba66SKatsushi Kobayashi sc->fc.config_rom[5] = 0; 6893c60ba66SKatsushi Kobayashi sc->fc.config_rom[0] = (4 << 24) | (5 << 16); 6903c60ba66SKatsushi Kobayashi 6913c60ba66SKatsushi Kobayashi sc->fc.config_rom[0] |= fw_crc16(&sc->fc.config_rom[1], 5*4); 69277ee030bSHidetoshi Shimokawa #endif 6933c60ba66SKatsushi Kobayashi 6943c60ba66SKatsushi Kobayashi 69595a24954SDoug Rabson /* SID recieve buffer must align 2^11 */ 6963c60ba66SKatsushi Kobayashi #define OHCI_SIDSIZE (1 << 11) 69777ee030bSHidetoshi Shimokawa sc->sid_buf = fwdma_malloc(&sc->fc, OHCI_SIDSIZE, OHCI_SIDSIZE, 69877ee030bSHidetoshi Shimokawa &sc->sid_dma, BUS_DMA_WAITOK); 69977ee030bSHidetoshi Shimokawa if (sc->sid_buf == NULL) { 70077ee030bSHidetoshi Shimokawa device_printf(dev, "sid_buf alloc failed."); 70116e0f484SHidetoshi Shimokawa return ENOMEM; 70216e0f484SHidetoshi Shimokawa } 7033c60ba66SKatsushi Kobayashi 70403161bbcSDoug Rabson fwdma_malloc(&sc->fc, sizeof(uint32_t), sizeof(uint32_t), 70577ee030bSHidetoshi Shimokawa &sc->dummy_dma, BUS_DMA_WAITOK); 70677ee030bSHidetoshi Shimokawa 70777ee030bSHidetoshi Shimokawa if (sc->dummy_dma.v_addr == NULL) { 70877ee030bSHidetoshi Shimokawa device_printf(dev, "dummy_dma alloc failed."); 70977ee030bSHidetoshi Shimokawa return ENOMEM; 71077ee030bSHidetoshi Shimokawa } 71177ee030bSHidetoshi Shimokawa 71277ee030bSHidetoshi Shimokawa fwohci_db_init(sc, &sc->arrq); 7131f2361f8SHidetoshi Shimokawa if ((sc->arrq.flags & FWOHCI_DBCH_INIT) == 0) 7141f2361f8SHidetoshi Shimokawa return ENOMEM; 7151f2361f8SHidetoshi Shimokawa 71677ee030bSHidetoshi Shimokawa fwohci_db_init(sc, &sc->arrs); 7171f2361f8SHidetoshi Shimokawa if ((sc->arrs.flags & FWOHCI_DBCH_INIT) == 0) 7181f2361f8SHidetoshi Shimokawa return ENOMEM; 7193c60ba66SKatsushi Kobayashi 72077ee030bSHidetoshi Shimokawa fwohci_db_init(sc, &sc->atrq); 7211f2361f8SHidetoshi Shimokawa if ((sc->atrq.flags & FWOHCI_DBCH_INIT) == 0) 7221f2361f8SHidetoshi Shimokawa return ENOMEM; 7231f2361f8SHidetoshi Shimokawa 72477ee030bSHidetoshi Shimokawa fwohci_db_init(sc, &sc->atrs); 7251f2361f8SHidetoshi Shimokawa if ((sc->atrs.flags & FWOHCI_DBCH_INIT) == 0) 7261f2361f8SHidetoshi Shimokawa return ENOMEM; 7273c60ba66SKatsushi Kobayashi 728c547b896SHidetoshi Shimokawa sc->fc.eui.hi = OREAD(sc, FWOHCIGUID_H); 729c547b896SHidetoshi Shimokawa sc->fc.eui.lo = OREAD(sc, FWOHCIGUID_L); 730c547b896SHidetoshi Shimokawa for( i = 0 ; i < 8 ; i ++) 731c547b896SHidetoshi Shimokawa ui[i] = FW_EUI64_BYTE(&sc->fc.eui,i); 7323c60ba66SKatsushi Kobayashi device_printf(dev, "EUI64 %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", 733c547b896SHidetoshi Shimokawa ui[0], ui[1], ui[2], ui[3], ui[4], ui[5], ui[6], ui[7]); 734c547b896SHidetoshi Shimokawa 7353c60ba66SKatsushi Kobayashi sc->fc.ioctl = fwohci_ioctl; 7363c60ba66SKatsushi Kobayashi sc->fc.cyctimer = fwohci_cyctimer; 7373c60ba66SKatsushi Kobayashi sc->fc.set_bmr = fwohci_set_bus_manager; 7383c60ba66SKatsushi Kobayashi sc->fc.ibr = fwohci_ibr; 7393c60ba66SKatsushi Kobayashi sc->fc.irx_enable = fwohci_irx_enable; 7403c60ba66SKatsushi Kobayashi sc->fc.irx_disable = fwohci_irx_disable; 7413c60ba66SKatsushi Kobayashi 7423c60ba66SKatsushi Kobayashi sc->fc.itx_enable = fwohci_itxbuf_enable; 7433c60ba66SKatsushi Kobayashi sc->fc.itx_disable = fwohci_itx_disable; 74477ee030bSHidetoshi Shimokawa #if BYTE_ORDER == BIG_ENDIAN 7453c60ba66SKatsushi Kobayashi sc->fc.irx_post = fwohci_irx_post; 74677ee030bSHidetoshi Shimokawa #else 74777ee030bSHidetoshi Shimokawa sc->fc.irx_post = NULL; 74877ee030bSHidetoshi Shimokawa #endif 7493c60ba66SKatsushi Kobayashi sc->fc.itx_post = NULL; 7503c60ba66SKatsushi Kobayashi sc->fc.timeout = fwohci_timeout; 7513c60ba66SKatsushi Kobayashi sc->fc.poll = fwohci_poll; 7523c60ba66SKatsushi Kobayashi sc->fc.set_intr = fwohci_set_intr; 753c572b810SHidetoshi Shimokawa 75477ee030bSHidetoshi Shimokawa sc->intmask = sc->irstat = sc->itstat = 0; 75577ee030bSHidetoshi Shimokawa 756d0fd7bc6SHidetoshi Shimokawa fw_init(&sc->fc); 757d0fd7bc6SHidetoshi Shimokawa fwohci_reset(sc, dev); 7583c60ba66SKatsushi Kobayashi 759d0fd7bc6SHidetoshi Shimokawa return 0; 7603c60ba66SKatsushi Kobayashi } 761c572b810SHidetoshi Shimokawa 762c572b810SHidetoshi Shimokawa void 763c572b810SHidetoshi Shimokawa fwohci_timeout(void *arg) 7643c60ba66SKatsushi Kobayashi { 7653c60ba66SKatsushi Kobayashi struct fwohci_softc *sc; 7663c60ba66SKatsushi Kobayashi 7673c60ba66SKatsushi Kobayashi sc = (struct fwohci_softc *)arg; 7683c60ba66SKatsushi Kobayashi } 769c572b810SHidetoshi Shimokawa 77003161bbcSDoug Rabson uint32_t 771c572b810SHidetoshi Shimokawa fwohci_cyctimer(struct firewire_comm *fc) 7723c60ba66SKatsushi Kobayashi { 7733c60ba66SKatsushi Kobayashi struct fwohci_softc *sc = (struct fwohci_softc *)fc; 7743c60ba66SKatsushi Kobayashi return(OREAD(sc, OHCI_CYCLETIMER)); 7753c60ba66SKatsushi Kobayashi } 7763c60ba66SKatsushi Kobayashi 7771f2361f8SHidetoshi Shimokawa int 7781f2361f8SHidetoshi Shimokawa fwohci_detach(struct fwohci_softc *sc, device_t dev) 7791f2361f8SHidetoshi Shimokawa { 7801f2361f8SHidetoshi Shimokawa int i; 7811f2361f8SHidetoshi Shimokawa 78277ee030bSHidetoshi Shimokawa if (sc->sid_buf != NULL) 78377ee030bSHidetoshi Shimokawa fwdma_free(&sc->fc, &sc->sid_dma); 78477ee030bSHidetoshi Shimokawa if (sc->fc.config_rom != NULL) 78577ee030bSHidetoshi Shimokawa fwdma_free(&sc->fc, &sc->crom_dma); 7861f2361f8SHidetoshi Shimokawa 7871f2361f8SHidetoshi Shimokawa fwohci_db_free(&sc->arrq); 7881f2361f8SHidetoshi Shimokawa fwohci_db_free(&sc->arrs); 7891f2361f8SHidetoshi Shimokawa 7901f2361f8SHidetoshi Shimokawa fwohci_db_free(&sc->atrq); 7911f2361f8SHidetoshi Shimokawa fwohci_db_free(&sc->atrs); 7921f2361f8SHidetoshi Shimokawa 7931f2361f8SHidetoshi Shimokawa for( i = 0 ; i < sc->fc.nisodma ; i ++ ){ 7941f2361f8SHidetoshi Shimokawa fwohci_db_free(&sc->it[i]); 7951f2361f8SHidetoshi Shimokawa fwohci_db_free(&sc->ir[i]); 7961f2361f8SHidetoshi Shimokawa } 7971f2361f8SHidetoshi Shimokawa 7981f2361f8SHidetoshi Shimokawa return 0; 7991f2361f8SHidetoshi Shimokawa } 8001f2361f8SHidetoshi Shimokawa 801d6105b60SHidetoshi Shimokawa #define LAST_DB(dbtr, db) do { \ 802d6105b60SHidetoshi Shimokawa struct fwohcidb_tr *_dbtr = (dbtr); \ 803d6105b60SHidetoshi Shimokawa int _cnt = _dbtr->dbcnt; \ 804d6105b60SHidetoshi Shimokawa db = &_dbtr->db[ (_cnt > 2) ? (_cnt -1) : 0]; \ 805d6105b60SHidetoshi Shimokawa } while (0) 806d6105b60SHidetoshi Shimokawa 807c572b810SHidetoshi Shimokawa static void 80877ee030bSHidetoshi Shimokawa fwohci_execute_db(void *arg, bus_dma_segment_t *segs, int nseg, int error) 80977ee030bSHidetoshi Shimokawa { 81077ee030bSHidetoshi Shimokawa struct fwohcidb_tr *db_tr; 811c4778b5dSHidetoshi Shimokawa struct fwohcidb *db; 81277ee030bSHidetoshi Shimokawa bus_dma_segment_t *s; 81377ee030bSHidetoshi Shimokawa int i; 81477ee030bSHidetoshi Shimokawa 81577ee030bSHidetoshi Shimokawa db_tr = (struct fwohcidb_tr *)arg; 81677ee030bSHidetoshi Shimokawa db = &db_tr->db[db_tr->dbcnt]; 81777ee030bSHidetoshi Shimokawa if (error) { 81877ee030bSHidetoshi Shimokawa if (firewire_debug || error != EFBIG) 81977ee030bSHidetoshi Shimokawa printf("fwohci_execute_db: error=%d\n", error); 82077ee030bSHidetoshi Shimokawa return; 82177ee030bSHidetoshi Shimokawa } 82277ee030bSHidetoshi Shimokawa for (i = 0; i < nseg; i++) { 82377ee030bSHidetoshi Shimokawa s = &segs[i]; 82477ee030bSHidetoshi Shimokawa FWOHCI_DMA_WRITE(db->db.desc.addr, s->ds_addr); 82577ee030bSHidetoshi Shimokawa FWOHCI_DMA_WRITE(db->db.desc.cmd, s->ds_len); 82677ee030bSHidetoshi Shimokawa FWOHCI_DMA_WRITE(db->db.desc.res, 0); 82777ee030bSHidetoshi Shimokawa db++; 82877ee030bSHidetoshi Shimokawa db_tr->dbcnt++; 82977ee030bSHidetoshi Shimokawa } 83077ee030bSHidetoshi Shimokawa } 83177ee030bSHidetoshi Shimokawa 83277ee030bSHidetoshi Shimokawa static void 83377ee030bSHidetoshi Shimokawa fwohci_execute_db2(void *arg, bus_dma_segment_t *segs, int nseg, 83477ee030bSHidetoshi Shimokawa bus_size_t size, int error) 83577ee030bSHidetoshi Shimokawa { 83677ee030bSHidetoshi Shimokawa fwohci_execute_db(arg, segs, nseg, error); 83777ee030bSHidetoshi Shimokawa } 83877ee030bSHidetoshi Shimokawa 83977ee030bSHidetoshi Shimokawa static void 840c572b810SHidetoshi Shimokawa fwohci_start(struct fwohci_softc *sc, struct fwohci_dbch *dbch) 8413c60ba66SKatsushi Kobayashi { 8423c60ba66SKatsushi Kobayashi int i, s; 843c4778b5dSHidetoshi Shimokawa int tcode, hdr_len, pl_off; 8443c60ba66SKatsushi Kobayashi int fsegment = -1; 84503161bbcSDoug Rabson uint32_t off; 8463c60ba66SKatsushi Kobayashi struct fw_xfer *xfer; 8473c60ba66SKatsushi Kobayashi struct fw_pkt *fp; 848c4778b5dSHidetoshi Shimokawa struct fwohci_txpkthdr *ohcifp; 8493c60ba66SKatsushi Kobayashi struct fwohcidb_tr *db_tr; 850c4778b5dSHidetoshi Shimokawa struct fwohcidb *db; 85103161bbcSDoug Rabson uint32_t *ld; 8523c60ba66SKatsushi Kobayashi struct tcode_info *info; 853d6105b60SHidetoshi Shimokawa static int maxdesc=0; 8543c60ba66SKatsushi Kobayashi 8553c60ba66SKatsushi Kobayashi if(&sc->atrq == dbch){ 8563c60ba66SKatsushi Kobayashi off = OHCI_ATQOFF; 8573c60ba66SKatsushi Kobayashi }else if(&sc->atrs == dbch){ 8583c60ba66SKatsushi Kobayashi off = OHCI_ATSOFF; 8593c60ba66SKatsushi Kobayashi }else{ 8603c60ba66SKatsushi Kobayashi return; 8613c60ba66SKatsushi Kobayashi } 8623c60ba66SKatsushi Kobayashi 8633c60ba66SKatsushi Kobayashi if (dbch->flags & FWOHCI_DBCH_FULL) 8643c60ba66SKatsushi Kobayashi return; 8653c60ba66SKatsushi Kobayashi 8663c60ba66SKatsushi Kobayashi s = splfw(); 8673c60ba66SKatsushi Kobayashi db_tr = dbch->top; 8683c60ba66SKatsushi Kobayashi txloop: 8693c60ba66SKatsushi Kobayashi xfer = STAILQ_FIRST(&dbch->xferq.q); 8703c60ba66SKatsushi Kobayashi if(xfer == NULL){ 8713c60ba66SKatsushi Kobayashi goto kick; 8723c60ba66SKatsushi Kobayashi } 8733c60ba66SKatsushi Kobayashi if(dbch->xferq.queued == 0 ){ 8743c60ba66SKatsushi Kobayashi device_printf(sc->fc.dev, "TX queue empty\n"); 8753c60ba66SKatsushi Kobayashi } 8763c60ba66SKatsushi Kobayashi STAILQ_REMOVE_HEAD(&dbch->xferq.q, link); 8773c60ba66SKatsushi Kobayashi db_tr->xfer = xfer; 8783c60ba66SKatsushi Kobayashi xfer->state = FWXF_START; 8793c60ba66SKatsushi Kobayashi 880c4778b5dSHidetoshi Shimokawa fp = &xfer->send.hdr; 8813c60ba66SKatsushi Kobayashi tcode = fp->mode.common.tcode; 8823c60ba66SKatsushi Kobayashi 883c4778b5dSHidetoshi Shimokawa ohcifp = (struct fwohci_txpkthdr *) db_tr->db[1].db.immed; 8843c60ba66SKatsushi Kobayashi info = &tinfo[tcode]; 88577ee030bSHidetoshi Shimokawa hdr_len = pl_off = info->hdr_len; 886a1c9e73aSHidetoshi Shimokawa 887a1c9e73aSHidetoshi Shimokawa ld = &ohcifp->mode.ld[0]; 888a1c9e73aSHidetoshi Shimokawa ld[0] = ld[1] = ld[2] = ld[3] = 0; 889a1c9e73aSHidetoshi Shimokawa for( i = 0 ; i < pl_off ; i+= 4) 890a1c9e73aSHidetoshi Shimokawa ld[i/4] = fp->mode.ld[i/4]; 891a1c9e73aSHidetoshi Shimokawa 892c4778b5dSHidetoshi Shimokawa ohcifp->mode.common.spd = xfer->send.spd & 0x7; 8933c60ba66SKatsushi Kobayashi if (tcode == FWTCODE_STREAM ){ 8943c60ba66SKatsushi Kobayashi hdr_len = 8; 89577ee030bSHidetoshi Shimokawa ohcifp->mode.stream.len = fp->mode.stream.len; 8963c60ba66SKatsushi Kobayashi } else if (tcode == FWTCODE_PHY) { 8973c60ba66SKatsushi Kobayashi hdr_len = 12; 898a1c9e73aSHidetoshi Shimokawa ld[1] = fp->mode.ld[1]; 899a1c9e73aSHidetoshi Shimokawa ld[2] = fp->mode.ld[2]; 9003c60ba66SKatsushi Kobayashi ohcifp->mode.common.spd = 0; 9013c60ba66SKatsushi Kobayashi ohcifp->mode.common.tcode = FWOHCITCODE_PHY; 9023c60ba66SKatsushi Kobayashi } else { 90377ee030bSHidetoshi Shimokawa ohcifp->mode.asycomm.dst = fp->mode.hdr.dst; 9043c60ba66SKatsushi Kobayashi ohcifp->mode.asycomm.srcbus = OHCI_ASYSRCBUS; 9053c60ba66SKatsushi Kobayashi ohcifp->mode.asycomm.tlrt |= FWRETRY_X; 9063c60ba66SKatsushi Kobayashi } 9073c60ba66SKatsushi Kobayashi db = &db_tr->db[0]; 90877ee030bSHidetoshi Shimokawa FWOHCI_DMA_WRITE(db->db.desc.cmd, 90977ee030bSHidetoshi Shimokawa OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | hdr_len); 910a1c9e73aSHidetoshi Shimokawa FWOHCI_DMA_WRITE(db->db.desc.addr, 0); 91177ee030bSHidetoshi Shimokawa FWOHCI_DMA_WRITE(db->db.desc.res, 0); 9123c60ba66SKatsushi Kobayashi /* Specify bound timer of asy. responce */ 9133c60ba66SKatsushi Kobayashi if(&sc->atrs == dbch){ 91477ee030bSHidetoshi Shimokawa FWOHCI_DMA_WRITE(db->db.desc.res, 91577ee030bSHidetoshi Shimokawa (OREAD(sc, OHCI_CYCLETIMER) >> 12) + (1 << 13)); 9163c60ba66SKatsushi Kobayashi } 91777ee030bSHidetoshi Shimokawa #if BYTE_ORDER == BIG_ENDIAN 91877ee030bSHidetoshi Shimokawa if (tcode == FWTCODE_WREQQ || tcode == FWTCODE_RRESQ) 91977ee030bSHidetoshi Shimokawa hdr_len = 12; 92077ee030bSHidetoshi Shimokawa for (i = 0; i < hdr_len/4; i ++) 921a1c9e73aSHidetoshi Shimokawa FWOHCI_DMA_WRITE(ld[i], ld[i]); 92277ee030bSHidetoshi Shimokawa #endif 9233c60ba66SKatsushi Kobayashi 9242b4601d1SHidetoshi Shimokawa again: 9253c60ba66SKatsushi Kobayashi db_tr->dbcnt = 2; 9263c60ba66SKatsushi Kobayashi db = &db_tr->db[db_tr->dbcnt]; 927c4778b5dSHidetoshi Shimokawa if (xfer->send.pay_len > 0) { 92877ee030bSHidetoshi Shimokawa int err; 92977ee030bSHidetoshi Shimokawa /* handle payload */ 9303c60ba66SKatsushi Kobayashi if (xfer->mbuf == NULL) { 93177ee030bSHidetoshi Shimokawa err = bus_dmamap_load(dbch->dmat, db_tr->dma_map, 932c4778b5dSHidetoshi Shimokawa &xfer->send.payload[0], xfer->send.pay_len, 93377ee030bSHidetoshi Shimokawa fwohci_execute_db, db_tr, 93477ee030bSHidetoshi Shimokawa /*flags*/0); 9353c60ba66SKatsushi Kobayashi } else { 9362b4601d1SHidetoshi Shimokawa /* XXX we can handle only 6 (=8-2) mbuf chains */ 93777ee030bSHidetoshi Shimokawa err = bus_dmamap_load_mbuf(dbch->dmat, db_tr->dma_map, 93877ee030bSHidetoshi Shimokawa xfer->mbuf, 93977ee030bSHidetoshi Shimokawa fwohci_execute_db2, db_tr, 94077ee030bSHidetoshi Shimokawa /* flags */0); 94177ee030bSHidetoshi Shimokawa if (err == EFBIG) { 94277ee030bSHidetoshi Shimokawa struct mbuf *m0; 94377ee030bSHidetoshi Shimokawa 94477ee030bSHidetoshi Shimokawa if (firewire_debug) 94577ee030bSHidetoshi Shimokawa device_printf(sc->fc.dev, "EFBIG.\n"); 94677ee030bSHidetoshi Shimokawa m0 = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); 94777ee030bSHidetoshi Shimokawa if (m0 != NULL) { 9482b4601d1SHidetoshi Shimokawa m_copydata(xfer->mbuf, 0, 9492b4601d1SHidetoshi Shimokawa xfer->mbuf->m_pkthdr.len, 95077ee030bSHidetoshi Shimokawa mtod(m0, caddr_t)); 95177ee030bSHidetoshi Shimokawa m0->m_len = m0->m_pkthdr.len = 9522b4601d1SHidetoshi Shimokawa xfer->mbuf->m_pkthdr.len; 9532b4601d1SHidetoshi Shimokawa m_freem(xfer->mbuf); 95477ee030bSHidetoshi Shimokawa xfer->mbuf = m0; 9552b4601d1SHidetoshi Shimokawa goto again; 9562b4601d1SHidetoshi Shimokawa } 9572b4601d1SHidetoshi Shimokawa device_printf(sc->fc.dev, "m_getcl failed.\n"); 9582b4601d1SHidetoshi Shimokawa } 9593c60ba66SKatsushi Kobayashi } 96077ee030bSHidetoshi Shimokawa if (err) 96177ee030bSHidetoshi Shimokawa printf("dmamap_load: err=%d\n", err); 96277ee030bSHidetoshi Shimokawa bus_dmamap_sync(dbch->dmat, db_tr->dma_map, 96377ee030bSHidetoshi Shimokawa BUS_DMASYNC_PREWRITE); 96477ee030bSHidetoshi Shimokawa #if 0 /* OHCI_OUTPUT_MODE == 0 */ 96577ee030bSHidetoshi Shimokawa for (i = 2; i < db_tr->dbcnt; i++) 96677ee030bSHidetoshi Shimokawa FWOHCI_DMA_SET(db_tr->db[i].db.desc.cmd, 96777ee030bSHidetoshi Shimokawa OHCI_OUTPUT_MORE); 96877ee030bSHidetoshi Shimokawa #endif 969d6105b60SHidetoshi Shimokawa } 970d6105b60SHidetoshi Shimokawa if (maxdesc < db_tr->dbcnt) { 971d6105b60SHidetoshi Shimokawa maxdesc = db_tr->dbcnt; 972d6105b60SHidetoshi Shimokawa if (bootverbose) 973d6105b60SHidetoshi Shimokawa device_printf(sc->fc.dev, "maxdesc: %d\n", maxdesc); 974d6105b60SHidetoshi Shimokawa } 9753c60ba66SKatsushi Kobayashi /* last db */ 9763c60ba66SKatsushi Kobayashi LAST_DB(db_tr, db); 97777ee030bSHidetoshi Shimokawa FWOHCI_DMA_SET(db->db.desc.cmd, 97877ee030bSHidetoshi Shimokawa OHCI_OUTPUT_LAST | OHCI_INTERRUPT_ALWAYS | OHCI_BRANCH_ALWAYS); 97977ee030bSHidetoshi Shimokawa FWOHCI_DMA_WRITE(db->db.desc.depend, 98077ee030bSHidetoshi Shimokawa STAILQ_NEXT(db_tr, link)->bus_addr); 9813c60ba66SKatsushi Kobayashi 9823c60ba66SKatsushi Kobayashi if(fsegment == -1 ) 9833c60ba66SKatsushi Kobayashi fsegment = db_tr->dbcnt; 9843c60ba66SKatsushi Kobayashi if (dbch->pdb_tr != NULL) { 9853c60ba66SKatsushi Kobayashi LAST_DB(dbch->pdb_tr, db); 98677ee030bSHidetoshi Shimokawa FWOHCI_DMA_SET(db->db.desc.depend, db_tr->dbcnt); 9873c60ba66SKatsushi Kobayashi } 9883c60ba66SKatsushi Kobayashi dbch->pdb_tr = db_tr; 9893c60ba66SKatsushi Kobayashi db_tr = STAILQ_NEXT(db_tr, link); 9903c60ba66SKatsushi Kobayashi if(db_tr != dbch->bottom){ 9913c60ba66SKatsushi Kobayashi goto txloop; 9923c60ba66SKatsushi Kobayashi } else { 99317c3d42cSHidetoshi Shimokawa device_printf(sc->fc.dev, "fwohci_start: lack of db_trq\n"); 9943c60ba66SKatsushi Kobayashi dbch->flags |= FWOHCI_DBCH_FULL; 9953c60ba66SKatsushi Kobayashi } 9963c60ba66SKatsushi Kobayashi kick: 9973c60ba66SKatsushi Kobayashi /* kick asy q */ 99877ee030bSHidetoshi Shimokawa fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREREAD); 99977ee030bSHidetoshi Shimokawa fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREWRITE); 10003c60ba66SKatsushi Kobayashi 10013c60ba66SKatsushi Kobayashi if(dbch->xferq.flag & FWXFERQ_RUNNING) { 10023c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_WAKE); 10033c60ba66SKatsushi Kobayashi } else { 100417c3d42cSHidetoshi Shimokawa if (bootverbose) 100517c3d42cSHidetoshi Shimokawa device_printf(sc->fc.dev, "start AT DMA status=%x\n", 10063c60ba66SKatsushi Kobayashi OREAD(sc, OHCI_DMACTL(off))); 100777ee030bSHidetoshi Shimokawa OWRITE(sc, OHCI_DMACMD(off), dbch->top->bus_addr | fsegment); 10083c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_RUN); 10093c60ba66SKatsushi Kobayashi dbch->xferq.flag |= FWXFERQ_RUNNING; 10103c60ba66SKatsushi Kobayashi } 1011c572b810SHidetoshi Shimokawa 10123c60ba66SKatsushi Kobayashi dbch->top = db_tr; 10133c60ba66SKatsushi Kobayashi splx(s); 10143c60ba66SKatsushi Kobayashi return; 10153c60ba66SKatsushi Kobayashi } 1016c572b810SHidetoshi Shimokawa 1017c572b810SHidetoshi Shimokawa static void 1018c572b810SHidetoshi Shimokawa fwohci_start_atq(struct firewire_comm *fc) 10193c60ba66SKatsushi Kobayashi { 10203c60ba66SKatsushi Kobayashi struct fwohci_softc *sc = (struct fwohci_softc *)fc; 10213c60ba66SKatsushi Kobayashi fwohci_start( sc, &(sc->atrq)); 10223c60ba66SKatsushi Kobayashi return; 10233c60ba66SKatsushi Kobayashi } 1024c572b810SHidetoshi Shimokawa 1025c572b810SHidetoshi Shimokawa static void 1026c572b810SHidetoshi Shimokawa fwohci_start_ats(struct firewire_comm *fc) 10273c60ba66SKatsushi Kobayashi { 10283c60ba66SKatsushi Kobayashi struct fwohci_softc *sc = (struct fwohci_softc *)fc; 10293c60ba66SKatsushi Kobayashi fwohci_start( sc, &(sc->atrs)); 10303c60ba66SKatsushi Kobayashi return; 10313c60ba66SKatsushi Kobayashi } 1032c572b810SHidetoshi Shimokawa 1033c572b810SHidetoshi Shimokawa void 1034c572b810SHidetoshi Shimokawa fwohci_txd(struct fwohci_softc *sc, struct fwohci_dbch *dbch) 10353c60ba66SKatsushi Kobayashi { 103677ee030bSHidetoshi Shimokawa int s, ch, err = 0; 10373c60ba66SKatsushi Kobayashi struct fwohcidb_tr *tr; 1038c4778b5dSHidetoshi Shimokawa struct fwohcidb *db; 10393c60ba66SKatsushi Kobayashi struct fw_xfer *xfer; 104003161bbcSDoug Rabson uint32_t off; 104177ee030bSHidetoshi Shimokawa u_int stat, status; 10423c60ba66SKatsushi Kobayashi int packets; 10433c60ba66SKatsushi Kobayashi struct firewire_comm *fc = (struct firewire_comm *)sc; 104477ee030bSHidetoshi Shimokawa 10453c60ba66SKatsushi Kobayashi if(&sc->atrq == dbch){ 10463c60ba66SKatsushi Kobayashi off = OHCI_ATQOFF; 104777ee030bSHidetoshi Shimokawa ch = ATRQ_CH; 10483c60ba66SKatsushi Kobayashi }else if(&sc->atrs == dbch){ 10493c60ba66SKatsushi Kobayashi off = OHCI_ATSOFF; 105077ee030bSHidetoshi Shimokawa ch = ATRS_CH; 10513c60ba66SKatsushi Kobayashi }else{ 10523c60ba66SKatsushi Kobayashi return; 10533c60ba66SKatsushi Kobayashi } 10543c60ba66SKatsushi Kobayashi s = splfw(); 10553c60ba66SKatsushi Kobayashi tr = dbch->bottom; 10563c60ba66SKatsushi Kobayashi packets = 0; 105777ee030bSHidetoshi Shimokawa fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_POSTREAD); 105877ee030bSHidetoshi Shimokawa fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_POSTWRITE); 10593c60ba66SKatsushi Kobayashi while(dbch->xferq.queued > 0){ 10603c60ba66SKatsushi Kobayashi LAST_DB(tr, db); 106177ee030bSHidetoshi Shimokawa status = FWOHCI_DMA_READ(db->db.desc.res) >> OHCI_STATUS_SHIFT; 106277ee030bSHidetoshi Shimokawa if(!(status & OHCI_CNTL_DMA_ACTIVE)){ 10633c60ba66SKatsushi Kobayashi if (fc->status != FWBUSRESET) 10643c60ba66SKatsushi Kobayashi /* maybe out of order?? */ 10653c60ba66SKatsushi Kobayashi goto out; 10663c60ba66SKatsushi Kobayashi } 106777ee030bSHidetoshi Shimokawa bus_dmamap_sync(dbch->dmat, tr->dma_map, 106877ee030bSHidetoshi Shimokawa BUS_DMASYNC_POSTWRITE); 106977ee030bSHidetoshi Shimokawa bus_dmamap_unload(dbch->dmat, tr->dma_map); 1070a1c9e73aSHidetoshi Shimokawa #if 1 1071a1c9e73aSHidetoshi Shimokawa if (firewire_debug) 10723c60ba66SKatsushi Kobayashi dump_db(sc, ch); 10733c60ba66SKatsushi Kobayashi #endif 107477ee030bSHidetoshi Shimokawa if(status & OHCI_CNTL_DMA_DEAD) { 10753c60ba66SKatsushi Kobayashi /* Stop DMA */ 10763c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_DMACTLCLR(off), OHCI_CNTL_DMA_RUN); 10773c60ba66SKatsushi Kobayashi device_printf(sc->fc.dev, "force reset AT FIFO\n"); 10783c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_LINKEN); 10793c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LPS | OHCI_HCC_LINKEN); 10803c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_DMACTLCLR(off), OHCI_CNTL_DMA_RUN); 10813c60ba66SKatsushi Kobayashi } 108277ee030bSHidetoshi Shimokawa stat = status & FWOHCIEV_MASK; 10833c60ba66SKatsushi Kobayashi switch(stat){ 10843c60ba66SKatsushi Kobayashi case FWOHCIEV_ACKPEND: 1085864d7e72SHidetoshi Shimokawa case FWOHCIEV_ACKCOMPL: 10863c60ba66SKatsushi Kobayashi err = 0; 10873c60ba66SKatsushi Kobayashi break; 10883c60ba66SKatsushi Kobayashi case FWOHCIEV_ACKBSA: 10893c60ba66SKatsushi Kobayashi case FWOHCIEV_ACKBSB: 10903c60ba66SKatsushi Kobayashi case FWOHCIEV_ACKBSX: 1091864d7e72SHidetoshi Shimokawa device_printf(sc->fc.dev, "txd err=%2x %s\n", stat, fwohcicode[stat]); 10923c60ba66SKatsushi Kobayashi err = EBUSY; 10933c60ba66SKatsushi Kobayashi break; 10943c60ba66SKatsushi Kobayashi case FWOHCIEV_FLUSHED: 10953c60ba66SKatsushi Kobayashi case FWOHCIEV_ACKTARD: 10963c60ba66SKatsushi Kobayashi device_printf(sc->fc.dev, "txd err=%2x %s\n", stat, fwohcicode[stat]); 10973c60ba66SKatsushi Kobayashi err = EAGAIN; 10983c60ba66SKatsushi Kobayashi break; 10993c60ba66SKatsushi Kobayashi case FWOHCIEV_MISSACK: 11003c60ba66SKatsushi Kobayashi case FWOHCIEV_UNDRRUN: 11013c60ba66SKatsushi Kobayashi case FWOHCIEV_OVRRUN: 11023c60ba66SKatsushi Kobayashi case FWOHCIEV_DESCERR: 11033c60ba66SKatsushi Kobayashi case FWOHCIEV_DTRDERR: 11043c60ba66SKatsushi Kobayashi case FWOHCIEV_TIMEOUT: 11053c60ba66SKatsushi Kobayashi case FWOHCIEV_TCODERR: 11063c60ba66SKatsushi Kobayashi case FWOHCIEV_UNKNOWN: 11073c60ba66SKatsushi Kobayashi case FWOHCIEV_ACKDERR: 11083c60ba66SKatsushi Kobayashi case FWOHCIEV_ACKTERR: 11093c60ba66SKatsushi Kobayashi default: 11103c60ba66SKatsushi Kobayashi device_printf(sc->fc.dev, "txd err=%2x %s\n", 11113c60ba66SKatsushi Kobayashi stat, fwohcicode[stat]); 11123c60ba66SKatsushi Kobayashi err = EINVAL; 11133c60ba66SKatsushi Kobayashi break; 11143c60ba66SKatsushi Kobayashi } 11153c60ba66SKatsushi Kobayashi if (tr->xfer != NULL) { 11163c60ba66SKatsushi Kobayashi xfer = tr->xfer; 111777ee030bSHidetoshi Shimokawa if (xfer->state == FWXF_RCVD) { 11181a753700SHidetoshi Shimokawa #if 0 111977ee030bSHidetoshi Shimokawa if (firewire_debug) 112077ee030bSHidetoshi Shimokawa printf("already rcvd\n"); 11211a753700SHidetoshi Shimokawa #endif 112277ee030bSHidetoshi Shimokawa fw_xfer_done(xfer); 112377ee030bSHidetoshi Shimokawa } else { 11243c60ba66SKatsushi Kobayashi xfer->state = FWXF_SENT; 11253c60ba66SKatsushi Kobayashi if (err == EBUSY && fc->status != FWBUSRESET) { 11263c60ba66SKatsushi Kobayashi xfer->state = FWXF_BUSY; 11273c60ba66SKatsushi Kobayashi xfer->resp = err; 1128864d7e72SHidetoshi Shimokawa if (xfer->retry_req != NULL) 11293c60ba66SKatsushi Kobayashi xfer->retry_req(xfer); 113013bd8601SHidetoshi Shimokawa else { 1131c4778b5dSHidetoshi Shimokawa xfer->recv.pay_len = 0; 1132864d7e72SHidetoshi Shimokawa fw_xfer_done(xfer); 113313bd8601SHidetoshi Shimokawa } 11343c60ba66SKatsushi Kobayashi } else if (stat != FWOHCIEV_ACKPEND) { 11353c60ba66SKatsushi Kobayashi if (stat != FWOHCIEV_ACKCOMPL) 11363c60ba66SKatsushi Kobayashi xfer->state = FWXF_SENTERR; 11373c60ba66SKatsushi Kobayashi xfer->resp = err; 1138c4778b5dSHidetoshi Shimokawa xfer->recv.pay_len = 0; 11393c60ba66SKatsushi Kobayashi fw_xfer_done(xfer); 11403c60ba66SKatsushi Kobayashi } 11413c60ba66SKatsushi Kobayashi } 1142864d7e72SHidetoshi Shimokawa /* 1143864d7e72SHidetoshi Shimokawa * The watchdog timer takes care of split 1144864d7e72SHidetoshi Shimokawa * transcation timeout for ACKPEND case. 1145864d7e72SHidetoshi Shimokawa */ 114677ee030bSHidetoshi Shimokawa } else { 114777ee030bSHidetoshi Shimokawa printf("this shouldn't happen\n"); 11483c60ba66SKatsushi Kobayashi } 114948249fe0SHidetoshi Shimokawa dbch->xferq.queued --; 11503c60ba66SKatsushi Kobayashi tr->xfer = NULL; 11513c60ba66SKatsushi Kobayashi 11523c60ba66SKatsushi Kobayashi packets ++; 11533c60ba66SKatsushi Kobayashi tr = STAILQ_NEXT(tr, link); 11543c60ba66SKatsushi Kobayashi dbch->bottom = tr; 11553b79dd16SHidetoshi Shimokawa if (dbch->bottom == dbch->top) { 11563b79dd16SHidetoshi Shimokawa /* we reaches the end of context program */ 11573b79dd16SHidetoshi Shimokawa if (firewire_debug && dbch->xferq.queued > 0) 11583b79dd16SHidetoshi Shimokawa printf("queued > 0\n"); 11593b79dd16SHidetoshi Shimokawa break; 11603b79dd16SHidetoshi Shimokawa } 11613c60ba66SKatsushi Kobayashi } 11623c60ba66SKatsushi Kobayashi out: 11633c60ba66SKatsushi Kobayashi if ((dbch->flags & FWOHCI_DBCH_FULL) && packets > 0) { 11643c60ba66SKatsushi Kobayashi printf("make free slot\n"); 11653c60ba66SKatsushi Kobayashi dbch->flags &= ~FWOHCI_DBCH_FULL; 11663c60ba66SKatsushi Kobayashi fwohci_start(sc, dbch); 11673c60ba66SKatsushi Kobayashi } 11683c60ba66SKatsushi Kobayashi splx(s); 11693c60ba66SKatsushi Kobayashi } 1170c572b810SHidetoshi Shimokawa 1171c572b810SHidetoshi Shimokawa static void 1172c572b810SHidetoshi Shimokawa fwohci_db_free(struct fwohci_dbch *dbch) 11733c60ba66SKatsushi Kobayashi { 11743c60ba66SKatsushi Kobayashi struct fwohcidb_tr *db_tr; 117577ee030bSHidetoshi Shimokawa int idb; 11763c60ba66SKatsushi Kobayashi 11771f2361f8SHidetoshi Shimokawa if ((dbch->flags & FWOHCI_DBCH_INIT) == 0) 11781f2361f8SHidetoshi Shimokawa return; 11791f2361f8SHidetoshi Shimokawa 118077ee030bSHidetoshi Shimokawa for(db_tr = STAILQ_FIRST(&dbch->db_trq), idb = 0; idb < dbch->ndb; 11813c60ba66SKatsushi Kobayashi db_tr = STAILQ_NEXT(db_tr, link), idb++){ 118277ee030bSHidetoshi Shimokawa if ((dbch->xferq.flag & FWXFERQ_EXTBUF) == 0 && 118377ee030bSHidetoshi Shimokawa db_tr->buf != NULL) { 118477ee030bSHidetoshi Shimokawa fwdma_free_size(dbch->dmat, db_tr->dma_map, 118577ee030bSHidetoshi Shimokawa db_tr->buf, dbch->xferq.psize); 11863c60ba66SKatsushi Kobayashi db_tr->buf = NULL; 118777ee030bSHidetoshi Shimokawa } else if (db_tr->dma_map != NULL) 118877ee030bSHidetoshi Shimokawa bus_dmamap_destroy(dbch->dmat, db_tr->dma_map); 11891f2361f8SHidetoshi Shimokawa } 11903c60ba66SKatsushi Kobayashi dbch->ndb = 0; 11913c60ba66SKatsushi Kobayashi db_tr = STAILQ_FIRST(&dbch->db_trq); 119277ee030bSHidetoshi Shimokawa fwdma_free_multiseg(dbch->am); 11935166f1dfSHidetoshi Shimokawa free(db_tr, M_FW); 11943c60ba66SKatsushi Kobayashi STAILQ_INIT(&dbch->db_trq); 11951f2361f8SHidetoshi Shimokawa dbch->flags &= ~FWOHCI_DBCH_INIT; 11963c60ba66SKatsushi Kobayashi } 1197c572b810SHidetoshi Shimokawa 1198c572b810SHidetoshi Shimokawa static void 119977ee030bSHidetoshi Shimokawa fwohci_db_init(struct fwohci_softc *sc, struct fwohci_dbch *dbch) 12003c60ba66SKatsushi Kobayashi { 12013c60ba66SKatsushi Kobayashi int idb; 12023c60ba66SKatsushi Kobayashi struct fwohcidb_tr *db_tr; 12039339321dSHidetoshi Shimokawa 12049339321dSHidetoshi Shimokawa if ((dbch->flags & FWOHCI_DBCH_INIT) != 0) 12059339321dSHidetoshi Shimokawa goto out; 12069339321dSHidetoshi Shimokawa 120777ee030bSHidetoshi Shimokawa /* create dma_tag for buffers */ 120877ee030bSHidetoshi Shimokawa #define MAX_REQCOUNT 0xffff 120977ee030bSHidetoshi Shimokawa if (bus_dma_tag_create(/*parent*/ sc->fc.dmat, 121077ee030bSHidetoshi Shimokawa /*alignment*/ 1, /*boundary*/ 0, 121177ee030bSHidetoshi Shimokawa /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT, 121277ee030bSHidetoshi Shimokawa /*highaddr*/ BUS_SPACE_MAXADDR, 121377ee030bSHidetoshi Shimokawa /*filter*/NULL, /*filterarg*/NULL, 121477ee030bSHidetoshi Shimokawa /*maxsize*/ dbch->xferq.psize, 121577ee030bSHidetoshi Shimokawa /*nsegments*/ dbch->ndesc > 3 ? dbch->ndesc - 2 : 1, 121677ee030bSHidetoshi Shimokawa /*maxsegsz*/ MAX_REQCOUNT, 1217f6b1c44dSScott Long /*flags*/ 0, 121810d3ed64SHidetoshi Shimokawa #if defined(__FreeBSD__) && __FreeBSD_version >= 501102 1219f6b1c44dSScott Long /*lockfunc*/busdma_lock_mutex, 12204f933468SHidetoshi Shimokawa /*lockarg*/&Giant, 12214f933468SHidetoshi Shimokawa #endif 12224f933468SHidetoshi Shimokawa &dbch->dmat)) 122377ee030bSHidetoshi Shimokawa return; 122477ee030bSHidetoshi Shimokawa 12253c60ba66SKatsushi Kobayashi /* allocate DB entries and attach one to each DMA channels */ 12263c60ba66SKatsushi Kobayashi /* DB entry must start at 16 bytes bounary. */ 12273c60ba66SKatsushi Kobayashi STAILQ_INIT(&dbch->db_trq); 12283c60ba66SKatsushi Kobayashi db_tr = (struct fwohcidb_tr *) 12293c60ba66SKatsushi Kobayashi malloc(sizeof(struct fwohcidb_tr) * dbch->ndb, 123077ee030bSHidetoshi Shimokawa M_FW, M_WAITOK | M_ZERO); 12313c60ba66SKatsushi Kobayashi if(db_tr == NULL){ 1232e2ad5d6eSHidetoshi Shimokawa printf("fwohci_db_init: malloc(1) failed\n"); 12333c60ba66SKatsushi Kobayashi return; 12343c60ba66SKatsushi Kobayashi } 1235e2ad5d6eSHidetoshi Shimokawa 123677ee030bSHidetoshi Shimokawa #define DB_SIZE(x) (sizeof(struct fwohcidb) * (x)->ndesc) 123777ee030bSHidetoshi Shimokawa dbch->am = fwdma_malloc_multiseg(&sc->fc, DB_SIZE(dbch), 123877ee030bSHidetoshi Shimokawa DB_SIZE(dbch), dbch->ndb, BUS_DMA_WAITOK); 123977ee030bSHidetoshi Shimokawa if (dbch->am == NULL) { 124077ee030bSHidetoshi Shimokawa printf("fwohci_db_init: fwdma_malloc_multiseg failed\n"); 12414c790222SHidetoshi Shimokawa free(db_tr, M_FW); 1242e2ad5d6eSHidetoshi Shimokawa return; 1243e2ad5d6eSHidetoshi Shimokawa } 12443c60ba66SKatsushi Kobayashi /* Attach DB to DMA ch. */ 12453c60ba66SKatsushi Kobayashi for(idb = 0 ; idb < dbch->ndb ; idb++){ 12463c60ba66SKatsushi Kobayashi db_tr->dbcnt = 0; 124777ee030bSHidetoshi Shimokawa db_tr->db = (struct fwohcidb *)fwdma_v_addr(dbch->am, idb); 124877ee030bSHidetoshi Shimokawa db_tr->bus_addr = fwdma_bus_addr(dbch->am, idb); 124977ee030bSHidetoshi Shimokawa /* create dmamap for buffers */ 125077ee030bSHidetoshi Shimokawa /* XXX do we need 4bytes alignment tag? */ 125177ee030bSHidetoshi Shimokawa /* XXX don't alloc dma_map for AR */ 125277ee030bSHidetoshi Shimokawa if (bus_dmamap_create(dbch->dmat, 0, &db_tr->dma_map) != 0) { 125377ee030bSHidetoshi Shimokawa printf("bus_dmamap_create failed\n"); 125477ee030bSHidetoshi Shimokawa dbch->flags = FWOHCI_DBCH_INIT; /* XXX fake */ 125577ee030bSHidetoshi Shimokawa fwohci_db_free(dbch); 125677ee030bSHidetoshi Shimokawa return; 125777ee030bSHidetoshi Shimokawa } 12583c60ba66SKatsushi Kobayashi STAILQ_INSERT_TAIL(&dbch->db_trq, db_tr, link); 125977ee030bSHidetoshi Shimokawa if (dbch->xferq.flag & FWXFERQ_EXTBUF) { 1260d0fd7bc6SHidetoshi Shimokawa if (idb % dbch->xferq.bnpacket == 0) 1261d0fd7bc6SHidetoshi Shimokawa dbch->xferq.bulkxfer[idb / dbch->xferq.bnpacket 1262d0fd7bc6SHidetoshi Shimokawa ].start = (caddr_t)db_tr; 1263d0fd7bc6SHidetoshi Shimokawa if ((idb + 1) % dbch->xferq.bnpacket == 0) 1264d0fd7bc6SHidetoshi Shimokawa dbch->xferq.bulkxfer[idb / dbch->xferq.bnpacket 1265d0fd7bc6SHidetoshi Shimokawa ].end = (caddr_t)db_tr; 12663c60ba66SKatsushi Kobayashi } 12673c60ba66SKatsushi Kobayashi db_tr++; 12683c60ba66SKatsushi Kobayashi } 12693c60ba66SKatsushi Kobayashi STAILQ_LAST(&dbch->db_trq, fwohcidb_tr,link)->link.stqe_next 12703c60ba66SKatsushi Kobayashi = STAILQ_FIRST(&dbch->db_trq); 12719339321dSHidetoshi Shimokawa out: 12729339321dSHidetoshi Shimokawa dbch->xferq.queued = 0; 12739339321dSHidetoshi Shimokawa dbch->pdb_tr = NULL; 12743c60ba66SKatsushi Kobayashi dbch->top = STAILQ_FIRST(&dbch->db_trq); 12753c60ba66SKatsushi Kobayashi dbch->bottom = dbch->top; 12761f2361f8SHidetoshi Shimokawa dbch->flags = FWOHCI_DBCH_INIT; 12773c60ba66SKatsushi Kobayashi } 1278c572b810SHidetoshi Shimokawa 1279c572b810SHidetoshi Shimokawa static int 1280c572b810SHidetoshi Shimokawa fwohci_itx_disable(struct firewire_comm *fc, int dmach) 12813c60ba66SKatsushi Kobayashi { 12823c60ba66SKatsushi Kobayashi struct fwohci_softc *sc = (struct fwohci_softc *)fc; 128377ee030bSHidetoshi Shimokawa int sleepch; 12845a7ba74dSHidetoshi Shimokawa 128577ee030bSHidetoshi Shimokawa OWRITE(sc, OHCI_ITCTLCLR(dmach), 128677ee030bSHidetoshi Shimokawa OHCI_CNTL_DMA_RUN | OHCI_CNTL_CYCMATCH_S); 12873c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach); 12883c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach); 12895a7ba74dSHidetoshi Shimokawa /* XXX we cannot free buffers until the DMA really stops */ 129077ee030bSHidetoshi Shimokawa tsleep((void *)&sleepch, FWPRI, "fwitxd", hz); 12913c60ba66SKatsushi Kobayashi fwohci_db_free(&sc->it[dmach]); 12923c60ba66SKatsushi Kobayashi sc->it[dmach].xferq.flag &= ~FWXFERQ_RUNNING; 12933c60ba66SKatsushi Kobayashi return 0; 12943c60ba66SKatsushi Kobayashi } 1295c572b810SHidetoshi Shimokawa 1296c572b810SHidetoshi Shimokawa static int 1297c572b810SHidetoshi Shimokawa fwohci_irx_disable(struct firewire_comm *fc, int dmach) 12983c60ba66SKatsushi Kobayashi { 12993c60ba66SKatsushi Kobayashi struct fwohci_softc *sc = (struct fwohci_softc *)fc; 130077ee030bSHidetoshi Shimokawa int sleepch; 13013c60ba66SKatsushi Kobayashi 13023c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN); 13033c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach); 13043c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach); 13055a7ba74dSHidetoshi Shimokawa /* XXX we cannot free buffers until the DMA really stops */ 130677ee030bSHidetoshi Shimokawa tsleep((void *)&sleepch, FWPRI, "fwirxd", hz); 13073c60ba66SKatsushi Kobayashi fwohci_db_free(&sc->ir[dmach]); 13083c60ba66SKatsushi Kobayashi sc->ir[dmach].xferq.flag &= ~FWXFERQ_RUNNING; 13093c60ba66SKatsushi Kobayashi return 0; 13103c60ba66SKatsushi Kobayashi } 1311c572b810SHidetoshi Shimokawa 131277ee030bSHidetoshi Shimokawa #if BYTE_ORDER == BIG_ENDIAN 1313c572b810SHidetoshi Shimokawa static void 131403161bbcSDoug Rabson fwohci_irx_post (struct firewire_comm *fc , uint32_t *qld) 13153c60ba66SKatsushi Kobayashi { 131677ee030bSHidetoshi Shimokawa qld[0] = FWOHCI_DMA_READ(qld[0]); 13173c60ba66SKatsushi Kobayashi return; 13183c60ba66SKatsushi Kobayashi } 13193c60ba66SKatsushi Kobayashi #endif 13203c60ba66SKatsushi Kobayashi 1321c572b810SHidetoshi Shimokawa static int 1322c572b810SHidetoshi Shimokawa fwohci_tx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch) 13233c60ba66SKatsushi Kobayashi { 13243c60ba66SKatsushi Kobayashi int err = 0; 132577ee030bSHidetoshi Shimokawa int idb, z, i, dmach = 0, ldesc; 132603161bbcSDoug Rabson uint32_t off = 0; 13273c60ba66SKatsushi Kobayashi struct fwohcidb_tr *db_tr; 1328c4778b5dSHidetoshi Shimokawa struct fwohcidb *db; 13293c60ba66SKatsushi Kobayashi 13303c60ba66SKatsushi Kobayashi if(!(dbch->xferq.flag & FWXFERQ_EXTBUF)){ 13313c60ba66SKatsushi Kobayashi err = EINVAL; 13323c60ba66SKatsushi Kobayashi return err; 13333c60ba66SKatsushi Kobayashi } 13343c60ba66SKatsushi Kobayashi z = dbch->ndesc; 13353c60ba66SKatsushi Kobayashi for(dmach = 0 ; dmach < sc->fc.nisodma ; dmach++){ 13363c60ba66SKatsushi Kobayashi if( &sc->it[dmach] == dbch){ 13373c60ba66SKatsushi Kobayashi off = OHCI_ITOFF(dmach); 13383c60ba66SKatsushi Kobayashi break; 13393c60ba66SKatsushi Kobayashi } 13403c60ba66SKatsushi Kobayashi } 1341a89ec05eSPeter Wemm if(off == 0){ 13423c60ba66SKatsushi Kobayashi err = EINVAL; 13433c60ba66SKatsushi Kobayashi return err; 13443c60ba66SKatsushi Kobayashi } 13453c60ba66SKatsushi Kobayashi if(dbch->xferq.flag & FWXFERQ_RUNNING) 13463c60ba66SKatsushi Kobayashi return err; 13473c60ba66SKatsushi Kobayashi dbch->xferq.flag |= FWXFERQ_RUNNING; 13483c60ba66SKatsushi Kobayashi for( i = 0, dbch->bottom = dbch->top; i < (dbch->ndb - 1); i++){ 13493c60ba66SKatsushi Kobayashi dbch->bottom = STAILQ_NEXT(dbch->bottom, link); 13503c60ba66SKatsushi Kobayashi } 13513c60ba66SKatsushi Kobayashi db_tr = dbch->top; 13523c60ba66SKatsushi Kobayashi for (idb = 0; idb < dbch->ndb; idb ++) { 135377ee030bSHidetoshi Shimokawa fwohci_add_tx_buf(dbch, db_tr, idb); 13543c60ba66SKatsushi Kobayashi if(STAILQ_NEXT(db_tr, link) == NULL){ 13553c60ba66SKatsushi Kobayashi break; 13563c60ba66SKatsushi Kobayashi } 135753f1eb86SHidetoshi Shimokawa db = db_tr->db; 135877ee030bSHidetoshi Shimokawa ldesc = db_tr->dbcnt - 1; 135977ee030bSHidetoshi Shimokawa FWOHCI_DMA_WRITE(db[0].db.desc.depend, 136077ee030bSHidetoshi Shimokawa STAILQ_NEXT(db_tr, link)->bus_addr | z); 136177ee030bSHidetoshi Shimokawa db[ldesc].db.desc.depend = db[0].db.desc.depend; 13623c60ba66SKatsushi Kobayashi if(dbch->xferq.flag & FWXFERQ_EXTBUF){ 13633c60ba66SKatsushi Kobayashi if(((idb + 1 ) % dbch->xferq.bnpacket) == 0){ 136477ee030bSHidetoshi Shimokawa FWOHCI_DMA_SET( 136577ee030bSHidetoshi Shimokawa db[ldesc].db.desc.cmd, 136677ee030bSHidetoshi Shimokawa OHCI_INTERRUPT_ALWAYS); 13674ed65ce9SHidetoshi Shimokawa /* OHCI 1.1 and above */ 136877ee030bSHidetoshi Shimokawa FWOHCI_DMA_SET( 136977ee030bSHidetoshi Shimokawa db[0].db.desc.cmd, 137077ee030bSHidetoshi Shimokawa OHCI_INTERRUPT_ALWAYS); 13713c60ba66SKatsushi Kobayashi } 13723c60ba66SKatsushi Kobayashi } 13733c60ba66SKatsushi Kobayashi db_tr = STAILQ_NEXT(db_tr, link); 13743c60ba66SKatsushi Kobayashi } 137577ee030bSHidetoshi Shimokawa FWOHCI_DMA_CLEAR( 137677ee030bSHidetoshi Shimokawa dbch->bottom->db[dbch->bottom->dbcnt - 1].db.desc.depend, 0xf); 13773c60ba66SKatsushi Kobayashi return err; 13783c60ba66SKatsushi Kobayashi } 1379c572b810SHidetoshi Shimokawa 1380c572b810SHidetoshi Shimokawa static int 1381c572b810SHidetoshi Shimokawa fwohci_rx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch) 13823c60ba66SKatsushi Kobayashi { 13833c60ba66SKatsushi Kobayashi int err = 0; 138453f1eb86SHidetoshi Shimokawa int idb, z, i, dmach = 0, ldesc; 138503161bbcSDoug Rabson uint32_t off = 0; 13863c60ba66SKatsushi Kobayashi struct fwohcidb_tr *db_tr; 1387c4778b5dSHidetoshi Shimokawa struct fwohcidb *db; 13883c60ba66SKatsushi Kobayashi 13893c60ba66SKatsushi Kobayashi z = dbch->ndesc; 13903c60ba66SKatsushi Kobayashi if(&sc->arrq == dbch){ 13913c60ba66SKatsushi Kobayashi off = OHCI_ARQOFF; 13923c60ba66SKatsushi Kobayashi }else if(&sc->arrs == dbch){ 13933c60ba66SKatsushi Kobayashi off = OHCI_ARSOFF; 13943c60ba66SKatsushi Kobayashi }else{ 13953c60ba66SKatsushi Kobayashi for(dmach = 0 ; dmach < sc->fc.nisodma ; dmach++){ 13963c60ba66SKatsushi Kobayashi if( &sc->ir[dmach] == dbch){ 13973c60ba66SKatsushi Kobayashi off = OHCI_IROFF(dmach); 13983c60ba66SKatsushi Kobayashi break; 13993c60ba66SKatsushi Kobayashi } 14003c60ba66SKatsushi Kobayashi } 14013c60ba66SKatsushi Kobayashi } 1402a89ec05eSPeter Wemm if(off == 0){ 14033c60ba66SKatsushi Kobayashi err = EINVAL; 14043c60ba66SKatsushi Kobayashi return err; 14053c60ba66SKatsushi Kobayashi } 14063c60ba66SKatsushi Kobayashi if(dbch->xferq.flag & FWXFERQ_STREAM){ 14073c60ba66SKatsushi Kobayashi if(dbch->xferq.flag & FWXFERQ_RUNNING) 14083c60ba66SKatsushi Kobayashi return err; 14093c60ba66SKatsushi Kobayashi }else{ 14103c60ba66SKatsushi Kobayashi if(dbch->xferq.flag & FWXFERQ_RUNNING){ 14113c60ba66SKatsushi Kobayashi err = EBUSY; 14123c60ba66SKatsushi Kobayashi return err; 14133c60ba66SKatsushi Kobayashi } 14143c60ba66SKatsushi Kobayashi } 14153c60ba66SKatsushi Kobayashi dbch->xferq.flag |= FWXFERQ_RUNNING; 14169339321dSHidetoshi Shimokawa dbch->top = STAILQ_FIRST(&dbch->db_trq); 14173c60ba66SKatsushi Kobayashi for( i = 0, dbch->bottom = dbch->top; i < (dbch->ndb - 1); i++){ 14183c60ba66SKatsushi Kobayashi dbch->bottom = STAILQ_NEXT(dbch->bottom, link); 14193c60ba66SKatsushi Kobayashi } 14203c60ba66SKatsushi Kobayashi db_tr = dbch->top; 14213c60ba66SKatsushi Kobayashi for (idb = 0; idb < dbch->ndb; idb ++) { 142277ee030bSHidetoshi Shimokawa fwohci_add_rx_buf(dbch, db_tr, idb, &sc->dummy_dma); 142377ee030bSHidetoshi Shimokawa if (STAILQ_NEXT(db_tr, link) == NULL) 14243c60ba66SKatsushi Kobayashi break; 142553f1eb86SHidetoshi Shimokawa db = db_tr->db; 142653f1eb86SHidetoshi Shimokawa ldesc = db_tr->dbcnt - 1; 142777ee030bSHidetoshi Shimokawa FWOHCI_DMA_WRITE(db[ldesc].db.desc.depend, 142877ee030bSHidetoshi Shimokawa STAILQ_NEXT(db_tr, link)->bus_addr | z); 14293c60ba66SKatsushi Kobayashi if(dbch->xferq.flag & FWXFERQ_EXTBUF){ 14303c60ba66SKatsushi Kobayashi if(((idb + 1 ) % dbch->xferq.bnpacket) == 0){ 143177ee030bSHidetoshi Shimokawa FWOHCI_DMA_SET( 143277ee030bSHidetoshi Shimokawa db[ldesc].db.desc.cmd, 143377ee030bSHidetoshi Shimokawa OHCI_INTERRUPT_ALWAYS); 143477ee030bSHidetoshi Shimokawa FWOHCI_DMA_CLEAR( 143577ee030bSHidetoshi Shimokawa db[ldesc].db.desc.depend, 143677ee030bSHidetoshi Shimokawa 0xf); 14373c60ba66SKatsushi Kobayashi } 14383c60ba66SKatsushi Kobayashi } 14393c60ba66SKatsushi Kobayashi db_tr = STAILQ_NEXT(db_tr, link); 14403c60ba66SKatsushi Kobayashi } 144177ee030bSHidetoshi Shimokawa FWOHCI_DMA_CLEAR( 144277ee030bSHidetoshi Shimokawa dbch->bottom->db[db_tr->dbcnt - 1].db.desc.depend, 0xf); 14433c60ba66SKatsushi Kobayashi dbch->buf_offset = 0; 144477ee030bSHidetoshi Shimokawa fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREREAD); 144577ee030bSHidetoshi Shimokawa fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREWRITE); 14463c60ba66SKatsushi Kobayashi if(dbch->xferq.flag & FWXFERQ_STREAM){ 14473c60ba66SKatsushi Kobayashi return err; 14483c60ba66SKatsushi Kobayashi }else{ 144977ee030bSHidetoshi Shimokawa OWRITE(sc, OHCI_DMACMD(off), dbch->top->bus_addr | z); 14503c60ba66SKatsushi Kobayashi } 14513c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_RUN); 14523c60ba66SKatsushi Kobayashi return err; 14533c60ba66SKatsushi Kobayashi } 1454c572b810SHidetoshi Shimokawa 1455c572b810SHidetoshi Shimokawa static int 145677ee030bSHidetoshi Shimokawa fwohci_next_cycle(struct firewire_comm *fc, int cycle_now) 14573c60ba66SKatsushi Kobayashi { 14585a7ba74dSHidetoshi Shimokawa int sec, cycle, cycle_match; 14593c60ba66SKatsushi Kobayashi 146097ae6c1fSHidetoshi Shimokawa cycle = cycle_now & 0x1fff; 146197ae6c1fSHidetoshi Shimokawa sec = cycle_now >> 13; 146297ae6c1fSHidetoshi Shimokawa #define CYCLE_MOD 0x10 146377ee030bSHidetoshi Shimokawa #if 1 146497ae6c1fSHidetoshi Shimokawa #define CYCLE_DELAY 8 /* min delay to start DMA */ 146577ee030bSHidetoshi Shimokawa #else 146677ee030bSHidetoshi Shimokawa #define CYCLE_DELAY 7000 /* min delay to start DMA */ 146777ee030bSHidetoshi Shimokawa #endif 146897ae6c1fSHidetoshi Shimokawa cycle = cycle + CYCLE_DELAY; 146997ae6c1fSHidetoshi Shimokawa if (cycle >= 8000) { 147097ae6c1fSHidetoshi Shimokawa sec ++; 147197ae6c1fSHidetoshi Shimokawa cycle -= 8000; 147297ae6c1fSHidetoshi Shimokawa } 147377ee030bSHidetoshi Shimokawa cycle = roundup2(cycle, CYCLE_MOD); 147497ae6c1fSHidetoshi Shimokawa if (cycle >= 8000) { 147597ae6c1fSHidetoshi Shimokawa sec ++; 147697ae6c1fSHidetoshi Shimokawa if (cycle == 8000) 147797ae6c1fSHidetoshi Shimokawa cycle = 0; 147897ae6c1fSHidetoshi Shimokawa else 147997ae6c1fSHidetoshi Shimokawa cycle = CYCLE_MOD; 148097ae6c1fSHidetoshi Shimokawa } 148197ae6c1fSHidetoshi Shimokawa cycle_match = ((sec << 13) | cycle) & 0x7ffff; 14825a7ba74dSHidetoshi Shimokawa 14835a7ba74dSHidetoshi Shimokawa return(cycle_match); 14845a7ba74dSHidetoshi Shimokawa } 14855a7ba74dSHidetoshi Shimokawa 14865a7ba74dSHidetoshi Shimokawa static int 14875a7ba74dSHidetoshi Shimokawa fwohci_itxbuf_enable(struct firewire_comm *fc, int dmach) 14885a7ba74dSHidetoshi Shimokawa { 14895a7ba74dSHidetoshi Shimokawa struct fwohci_softc *sc = (struct fwohci_softc *)fc; 14905a7ba74dSHidetoshi Shimokawa int err = 0; 14915a7ba74dSHidetoshi Shimokawa unsigned short tag, ich; 14925a7ba74dSHidetoshi Shimokawa struct fwohci_dbch *dbch; 14935a7ba74dSHidetoshi Shimokawa int cycle_match, cycle_now, s, ldesc; 149403161bbcSDoug Rabson uint32_t stat; 14955a7ba74dSHidetoshi Shimokawa struct fw_bulkxfer *first, *chunk, *prev; 14965a7ba74dSHidetoshi Shimokawa struct fw_xferq *it; 14975a7ba74dSHidetoshi Shimokawa 14985a7ba74dSHidetoshi Shimokawa dbch = &sc->it[dmach]; 14995a7ba74dSHidetoshi Shimokawa it = &dbch->xferq; 15005a7ba74dSHidetoshi Shimokawa 15015a7ba74dSHidetoshi Shimokawa tag = (it->flag >> 6) & 3; 15025a7ba74dSHidetoshi Shimokawa ich = it->flag & 0x3f; 15035a7ba74dSHidetoshi Shimokawa if ((dbch->flags & FWOHCI_DBCH_INIT) == 0) { 15045a7ba74dSHidetoshi Shimokawa dbch->ndb = it->bnpacket * it->bnchunk; 15055a7ba74dSHidetoshi Shimokawa dbch->ndesc = 3; 150677ee030bSHidetoshi Shimokawa fwohci_db_init(sc, dbch); 15075a7ba74dSHidetoshi Shimokawa if ((dbch->flags & FWOHCI_DBCH_INIT) == 0) 15085a7ba74dSHidetoshi Shimokawa return ENOMEM; 15095a7ba74dSHidetoshi Shimokawa err = fwohci_tx_enable(sc, dbch); 15105a7ba74dSHidetoshi Shimokawa } 15115a7ba74dSHidetoshi Shimokawa if(err) 15125a7ba74dSHidetoshi Shimokawa return err; 15135a7ba74dSHidetoshi Shimokawa 151453f1eb86SHidetoshi Shimokawa ldesc = dbch->ndesc - 1; 15155a7ba74dSHidetoshi Shimokawa s = splfw(); 15165a7ba74dSHidetoshi Shimokawa prev = STAILQ_LAST(&it->stdma, fw_bulkxfer, link); 15175a7ba74dSHidetoshi Shimokawa while ((chunk = STAILQ_FIRST(&it->stvalid)) != NULL) { 1518c4778b5dSHidetoshi Shimokawa struct fwohcidb *db; 15195a7ba74dSHidetoshi Shimokawa 152077ee030bSHidetoshi Shimokawa fwdma_sync_multiseg(it->buf, chunk->poffset, it->bnpacket, 152177ee030bSHidetoshi Shimokawa BUS_DMASYNC_PREWRITE); 15225a7ba74dSHidetoshi Shimokawa fwohci_txbufdb(sc, dmach, chunk); 15235a7ba74dSHidetoshi Shimokawa if (prev != NULL) { 15245a7ba74dSHidetoshi Shimokawa db = ((struct fwohcidb_tr *)(prev->end))->db; 152577ee030bSHidetoshi Shimokawa #if 0 /* XXX necessary? */ 152677ee030bSHidetoshi Shimokawa FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, 152777ee030bSHidetoshi Shimokawa OHCI_BRANCH_ALWAYS); 152877ee030bSHidetoshi Shimokawa #endif 152953f1eb86SHidetoshi Shimokawa #if 0 /* if bulkxfer->npacket changes */ 15305a7ba74dSHidetoshi Shimokawa db[ldesc].db.desc.depend = db[0].db.desc.depend = 153177ee030bSHidetoshi Shimokawa ((struct fwohcidb_tr *) 153277ee030bSHidetoshi Shimokawa (chunk->start))->bus_addr | dbch->ndesc; 153353f1eb86SHidetoshi Shimokawa #else 153477ee030bSHidetoshi Shimokawa FWOHCI_DMA_SET(db[0].db.desc.depend, dbch->ndesc); 153577ee030bSHidetoshi Shimokawa FWOHCI_DMA_SET(db[ldesc].db.desc.depend, dbch->ndesc); 153653f1eb86SHidetoshi Shimokawa #endif 15375a7ba74dSHidetoshi Shimokawa } 15385a7ba74dSHidetoshi Shimokawa STAILQ_REMOVE_HEAD(&it->stvalid, link); 15395a7ba74dSHidetoshi Shimokawa STAILQ_INSERT_TAIL(&it->stdma, chunk, link); 15405a7ba74dSHidetoshi Shimokawa prev = chunk; 15415a7ba74dSHidetoshi Shimokawa } 154277ee030bSHidetoshi Shimokawa fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREWRITE); 154377ee030bSHidetoshi Shimokawa fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREREAD); 15445a7ba74dSHidetoshi Shimokawa splx(s); 15455a7ba74dSHidetoshi Shimokawa stat = OREAD(sc, OHCI_ITCTL(dmach)); 154677ee030bSHidetoshi Shimokawa if (firewire_debug && (stat & OHCI_CNTL_CYCMATCH_S)) 154777ee030bSHidetoshi Shimokawa printf("stat 0x%x\n", stat); 154877ee030bSHidetoshi Shimokawa 15495a7ba74dSHidetoshi Shimokawa if (stat & (OHCI_CNTL_DMA_ACTIVE | OHCI_CNTL_CYCMATCH_S)) 15505a7ba74dSHidetoshi Shimokawa return 0; 15515a7ba74dSHidetoshi Shimokawa 155277ee030bSHidetoshi Shimokawa #if 0 15535a7ba74dSHidetoshi Shimokawa OWRITE(sc, OHCI_ITCTLCLR(dmach), OHCI_CNTL_DMA_RUN); 155477ee030bSHidetoshi Shimokawa #endif 15555a7ba74dSHidetoshi Shimokawa OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach); 15565a7ba74dSHidetoshi Shimokawa OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach); 15575a7ba74dSHidetoshi Shimokawa OWRITE(sc, OHCI_IT_MASK, 1 << dmach); 155877ee030bSHidetoshi Shimokawa OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IT); 15595a7ba74dSHidetoshi Shimokawa 15605a7ba74dSHidetoshi Shimokawa first = STAILQ_FIRST(&it->stdma); 156177ee030bSHidetoshi Shimokawa OWRITE(sc, OHCI_ITCMD(dmach), 156277ee030bSHidetoshi Shimokawa ((struct fwohcidb_tr *)(first->start))->bus_addr | dbch->ndesc); 156377ee030bSHidetoshi Shimokawa if (firewire_debug) { 15645a7ba74dSHidetoshi Shimokawa printf("fwohci_itxbuf_enable: kick 0x%08x\n", stat); 156577ee030bSHidetoshi Shimokawa #if 1 156677ee030bSHidetoshi Shimokawa dump_dma(sc, ITX_CH + dmach); 156777ee030bSHidetoshi Shimokawa #endif 156877ee030bSHidetoshi Shimokawa } 15695a7ba74dSHidetoshi Shimokawa if ((stat & OHCI_CNTL_DMA_RUN) == 0) { 15705a7ba74dSHidetoshi Shimokawa #if 1 15715a7ba74dSHidetoshi Shimokawa /* Don't start until all chunks are buffered */ 15725a7ba74dSHidetoshi Shimokawa if (STAILQ_FIRST(&it->stfree) != NULL) 15735a7ba74dSHidetoshi Shimokawa goto out; 15745a7ba74dSHidetoshi Shimokawa #endif 157577ee030bSHidetoshi Shimokawa #if 1 157697ae6c1fSHidetoshi Shimokawa /* Clear cycle match counter bits */ 157797ae6c1fSHidetoshi Shimokawa OWRITE(sc, OHCI_ITCTLCLR(dmach), 0xffff0000); 15785a7ba74dSHidetoshi Shimokawa 15795a7ba74dSHidetoshi Shimokawa /* 2bit second + 13bit cycle */ 15805a7ba74dSHidetoshi Shimokawa cycle_now = (fc->cyctimer(fc) >> 12) & 0x7fff; 158177ee030bSHidetoshi Shimokawa cycle_match = fwohci_next_cycle(fc, cycle_now); 15825a7ba74dSHidetoshi Shimokawa 158397ae6c1fSHidetoshi Shimokawa OWRITE(sc, OHCI_ITCTL(dmach), 158497ae6c1fSHidetoshi Shimokawa OHCI_CNTL_CYCMATCH_S | (cycle_match << 16) 158597ae6c1fSHidetoshi Shimokawa | OHCI_CNTL_DMA_RUN); 158677ee030bSHidetoshi Shimokawa #else 158777ee030bSHidetoshi Shimokawa OWRITE(sc, OHCI_ITCTL(dmach), OHCI_CNTL_DMA_RUN); 158877ee030bSHidetoshi Shimokawa #endif 158977ee030bSHidetoshi Shimokawa if (firewire_debug) { 15907643dc18SHidetoshi Shimokawa printf("cycle_match: 0x%04x->0x%04x\n", 15917643dc18SHidetoshi Shimokawa cycle_now, cycle_match); 159277ee030bSHidetoshi Shimokawa dump_dma(sc, ITX_CH + dmach); 159377ee030bSHidetoshi Shimokawa dump_db(sc, ITX_CH + dmach); 159477ee030bSHidetoshi Shimokawa } 15957643dc18SHidetoshi Shimokawa } else if ((stat & OHCI_CNTL_CYCMATCH_S) == 0) { 15965a7ba74dSHidetoshi Shimokawa device_printf(sc->fc.dev, 15975a7ba74dSHidetoshi Shimokawa "IT DMA underrun (0x%08x)\n", stat); 159877ee030bSHidetoshi Shimokawa OWRITE(sc, OHCI_ITCTL(dmach), OHCI_CNTL_DMA_WAKE); 15993c60ba66SKatsushi Kobayashi } 16005a7ba74dSHidetoshi Shimokawa out: 16013c60ba66SKatsushi Kobayashi return err; 16023c60ba66SKatsushi Kobayashi } 1603c572b810SHidetoshi Shimokawa 1604c572b810SHidetoshi Shimokawa static int 160577ee030bSHidetoshi Shimokawa fwohci_irx_enable(struct firewire_comm *fc, int dmach) 16063c60ba66SKatsushi Kobayashi { 16073c60ba66SKatsushi Kobayashi struct fwohci_softc *sc = (struct fwohci_softc *)fc; 16085a7ba74dSHidetoshi Shimokawa int err = 0, s, ldesc; 16093c60ba66SKatsushi Kobayashi unsigned short tag, ich; 161003161bbcSDoug Rabson uint32_t stat; 16115a7ba74dSHidetoshi Shimokawa struct fwohci_dbch *dbch; 161277ee030bSHidetoshi Shimokawa struct fwohcidb_tr *db_tr; 16135a7ba74dSHidetoshi Shimokawa struct fw_bulkxfer *first, *prev, *chunk; 16145a7ba74dSHidetoshi Shimokawa struct fw_xferq *ir; 1615435dd29bSHidetoshi Shimokawa 16165a7ba74dSHidetoshi Shimokawa dbch = &sc->ir[dmach]; 16175a7ba74dSHidetoshi Shimokawa ir = &dbch->xferq; 16185a7ba74dSHidetoshi Shimokawa 16195a7ba74dSHidetoshi Shimokawa if ((ir->flag & FWXFERQ_RUNNING) == 0) { 16205a7ba74dSHidetoshi Shimokawa tag = (ir->flag >> 6) & 3; 16215a7ba74dSHidetoshi Shimokawa ich = ir->flag & 0x3f; 16223c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_IRMATCH(dmach), tagbit[tag] | ich); 16233c60ba66SKatsushi Kobayashi 16245a7ba74dSHidetoshi Shimokawa ir->queued = 0; 16255a7ba74dSHidetoshi Shimokawa dbch->ndb = ir->bnpacket * ir->bnchunk; 16265a7ba74dSHidetoshi Shimokawa dbch->ndesc = 2; 162777ee030bSHidetoshi Shimokawa fwohci_db_init(sc, dbch); 16285a7ba74dSHidetoshi Shimokawa if ((dbch->flags & FWOHCI_DBCH_INIT) == 0) 16290aaa9a23SHidetoshi Shimokawa return ENOMEM; 16305a7ba74dSHidetoshi Shimokawa err = fwohci_rx_enable(sc, dbch); 16313c60ba66SKatsushi Kobayashi } 16323c60ba66SKatsushi Kobayashi if(err) 16333c60ba66SKatsushi Kobayashi return err; 16343c60ba66SKatsushi Kobayashi 16355a7ba74dSHidetoshi Shimokawa first = STAILQ_FIRST(&ir->stfree); 16365a7ba74dSHidetoshi Shimokawa if (first == NULL) { 16375a7ba74dSHidetoshi Shimokawa device_printf(fc->dev, "IR DMA no free chunk\n"); 16385a7ba74dSHidetoshi Shimokawa return 0; 16395a7ba74dSHidetoshi Shimokawa } 16405a7ba74dSHidetoshi Shimokawa 16419ca8add3SHidetoshi Shimokawa ldesc = dbch->ndesc - 1; 16429ca8add3SHidetoshi Shimokawa s = splfw(); 16435a7ba74dSHidetoshi Shimokawa prev = STAILQ_LAST(&ir->stdma, fw_bulkxfer, link); 16445a7ba74dSHidetoshi Shimokawa while ((chunk = STAILQ_FIRST(&ir->stfree)) != NULL) { 1645c4778b5dSHidetoshi Shimokawa struct fwohcidb *db; 16465a7ba74dSHidetoshi Shimokawa 16472b4601d1SHidetoshi Shimokawa #if 1 /* XXX for if_fwe */ 164877ee030bSHidetoshi Shimokawa if (chunk->mbuf != NULL) { 164977ee030bSHidetoshi Shimokawa db_tr = (struct fwohcidb_tr *)(chunk->start); 165077ee030bSHidetoshi Shimokawa db_tr->dbcnt = 1; 165177ee030bSHidetoshi Shimokawa err = bus_dmamap_load_mbuf(dbch->dmat, db_tr->dma_map, 165277ee030bSHidetoshi Shimokawa chunk->mbuf, fwohci_execute_db2, db_tr, 165377ee030bSHidetoshi Shimokawa /* flags */0); 165477ee030bSHidetoshi Shimokawa FWOHCI_DMA_SET(db_tr->db[1].db.desc.cmd, 165577ee030bSHidetoshi Shimokawa OHCI_UPDATE | OHCI_INPUT_LAST | 165677ee030bSHidetoshi Shimokawa OHCI_INTERRUPT_ALWAYS | OHCI_BRANCH_ALWAYS); 165777ee030bSHidetoshi Shimokawa } 16582b4601d1SHidetoshi Shimokawa #endif 16595a7ba74dSHidetoshi Shimokawa db = ((struct fwohcidb_tr *)(chunk->end))->db; 166077ee030bSHidetoshi Shimokawa FWOHCI_DMA_WRITE(db[ldesc].db.desc.res, 0); 166177ee030bSHidetoshi Shimokawa FWOHCI_DMA_CLEAR(db[ldesc].db.desc.depend, 0xf); 16625a7ba74dSHidetoshi Shimokawa if (prev != NULL) { 16635a7ba74dSHidetoshi Shimokawa db = ((struct fwohcidb_tr *)(prev->end))->db; 166477ee030bSHidetoshi Shimokawa FWOHCI_DMA_SET(db[ldesc].db.desc.depend, dbch->ndesc); 16655a7ba74dSHidetoshi Shimokawa } 16665a7ba74dSHidetoshi Shimokawa STAILQ_REMOVE_HEAD(&ir->stfree, link); 16675a7ba74dSHidetoshi Shimokawa STAILQ_INSERT_TAIL(&ir->stdma, chunk, link); 16685a7ba74dSHidetoshi Shimokawa prev = chunk; 16695a7ba74dSHidetoshi Shimokawa } 167077ee030bSHidetoshi Shimokawa fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREWRITE); 167177ee030bSHidetoshi Shimokawa fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREREAD); 16725a7ba74dSHidetoshi Shimokawa splx(s); 16735a7ba74dSHidetoshi Shimokawa stat = OREAD(sc, OHCI_IRCTL(dmach)); 16745a7ba74dSHidetoshi Shimokawa if (stat & OHCI_CNTL_DMA_ACTIVE) 16755a7ba74dSHidetoshi Shimokawa return 0; 16765a7ba74dSHidetoshi Shimokawa if (stat & OHCI_CNTL_DMA_RUN) { 16773c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN); 16785a7ba74dSHidetoshi Shimokawa device_printf(sc->fc.dev, "IR DMA overrun (0x%08x)\n", stat); 16795a7ba74dSHidetoshi Shimokawa } 16805a7ba74dSHidetoshi Shimokawa 168177ee030bSHidetoshi Shimokawa if (firewire_debug) 168277ee030bSHidetoshi Shimokawa printf("start IR DMA 0x%x\n", stat); 16833c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach); 16843c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach); 16853c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_IR_MASK, 1 << dmach); 16863c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_IRCTLCLR(dmach), 0xf0000000); 16873c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_ISOHDR); 16883c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_IRCMD(dmach), 168977ee030bSHidetoshi Shimokawa ((struct fwohcidb_tr *)(first->start))->bus_addr 16905a7ba74dSHidetoshi Shimokawa | dbch->ndesc); 16913c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_DMA_RUN); 16923c60ba66SKatsushi Kobayashi OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IR); 169377ee030bSHidetoshi Shimokawa #if 0 169477ee030bSHidetoshi Shimokawa dump_db(sc, IRX_CH + dmach); 169577ee030bSHidetoshi Shimokawa #endif 16963c60ba66SKatsushi Kobayashi return err; 16973c60ba66SKatsushi Kobayashi } 1698c572b810SHidetoshi Shimokawa 1699c572b810SHidetoshi Shimokawa int 170064cf5240SHidetoshi Shimokawa fwohci_stop(struct fwohci_softc *sc, device_t dev) 17013c60ba66SKatsushi Kobayashi { 17023c60ba66SKatsushi Kobayashi u_int i; 17033c60ba66SKatsushi Kobayashi 17043c60ba66SKatsushi Kobayashi /* Now stopping all DMA channel */ 17053c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN); 17063c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN); 17073c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN); 17083c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN); 17093c60ba66SKatsushi Kobayashi 17103c60ba66SKatsushi Kobayashi for( i = 0 ; i < sc->fc.nisodma ; i ++ ){ 17113c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN); 17123c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN); 17133c60ba66SKatsushi Kobayashi } 17143c60ba66SKatsushi Kobayashi 17153c60ba66SKatsushi Kobayashi /* FLUSH FIFO and reset Transmitter/Reciever */ 17163c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_RESET); 17173c60ba66SKatsushi Kobayashi 17183c60ba66SKatsushi Kobayashi /* Stop interrupt */ 17193c60ba66SKatsushi Kobayashi OWRITE(sc, FWOHCI_INTMASKCLR, 17203c60ba66SKatsushi Kobayashi OHCI_INT_EN | OHCI_INT_ERR | OHCI_INT_PHY_SID 17213c60ba66SKatsushi Kobayashi | OHCI_INT_PHY_INT 17223c60ba66SKatsushi Kobayashi | OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS 17233c60ba66SKatsushi Kobayashi | OHCI_INT_DMA_PRRQ | OHCI_INT_DMA_PRRS 17243c60ba66SKatsushi Kobayashi | OHCI_INT_DMA_ARRQ | OHCI_INT_DMA_ARRS 17253c60ba66SKatsushi Kobayashi | OHCI_INT_PHY_BUS_R); 1726630529adSHidetoshi Shimokawa 172718349893SHidetoshi Shimokawa if (sc->fc.arq !=0 && sc->fc.arq->maxq > 0) 1728630529adSHidetoshi Shimokawa fw_drain_txq(&sc->fc); 1729630529adSHidetoshi Shimokawa 17309339321dSHidetoshi Shimokawa /* XXX Link down? Bus reset? */ 17319339321dSHidetoshi Shimokawa return 0; 17329339321dSHidetoshi Shimokawa } 17339339321dSHidetoshi Shimokawa 17349339321dSHidetoshi Shimokawa int 17359339321dSHidetoshi Shimokawa fwohci_resume(struct fwohci_softc *sc, device_t dev) 17369339321dSHidetoshi Shimokawa { 17379339321dSHidetoshi Shimokawa int i; 1738630529adSHidetoshi Shimokawa struct fw_xferq *ir; 1739630529adSHidetoshi Shimokawa struct fw_bulkxfer *chunk; 17409339321dSHidetoshi Shimokawa 17419339321dSHidetoshi Shimokawa fwohci_reset(sc, dev); 174295a24954SDoug Rabson /* XXX resume isochronous receive automatically. (how about TX?) */ 17439339321dSHidetoshi Shimokawa for(i = 0; i < sc->fc.nisodma; i ++) { 1744630529adSHidetoshi Shimokawa ir = &sc->ir[i].xferq; 1745630529adSHidetoshi Shimokawa if((ir->flag & FWXFERQ_RUNNING) != 0) { 17469339321dSHidetoshi Shimokawa device_printf(sc->fc.dev, 17479339321dSHidetoshi Shimokawa "resume iso receive ch: %d\n", i); 1748630529adSHidetoshi Shimokawa ir->flag &= ~FWXFERQ_RUNNING; 1749630529adSHidetoshi Shimokawa /* requeue stdma to stfree */ 1750630529adSHidetoshi Shimokawa while((chunk = STAILQ_FIRST(&ir->stdma)) != NULL) { 1751630529adSHidetoshi Shimokawa STAILQ_REMOVE_HEAD(&ir->stdma, link); 1752630529adSHidetoshi Shimokawa STAILQ_INSERT_TAIL(&ir->stfree, chunk, link); 1753630529adSHidetoshi Shimokawa } 17549339321dSHidetoshi Shimokawa sc->fc.irx_enable(&sc->fc, i); 17559339321dSHidetoshi Shimokawa } 17569339321dSHidetoshi Shimokawa } 17579339321dSHidetoshi Shimokawa 17589339321dSHidetoshi Shimokawa bus_generic_resume(dev); 17599339321dSHidetoshi Shimokawa sc->fc.ibr(&sc->fc); 17603c60ba66SKatsushi Kobayashi return 0; 17613c60ba66SKatsushi Kobayashi } 17623c60ba66SKatsushi Kobayashi 17633c60ba66SKatsushi Kobayashi #define ACK_ALL 17643c60ba66SKatsushi Kobayashi static void 176503161bbcSDoug Rabson fwohci_intr_body(struct fwohci_softc *sc, uint32_t stat, int count) 17663c60ba66SKatsushi Kobayashi { 176703161bbcSDoug Rabson uint32_t irstat, itstat; 17683c60ba66SKatsushi Kobayashi u_int i; 17693c60ba66SKatsushi Kobayashi struct firewire_comm *fc = (struct firewire_comm *)sc; 17703c60ba66SKatsushi Kobayashi 17713c60ba66SKatsushi Kobayashi #ifdef OHCI_DEBUG 17723c60ba66SKatsushi Kobayashi if(stat & OREAD(sc, FWOHCI_INTMASK)) 17733c60ba66SKatsushi Kobayashi 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", 17743c60ba66SKatsushi Kobayashi stat & OHCI_INT_EN ? "DMA_EN ":"", 17753c60ba66SKatsushi Kobayashi stat & OHCI_INT_PHY_REG ? "PHY_REG ":"", 17763c60ba66SKatsushi Kobayashi stat & OHCI_INT_CYC_LONG ? "CYC_LONG ":"", 17773c60ba66SKatsushi Kobayashi stat & OHCI_INT_ERR ? "INT_ERR ":"", 17783c60ba66SKatsushi Kobayashi stat & OHCI_INT_CYC_ERR ? "CYC_ERR ":"", 17793c60ba66SKatsushi Kobayashi stat & OHCI_INT_CYC_LOST ? "CYC_LOST ":"", 17803c60ba66SKatsushi Kobayashi stat & OHCI_INT_CYC_64SECOND ? "CYC_64SECOND ":"", 17813c60ba66SKatsushi Kobayashi stat & OHCI_INT_CYC_START ? "CYC_START ":"", 17823c60ba66SKatsushi Kobayashi stat & OHCI_INT_PHY_INT ? "PHY_INT ":"", 17833c60ba66SKatsushi Kobayashi stat & OHCI_INT_PHY_BUS_R ? "BUS_RESET ":"", 17843c60ba66SKatsushi Kobayashi stat & OHCI_INT_PHY_SID ? "SID ":"", 17853c60ba66SKatsushi Kobayashi stat & OHCI_INT_LR_ERR ? "DMA_LR_ERR ":"", 17863c60ba66SKatsushi Kobayashi stat & OHCI_INT_PW_ERR ? "DMA_PW_ERR ":"", 17873c60ba66SKatsushi Kobayashi stat & OHCI_INT_DMA_IR ? "DMA_IR ":"", 17883c60ba66SKatsushi Kobayashi stat & OHCI_INT_DMA_IT ? "DMA_IT " :"", 17893c60ba66SKatsushi Kobayashi stat & OHCI_INT_DMA_PRRS ? "DMA_PRRS " :"", 17903c60ba66SKatsushi Kobayashi stat & OHCI_INT_DMA_PRRQ ? "DMA_PRRQ " :"", 17913c60ba66SKatsushi Kobayashi stat & OHCI_INT_DMA_ARRS ? "DMA_ARRS " :"", 17923c60ba66SKatsushi Kobayashi stat & OHCI_INT_DMA_ARRQ ? "DMA_ARRQ " :"", 17933c60ba66SKatsushi Kobayashi stat & OHCI_INT_DMA_ATRS ? "DMA_ATRS " :"", 17943c60ba66SKatsushi Kobayashi stat & OHCI_INT_DMA_ATRQ ? "DMA_ATRQ " :"", 17953c60ba66SKatsushi Kobayashi stat, OREAD(sc, FWOHCI_INTMASK) 17963c60ba66SKatsushi Kobayashi ); 17973c60ba66SKatsushi Kobayashi #endif 17983c60ba66SKatsushi Kobayashi /* Bus reset */ 17993c60ba66SKatsushi Kobayashi if(stat & OHCI_INT_PHY_BUS_R ){ 18001adf6842SHidetoshi Shimokawa if (fc->status == FWBUSRESET) 18011adf6842SHidetoshi Shimokawa goto busresetout; 18021adf6842SHidetoshi Shimokawa /* Disable bus reset interrupt until sid recv. */ 18031adf6842SHidetoshi Shimokawa OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_PHY_BUS_R); 18041adf6842SHidetoshi Shimokawa 18053c60ba66SKatsushi Kobayashi device_printf(fc->dev, "BUS reset\n"); 18063c60ba66SKatsushi Kobayashi OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST); 18073c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCSRC); 18083c60ba66SKatsushi Kobayashi 18093c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN); 18103c60ba66SKatsushi Kobayashi sc->atrq.xferq.flag &= ~FWXFERQ_RUNNING; 18113c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN); 18123c60ba66SKatsushi Kobayashi sc->atrs.xferq.flag &= ~FWXFERQ_RUNNING; 18133c60ba66SKatsushi Kobayashi 18143c60ba66SKatsushi Kobayashi #ifndef ACK_ALL 18153c60ba66SKatsushi Kobayashi OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_BUS_R); 18163c60ba66SKatsushi Kobayashi #endif 1817627d85fbSHidetoshi Shimokawa fw_busreset(fc); 18180bc666e0SHidetoshi Shimokawa OWRITE(sc, OHCI_CROMHDR, ntohl(sc->fc.config_rom[0])); 18190bc666e0SHidetoshi Shimokawa OWRITE(sc, OHCI_BUS_OPT, ntohl(sc->fc.config_rom[2])); 18203c60ba66SKatsushi Kobayashi } 18211adf6842SHidetoshi Shimokawa busresetout: 18223c60ba66SKatsushi Kobayashi if((stat & OHCI_INT_DMA_IR )){ 18233c60ba66SKatsushi Kobayashi #ifndef ACK_ALL 18243c60ba66SKatsushi Kobayashi OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_IR); 18253c60ba66SKatsushi Kobayashi #endif 182610d3ed64SHidetoshi Shimokawa #if defined(__DragonFly__) || __FreeBSD_version < 500000 182777ee030bSHidetoshi Shimokawa irstat = sc->irstat; 182877ee030bSHidetoshi Shimokawa sc->irstat = 0; 182910d3ed64SHidetoshi Shimokawa #else 183010d3ed64SHidetoshi Shimokawa irstat = atomic_readandclear_int(&sc->irstat); 183177ee030bSHidetoshi Shimokawa #endif 18323c60ba66SKatsushi Kobayashi for(i = 0; i < fc->nisodma ; i++){ 1833b9b35d19SHidetoshi Shimokawa struct fwohci_dbch *dbch; 1834b9b35d19SHidetoshi Shimokawa 18353c60ba66SKatsushi Kobayashi if((irstat & (1 << i)) != 0){ 1836b9b35d19SHidetoshi Shimokawa dbch = &sc->ir[i]; 1837b9b35d19SHidetoshi Shimokawa if ((dbch->xferq.flag & FWXFERQ_OPEN) == 0) { 1838b9b35d19SHidetoshi Shimokawa device_printf(sc->fc.dev, 1839b9b35d19SHidetoshi Shimokawa "dma(%d) not active\n", i); 1840b9b35d19SHidetoshi Shimokawa continue; 1841b9b35d19SHidetoshi Shimokawa } 18423c60ba66SKatsushi Kobayashi fwohci_rbuf_update(sc, i); 18433c60ba66SKatsushi Kobayashi } 18443c60ba66SKatsushi Kobayashi } 18453c60ba66SKatsushi Kobayashi } 18463c60ba66SKatsushi Kobayashi if((stat & OHCI_INT_DMA_IT )){ 18473c60ba66SKatsushi Kobayashi #ifndef ACK_ALL 18483c60ba66SKatsushi Kobayashi OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_IT); 18493c60ba66SKatsushi Kobayashi #endif 185010d3ed64SHidetoshi Shimokawa #if defined(__DragonFly__) || __FreeBSD_version < 500000 185177ee030bSHidetoshi Shimokawa itstat = sc->itstat; 185277ee030bSHidetoshi Shimokawa sc->itstat = 0; 185310d3ed64SHidetoshi Shimokawa #else 185410d3ed64SHidetoshi Shimokawa itstat = atomic_readandclear_int(&sc->itstat); 185577ee030bSHidetoshi Shimokawa #endif 18563c60ba66SKatsushi Kobayashi for(i = 0; i < fc->nisodma ; i++){ 18573c60ba66SKatsushi Kobayashi if((itstat & (1 << i)) != 0){ 18583c60ba66SKatsushi Kobayashi fwohci_tbuf_update(sc, i); 18593c60ba66SKatsushi Kobayashi } 18603c60ba66SKatsushi Kobayashi } 18613c60ba66SKatsushi Kobayashi } 18623c60ba66SKatsushi Kobayashi if((stat & OHCI_INT_DMA_PRRS )){ 18633c60ba66SKatsushi Kobayashi #ifndef ACK_ALL 18643c60ba66SKatsushi Kobayashi OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_PRRS); 18653c60ba66SKatsushi Kobayashi #endif 18663c60ba66SKatsushi Kobayashi #if 0 18673c60ba66SKatsushi Kobayashi dump_dma(sc, ARRS_CH); 18683c60ba66SKatsushi Kobayashi dump_db(sc, ARRS_CH); 18693c60ba66SKatsushi Kobayashi #endif 1870783058faSHidetoshi Shimokawa fwohci_arcv(sc, &sc->arrs, count); 18713c60ba66SKatsushi Kobayashi } 18723c60ba66SKatsushi Kobayashi if((stat & OHCI_INT_DMA_PRRQ )){ 18733c60ba66SKatsushi Kobayashi #ifndef ACK_ALL 18743c60ba66SKatsushi Kobayashi OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_PRRQ); 18753c60ba66SKatsushi Kobayashi #endif 18763c60ba66SKatsushi Kobayashi #if 0 18773c60ba66SKatsushi Kobayashi dump_dma(sc, ARRQ_CH); 18783c60ba66SKatsushi Kobayashi dump_db(sc, ARRQ_CH); 18793c60ba66SKatsushi Kobayashi #endif 1880783058faSHidetoshi Shimokawa fwohci_arcv(sc, &sc->arrq, count); 18813c60ba66SKatsushi Kobayashi } 18823c60ba66SKatsushi Kobayashi if(stat & OHCI_INT_PHY_SID){ 188303161bbcSDoug Rabson uint32_t *buf, node_id; 18843c60ba66SKatsushi Kobayashi int plen; 18853c60ba66SKatsushi Kobayashi 18863c60ba66SKatsushi Kobayashi #ifndef ACK_ALL 18873c60ba66SKatsushi Kobayashi OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_SID); 18883c60ba66SKatsushi Kobayashi #endif 18891adf6842SHidetoshi Shimokawa /* Enable bus reset interrupt */ 18901adf6842SHidetoshi Shimokawa OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_PHY_BUS_R); 1891dcae7539SHidetoshi Shimokawa /* Allow async. request to us */ 1892dcae7539SHidetoshi Shimokawa OWRITE(sc, OHCI_AREQHI, 1 << 31); 1893dcae7539SHidetoshi Shimokawa /* XXX insecure ?? */ 1894dcae7539SHidetoshi Shimokawa OWRITE(sc, OHCI_PREQHI, 0x7fffffff); 1895dcae7539SHidetoshi Shimokawa OWRITE(sc, OHCI_PREQLO, 0xffffffff); 1896dcae7539SHidetoshi Shimokawa OWRITE(sc, OHCI_PREQUPPER, 0x10000); 189773aa55baSHidetoshi Shimokawa /* Set ATRetries register */ 189873aa55baSHidetoshi Shimokawa OWRITE(sc, OHCI_ATRETRY, 1<<(13+16) | 0xfff); 18993c60ba66SKatsushi Kobayashi /* 19003c60ba66SKatsushi Kobayashi ** Checking whether the node is root or not. If root, turn on 19013c60ba66SKatsushi Kobayashi ** cycle master. 19023c60ba66SKatsushi Kobayashi */ 190377ee030bSHidetoshi Shimokawa node_id = OREAD(sc, FWOHCI_NODEID); 190477ee030bSHidetoshi Shimokawa plen = OREAD(sc, OHCI_SID_CNT); 190577ee030bSHidetoshi Shimokawa 190677ee030bSHidetoshi Shimokawa device_printf(fc->dev, "node_id=0x%08x, gen=%d, ", 190777ee030bSHidetoshi Shimokawa node_id, (plen >> 16) & 0xff); 190877ee030bSHidetoshi Shimokawa if (!(node_id & OHCI_NODE_VALID)) { 19093c60ba66SKatsushi Kobayashi printf("Bus reset failure\n"); 19103c60ba66SKatsushi Kobayashi goto sidout; 19113c60ba66SKatsushi Kobayashi } 191277ee030bSHidetoshi Shimokawa if (node_id & OHCI_NODE_ROOT) { 19133c60ba66SKatsushi Kobayashi printf("CYCLEMASTER mode\n"); 19143c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_LNKCTL, 19153c60ba66SKatsushi Kobayashi OHCI_CNTL_CYCMTR | OHCI_CNTL_CYCTIMER); 19163c60ba66SKatsushi Kobayashi } else { 19173c60ba66SKatsushi Kobayashi printf("non CYCLEMASTER mode\n"); 19183c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCMTR); 19193c60ba66SKatsushi Kobayashi OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_CYCTIMER); 19203c60ba66SKatsushi Kobayashi } 192177ee030bSHidetoshi Shimokawa fc->nodeid = node_id & 0x3f; 19223c60ba66SKatsushi Kobayashi 192377ee030bSHidetoshi Shimokawa if (plen & OHCI_SID_ERR) { 192477ee030bSHidetoshi Shimokawa device_printf(fc->dev, "SID Error\n"); 192577ee030bSHidetoshi Shimokawa goto sidout; 192677ee030bSHidetoshi Shimokawa } 192777ee030bSHidetoshi Shimokawa plen &= OHCI_SID_CNT_MASK; 192816e0f484SHidetoshi Shimokawa if (plen < 4 || plen > OHCI_SIDSIZE) { 192916e0f484SHidetoshi Shimokawa device_printf(fc->dev, "invalid SID len = %d\n", plen); 193016e0f484SHidetoshi Shimokawa goto sidout; 193116e0f484SHidetoshi Shimokawa } 19323c60ba66SKatsushi Kobayashi plen -= 4; /* chop control info */ 193303161bbcSDoug Rabson buf = (uint32_t *)malloc(OHCI_SIDSIZE, M_FW, M_NOWAIT); 193477ee030bSHidetoshi Shimokawa if (buf == NULL) { 193577ee030bSHidetoshi Shimokawa device_printf(fc->dev, "malloc failed\n"); 193677ee030bSHidetoshi Shimokawa goto sidout; 193777ee030bSHidetoshi Shimokawa } 193877ee030bSHidetoshi Shimokawa for (i = 0; i < plen / 4; i ++) 193977ee030bSHidetoshi Shimokawa buf[i] = FWOHCI_DMA_READ(sc->sid_buf[i+1]); 194010d3ed64SHidetoshi Shimokawa #if 1 /* XXX needed?? */ 194148249fe0SHidetoshi Shimokawa /* pending all pre-bus_reset packets */ 194248249fe0SHidetoshi Shimokawa fwohci_txd(sc, &sc->atrq); 194348249fe0SHidetoshi Shimokawa fwohci_txd(sc, &sc->atrs); 194448249fe0SHidetoshi Shimokawa fwohci_arcv(sc, &sc->arrs, -1); 194548249fe0SHidetoshi Shimokawa fwohci_arcv(sc, &sc->arrq, -1); 1946627d85fbSHidetoshi Shimokawa fw_drain_txq(fc); 194748249fe0SHidetoshi Shimokawa #endif 194877ee030bSHidetoshi Shimokawa fw_sidrcv(fc, buf, plen); 194977ee030bSHidetoshi Shimokawa free(buf, M_FW); 19503c60ba66SKatsushi Kobayashi } 19513c60ba66SKatsushi Kobayashi sidout: 19523c60ba66SKatsushi Kobayashi if((stat & OHCI_INT_DMA_ATRQ )){ 19533c60ba66SKatsushi Kobayashi #ifndef ACK_ALL 19543c60ba66SKatsushi Kobayashi OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_ATRQ); 19553c60ba66SKatsushi Kobayashi #endif 19563c60ba66SKatsushi Kobayashi fwohci_txd(sc, &(sc->atrq)); 19573c60ba66SKatsushi Kobayashi } 19583c60ba66SKatsushi Kobayashi if((stat & OHCI_INT_DMA_ATRS )){ 19593c60ba66SKatsushi Kobayashi #ifndef ACK_ALL 19603c60ba66SKatsushi Kobayashi OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_ATRS); 19613c60ba66SKatsushi Kobayashi #endif 19623c60ba66SKatsushi Kobayashi fwohci_txd(sc, &(sc->atrs)); 19633c60ba66SKatsushi Kobayashi } 19643c60ba66SKatsushi Kobayashi if((stat & OHCI_INT_PW_ERR )){ 19653c60ba66SKatsushi Kobayashi #ifndef ACK_ALL 19663c60ba66SKatsushi Kobayashi OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PW_ERR); 19673c60ba66SKatsushi Kobayashi #endif 19683c60ba66SKatsushi Kobayashi device_printf(fc->dev, "posted write error\n"); 19693c60ba66SKatsushi Kobayashi } 19703c60ba66SKatsushi Kobayashi if((stat & OHCI_INT_ERR )){ 19713c60ba66SKatsushi Kobayashi #ifndef ACK_ALL 19723c60ba66SKatsushi Kobayashi OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_ERR); 19733c60ba66SKatsushi Kobayashi #endif 19743c60ba66SKatsushi Kobayashi device_printf(fc->dev, "unrecoverable error\n"); 19753c60ba66SKatsushi Kobayashi } 19763c60ba66SKatsushi Kobayashi if((stat & OHCI_INT_PHY_INT)) { 19773c60ba66SKatsushi Kobayashi #ifndef ACK_ALL 19783c60ba66SKatsushi Kobayashi OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_INT); 19793c60ba66SKatsushi Kobayashi #endif 19803c60ba66SKatsushi Kobayashi device_printf(fc->dev, "phy int\n"); 19813c60ba66SKatsushi Kobayashi } 19823c60ba66SKatsushi Kobayashi 19833c60ba66SKatsushi Kobayashi return; 19843c60ba66SKatsushi Kobayashi } 19853c60ba66SKatsushi Kobayashi 198677ee030bSHidetoshi Shimokawa #if FWOHCI_TASKQUEUE 198777ee030bSHidetoshi Shimokawa static void 198877ee030bSHidetoshi Shimokawa fwohci_complete(void *arg, int pending) 198977ee030bSHidetoshi Shimokawa { 199077ee030bSHidetoshi Shimokawa struct fwohci_softc *sc = (struct fwohci_softc *)arg; 199103161bbcSDoug Rabson uint32_t stat; 199277ee030bSHidetoshi Shimokawa 199377ee030bSHidetoshi Shimokawa again: 199477ee030bSHidetoshi Shimokawa stat = atomic_readandclear_int(&sc->intstat); 199577ee030bSHidetoshi Shimokawa if (stat) 199677ee030bSHidetoshi Shimokawa fwohci_intr_body(sc, stat, -1); 199777ee030bSHidetoshi Shimokawa else 199877ee030bSHidetoshi Shimokawa return; 199977ee030bSHidetoshi Shimokawa goto again; 200077ee030bSHidetoshi Shimokawa } 200177ee030bSHidetoshi Shimokawa #endif 200277ee030bSHidetoshi Shimokawa 200303161bbcSDoug Rabson static uint32_t 200477ee030bSHidetoshi Shimokawa fwochi_check_stat(struct fwohci_softc *sc) 200577ee030bSHidetoshi Shimokawa { 200603161bbcSDoug Rabson uint32_t stat, irstat, itstat; 200777ee030bSHidetoshi Shimokawa 200877ee030bSHidetoshi Shimokawa stat = OREAD(sc, FWOHCI_INTSTAT); 200977ee030bSHidetoshi Shimokawa if (stat == 0xffffffff) { 201077ee030bSHidetoshi Shimokawa device_printf(sc->fc.dev, 201177ee030bSHidetoshi Shimokawa "device physically ejected?\n"); 201277ee030bSHidetoshi Shimokawa return(stat); 201377ee030bSHidetoshi Shimokawa } 201477ee030bSHidetoshi Shimokawa #ifdef ACK_ALL 201577ee030bSHidetoshi Shimokawa if (stat) 201677ee030bSHidetoshi Shimokawa OWRITE(sc, FWOHCI_INTSTATCLR, stat); 201777ee030bSHidetoshi Shimokawa #endif 201877ee030bSHidetoshi Shimokawa if (stat & OHCI_INT_DMA_IR) { 201977ee030bSHidetoshi Shimokawa irstat = OREAD(sc, OHCI_IR_STAT); 202077ee030bSHidetoshi Shimokawa OWRITE(sc, OHCI_IR_STATCLR, irstat); 202177ee030bSHidetoshi Shimokawa atomic_set_int(&sc->irstat, irstat); 202277ee030bSHidetoshi Shimokawa } 202377ee030bSHidetoshi Shimokawa if (stat & OHCI_INT_DMA_IT) { 202477ee030bSHidetoshi Shimokawa itstat = OREAD(sc, OHCI_IT_STAT); 202577ee030bSHidetoshi Shimokawa OWRITE(sc, OHCI_IT_STATCLR, itstat); 202677ee030bSHidetoshi Shimokawa atomic_set_int(&sc->itstat, itstat); 202777ee030bSHidetoshi Shimokawa } 202877ee030bSHidetoshi Shimokawa return(stat); 202977ee030bSHidetoshi Shimokawa } 203077ee030bSHidetoshi Shimokawa 20313c60ba66SKatsushi Kobayashi void 20323c60ba66SKatsushi Kobayashi fwohci_intr(void *arg) 20333c60ba66SKatsushi Kobayashi { 20343c60ba66SKatsushi Kobayashi struct fwohci_softc *sc = (struct fwohci_softc *)arg; 203503161bbcSDoug Rabson uint32_t stat; 203677ee030bSHidetoshi Shimokawa #if !FWOHCI_TASKQUEUE 203703161bbcSDoug Rabson uint32_t bus_reset = 0; 203877ee030bSHidetoshi Shimokawa #endif 20393c60ba66SKatsushi Kobayashi 20403c60ba66SKatsushi Kobayashi if (!(sc->intmask & OHCI_INT_EN)) { 20413c60ba66SKatsushi Kobayashi /* polling mode */ 20423c60ba66SKatsushi Kobayashi return; 20433c60ba66SKatsushi Kobayashi } 20443c60ba66SKatsushi Kobayashi 204577ee030bSHidetoshi Shimokawa #if !FWOHCI_TASKQUEUE 204677ee030bSHidetoshi Shimokawa again: 20473c60ba66SKatsushi Kobayashi #endif 204877ee030bSHidetoshi Shimokawa stat = fwochi_check_stat(sc); 204977ee030bSHidetoshi Shimokawa if (stat == 0 || stat == 0xffffffff) 205077ee030bSHidetoshi Shimokawa return; 205177ee030bSHidetoshi Shimokawa #if FWOHCI_TASKQUEUE 205277ee030bSHidetoshi Shimokawa atomic_set_int(&sc->intstat, stat); 205377ee030bSHidetoshi Shimokawa /* XXX mask bus reset intr. during bus reset phase */ 205477ee030bSHidetoshi Shimokawa if (stat) 205577ee030bSHidetoshi Shimokawa taskqueue_enqueue(taskqueue_swi_giant, &sc->fwohci_task_complete); 205677ee030bSHidetoshi Shimokawa #else 20571adf6842SHidetoshi Shimokawa /* We cannot clear bus reset event during bus reset phase */ 20581adf6842SHidetoshi Shimokawa if ((stat & ~bus_reset) == 0) 20591adf6842SHidetoshi Shimokawa return; 20601adf6842SHidetoshi Shimokawa bus_reset = stat & OHCI_INT_PHY_BUS_R; 2061783058faSHidetoshi Shimokawa fwohci_intr_body(sc, stat, -1); 206277ee030bSHidetoshi Shimokawa goto again; 206377ee030bSHidetoshi Shimokawa #endif 20643c60ba66SKatsushi Kobayashi } 20653c60ba66SKatsushi Kobayashi 2066740b10aaSHidetoshi Shimokawa void 20673c60ba66SKatsushi Kobayashi fwohci_poll(struct firewire_comm *fc, int quick, int count) 20683c60ba66SKatsushi Kobayashi { 20693c60ba66SKatsushi Kobayashi int s; 207003161bbcSDoug Rabson uint32_t stat; 20713c60ba66SKatsushi Kobayashi struct fwohci_softc *sc; 20723c60ba66SKatsushi Kobayashi 20733c60ba66SKatsushi Kobayashi 20743c60ba66SKatsushi Kobayashi sc = (struct fwohci_softc *)fc; 20753c60ba66SKatsushi Kobayashi stat = OHCI_INT_DMA_IR | OHCI_INT_DMA_IT | 20763c60ba66SKatsushi Kobayashi OHCI_INT_DMA_PRRS | OHCI_INT_DMA_PRRQ | 20773c60ba66SKatsushi Kobayashi OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS; 20783c60ba66SKatsushi Kobayashi #if 0 20793c60ba66SKatsushi Kobayashi if (!quick) { 20803c60ba66SKatsushi Kobayashi #else 20813c60ba66SKatsushi Kobayashi if (1) { 20823c60ba66SKatsushi Kobayashi #endif 208377ee030bSHidetoshi Shimokawa stat = fwochi_check_stat(sc); 208477ee030bSHidetoshi Shimokawa if (stat == 0 || stat == 0xffffffff) 20853c60ba66SKatsushi Kobayashi return; 20863c60ba66SKatsushi Kobayashi } 20873c60ba66SKatsushi Kobayashi s = splfw(); 2088783058faSHidetoshi Shimokawa fwohci_intr_body(sc, stat, count); 20893c60ba66SKatsushi Kobayashi splx(s); 20903c60ba66SKatsushi Kobayashi } 20913c60ba66SKatsushi Kobayashi 20923c60ba66SKatsushi Kobayashi static void 20933c60ba66SKatsushi Kobayashi fwohci_set_intr(struct firewire_comm *fc, int enable) 20943c60ba66SKatsushi Kobayashi { 20953c60ba66SKatsushi Kobayashi struct fwohci_softc *sc; 20963c60ba66SKatsushi Kobayashi 20973c60ba66SKatsushi Kobayashi sc = (struct fwohci_softc *)fc; 209817c3d42cSHidetoshi Shimokawa if (bootverbose) 20999339321dSHidetoshi Shimokawa device_printf(sc->fc.dev, "fwohci_set_intr: %d\n", enable); 21003c60ba66SKatsushi Kobayashi if (enable) { 21013c60ba66SKatsushi Kobayashi sc->intmask |= OHCI_INT_EN; 21023c60ba66SKatsushi Kobayashi OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_EN); 21033c60ba66SKatsushi Kobayashi } else { 21043c60ba66SKatsushi Kobayashi sc->intmask &= ~OHCI_INT_EN; 21053c60ba66SKatsushi Kobayashi OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_EN); 21063c60ba66SKatsushi Kobayashi } 21073c60ba66SKatsushi Kobayashi } 21083c60ba66SKatsushi Kobayashi 2109c572b810SHidetoshi Shimokawa static void 2110c572b810SHidetoshi Shimokawa fwohci_tbuf_update(struct fwohci_softc *sc, int dmach) 21113c60ba66SKatsushi Kobayashi { 21123c60ba66SKatsushi Kobayashi struct firewire_comm *fc = &sc->fc; 2113c4778b5dSHidetoshi Shimokawa struct fwohcidb *db; 21145a7ba74dSHidetoshi Shimokawa struct fw_bulkxfer *chunk; 21155a7ba74dSHidetoshi Shimokawa struct fw_xferq *it; 211603161bbcSDoug Rabson uint32_t stat, count; 211777ee030bSHidetoshi Shimokawa int s, w=0, ldesc; 21183c60ba66SKatsushi Kobayashi 21195a7ba74dSHidetoshi Shimokawa it = fc->it[dmach]; 212077ee030bSHidetoshi Shimokawa ldesc = sc->it[dmach].ndesc - 1; 21215a7ba74dSHidetoshi Shimokawa s = splfw(); /* unnecessary ? */ 212277ee030bSHidetoshi Shimokawa fwdma_sync_multiseg_all(sc->it[dmach].am, BUS_DMASYNC_POSTREAD); 2123a1c9e73aSHidetoshi Shimokawa if (firewire_debug) 2124a1c9e73aSHidetoshi Shimokawa dump_db(sc, ITX_CH + dmach); 21255a7ba74dSHidetoshi Shimokawa while ((chunk = STAILQ_FIRST(&it->stdma)) != NULL) { 21265a7ba74dSHidetoshi Shimokawa db = ((struct fwohcidb_tr *)(chunk->end))->db; 212777ee030bSHidetoshi Shimokawa stat = FWOHCI_DMA_READ(db[ldesc].db.desc.res) 212877ee030bSHidetoshi Shimokawa >> OHCI_STATUS_SHIFT; 21295a7ba74dSHidetoshi Shimokawa db = ((struct fwohcidb_tr *)(chunk->start))->db; 2130a1c9e73aSHidetoshi Shimokawa /* timestamp */ 213177ee030bSHidetoshi Shimokawa count = FWOHCI_DMA_READ(db[ldesc].db.desc.res) 213277ee030bSHidetoshi Shimokawa & OHCI_COUNT_MASK; 21335a7ba74dSHidetoshi Shimokawa if (stat == 0) 21345a7ba74dSHidetoshi Shimokawa break; 21355a7ba74dSHidetoshi Shimokawa STAILQ_REMOVE_HEAD(&it->stdma, link); 21365a7ba74dSHidetoshi Shimokawa switch (stat & FWOHCIEV_MASK){ 21373c60ba66SKatsushi Kobayashi case FWOHCIEV_ACKCOMPL: 21385a7ba74dSHidetoshi Shimokawa #if 0 21395a7ba74dSHidetoshi Shimokawa device_printf(fc->dev, "0x%08x\n", count); 21400aaa9a23SHidetoshi Shimokawa #endif 21413c60ba66SKatsushi Kobayashi break; 21423c60ba66SKatsushi Kobayashi default: 21435a7ba74dSHidetoshi Shimokawa device_printf(fc->dev, 214477ee030bSHidetoshi Shimokawa "Isochronous transmit err %02x(%s)\n", 214577ee030bSHidetoshi Shimokawa stat, fwohcicode[stat & 0x1f]); 21463c60ba66SKatsushi Kobayashi } 21475a7ba74dSHidetoshi Shimokawa STAILQ_INSERT_TAIL(&it->stfree, chunk, link); 21485a7ba74dSHidetoshi Shimokawa w++; 21495a7ba74dSHidetoshi Shimokawa } 21505a7ba74dSHidetoshi Shimokawa splx(s); 21515a7ba74dSHidetoshi Shimokawa if (w) 21525a7ba74dSHidetoshi Shimokawa wakeup(it); 21533c60ba66SKatsushi Kobayashi } 2154c572b810SHidetoshi Shimokawa 2155c572b810SHidetoshi Shimokawa static void 2156c572b810SHidetoshi Shimokawa fwohci_rbuf_update(struct fwohci_softc *sc, int dmach) 21573c60ba66SKatsushi Kobayashi { 21580aaa9a23SHidetoshi Shimokawa struct firewire_comm *fc = &sc->fc; 2159c4778b5dSHidetoshi Shimokawa struct fwohcidb_tr *db_tr; 21605a7ba74dSHidetoshi Shimokawa struct fw_bulkxfer *chunk; 21615a7ba74dSHidetoshi Shimokawa struct fw_xferq *ir; 216203161bbcSDoug Rabson uint32_t stat; 216377ee030bSHidetoshi Shimokawa int s, w=0, ldesc; 21640aaa9a23SHidetoshi Shimokawa 21655a7ba74dSHidetoshi Shimokawa ir = fc->ir[dmach]; 216677ee030bSHidetoshi Shimokawa ldesc = sc->ir[dmach].ndesc - 1; 216777ee030bSHidetoshi Shimokawa #if 0 216877ee030bSHidetoshi Shimokawa dump_db(sc, dmach); 216977ee030bSHidetoshi Shimokawa #endif 21705a7ba74dSHidetoshi Shimokawa s = splfw(); 217177ee030bSHidetoshi Shimokawa fwdma_sync_multiseg_all(sc->ir[dmach].am, BUS_DMASYNC_POSTREAD); 21725a7ba74dSHidetoshi Shimokawa while ((chunk = STAILQ_FIRST(&ir->stdma)) != NULL) { 217377ee030bSHidetoshi Shimokawa db_tr = (struct fwohcidb_tr *)chunk->end; 217477ee030bSHidetoshi Shimokawa stat = FWOHCI_DMA_READ(db_tr->db[ldesc].db.desc.res) 217577ee030bSHidetoshi Shimokawa >> OHCI_STATUS_SHIFT; 21765a7ba74dSHidetoshi Shimokawa if (stat == 0) 21775a7ba74dSHidetoshi Shimokawa break; 217877ee030bSHidetoshi Shimokawa 217977ee030bSHidetoshi Shimokawa if (chunk->mbuf != NULL) { 218077ee030bSHidetoshi Shimokawa bus_dmamap_sync(sc->ir[dmach].dmat, db_tr->dma_map, 218177ee030bSHidetoshi Shimokawa BUS_DMASYNC_POSTREAD); 218277ee030bSHidetoshi Shimokawa bus_dmamap_unload(sc->ir[dmach].dmat, db_tr->dma_map); 218377ee030bSHidetoshi Shimokawa } else if (ir->buf != NULL) { 218477ee030bSHidetoshi Shimokawa fwdma_sync_multiseg(ir->buf, chunk->poffset, 218577ee030bSHidetoshi Shimokawa ir->bnpacket, BUS_DMASYNC_POSTREAD); 218677ee030bSHidetoshi Shimokawa } else { 218777ee030bSHidetoshi Shimokawa /* XXX */ 218877ee030bSHidetoshi Shimokawa printf("fwohci_rbuf_update: this shouldn't happend\n"); 218977ee030bSHidetoshi Shimokawa } 219077ee030bSHidetoshi Shimokawa 21915a7ba74dSHidetoshi Shimokawa STAILQ_REMOVE_HEAD(&ir->stdma, link); 21925a7ba74dSHidetoshi Shimokawa STAILQ_INSERT_TAIL(&ir->stvalid, chunk, link); 21935a7ba74dSHidetoshi Shimokawa switch (stat & FWOHCIEV_MASK) { 21943c60ba66SKatsushi Kobayashi case FWOHCIEV_ACKCOMPL: 21952b4601d1SHidetoshi Shimokawa chunk->resp = 0; 21963c60ba66SKatsushi Kobayashi break; 21973c60ba66SKatsushi Kobayashi default: 21982b4601d1SHidetoshi Shimokawa chunk->resp = EINVAL; 21995a7ba74dSHidetoshi Shimokawa device_printf(fc->dev, 220077ee030bSHidetoshi Shimokawa "Isochronous receive err %02x(%s)\n", 220177ee030bSHidetoshi Shimokawa stat, fwohcicode[stat & 0x1f]); 22023c60ba66SKatsushi Kobayashi } 22035a7ba74dSHidetoshi Shimokawa w++; 22045a7ba74dSHidetoshi Shimokawa } 22055a7ba74dSHidetoshi Shimokawa splx(s); 22062b4601d1SHidetoshi Shimokawa if (w) { 22072b4601d1SHidetoshi Shimokawa if (ir->flag & FWXFERQ_HANDLER) 22082b4601d1SHidetoshi Shimokawa ir->hand(ir); 22092b4601d1SHidetoshi Shimokawa else 22105a7ba74dSHidetoshi Shimokawa wakeup(ir); 22113c60ba66SKatsushi Kobayashi } 22122b4601d1SHidetoshi Shimokawa } 2213c572b810SHidetoshi Shimokawa 2214c572b810SHidetoshi Shimokawa void 221503161bbcSDoug Rabson dump_dma(struct fwohci_softc *sc, uint32_t ch) 2216c572b810SHidetoshi Shimokawa { 221703161bbcSDoug Rabson uint32_t off, cntl, stat, cmd, match; 22183c60ba66SKatsushi Kobayashi 22193c60ba66SKatsushi Kobayashi if(ch == 0){ 22203c60ba66SKatsushi Kobayashi off = OHCI_ATQOFF; 22213c60ba66SKatsushi Kobayashi }else if(ch == 1){ 22223c60ba66SKatsushi Kobayashi off = OHCI_ATSOFF; 22233c60ba66SKatsushi Kobayashi }else if(ch == 2){ 22243c60ba66SKatsushi Kobayashi off = OHCI_ARQOFF; 22253c60ba66SKatsushi Kobayashi }else if(ch == 3){ 22263c60ba66SKatsushi Kobayashi off = OHCI_ARSOFF; 22273c60ba66SKatsushi Kobayashi }else if(ch < IRX_CH){ 22283c60ba66SKatsushi Kobayashi off = OHCI_ITCTL(ch - ITX_CH); 22293c60ba66SKatsushi Kobayashi }else{ 22303c60ba66SKatsushi Kobayashi off = OHCI_IRCTL(ch - IRX_CH); 22313c60ba66SKatsushi Kobayashi } 22323c60ba66SKatsushi Kobayashi cntl = stat = OREAD(sc, off); 22333c60ba66SKatsushi Kobayashi cmd = OREAD(sc, off + 0xc); 22343c60ba66SKatsushi Kobayashi match = OREAD(sc, off + 0x10); 22353c60ba66SKatsushi Kobayashi 223677ee030bSHidetoshi Shimokawa device_printf(sc->fc.dev, "ch %1x cntl:0x%08x cmd:0x%08x match:0x%08x\n", 22373c60ba66SKatsushi Kobayashi ch, 22383c60ba66SKatsushi Kobayashi cntl, 22393c60ba66SKatsushi Kobayashi cmd, 22403c60ba66SKatsushi Kobayashi match); 22413c60ba66SKatsushi Kobayashi stat &= 0xffff ; 224277ee030bSHidetoshi Shimokawa if (stat) { 22433c60ba66SKatsushi Kobayashi device_printf(sc->fc.dev, "dma %d ch:%s%s%s%s%s%s %s(%x)\n", 22443c60ba66SKatsushi Kobayashi ch, 22453c60ba66SKatsushi Kobayashi stat & OHCI_CNTL_DMA_RUN ? "RUN," : "", 22463c60ba66SKatsushi Kobayashi stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "", 22473c60ba66SKatsushi Kobayashi stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "", 22483c60ba66SKatsushi Kobayashi stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "", 22493c60ba66SKatsushi Kobayashi stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "", 22503c60ba66SKatsushi Kobayashi stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "", 22513c60ba66SKatsushi Kobayashi fwohcicode[stat & 0x1f], 22523c60ba66SKatsushi Kobayashi stat & 0x1f 22533c60ba66SKatsushi Kobayashi ); 22543c60ba66SKatsushi Kobayashi }else{ 22553c60ba66SKatsushi Kobayashi device_printf(sc->fc.dev, "dma %d ch: Nostat\n", ch); 22563c60ba66SKatsushi Kobayashi } 22573c60ba66SKatsushi Kobayashi } 2258c572b810SHidetoshi Shimokawa 2259c572b810SHidetoshi Shimokawa void 226003161bbcSDoug Rabson dump_db(struct fwohci_softc *sc, uint32_t ch) 2261c572b810SHidetoshi Shimokawa { 22623c60ba66SKatsushi Kobayashi struct fwohci_dbch *dbch; 226377ee030bSHidetoshi Shimokawa struct fwohcidb_tr *cp = NULL, *pp, *np = NULL; 2264c4778b5dSHidetoshi Shimokawa struct fwohcidb *curr = NULL, *prev, *next = NULL; 22653c60ba66SKatsushi Kobayashi int idb, jdb; 226603161bbcSDoug Rabson uint32_t cmd, off; 22673c60ba66SKatsushi Kobayashi if(ch == 0){ 22683c60ba66SKatsushi Kobayashi off = OHCI_ATQOFF; 22693c60ba66SKatsushi Kobayashi dbch = &sc->atrq; 22703c60ba66SKatsushi Kobayashi }else if(ch == 1){ 22713c60ba66SKatsushi Kobayashi off = OHCI_ATSOFF; 22723c60ba66SKatsushi Kobayashi dbch = &sc->atrs; 22733c60ba66SKatsushi Kobayashi }else if(ch == 2){ 22743c60ba66SKatsushi Kobayashi off = OHCI_ARQOFF; 22753c60ba66SKatsushi Kobayashi dbch = &sc->arrq; 22763c60ba66SKatsushi Kobayashi }else if(ch == 3){ 22773c60ba66SKatsushi Kobayashi off = OHCI_ARSOFF; 22783c60ba66SKatsushi Kobayashi dbch = &sc->arrs; 22793c60ba66SKatsushi Kobayashi }else if(ch < IRX_CH){ 22803c60ba66SKatsushi Kobayashi off = OHCI_ITCTL(ch - ITX_CH); 22813c60ba66SKatsushi Kobayashi dbch = &sc->it[ch - ITX_CH]; 22823c60ba66SKatsushi Kobayashi }else { 22833c60ba66SKatsushi Kobayashi off = OHCI_IRCTL(ch - IRX_CH); 22843c60ba66SKatsushi Kobayashi dbch = &sc->ir[ch - IRX_CH]; 22853c60ba66SKatsushi Kobayashi } 22863c60ba66SKatsushi Kobayashi cmd = OREAD(sc, off + 0xc); 22873c60ba66SKatsushi Kobayashi 22883c60ba66SKatsushi Kobayashi if( dbch->ndb == 0 ){ 22893c60ba66SKatsushi Kobayashi device_printf(sc->fc.dev, "No DB is attached ch=%d\n", ch); 22903c60ba66SKatsushi Kobayashi return; 22913c60ba66SKatsushi Kobayashi } 22923c60ba66SKatsushi Kobayashi pp = dbch->top; 22933c60ba66SKatsushi Kobayashi prev = pp->db; 22943c60ba66SKatsushi Kobayashi for(idb = 0 ; idb < dbch->ndb ; idb ++ ){ 22953c60ba66SKatsushi Kobayashi if(pp == NULL){ 22963c60ba66SKatsushi Kobayashi curr = NULL; 22973c60ba66SKatsushi Kobayashi goto outdb; 22983c60ba66SKatsushi Kobayashi } 22993c60ba66SKatsushi Kobayashi cp = STAILQ_NEXT(pp, link); 23003c60ba66SKatsushi Kobayashi if(cp == NULL){ 23013c60ba66SKatsushi Kobayashi curr = NULL; 23023c60ba66SKatsushi Kobayashi goto outdb; 23033c60ba66SKatsushi Kobayashi } 23043c60ba66SKatsushi Kobayashi np = STAILQ_NEXT(cp, link); 23053c60ba66SKatsushi Kobayashi for(jdb = 0 ; jdb < dbch->ndesc ; jdb ++ ){ 230677ee030bSHidetoshi Shimokawa if ((cmd & 0xfffffff0) == cp->bus_addr) { 23073c60ba66SKatsushi Kobayashi curr = cp->db; 23083c60ba66SKatsushi Kobayashi if(np != NULL){ 23093c60ba66SKatsushi Kobayashi next = np->db; 23103c60ba66SKatsushi Kobayashi }else{ 23113c60ba66SKatsushi Kobayashi next = NULL; 23123c60ba66SKatsushi Kobayashi } 23133c60ba66SKatsushi Kobayashi goto outdb; 23143c60ba66SKatsushi Kobayashi } 23153c60ba66SKatsushi Kobayashi } 23163c60ba66SKatsushi Kobayashi pp = STAILQ_NEXT(pp, link); 23173c60ba66SKatsushi Kobayashi prev = pp->db; 23183c60ba66SKatsushi Kobayashi } 23193c60ba66SKatsushi Kobayashi outdb: 23203c60ba66SKatsushi Kobayashi if( curr != NULL){ 232177ee030bSHidetoshi Shimokawa #if 0 23223c60ba66SKatsushi Kobayashi printf("Prev DB %d\n", ch); 232377ee030bSHidetoshi Shimokawa print_db(pp, prev, ch, dbch->ndesc); 232477ee030bSHidetoshi Shimokawa #endif 23253c60ba66SKatsushi Kobayashi printf("Current DB %d\n", ch); 232677ee030bSHidetoshi Shimokawa print_db(cp, curr, ch, dbch->ndesc); 232777ee030bSHidetoshi Shimokawa #if 0 23283c60ba66SKatsushi Kobayashi printf("Next DB %d\n", ch); 232977ee030bSHidetoshi Shimokawa print_db(np, next, ch, dbch->ndesc); 233077ee030bSHidetoshi Shimokawa #endif 23313c60ba66SKatsushi Kobayashi }else{ 23323c60ba66SKatsushi Kobayashi printf("dbdump err ch = %d cmd = 0x%08x\n", ch, cmd); 23333c60ba66SKatsushi Kobayashi } 23343c60ba66SKatsushi Kobayashi return; 23353c60ba66SKatsushi Kobayashi } 2336c572b810SHidetoshi Shimokawa 2337c572b810SHidetoshi Shimokawa void 2338c4778b5dSHidetoshi Shimokawa print_db(struct fwohcidb_tr *db_tr, struct fwohcidb *db, 233903161bbcSDoug Rabson uint32_t ch, uint32_t max) 2340c572b810SHidetoshi Shimokawa { 23413c60ba66SKatsushi Kobayashi fwohcireg_t stat; 23423c60ba66SKatsushi Kobayashi int i, key; 234303161bbcSDoug Rabson uint32_t cmd, res; 23443c60ba66SKatsushi Kobayashi 23453c60ba66SKatsushi Kobayashi if(db == NULL){ 23463c60ba66SKatsushi Kobayashi printf("No Descriptor is found\n"); 23473c60ba66SKatsushi Kobayashi return; 23483c60ba66SKatsushi Kobayashi } 23493c60ba66SKatsushi Kobayashi 23503c60ba66SKatsushi Kobayashi printf("ch = %d\n%8s %s %s %s %s %4s %8s %8s %4s:%4s\n", 23513c60ba66SKatsushi Kobayashi ch, 23523c60ba66SKatsushi Kobayashi "Current", 23533c60ba66SKatsushi Kobayashi "OP ", 23543c60ba66SKatsushi Kobayashi "KEY", 23553c60ba66SKatsushi Kobayashi "INT", 23563c60ba66SKatsushi Kobayashi "BR ", 23573c60ba66SKatsushi Kobayashi "len", 23583c60ba66SKatsushi Kobayashi "Addr", 23593c60ba66SKatsushi Kobayashi "Depend", 23603c60ba66SKatsushi Kobayashi "Stat", 23613c60ba66SKatsushi Kobayashi "Cnt"); 23623c60ba66SKatsushi Kobayashi for( i = 0 ; i <= max ; i ++){ 236377ee030bSHidetoshi Shimokawa cmd = FWOHCI_DMA_READ(db[i].db.desc.cmd); 236477ee030bSHidetoshi Shimokawa res = FWOHCI_DMA_READ(db[i].db.desc.res); 236577ee030bSHidetoshi Shimokawa key = cmd & OHCI_KEY_MASK; 236677ee030bSHidetoshi Shimokawa stat = res >> OHCI_STATUS_SHIFT; 236710d3ed64SHidetoshi Shimokawa #if defined(__DragonFly__) || __FreeBSD_version < 500000 2368a4239576SHidetoshi Shimokawa printf("%08x %s %s %s %s %5d %08x %08x %04x:%04x", 236970b400a8SHidetoshi Shimokawa db_tr->bus_addr, 237010d3ed64SHidetoshi Shimokawa #else 237110d3ed64SHidetoshi Shimokawa printf("%08jx %s %s %s %s %5d %08x %08x %04x:%04x", 237210d3ed64SHidetoshi Shimokawa (uintmax_t)db_tr->bus_addr, 2373a4239576SHidetoshi Shimokawa #endif 237477ee030bSHidetoshi Shimokawa dbcode[(cmd >> 28) & 0xf], 237577ee030bSHidetoshi Shimokawa dbkey[(cmd >> 24) & 0x7], 237677ee030bSHidetoshi Shimokawa dbcond[(cmd >> 20) & 0x3], 237777ee030bSHidetoshi Shimokawa dbcond[(cmd >> 18) & 0x3], 237877ee030bSHidetoshi Shimokawa cmd & OHCI_COUNT_MASK, 237977ee030bSHidetoshi Shimokawa FWOHCI_DMA_READ(db[i].db.desc.addr), 238077ee030bSHidetoshi Shimokawa FWOHCI_DMA_READ(db[i].db.desc.depend), 238177ee030bSHidetoshi Shimokawa stat, 238277ee030bSHidetoshi Shimokawa res & OHCI_COUNT_MASK); 23833c60ba66SKatsushi Kobayashi if(stat & 0xff00){ 23843c60ba66SKatsushi Kobayashi printf(" %s%s%s%s%s%s %s(%x)\n", 23853c60ba66SKatsushi Kobayashi stat & OHCI_CNTL_DMA_RUN ? "RUN," : "", 23863c60ba66SKatsushi Kobayashi stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "", 23873c60ba66SKatsushi Kobayashi stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "", 23883c60ba66SKatsushi Kobayashi stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "", 23893c60ba66SKatsushi Kobayashi stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "", 23903c60ba66SKatsushi Kobayashi stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "", 23913c60ba66SKatsushi Kobayashi fwohcicode[stat & 0x1f], 23923c60ba66SKatsushi Kobayashi stat & 0x1f 23933c60ba66SKatsushi Kobayashi ); 23943c60ba66SKatsushi Kobayashi }else{ 23953c60ba66SKatsushi Kobayashi printf(" Nostat\n"); 23963c60ba66SKatsushi Kobayashi } 23973c60ba66SKatsushi Kobayashi if(key == OHCI_KEY_ST2 ){ 23983c60ba66SKatsushi Kobayashi printf("0x%08x 0x%08x 0x%08x 0x%08x\n", 239977ee030bSHidetoshi Shimokawa FWOHCI_DMA_READ(db[i+1].db.immed[0]), 240077ee030bSHidetoshi Shimokawa FWOHCI_DMA_READ(db[i+1].db.immed[1]), 240177ee030bSHidetoshi Shimokawa FWOHCI_DMA_READ(db[i+1].db.immed[2]), 240277ee030bSHidetoshi Shimokawa FWOHCI_DMA_READ(db[i+1].db.immed[3])); 24033c60ba66SKatsushi Kobayashi } 24043c60ba66SKatsushi Kobayashi if(key == OHCI_KEY_DEVICE){ 24053c60ba66SKatsushi Kobayashi return; 24063c60ba66SKatsushi Kobayashi } 240777ee030bSHidetoshi Shimokawa if((cmd & OHCI_BRANCH_MASK) 24083c60ba66SKatsushi Kobayashi == OHCI_BRANCH_ALWAYS){ 24093c60ba66SKatsushi Kobayashi return; 24103c60ba66SKatsushi Kobayashi } 241177ee030bSHidetoshi Shimokawa if((cmd & OHCI_CMD_MASK) 24123c60ba66SKatsushi Kobayashi == OHCI_OUTPUT_LAST){ 24133c60ba66SKatsushi Kobayashi return; 24143c60ba66SKatsushi Kobayashi } 241577ee030bSHidetoshi Shimokawa if((cmd & OHCI_CMD_MASK) 24163c60ba66SKatsushi Kobayashi == OHCI_INPUT_LAST){ 24173c60ba66SKatsushi Kobayashi return; 24183c60ba66SKatsushi Kobayashi } 24193c60ba66SKatsushi Kobayashi if(key == OHCI_KEY_ST2 ){ 24203c60ba66SKatsushi Kobayashi i++; 24213c60ba66SKatsushi Kobayashi } 24223c60ba66SKatsushi Kobayashi } 24233c60ba66SKatsushi Kobayashi return; 24243c60ba66SKatsushi Kobayashi } 2425c572b810SHidetoshi Shimokawa 2426c572b810SHidetoshi Shimokawa void 2427c572b810SHidetoshi Shimokawa fwohci_ibr(struct firewire_comm *fc) 24283c60ba66SKatsushi Kobayashi { 24293c60ba66SKatsushi Kobayashi struct fwohci_softc *sc; 243003161bbcSDoug Rabson uint32_t fun; 24313c60ba66SKatsushi Kobayashi 2432864d7e72SHidetoshi Shimokawa device_printf(fc->dev, "Initiate bus reset\n"); 24333c60ba66SKatsushi Kobayashi sc = (struct fwohci_softc *)fc; 2434ac9f6692SHidetoshi Shimokawa 2435ac9f6692SHidetoshi Shimokawa /* 2436ac9f6692SHidetoshi Shimokawa * Set root hold-off bit so that non cyclemaster capable node 2437ac9f6692SHidetoshi Shimokawa * shouldn't became the root node. 2438ac9f6692SHidetoshi Shimokawa */ 24393c60ba66SKatsushi Kobayashi #if 1 24403c60ba66SKatsushi Kobayashi fun = fwphy_rddata(sc, FW_PHY_IBR_REG); 24414ed65ce9SHidetoshi Shimokawa fun |= FW_PHY_IBR | FW_PHY_RHB; 24423c60ba66SKatsushi Kobayashi fun = fwphy_wrdata(sc, FW_PHY_IBR_REG, fun); 24434ed65ce9SHidetoshi Shimokawa #else /* Short bus reset */ 24443c60ba66SKatsushi Kobayashi fun = fwphy_rddata(sc, FW_PHY_ISBR_REG); 24454ed65ce9SHidetoshi Shimokawa fun |= FW_PHY_ISBR | FW_PHY_RHB; 24463c60ba66SKatsushi Kobayashi fun = fwphy_wrdata(sc, FW_PHY_ISBR_REG, fun); 24473c60ba66SKatsushi Kobayashi #endif 24483c60ba66SKatsushi Kobayashi } 2449c572b810SHidetoshi Shimokawa 2450c572b810SHidetoshi Shimokawa void 2451c572b810SHidetoshi Shimokawa fwohci_txbufdb(struct fwohci_softc *sc, int dmach, struct fw_bulkxfer *bulkxfer) 24523c60ba66SKatsushi Kobayashi { 24533c60ba66SKatsushi Kobayashi struct fwohcidb_tr *db_tr, *fdb_tr; 24543c60ba66SKatsushi Kobayashi struct fwohci_dbch *dbch; 2455c4778b5dSHidetoshi Shimokawa struct fwohcidb *db; 24563c60ba66SKatsushi Kobayashi struct fw_pkt *fp; 2457c4778b5dSHidetoshi Shimokawa struct fwohci_txpkthdr *ohcifp; 24583c60ba66SKatsushi Kobayashi unsigned short chtag; 24593c60ba66SKatsushi Kobayashi int idb; 24603c60ba66SKatsushi Kobayashi 24613c60ba66SKatsushi Kobayashi dbch = &sc->it[dmach]; 24623c60ba66SKatsushi Kobayashi chtag = sc->it[dmach].xferq.flag & 0xff; 24633c60ba66SKatsushi Kobayashi 24643c60ba66SKatsushi Kobayashi db_tr = (struct fwohcidb_tr *)(bulkxfer->start); 24653c60ba66SKatsushi Kobayashi fdb_tr = (struct fwohcidb_tr *)(bulkxfer->end); 24663c60ba66SKatsushi Kobayashi /* 246777ee030bSHidetoshi Shimokawa device_printf(sc->fc.dev, "DB %08x %08x %08x\n", bulkxfer, db_tr->bus_addr, fdb_tr->bus_addr); 24683c60ba66SKatsushi Kobayashi */ 246977ee030bSHidetoshi Shimokawa for (idb = 0; idb < dbch->xferq.bnpacket; idb ++) { 247053f1eb86SHidetoshi Shimokawa db = db_tr->db; 24713c60ba66SKatsushi Kobayashi fp = (struct fw_pkt *)db_tr->buf; 2472c4778b5dSHidetoshi Shimokawa ohcifp = (struct fwohci_txpkthdr *) db[1].db.immed; 247377ee030bSHidetoshi Shimokawa ohcifp->mode.ld[0] = fp->mode.ld[0]; 2474a1c9e73aSHidetoshi Shimokawa ohcifp->mode.common.spd = 0 & 0x7; 247577ee030bSHidetoshi Shimokawa ohcifp->mode.stream.len = fp->mode.stream.len; 24763c60ba66SKatsushi Kobayashi ohcifp->mode.stream.chtag = chtag; 24773c60ba66SKatsushi Kobayashi ohcifp->mode.stream.tcode = 0xa; 247877ee030bSHidetoshi Shimokawa #if BYTE_ORDER == BIG_ENDIAN 247977ee030bSHidetoshi Shimokawa FWOHCI_DMA_WRITE(db[1].db.immed[0], db[1].db.immed[0]); 248077ee030bSHidetoshi Shimokawa FWOHCI_DMA_WRITE(db[1].db.immed[1], db[1].db.immed[1]); 248177ee030bSHidetoshi Shimokawa #endif 24823c60ba66SKatsushi Kobayashi 248377ee030bSHidetoshi Shimokawa FWOHCI_DMA_CLEAR(db[2].db.desc.cmd, OHCI_COUNT_MASK); 248477ee030bSHidetoshi Shimokawa FWOHCI_DMA_SET(db[2].db.desc.cmd, fp->mode.stream.len); 248577ee030bSHidetoshi Shimokawa FWOHCI_DMA_WRITE(db[2].db.desc.res, 0); 248653f1eb86SHidetoshi Shimokawa #if 0 /* if bulkxfer->npackets changes */ 248777ee030bSHidetoshi Shimokawa db[2].db.desc.cmd = OHCI_OUTPUT_LAST 24883c60ba66SKatsushi Kobayashi | OHCI_UPDATE 248953f1eb86SHidetoshi Shimokawa | OHCI_BRANCH_ALWAYS; 249053f1eb86SHidetoshi Shimokawa db[0].db.desc.depend = 249153f1eb86SHidetoshi Shimokawa = db[dbch->ndesc - 1].db.desc.depend 249277ee030bSHidetoshi Shimokawa = STAILQ_NEXT(db_tr, link)->bus_addr | dbch->ndesc; 249353f1eb86SHidetoshi Shimokawa #else 249477ee030bSHidetoshi Shimokawa FWOHCI_DMA_SET(db[0].db.desc.depend, dbch->ndesc); 249577ee030bSHidetoshi Shimokawa FWOHCI_DMA_SET(db[dbch->ndesc - 1].db.desc.depend, dbch->ndesc); 249653f1eb86SHidetoshi Shimokawa #endif 24973c60ba66SKatsushi Kobayashi bulkxfer->end = (caddr_t)db_tr; 24983c60ba66SKatsushi Kobayashi db_tr = STAILQ_NEXT(db_tr, link); 24993c60ba66SKatsushi Kobayashi } 250053f1eb86SHidetoshi Shimokawa db = ((struct fwohcidb_tr *)bulkxfer->end)->db; 250177ee030bSHidetoshi Shimokawa FWOHCI_DMA_CLEAR(db[0].db.desc.depend, 0xf); 250277ee030bSHidetoshi Shimokawa FWOHCI_DMA_CLEAR(db[dbch->ndesc - 1].db.desc.depend, 0xf); 250353f1eb86SHidetoshi Shimokawa #if 0 /* if bulkxfer->npackets changes */ 250453f1eb86SHidetoshi Shimokawa db[dbch->ndesc - 1].db.desc.control |= OHCI_INTERRUPT_ALWAYS; 25054ed65ce9SHidetoshi Shimokawa /* OHCI 1.1 and above */ 250653f1eb86SHidetoshi Shimokawa db[0].db.desc.control |= OHCI_INTERRUPT_ALWAYS; 250753f1eb86SHidetoshi Shimokawa #endif 250853f1eb86SHidetoshi Shimokawa /* 25093c60ba66SKatsushi Kobayashi db_tr = (struct fwohcidb_tr *)bulkxfer->start; 25103c60ba66SKatsushi Kobayashi fdb_tr = (struct fwohcidb_tr *)bulkxfer->end; 251177ee030bSHidetoshi Shimokawa device_printf(sc->fc.dev, "DB %08x %3d %08x %08x\n", bulkxfer, bulkxfer->npacket, db_tr->bus_addr, fdb_tr->bus_addr); 25123c60ba66SKatsushi Kobayashi */ 25133c60ba66SKatsushi Kobayashi return; 25143c60ba66SKatsushi Kobayashi } 2515c572b810SHidetoshi Shimokawa 2516c572b810SHidetoshi Shimokawa static int 251777ee030bSHidetoshi Shimokawa fwohci_add_tx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr, 251877ee030bSHidetoshi Shimokawa int poffset) 25193c60ba66SKatsushi Kobayashi { 2520c4778b5dSHidetoshi Shimokawa struct fwohcidb *db = db_tr->db; 252177ee030bSHidetoshi Shimokawa struct fw_xferq *it; 25223c60ba66SKatsushi Kobayashi int err = 0; 252377ee030bSHidetoshi Shimokawa 252477ee030bSHidetoshi Shimokawa it = &dbch->xferq; 252577ee030bSHidetoshi Shimokawa if(it->buf == 0){ 25263c60ba66SKatsushi Kobayashi err = EINVAL; 25273c60ba66SKatsushi Kobayashi return err; 25283c60ba66SKatsushi Kobayashi } 252977ee030bSHidetoshi Shimokawa db_tr->buf = fwdma_v_addr(it->buf, poffset); 25303c60ba66SKatsushi Kobayashi db_tr->dbcnt = 3; 25313c60ba66SKatsushi Kobayashi 253277ee030bSHidetoshi Shimokawa FWOHCI_DMA_WRITE(db[0].db.desc.cmd, 253377ee030bSHidetoshi Shimokawa OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | 8); 2534a1c9e73aSHidetoshi Shimokawa FWOHCI_DMA_WRITE(db[0].db.desc.addr, 0); 2535c4778b5dSHidetoshi Shimokawa bzero((void *)&db[1].db.immed[0], sizeof(db[1].db.immed)); 253677ee030bSHidetoshi Shimokawa FWOHCI_DMA_WRITE(db[2].db.desc.addr, 253703161bbcSDoug Rabson fwdma_bus_addr(it->buf, poffset) + sizeof(uint32_t)); 253877ee030bSHidetoshi Shimokawa 253977ee030bSHidetoshi Shimokawa FWOHCI_DMA_WRITE(db[2].db.desc.cmd, 254077ee030bSHidetoshi Shimokawa OHCI_OUTPUT_LAST | OHCI_UPDATE | OHCI_BRANCH_ALWAYS); 254153f1eb86SHidetoshi Shimokawa #if 1 254277ee030bSHidetoshi Shimokawa FWOHCI_DMA_WRITE(db[0].db.desc.res, 0); 254377ee030bSHidetoshi Shimokawa FWOHCI_DMA_WRITE(db[2].db.desc.res, 0); 254453f1eb86SHidetoshi Shimokawa #endif 254577ee030bSHidetoshi Shimokawa return 0; 25463c60ba66SKatsushi Kobayashi } 2547c572b810SHidetoshi Shimokawa 2548c572b810SHidetoshi Shimokawa int 254977ee030bSHidetoshi Shimokawa fwohci_add_rx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr, 255077ee030bSHidetoshi Shimokawa int poffset, struct fwdma_alloc *dummy_dma) 25513c60ba66SKatsushi Kobayashi { 2552c4778b5dSHidetoshi Shimokawa struct fwohcidb *db = db_tr->db; 255377ee030bSHidetoshi Shimokawa struct fw_xferq *ir; 255477ee030bSHidetoshi Shimokawa int i, ldesc; 255577ee030bSHidetoshi Shimokawa bus_addr_t dbuf[2]; 25563c60ba66SKatsushi Kobayashi int dsiz[2]; 25573c60ba66SKatsushi Kobayashi 255877ee030bSHidetoshi Shimokawa ir = &dbch->xferq; 255977ee030bSHidetoshi Shimokawa if (ir->buf == NULL && (dbch->xferq.flag & FWXFERQ_EXTBUF) == 0) { 256077ee030bSHidetoshi Shimokawa db_tr->buf = fwdma_malloc_size(dbch->dmat, &db_tr->dma_map, 256177ee030bSHidetoshi Shimokawa ir->psize, &dbuf[0], BUS_DMA_NOWAIT); 256277ee030bSHidetoshi Shimokawa if (db_tr->buf == NULL) 256377ee030bSHidetoshi Shimokawa return(ENOMEM); 25643c60ba66SKatsushi Kobayashi db_tr->dbcnt = 1; 256577ee030bSHidetoshi Shimokawa dsiz[0] = ir->psize; 256677ee030bSHidetoshi Shimokawa bus_dmamap_sync(dbch->dmat, db_tr->dma_map, 256777ee030bSHidetoshi Shimokawa BUS_DMASYNC_PREREAD); 25683c60ba66SKatsushi Kobayashi } else { 256977ee030bSHidetoshi Shimokawa db_tr->dbcnt = 0; 257077ee030bSHidetoshi Shimokawa if (dummy_dma != NULL) { 257103161bbcSDoug Rabson dsiz[db_tr->dbcnt] = sizeof(uint32_t); 257277ee030bSHidetoshi Shimokawa dbuf[db_tr->dbcnt++] = dummy_dma->bus_addr; 257377ee030bSHidetoshi Shimokawa } 257477ee030bSHidetoshi Shimokawa dsiz[db_tr->dbcnt] = ir->psize; 257577ee030bSHidetoshi Shimokawa if (ir->buf != NULL) { 257677ee030bSHidetoshi Shimokawa db_tr->buf = fwdma_v_addr(ir->buf, poffset); 257777ee030bSHidetoshi Shimokawa dbuf[db_tr->dbcnt] = fwdma_bus_addr( ir->buf, poffset); 257877ee030bSHidetoshi Shimokawa } 257977ee030bSHidetoshi Shimokawa db_tr->dbcnt++; 25803c60ba66SKatsushi Kobayashi } 25813c60ba66SKatsushi Kobayashi for(i = 0 ; i < db_tr->dbcnt ; i++){ 258277ee030bSHidetoshi Shimokawa FWOHCI_DMA_WRITE(db[i].db.desc.addr, dbuf[i]); 258377ee030bSHidetoshi Shimokawa FWOHCI_DMA_WRITE(db[i].db.desc.cmd, OHCI_INPUT_MORE | dsiz[i]); 258477ee030bSHidetoshi Shimokawa if (ir->flag & FWXFERQ_STREAM) { 258577ee030bSHidetoshi Shimokawa FWOHCI_DMA_SET(db[i].db.desc.cmd, OHCI_UPDATE); 25863c60ba66SKatsushi Kobayashi } 258777ee030bSHidetoshi Shimokawa FWOHCI_DMA_WRITE(db[i].db.desc.res, dsiz[i]); 25883c60ba66SKatsushi Kobayashi } 258977ee030bSHidetoshi Shimokawa ldesc = db_tr->dbcnt - 1; 259077ee030bSHidetoshi Shimokawa if (ir->flag & FWXFERQ_STREAM) { 259177ee030bSHidetoshi Shimokawa FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, OHCI_INPUT_LAST); 25923c60ba66SKatsushi Kobayashi } 259377ee030bSHidetoshi Shimokawa FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, OHCI_BRANCH_ALWAYS); 259477ee030bSHidetoshi Shimokawa return 0; 25953c60ba66SKatsushi Kobayashi } 2596c572b810SHidetoshi Shimokawa 259777ee030bSHidetoshi Shimokawa 259877ee030bSHidetoshi Shimokawa static int 259977ee030bSHidetoshi Shimokawa fwohci_arcv_swap(struct fw_pkt *fp, int len) 26003c60ba66SKatsushi Kobayashi { 260177ee030bSHidetoshi Shimokawa struct fw_pkt *fp0; 260203161bbcSDoug Rabson uint32_t ld0; 2603c4778b5dSHidetoshi Shimokawa int slen, hlen; 260477ee030bSHidetoshi Shimokawa #if BYTE_ORDER == BIG_ENDIAN 260577ee030bSHidetoshi Shimokawa int i; 260677ee030bSHidetoshi Shimokawa #endif 26073c60ba66SKatsushi Kobayashi 260877ee030bSHidetoshi Shimokawa ld0 = FWOHCI_DMA_READ(fp->mode.ld[0]); 260977ee030bSHidetoshi Shimokawa #if 0 261077ee030bSHidetoshi Shimokawa printf("ld0: x%08x\n", ld0); 261177ee030bSHidetoshi Shimokawa #endif 261277ee030bSHidetoshi Shimokawa fp0 = (struct fw_pkt *)&ld0; 2613c4778b5dSHidetoshi Shimokawa /* determine length to swap */ 261477ee030bSHidetoshi Shimokawa switch (fp0->mode.common.tcode) { 261577ee030bSHidetoshi Shimokawa case FWTCODE_RREQQ: 261677ee030bSHidetoshi Shimokawa case FWTCODE_WRES: 261777ee030bSHidetoshi Shimokawa case FWTCODE_WREQQ: 261877ee030bSHidetoshi Shimokawa case FWTCODE_RRESQ: 261977ee030bSHidetoshi Shimokawa case FWOHCITCODE_PHY: 262077ee030bSHidetoshi Shimokawa slen = 12; 26213c60ba66SKatsushi Kobayashi break; 262277ee030bSHidetoshi Shimokawa case FWTCODE_RREQB: 262377ee030bSHidetoshi Shimokawa case FWTCODE_WREQB: 262477ee030bSHidetoshi Shimokawa case FWTCODE_LREQ: 262577ee030bSHidetoshi Shimokawa case FWTCODE_RRESB: 262677ee030bSHidetoshi Shimokawa case FWTCODE_LRES: 262777ee030bSHidetoshi Shimokawa slen = 16; 26283c60ba66SKatsushi Kobayashi break; 26293c60ba66SKatsushi Kobayashi default: 263077ee030bSHidetoshi Shimokawa printf("Unknown tcode %d\n", fp0->mode.common.tcode); 263177ee030bSHidetoshi Shimokawa return(0); 26323c60ba66SKatsushi Kobayashi } 2633c4778b5dSHidetoshi Shimokawa hlen = tinfo[fp0->mode.common.tcode].hdr_len; 2634c4778b5dSHidetoshi Shimokawa if (hlen > len) { 263577ee030bSHidetoshi Shimokawa if (firewire_debug) 263677ee030bSHidetoshi Shimokawa printf("splitted header\n"); 2637c4778b5dSHidetoshi Shimokawa return(-hlen); 26383c60ba66SKatsushi Kobayashi } 263977ee030bSHidetoshi Shimokawa #if BYTE_ORDER == BIG_ENDIAN 264077ee030bSHidetoshi Shimokawa for(i = 0; i < slen/4; i ++) 264177ee030bSHidetoshi Shimokawa fp->mode.ld[i] = FWOHCI_DMA_READ(fp->mode.ld[i]); 264277ee030bSHidetoshi Shimokawa #endif 2643c4778b5dSHidetoshi Shimokawa return(hlen); 26443c60ba66SKatsushi Kobayashi } 26453c60ba66SKatsushi Kobayashi 26463c60ba66SKatsushi Kobayashi static int 264777ee030bSHidetoshi Shimokawa fwohci_get_plen(struct fwohci_softc *sc, struct fwohci_dbch *dbch, struct fw_pkt *fp) 26483c60ba66SKatsushi Kobayashi { 2649c4778b5dSHidetoshi Shimokawa struct tcode_info *info; 265077ee030bSHidetoshi Shimokawa int r; 26513c60ba66SKatsushi Kobayashi 2652c4778b5dSHidetoshi Shimokawa info = &tinfo[fp->mode.common.tcode]; 265303161bbcSDoug Rabson r = info->hdr_len + sizeof(uint32_t); 2654c4778b5dSHidetoshi Shimokawa if ((info->flag & FWTI_BLOCK_ASY) != 0) 265503161bbcSDoug Rabson r += roundup2(fp->mode.wreqb.len, sizeof(uint32_t)); 2656c4778b5dSHidetoshi Shimokawa 265703161bbcSDoug Rabson if (r == sizeof(uint32_t)) 2658c4778b5dSHidetoshi Shimokawa /* XXX */ 2659627d85fbSHidetoshi Shimokawa device_printf(sc->fc.dev, "Unknown tcode %d\n", 2660627d85fbSHidetoshi Shimokawa fp->mode.common.tcode); 2661c4778b5dSHidetoshi Shimokawa 2662627d85fbSHidetoshi Shimokawa if (r > dbch->xferq.psize) { 2663627d85fbSHidetoshi Shimokawa device_printf(sc->fc.dev, "Invalid packet length %d\n", r); 2664627d85fbSHidetoshi Shimokawa /* panic ? */ 2665627d85fbSHidetoshi Shimokawa } 2666c4778b5dSHidetoshi Shimokawa 2667627d85fbSHidetoshi Shimokawa return r; 26683c60ba66SKatsushi Kobayashi } 26693c60ba66SKatsushi Kobayashi 2670c572b810SHidetoshi Shimokawa static void 267177ee030bSHidetoshi Shimokawa fwohci_arcv_free_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr) 267277ee030bSHidetoshi Shimokawa { 2673c4778b5dSHidetoshi Shimokawa struct fwohcidb *db = &db_tr->db[0]; 267477ee030bSHidetoshi Shimokawa 267577ee030bSHidetoshi Shimokawa FWOHCI_DMA_CLEAR(db->db.desc.depend, 0xf); 267677ee030bSHidetoshi Shimokawa FWOHCI_DMA_WRITE(db->db.desc.res, dbch->xferq.psize); 267777ee030bSHidetoshi Shimokawa FWOHCI_DMA_SET(dbch->bottom->db[0].db.desc.depend, 1); 267877ee030bSHidetoshi Shimokawa fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREWRITE); 267977ee030bSHidetoshi Shimokawa dbch->bottom = db_tr; 268077ee030bSHidetoshi Shimokawa } 268177ee030bSHidetoshi Shimokawa 268277ee030bSHidetoshi Shimokawa static void 2683c572b810SHidetoshi Shimokawa fwohci_arcv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count) 26843c60ba66SKatsushi Kobayashi { 26853c60ba66SKatsushi Kobayashi struct fwohcidb_tr *db_tr; 268677ee030bSHidetoshi Shimokawa struct iovec vec[2]; 268777ee030bSHidetoshi Shimokawa struct fw_pkt pktbuf; 268877ee030bSHidetoshi Shimokawa int nvec; 26893c60ba66SKatsushi Kobayashi struct fw_pkt *fp; 269003161bbcSDoug Rabson uint8_t *ld; 269103161bbcSDoug Rabson uint32_t stat, off, status; 26923c60ba66SKatsushi Kobayashi u_int spd; 269377ee030bSHidetoshi Shimokawa int len, plen, hlen, pcnt, offset; 26943c60ba66SKatsushi Kobayashi int s; 26953c60ba66SKatsushi Kobayashi caddr_t buf; 26963c60ba66SKatsushi Kobayashi int resCount; 26973c60ba66SKatsushi Kobayashi 26983c60ba66SKatsushi Kobayashi if(&sc->arrq == dbch){ 26993c60ba66SKatsushi Kobayashi off = OHCI_ARQOFF; 27003c60ba66SKatsushi Kobayashi }else if(&sc->arrs == dbch){ 27013c60ba66SKatsushi Kobayashi off = OHCI_ARSOFF; 27023c60ba66SKatsushi Kobayashi }else{ 27033c60ba66SKatsushi Kobayashi return; 27043c60ba66SKatsushi Kobayashi } 27053c60ba66SKatsushi Kobayashi 27063c60ba66SKatsushi Kobayashi s = splfw(); 27073c60ba66SKatsushi Kobayashi db_tr = dbch->top; 27083c60ba66SKatsushi Kobayashi pcnt = 0; 27093c60ba66SKatsushi Kobayashi /* XXX we cannot handle a packet which lies in more than two buf */ 271077ee030bSHidetoshi Shimokawa fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_POSTREAD); 271177ee030bSHidetoshi Shimokawa fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_POSTWRITE); 271277ee030bSHidetoshi Shimokawa status = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) >> OHCI_STATUS_SHIFT; 271377ee030bSHidetoshi Shimokawa resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) & OHCI_COUNT_MASK; 271477ee030bSHidetoshi Shimokawa #if 0 271577ee030bSHidetoshi Shimokawa printf("status 0x%04x, resCount 0x%04x\n", status, resCount); 271677ee030bSHidetoshi Shimokawa #endif 271777ee030bSHidetoshi Shimokawa while (status & OHCI_CNTL_DMA_ACTIVE) { 271877ee030bSHidetoshi Shimokawa len = dbch->xferq.psize - resCount; 271903161bbcSDoug Rabson ld = (uint8_t *)db_tr->buf; 272077ee030bSHidetoshi Shimokawa if (dbch->pdb_tr == NULL) { 272177ee030bSHidetoshi Shimokawa len -= dbch->buf_offset; 272277ee030bSHidetoshi Shimokawa ld += dbch->buf_offset; 272377ee030bSHidetoshi Shimokawa } 272477ee030bSHidetoshi Shimokawa if (len > 0) 272577ee030bSHidetoshi Shimokawa bus_dmamap_sync(dbch->dmat, db_tr->dma_map, 272677ee030bSHidetoshi Shimokawa BUS_DMASYNC_POSTREAD); 27273c60ba66SKatsushi Kobayashi while (len > 0 ) { 2728783058faSHidetoshi Shimokawa if (count >= 0 && count-- == 0) 2729783058faSHidetoshi Shimokawa goto out; 273077ee030bSHidetoshi Shimokawa if(dbch->pdb_tr != NULL){ 273177ee030bSHidetoshi Shimokawa /* we have a fragment in previous buffer */ 273277ee030bSHidetoshi Shimokawa int rlen; 27333c60ba66SKatsushi Kobayashi 273477ee030bSHidetoshi Shimokawa offset = dbch->buf_offset; 273577ee030bSHidetoshi Shimokawa if (offset < 0) 273677ee030bSHidetoshi Shimokawa offset = - offset; 273777ee030bSHidetoshi Shimokawa buf = dbch->pdb_tr->buf + offset; 273877ee030bSHidetoshi Shimokawa rlen = dbch->xferq.psize - offset; 273977ee030bSHidetoshi Shimokawa if (firewire_debug) 274077ee030bSHidetoshi Shimokawa printf("rlen=%d, offset=%d\n", 274177ee030bSHidetoshi Shimokawa rlen, dbch->buf_offset); 274277ee030bSHidetoshi Shimokawa if (dbch->buf_offset < 0) { 274377ee030bSHidetoshi Shimokawa /* splitted in header, pull up */ 274477ee030bSHidetoshi Shimokawa char *p; 274577ee030bSHidetoshi Shimokawa 274677ee030bSHidetoshi Shimokawa p = (char *)&pktbuf; 274777ee030bSHidetoshi Shimokawa bcopy(buf, p, rlen); 274877ee030bSHidetoshi Shimokawa p += rlen; 274977ee030bSHidetoshi Shimokawa /* this must be too long but harmless */ 275077ee030bSHidetoshi Shimokawa rlen = sizeof(pktbuf) - rlen; 275177ee030bSHidetoshi Shimokawa if (rlen < 0) 275277ee030bSHidetoshi Shimokawa printf("why rlen < 0\n"); 275377ee030bSHidetoshi Shimokawa bcopy(db_tr->buf, p, rlen); 27543c60ba66SKatsushi Kobayashi ld += rlen; 27553c60ba66SKatsushi Kobayashi len -= rlen; 275677ee030bSHidetoshi Shimokawa hlen = fwohci_arcv_swap(&pktbuf, sizeof(pktbuf)); 275777ee030bSHidetoshi Shimokawa if (hlen < 0) { 275877ee030bSHidetoshi Shimokawa printf("hlen < 0 shouldn't happen"); 27593c60ba66SKatsushi Kobayashi } 276077ee030bSHidetoshi Shimokawa offset = sizeof(pktbuf); 276177ee030bSHidetoshi Shimokawa vec[0].iov_base = (char *)&pktbuf; 276277ee030bSHidetoshi Shimokawa vec[0].iov_len = offset; 27633c60ba66SKatsushi Kobayashi } else { 276477ee030bSHidetoshi Shimokawa /* splitted in payload */ 276577ee030bSHidetoshi Shimokawa offset = rlen; 276677ee030bSHidetoshi Shimokawa vec[0].iov_base = buf; 276777ee030bSHidetoshi Shimokawa vec[0].iov_len = rlen; 276877ee030bSHidetoshi Shimokawa } 276977ee030bSHidetoshi Shimokawa fp=(struct fw_pkt *)vec[0].iov_base; 277077ee030bSHidetoshi Shimokawa nvec = 1; 277177ee030bSHidetoshi Shimokawa } else { 277277ee030bSHidetoshi Shimokawa /* no fragment in previous buffer */ 27733c60ba66SKatsushi Kobayashi fp=(struct fw_pkt *)ld; 277477ee030bSHidetoshi Shimokawa hlen = fwohci_arcv_swap(fp, len); 277577ee030bSHidetoshi Shimokawa if (hlen == 0) 277677ee030bSHidetoshi Shimokawa /* XXX need reset */ 277777ee030bSHidetoshi Shimokawa goto out; 277877ee030bSHidetoshi Shimokawa if (hlen < 0) { 277977ee030bSHidetoshi Shimokawa dbch->pdb_tr = db_tr; 278077ee030bSHidetoshi Shimokawa dbch->buf_offset = - dbch->buf_offset; 278177ee030bSHidetoshi Shimokawa /* sanity check */ 278277ee030bSHidetoshi Shimokawa if (resCount != 0) 27835b50d9adSHidetoshi Shimokawa printf("resCount = %d !?\n", 27845b50d9adSHidetoshi Shimokawa resCount); 27855b50d9adSHidetoshi Shimokawa /* XXX clear pdb_tr */ 27863c60ba66SKatsushi Kobayashi goto out; 27873c60ba66SKatsushi Kobayashi } 278877ee030bSHidetoshi Shimokawa offset = 0; 278977ee030bSHidetoshi Shimokawa nvec = 0; 27903c60ba66SKatsushi Kobayashi } 279177ee030bSHidetoshi Shimokawa plen = fwohci_get_plen(sc, dbch, fp) - offset; 27923c60ba66SKatsushi Kobayashi if (plen < 0) { 279377ee030bSHidetoshi Shimokawa /* minimum header size + trailer 279477ee030bSHidetoshi Shimokawa = sizeof(fw_pkt) so this shouldn't happens */ 2795c4778b5dSHidetoshi Shimokawa printf("plen(%d) is negative! offset=%d\n", 2796c4778b5dSHidetoshi Shimokawa plen, offset); 27975b50d9adSHidetoshi Shimokawa /* XXX clear pdb_tr */ 279877ee030bSHidetoshi Shimokawa goto out; 27993c60ba66SKatsushi Kobayashi } 280077ee030bSHidetoshi Shimokawa if (plen > 0) { 280177ee030bSHidetoshi Shimokawa len -= plen; 280277ee030bSHidetoshi Shimokawa if (len < 0) { 280377ee030bSHidetoshi Shimokawa dbch->pdb_tr = db_tr; 280477ee030bSHidetoshi Shimokawa if (firewire_debug) 280577ee030bSHidetoshi Shimokawa printf("splitted payload\n"); 280677ee030bSHidetoshi Shimokawa /* sanity check */ 280777ee030bSHidetoshi Shimokawa if (resCount != 0) 28085b50d9adSHidetoshi Shimokawa printf("resCount = %d !?\n", 28095b50d9adSHidetoshi Shimokawa resCount); 28105b50d9adSHidetoshi Shimokawa /* XXX clear pdb_tr */ 281177ee030bSHidetoshi Shimokawa goto out; 28123c60ba66SKatsushi Kobayashi } 281377ee030bSHidetoshi Shimokawa vec[nvec].iov_base = ld; 281477ee030bSHidetoshi Shimokawa vec[nvec].iov_len = plen; 281577ee030bSHidetoshi Shimokawa nvec ++; 28163c60ba66SKatsushi Kobayashi ld += plen; 28173c60ba66SKatsushi Kobayashi } 281803161bbcSDoug Rabson dbch->buf_offset = ld - (uint8_t *)db_tr->buf; 281977ee030bSHidetoshi Shimokawa if (nvec == 0) 282077ee030bSHidetoshi Shimokawa printf("nvec == 0\n"); 282177ee030bSHidetoshi Shimokawa 28223c60ba66SKatsushi Kobayashi /* DMA result-code will be written at the tail of packet */ 282377ee030bSHidetoshi Shimokawa #if BYTE_ORDER == BIG_ENDIAN 282477ee030bSHidetoshi Shimokawa stat = FWOHCI_DMA_READ(((struct fwohci_trailer *)(ld - sizeof(struct fwohci_trailer)))->stat) >> 16; 282577ee030bSHidetoshi Shimokawa #else 28263c60ba66SKatsushi Kobayashi stat = ((struct fwohci_trailer *)(ld - sizeof(struct fwohci_trailer)))->stat; 282777ee030bSHidetoshi Shimokawa #endif 282877ee030bSHidetoshi Shimokawa #if 0 2829c4778b5dSHidetoshi Shimokawa printf("plen: %d, stat %x\n", 2830c4778b5dSHidetoshi Shimokawa plen ,stat); 283177ee030bSHidetoshi Shimokawa #endif 28323c60ba66SKatsushi Kobayashi spd = (stat >> 5) & 0x3; 28333c60ba66SKatsushi Kobayashi stat &= 0x1f; 28343c60ba66SKatsushi Kobayashi switch(stat){ 28353c60ba66SKatsushi Kobayashi case FWOHCIEV_ACKPEND: 2836864d7e72SHidetoshi Shimokawa #if 0 283773aa55baSHidetoshi Shimokawa printf("fwohci_arcv: ack pending tcode=0x%x..\n", fp->mode.common.tcode); 28383c60ba66SKatsushi Kobayashi #endif 28393c60ba66SKatsushi Kobayashi /* fall through */ 28403c60ba66SKatsushi Kobayashi case FWOHCIEV_ACKCOMPL: 2841c4778b5dSHidetoshi Shimokawa { 2842c4778b5dSHidetoshi Shimokawa struct fw_rcv_buf rb; 2843c4778b5dSHidetoshi Shimokawa 284477ee030bSHidetoshi Shimokawa if ((vec[nvec-1].iov_len -= 284577ee030bSHidetoshi Shimokawa sizeof(struct fwohci_trailer)) == 0) 284677ee030bSHidetoshi Shimokawa nvec--; 2847c4778b5dSHidetoshi Shimokawa rb.fc = &sc->fc; 2848c4778b5dSHidetoshi Shimokawa rb.vec = vec; 2849c4778b5dSHidetoshi Shimokawa rb.nvec = nvec; 2850c4778b5dSHidetoshi Shimokawa rb.spd = spd; 2851c4778b5dSHidetoshi Shimokawa fw_rcv(&rb); 28523c60ba66SKatsushi Kobayashi break; 2853c4778b5dSHidetoshi Shimokawa } 28543c60ba66SKatsushi Kobayashi case FWOHCIEV_BUSRST: 28553c60ba66SKatsushi Kobayashi if (sc->fc.status != FWBUSRESET) 28563c60ba66SKatsushi Kobayashi printf("got BUSRST packet!?\n"); 28573c60ba66SKatsushi Kobayashi break; 28583c60ba66SKatsushi Kobayashi default: 28593c60ba66SKatsushi Kobayashi device_printf(sc->fc.dev, "Async DMA Receive error err = %02x %s\n", stat, fwohcicode[stat]); 28603c60ba66SKatsushi Kobayashi #if 0 /* XXX */ 28613c60ba66SKatsushi Kobayashi goto out; 28623c60ba66SKatsushi Kobayashi #endif 28633c60ba66SKatsushi Kobayashi break; 28643c60ba66SKatsushi Kobayashi } 28653c60ba66SKatsushi Kobayashi pcnt ++; 286677ee030bSHidetoshi Shimokawa if (dbch->pdb_tr != NULL) { 286777ee030bSHidetoshi Shimokawa fwohci_arcv_free_buf(dbch, dbch->pdb_tr); 286877ee030bSHidetoshi Shimokawa dbch->pdb_tr = NULL; 286977ee030bSHidetoshi Shimokawa } 287077ee030bSHidetoshi Shimokawa 287177ee030bSHidetoshi Shimokawa } 28723c60ba66SKatsushi Kobayashi out: 28733c60ba66SKatsushi Kobayashi if (resCount == 0) { 28743c60ba66SKatsushi Kobayashi /* done on this buffer */ 287577ee030bSHidetoshi Shimokawa if (dbch->pdb_tr == NULL) { 287677ee030bSHidetoshi Shimokawa fwohci_arcv_free_buf(dbch, db_tr); 28773c60ba66SKatsushi Kobayashi dbch->buf_offset = 0; 287877ee030bSHidetoshi Shimokawa } else 287977ee030bSHidetoshi Shimokawa if (dbch->pdb_tr != db_tr) 288077ee030bSHidetoshi Shimokawa printf("pdb_tr != db_tr\n"); 288177ee030bSHidetoshi Shimokawa db_tr = STAILQ_NEXT(db_tr, link); 288277ee030bSHidetoshi Shimokawa status = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) 288377ee030bSHidetoshi Shimokawa >> OHCI_STATUS_SHIFT; 288477ee030bSHidetoshi Shimokawa resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) 288577ee030bSHidetoshi Shimokawa & OHCI_COUNT_MASK; 288677ee030bSHidetoshi Shimokawa /* XXX check buffer overrun */ 288777ee030bSHidetoshi Shimokawa dbch->top = db_tr; 28883c60ba66SKatsushi Kobayashi } else { 28893c60ba66SKatsushi Kobayashi dbch->buf_offset = dbch->xferq.psize - resCount; 28903c60ba66SKatsushi Kobayashi break; 28913c60ba66SKatsushi Kobayashi } 28923c60ba66SKatsushi Kobayashi /* XXX make sure DMA is not dead */ 28933c60ba66SKatsushi Kobayashi } 28943c60ba66SKatsushi Kobayashi #if 0 28953c60ba66SKatsushi Kobayashi if (pcnt < 1) 28963c60ba66SKatsushi Kobayashi printf("fwohci_arcv: no packets\n"); 28973c60ba66SKatsushi Kobayashi #endif 28983c60ba66SKatsushi Kobayashi splx(s); 28993c60ba66SKatsushi Kobayashi } 2900