fwohci.c revision 108527
11541Srgrimes/* 21541Srgrimes * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa 31541Srgrimes * All rights reserved. 41541Srgrimes * 51541Srgrimes * Redistribution and use in source and binary forms, with or without 61541Srgrimes * modification, are permitted provided that the following conditions 71541Srgrimes * are met: 81541Srgrimes * 1. Redistributions of source code must retain the above copyright 91541Srgrimes * notice, this list of conditions and the following disclaimer. 101541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111541Srgrimes * notice, this list of conditions and the following disclaimer in the 121541Srgrimes * documentation and/or other materials provided with the distribution. 131541Srgrimes * 3. All advertising materials mentioning features or use of this software 141541Srgrimes * must display the acknowledgement as bellow: 151541Srgrimes * 161541Srgrimes * This product includes software developed by K. Kobayashi and H. Shimokawa 171541Srgrimes * 181541Srgrimes * 4. The name of the author may not be used to endorse or promote products 191541Srgrimes * derived from this software without specific prior written permission. 201541Srgrimes * 211541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 221541Srgrimes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 231541Srgrimes * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 241541Srgrimes * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 251541Srgrimes * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 261541Srgrimes * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 271541Srgrimes * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 291541Srgrimes * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 301541Srgrimes * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 311541Srgrimes * POSSIBILITY OF SUCH DAMAGE. 321541Srgrimes * 331541Srgrimes * $FreeBSD: head/sys/dev/firewire/fwohci.c 108527 2003-01-01 04:23:54Z simokawa $ 341541Srgrimes * 351541Srgrimes */ 3636503Speter 3736503Speter#define ATRQ_CH 0 381541Srgrimes#define ATRS_CH 1 391541Srgrimes#define ARRQ_CH 2 401541Srgrimes#define ARRS_CH 3 419336Sdfr#define ITX_CH 4 421541Srgrimes#define IRX_CH 0x24 431541Srgrimes 441541Srgrimes#include <sys/param.h> 451541Srgrimes#include <sys/systm.h> 461541Srgrimes#include <sys/types.h> 471541Srgrimes#include <sys/mbuf.h> 481541Srgrimes#include <sys/mman.h> 491541Srgrimes#include <sys/socket.h> 501541Srgrimes#include <sys/socketvar.h> 511541Srgrimes#include <sys/signalvar.h> 521541Srgrimes#include <sys/malloc.h> 531541Srgrimes#include <sys/uio.h> 541541Srgrimes#include <sys/sockio.h> 551541Srgrimes#include <sys/bus.h> 569336Sdfr#include <sys/kernel.h> 579336Sdfr#include <sys/conf.h> 581541Srgrimes 591541Srgrimes#include <machine/bus.h> 601541Srgrimes#include <machine/resource.h> 611541Srgrimes#include <sys/rman.h> 621541Srgrimes 631541Srgrimes#include <machine/cpufunc.h> /* for rdtsc proto for clock.h below */ 6418020Sbde#include <machine/clock.h> 651541Srgrimes#include <pci/pcivar.h> 661541Srgrimes#include <pci/pcireg.h> 679336Sdfr#include <vm/vm.h> 689336Sdfr#include <vm/vm_extern.h> 6929024Sbde#include <vm/pmap.h> /* for vtophys proto */ 701541Srgrimes 711541Srgrimes#include <dev/firewire/firewire.h> 721541Srgrimes#include <dev/firewire/firewirebusreg.h> 739336Sdfr#include <dev/firewire/firewirereg.h> 7412911Sphk#include <dev/firewire/fwohcireg.h> 751541Srgrimes#include <dev/firewire/fwohcivar.h> 761541Srgrimes#include <dev/firewire/firewire_phy.h> 7712662Sdg 7832011Sbde#undef OHCI_DEBUG 7932937Sdyson 801541Srgrimesstatic char dbcode[16][0x10]={"OUTM", "OUTL","INPM","INPL", 819336Sdfr "STOR","LOAD","NOP ","STOP",}; 821541Srgrimesstatic char dbkey[8][0x10]={"ST0", "ST1","ST2","ST3", 831541Srgrimes "UNDEF","REG","SYS","DEV"}; 841541Srgrimeschar fwohcicode[32][0x20]={ 851541Srgrimes "No stat","Undef","long","miss Ack err", 861541Srgrimes "underrun","overrun","desc err", "data read err", 871541Srgrimes "data write err","bus reset","timeout","tcode err", 8813416Sphk "Undef","Undef","unknown event","flushed", 8913416Sphk "Undef","ack complete","ack pend","Undef", 9013416Sphk "ack busy_X","ack busy_A","ack busy_B","Undef", 9113416Sphk "Undef","Undef","Undef","ack tardy", 9213416Sphk "Undef","ack data_err","ack type_err",""}; 931541Srgrimes#define MAX_SPEED 2 941541Srgrimesextern char linkspeed[MAX_SPEED+1][0x10]; 951541Srgrimesextern int maxrec[MAX_SPEED+1]; 969336Sdfrstatic char dbcond[4][0x10]={"NEV","C=1", "C=0", "ALL"}; 979336Sdfru_int32_t tagbit[4] = { 1 << 28, 1 << 29, 1 << 30, 1 << 31}; 9813416Sphk 999336Sdfrstatic struct tcode_info tinfo[] = { 10025664Sdfr/* hdr_len block flag*/ 1011541Srgrimes/* 0 WREQQ */ {16, FWTI_REQ | FWTI_TLABEL}, 10233181Seivind/* 1 WREQB */ {16, FWTI_REQ | FWTI_TLABEL | FWTI_BLOCK_ASY}, 10315479Sbde/* 2 WRES */ {12, FWTI_RES}, 10410224Sdg/* 3 XXX */ { 0, 0}, 10512911Sphk/* 4 RREQQ */ {12, FWTI_REQ | FWTI_TLABEL}, 10636251Speter/* 5 RREQB */ {16, FWTI_REQ | FWTI_TLABEL}, 10712911Sphk/* 6 RRESQ */ {16, FWTI_RES}, 10812911Sphk/* 7 RRESB */ {16, FWTI_RES | FWTI_BLOCK_ASY}, 10912911Sphk/* 8 CYCS */ { 0, 0}, 1101541Srgrimes/* 9 LREQ */ {16, FWTI_REQ | FWTI_TLABEL | FWTI_BLOCK_ASY}, 1119336Sdfr/* a STREAM */ { 4, FWTI_REQ | FWTI_BLOCK_STR}, 1121541Srgrimes/* b LRES */ {16, FWTI_RES | FWTI_BLOCK_ASY}, 1131549Srgrimes/* c XXX */ { 0, 0}, 1149336Sdfr/* d XXX */ { 0, 0}, 1159336Sdfr/* e PHY */ {12, FWTI_REQ}, 1169336Sdfr/* f XXX */ { 0, 0} 1179336Sdfr}; 1189336Sdfr 1191541Srgrimes#define OHCI_WRITE_SIGMASK 0xffff0000 1209336Sdfr#define OHCI_READ_SIGMASK 0xffff0000 12128270Swollman 1229336Sdfr#define OWRITE(sc, r, x) bus_space_write_4((sc)->bst, (sc)->bsh, (r), (x)) 1239336Sdfr#define OREAD(sc, r) bus_space_read_4((sc)->bst, (sc)->bsh, (r)) 1241541Srgrimes 1259336Sdfrstatic void fwohci_ibr __P((struct firewire_comm *)); 1261541Srgrimesstatic void fwohci_db_init __P((struct fwohci_dbch *)); 1271541Srgrimesstatic void fwohci_db_free __P((struct fwohci_dbch *)); 1281541Srgrimesstatic void fwohci_arcv __P((struct fwohci_softc *, struct fwohci_dbch *, int)); 1291541Srgrimesstatic void fwohci_ircv __P((struct fwohci_softc *, struct fwohci_dbch *, int)); 1309336Sdfrstatic void fwohci_txd __P((struct fwohci_softc *, struct fwohci_dbch *)); 1311541Srgrimesstatic void fwohci_start_atq __P((struct firewire_comm *)); 1329336Sdfrstatic void fwohci_start_ats __P((struct firewire_comm *)); 1339336Sdfrstatic void fwohci_start __P((struct fwohci_softc *, struct fwohci_dbch *)); 1349336Sdfrstatic void fwohci_drain_atq __P((struct firewire_comm *, struct fw_xfer *)); 1351541Srgrimesstatic void fwohci_drain_ats __P((struct firewire_comm *, struct fw_xfer *)); 1361541Srgrimesstatic void fwohci_drain __P((struct firewire_comm *, struct fw_xfer *, struct fwohci_dbch *)); 1379336Sdfrstatic u_int32_t fwphy_wrdata __P(( struct fwohci_softc *, u_int32_t, u_int32_t)); 1389336Sdfrstatic u_int32_t fwphy_rddata __P(( struct fwohci_softc *, u_int32_t)); 1399336Sdfrstatic int fwohci_rx_enable __P((struct fwohci_softc *, struct fwohci_dbch *)); 1401541Srgrimesstatic int fwohci_tx_enable __P((struct fwohci_softc *, struct fwohci_dbch *)); 1411541Srgrimesstatic int fwohci_irx_enable __P((struct firewire_comm *, int)); 1429336Sdfrstatic int fwohci_irxpp_enable __P((struct firewire_comm *, int)); 14336503Speterstatic int fwohci_irxbuf_enable __P((struct firewire_comm *, int)); 14436503Speterstatic int fwohci_irx_disable __P((struct firewire_comm *, int)); 14536503Speterstatic void fwohci_irx_post __P((struct firewire_comm *, u_int32_t *)); 1469336Sdfrstatic int fwohci_itxbuf_enable __P((struct firewire_comm *, int)); 1479336Sdfrstatic int fwohci_itx_disable __P((struct firewire_comm *, int)); 1489336Sdfrstatic void fwohci_timeout __P((void *)); 1499336Sdfrstatic void fwohci_poll __P((struct firewire_comm *, int, int)); 1509336Sdfrstatic void fwohci_set_intr __P((struct firewire_comm *, int)); 1519336Sdfrstatic int fwohci_add_rx_buf __P((struct fwohcidb_tr *, unsigned short, int, void *, void *)); 15236251Speterstatic int fwohci_add_tx_buf __P((struct fwohcidb_tr *, unsigned short, int, void *)); 1539336Sdfrstatic void dump_db __P((struct fwohci_softc *, u_int32_t)); 1549336Sdfrstatic void print_db __P((volatile struct fwohcidb *, u_int32_t , u_int32_t)); 1559336Sdfrstatic void dump_dma __P((struct fwohci_softc *, u_int32_t)); 1569336Sdfrstatic u_int32_t fwohci_cyctimer __P((struct firewire_comm *)); 1579336Sdfrstatic void fwohci_rbuf_update __P((struct fwohci_softc *, int)); 1589336Sdfrstatic void fwohci_tbuf_update __P((struct fwohci_softc *, int)); 1599336Sdfrvoid fwohci_txbufdb __P((struct fwohci_softc *, int , struct fw_bulkxfer *)); 16036251Speter 1619336Sdfr/* 1629336Sdfr * memory allocated for DMA programs 1639336Sdfr */ 1649336Sdfr#define DMA_PROG_ALLOC (8 * PAGE_SIZE) 1659336Sdfr 1669336Sdfr/* #define NDB 1024 */ 16736251Speter#define NDB FWMAXQUEUE 1689336Sdfr#define NDVDB (DVBUF * NDB) 1699336Sdfr 17017761Sdyson#define OHCI_VERSION 0x00 1719336Sdfr#define OHCI_CROMHDR 0x18 1729336Sdfr#define OHCI_BUS_OPT 0x20 1739336Sdfr#define OHCI_BUSIRMC (1 << 31) 1749336Sdfr#define OHCI_BUSCMC (1 << 30) 1751541Srgrimes#define OHCI_BUSISC (1 << 29) 1761541Srgrimes#define OHCI_BUSBMC (1 << 28) 1771541Srgrimes#define OHCI_BUSPMC (1 << 27) 1781541Srgrimes#define OHCI_BUSFNC OHCI_BUSIRMC | OHCI_BUSCMC | OHCI_BUSISC |\ 1791541Srgrimes OHCI_BUSBMC | OHCI_BUSPMC 1801541Srgrimes 1811549Srgrimes#define OHCI_EUID_HI 0x24 1829336Sdfr#define OHCI_EUID_LO 0x28 1839336Sdfr 1849336Sdfr#define OHCI_CROMPTR 0x34 1859336Sdfr#define OHCI_HCCCTL 0x50 1869336Sdfr#define OHCI_HCCCTLCLR 0x54 1871541Srgrimes#define OHCI_AREQHI 0x100 1889336Sdfr#define OHCI_AREQHICLR 0x104 18928270Swollman#define OHCI_AREQLO 0x108 1909336Sdfr#define OHCI_AREQLOCLR 0x10c 1919336Sdfr#define OHCI_PREQHI 0x110 1929336Sdfr#define OHCI_PREQHICLR 0x114 1931541Srgrimes#define OHCI_PREQLO 0x118 1941541Srgrimes#define OHCI_PREQLOCLR 0x11c 1951541Srgrimes#define OHCI_PREQUPPER 0x120 1969336Sdfr 1971541Srgrimes#define OHCI_SID_BUF 0x64 1981541Srgrimes#define OHCI_SID_CNT 0x68 1991541Srgrimes#define OHCI_SID_CNT_MASK 0xffc 2001541Srgrimes 2011541Srgrimes#define OHCI_IT_STAT 0x90 2021541Srgrimes#define OHCI_IT_STATCLR 0x94 2031541Srgrimes#define OHCI_IT_MASK 0x98 2041541Srgrimes#define OHCI_IT_MASKCLR 0x9c 2051541Srgrimes 2061541Srgrimes#define OHCI_IR_STAT 0xa0 2071541Srgrimes#define OHCI_IR_STATCLR 0xa4 20836503Speter#define OHCI_IR_MASK 0xa8 20936503Speter#define OHCI_IR_MASKCLR 0xac 21036503Speter 2111541Srgrimes#define OHCI_LNKCTL 0xe0 2129336Sdfr#define OHCI_LNKCTLCLR 0xe4 2139336Sdfr 2149336Sdfr#define OHCI_PHYACCESS 0xec 2159336Sdfr#define OHCI_CYCLETIMER 0xf0 21617761Sdyson 2179336Sdfr#define OHCI_DMACTL(off) (off) 2189336Sdfr#define OHCI_DMACTLCLR(off) (off + 4) 2199336Sdfr#define OHCI_DMACMD(off) (off + 0xc) 2209336Sdfr#define OHCI_DMAMATCH(off) (off + 0x10) 2219336Sdfr 2221541Srgrimes#define OHCI_ATQOFF 0x180 2231541Srgrimes#define OHCI_ATQCTL OHCI_ATQOFF 2241541Srgrimes#define OHCI_ATQCTLCLR (OHCI_ATQOFF + 4) 2251541Srgrimes#define OHCI_ATQCMD (OHCI_ATQOFF + 0xc) 2261541Srgrimes#define OHCI_ATQMATCH (OHCI_ATQOFF + 0x10) 2271541Srgrimes 2281549Srgrimes#define OHCI_ATSOFF 0x1a0 2299336Sdfr#define OHCI_ATSCTL OHCI_ATSOFF 2309336Sdfr#define OHCI_ATSCTLCLR (OHCI_ATSOFF + 4) 2319336Sdfr#define OHCI_ATSCMD (OHCI_ATSOFF + 0xc) 2329336Sdfr#define OHCI_ATSMATCH (OHCI_ATSOFF + 0x10) 2339336Sdfr 2341541Srgrimes#define OHCI_ARQOFF 0x1c0 2359336Sdfr#define OHCI_ARQCTL OHCI_ARQOFF 23628270Swollman#define OHCI_ARQCTLCLR (OHCI_ARQOFF + 4) 2379336Sdfr#define OHCI_ARQCMD (OHCI_ARQOFF + 0xc) 2389336Sdfr#define OHCI_ARQMATCH (OHCI_ARQOFF + 0x10) 2399336Sdfr 2401541Srgrimes#define OHCI_ARSOFF 0x1e0 2411541Srgrimes#define OHCI_ARSCTL OHCI_ARSOFF 2429336Sdfr#define OHCI_ARSCTLCLR (OHCI_ARSOFF + 4) 2431541Srgrimes#define OHCI_ARSCMD (OHCI_ARSOFF + 0xc) 2449336Sdfr#define OHCI_ARSMATCH (OHCI_ARSOFF + 0x10) 2451541Srgrimes 2461541Srgrimes#define OHCI_ITOFF(CH) (0x200 + 0x10 * (CH)) 2471541Srgrimes#define OHCI_ITCTL(CH) (OHCI_ITOFF(CH)) 2481541Srgrimes#define OHCI_ITCTLCLR(CH) (OHCI_ITOFF(CH) + 4) 2499336Sdfr#define OHCI_ITCMD(CH) (OHCI_ITOFF(CH) + 0xc) 2509336Sdfr 2511541Srgrimes#define OHCI_IROFF(CH) (0x400 + 0x20 * (CH)) 2521541Srgrimes#define OHCI_IRCTL(CH) (OHCI_IROFF(CH)) 2539336Sdfr#define OHCI_IRCTLCLR(CH) (OHCI_IROFF(CH) + 4) 2549336Sdfr#define OHCI_IRCMD(CH) (OHCI_IROFF(CH) + 0xc) 2551541Srgrimes#define OHCI_IRMATCH(CH) (OHCI_IROFF(CH) + 0x10) 2561541Srgrimes 2571541Srgrimesd_ioctl_t fwohci_ioctl; 2581541Srgrimes 2599336Sdfr/* 2609336Sdfr * Communication with PHY device 2619336Sdfr */ 2629336Sdfrstatic u_int32_t 2639336Sdfrfwphy_wrdata( struct fwohci_softc *sc, u_int32_t addr, u_int32_t data) 2649336Sdfr{ 2659336Sdfr u_int32_t fun; 2669336Sdfr 2679336Sdfr addr &= 0xf; 2689336Sdfr data &= 0xff; 2699336Sdfr 2709336Sdfr fun = (PHYDEV_WRCMD | (addr << PHYDEV_REGADDR) | (data << PHYDEV_WRDATA)); 2719336Sdfr OWRITE(sc, OHCI_PHYACCESS, fun); 2729336Sdfr DELAY(100); 2739336Sdfr 2749336Sdfr return(fwphy_rddata( sc, addr)); 2759336Sdfr} 2769336Sdfr 2779336Sdfrstatic u_int32_t 2789336Sdfrfwohci_set_bus_manager(struct firewire_comm *fc, u_int node) 2799336Sdfr{ 2809336Sdfr struct fwohci_softc *sc = (struct fwohci_softc *)fc; 2819336Sdfr int i; 2829336Sdfr u_int32_t bm; 2839336Sdfr 2849336Sdfr#define OHCI_CSR_DATA 0x0c 2851541Srgrimes#define OHCI_CSR_COMP 0x10 2869336Sdfr#define OHCI_CSR_CONT 0x14 2871541Srgrimes#define OHCI_BUS_MANAGER_ID 0 28818397Snate 2899336Sdfr OWRITE(sc, OHCI_CSR_DATA, node); 29018397Snate OWRITE(sc, OHCI_CSR_COMP, 0x3f); 2911541Srgrimes OWRITE(sc, OHCI_CSR_CONT, OHCI_BUS_MANAGER_ID); 2921541Srgrimes for (i = 0; !(OREAD(sc, OHCI_CSR_CONT) & (1<<31)) && (i < 1000); i++) 2939336Sdfr DELAY(100); 2949336Sdfr bm = OREAD(sc, OHCI_CSR_DATA); 2959336Sdfr if((bm & 0x3f) == 0x3f) 2961541Srgrimes bm = node; 2971541Srgrimes if (bootverbose) 2981541Srgrimes device_printf(sc->fc.dev, 2999336Sdfr "fw_set_bus_manager: %d->%d (loop=%d)\n", bm, node, i); 3009336Sdfr 30136503Speter return(bm); 30236503Speter} 30336503Speter 3049336Sdfrstatic u_int32_t 3059336Sdfrfwphy_rddata(struct fwohci_softc *sc, u_int addr) 3069336Sdfr{ 3079336Sdfr u_int32_t fun, stat; 3089336Sdfr u_int i, retry = 0; 3099336Sdfr 3109336Sdfr addr &= 0xf; 3119336Sdfr#define MAX_RETRY 100 31218397Snateagain: 31318397Snate OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_REG_FAIL); 3149336Sdfr fun = PHYDEV_RDCMD | (addr << PHYDEV_REGADDR); 3159336Sdfr OWRITE(sc, OHCI_PHYACCESS, fun); 31617761Sdyson for ( i = 0 ; i < MAX_RETRY ; i ++ ){ 3179336Sdfr fun = OREAD(sc, OHCI_PHYACCESS); 3189336Sdfr if ((fun & PHYDEV_RDCMD) == 0 && (fun & PHYDEV_RDDONE) != 0) 3199336Sdfr break; 3209336Sdfr DELAY(1000); 3219336Sdfr } 3229336Sdfr if(i >= MAX_RETRY) { 3239336Sdfr device_printf(sc->fc.dev, "cannot read phy\n"); 3241541Srgrimes#if 0 3251541Srgrimes return 0; /* XXX */ 3261541Srgrimes#else 3271541Srgrimes if (++retry < MAX_RETRY) { 3281541Srgrimes DELAY(1000); 3291541Srgrimes goto again; 3301541Srgrimes } 3311541Srgrimes#endif 3321541Srgrimes } 3331541Srgrimes /* Make sure that SCLK is started */ 3341541Srgrimes stat = OREAD(sc, FWOHCI_INTSTAT); 3351541Srgrimes if ((stat & OHCI_INT_REG_FAIL) != 0 || 33636503Speter ((fun >> PHYDEV_REGADDR) & 0xf) != addr) { 33736503Speter if (++retry < MAX_RETRY) { 3389336Sdfr DELAY(1000); 3391541Srgrimes goto again; 3409336Sdfr } 3419336Sdfr } 3429336Sdfr if (bootverbose || retry >= MAX_RETRY) 3439336Sdfr device_printf(sc->fc.dev, 3441541Srgrimes "fwphy_rddata: loop=%d, retry=%d\n", i, retry); 34517761Sdyson#undef MAX_RETRY 3469336Sdfr return((fun >> PHYDEV_RDDATA )& 0xff); 3479336Sdfr} 3489336Sdfr/* Device specific ioctl. */ 3499336Sdfrint 3509336Sdfrfwohci_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td) 3519336Sdfr{ 3529336Sdfr struct firewire_softc *sc; 3531541Srgrimes struct fwohci_softc *fc; 3541541Srgrimes int unit = DEV2UNIT(dev); 3551541Srgrimes int err = 0; 3561541Srgrimes struct fw_reg_req_t *reg = (struct fw_reg_req_t *) data; 3571541Srgrimes u_int32_t *dmach = (u_int32_t *) data; 3581541Srgrimes 3591541Srgrimes sc = devclass_get_softc(firewire_devclass, unit); 3601549Srgrimes if(sc == NULL){ 3619336Sdfr return(EINVAL); 3629336Sdfr } 3639336Sdfr fc = (struct fwohci_softc *)sc->fc; 3649336Sdfr 3659336Sdfr if (!data) 3661541Srgrimes return(EINVAL); 3679336Sdfr 36828270Swollman switch (cmd) { 3699336Sdfr case FWOHCI_WRREG: 3709336Sdfr#define OHCI_MAX_REG 0x800 3719336Sdfr if(reg->addr <= OHCI_MAX_REG){ 37227446Sdfr OWRITE(fc, reg->addr, reg->data); 3739336Sdfr reg->data = OREAD(fc, reg->addr); 3749336Sdfr }else{ 3751541Srgrimes err = EINVAL; 3761541Srgrimes } 3771541Srgrimes break; 3781541Srgrimes case FWOHCI_RDREG: 3791541Srgrimes if(reg->addr <= OHCI_MAX_REG){ 3809336Sdfr reg->data = OREAD(fc, reg->addr); 38127446Sdfr }else{ 3821541Srgrimes err = EINVAL; 3831541Srgrimes } 3849336Sdfr break; 3859336Sdfr/* Read DMA descriptors for debug */ 3861541Srgrimes case DUMPDMA: 3871541Srgrimes if(*dmach <= OHCI_MAX_DMA_CH ){ 3881541Srgrimes dump_dma(fc, *dmach); 3899336Sdfr dump_db(fc, *dmach); 39027446Sdfr }else{ 39127446Sdfr err = EINVAL; 39227446Sdfr } 3931541Srgrimes break; 3941541Srgrimes default: 3951541Srgrimes break; 3969336Sdfr } 39727446Sdfr return err; 39827446Sdfr} 39927446Sdfr 40027446Sdfrint 40127446Sdfrfwohci_init(struct fwohci_softc *sc, device_t dev) 40227446Sdfr{ 40327446Sdfr int err = 0; 40427446Sdfr int i; 40527446Sdfr u_int32_t reg, reg2; 40627446Sdfr struct fwohcidb_tr *db_tr; 40727446Sdfr int e1394a = 1; 40827446Sdfr 40927446Sdfr reg = OREAD(sc, OHCI_VERSION); 41027446Sdfr device_printf(dev, "OHCI version %x.%x (ROM=%d)\n", 41127446Sdfr (reg>>16) & 0xff, reg & 0xff, (reg>>24) & 1); 41227446Sdfr 41327446Sdfr/* XXX: Available Isochrounous DMA channel probe */ 41427446Sdfr for( i = 0 ; i < 0x20 ; i ++ ){ 41527446Sdfr OWRITE(sc, OHCI_IRCTL(i), OHCI_CNTL_DMA_RUN); 41627446Sdfr reg = OREAD(sc, OHCI_IRCTL(i)); 41727446Sdfr if(!(reg & OHCI_CNTL_DMA_RUN)) break; 41827446Sdfr OWRITE(sc, OHCI_ITCTL(i), OHCI_CNTL_DMA_RUN); 41927446Sdfr reg = OREAD(sc, OHCI_ITCTL(i)); 42027446Sdfr if(!(reg & OHCI_CNTL_DMA_RUN)) break; 42127446Sdfr } 42227446Sdfr sc->fc.nisodma = i; 42327446Sdfr device_printf(dev, "No. of Isochronous channel is %d.\n", i); 42427446Sdfr 42527446Sdfr sc->fc.arq = &sc->arrq.xferq; 42627446Sdfr sc->fc.ars = &sc->arrs.xferq; 42727446Sdfr sc->fc.atq = &sc->atrq.xferq; 42827446Sdfr sc->fc.ats = &sc->atrs.xferq; 42927446Sdfr 43027446Sdfr sc->arrq.xferq.start = NULL; 43127446Sdfr sc->arrs.xferq.start = NULL; 43227446Sdfr sc->atrq.xferq.start = fwohci_start_atq; 43327446Sdfr sc->atrs.xferq.start = fwohci_start_ats; 43427446Sdfr 43527446Sdfr sc->arrq.xferq.drain = NULL; 43627446Sdfr sc->arrs.xferq.drain = NULL; 43727446Sdfr sc->atrq.xferq.drain = fwohci_drain_atq; 43827446Sdfr sc->atrs.xferq.drain = fwohci_drain_ats; 4399336Sdfr 4409336Sdfr sc->arrq.ndesc = 1; 4419336Sdfr sc->arrs.ndesc = 1; 4429336Sdfr sc->atrq.ndesc = 10; 44317761Sdyson sc->atrs.ndesc = 10 / 2; 4449336Sdfr 44527446Sdfr sc->arrq.ndb = NDB; 4469336Sdfr sc->arrs.ndb = NDB / 2; 4479336Sdfr sc->atrq.ndb = NDB; 4489336Sdfr sc->atrs.ndb = NDB / 2; 4499336Sdfr 4509336Sdfr sc->arrq.dummy = NULL; 45127446Sdfr sc->arrs.dummy = NULL; 45227446Sdfr sc->atrq.dummy = NULL; 45327446Sdfr sc->atrs.dummy = NULL; 45429653Sdyson for( i = 0 ; i < sc->fc.nisodma ; i ++ ){ 45527446Sdfr sc->fc.it[i] = &sc->it[i].xferq; 4561541Srgrimes sc->fc.ir[i] = &sc->ir[i].xferq; 4571541Srgrimes sc->it[i].ndb = 0; 4583305Sphk sc->ir[i].ndb = 0; 4599336Sdfr } 4609336Sdfr 46117761Sdyson sc->fc.tcode = tinfo; 4629336Sdfr 4633305Sphk sc->cromptr = (u_int32_t *) 4649336Sdfr contigmalloc(CROMSIZE * 2, M_DEVBUF, M_NOWAIT, 0, ~0, 1<<10, 0); 4659336Sdfr 4661541Srgrimes if(sc->cromptr == NULL){ 4679336Sdfr device_printf(dev, "cromptr alloc failed."); 4689336Sdfr return ENOMEM; 4699336Sdfr } 4709336Sdfr sc->fc.dev = dev; 4719336Sdfr sc->fc.config_rom = &(sc->cromptr[CROMSIZE/4]); 4729336Sdfr 4739336Sdfr sc->fc.config_rom[1] = 0x31333934; 4741541Srgrimes sc->fc.config_rom[2] = 0xf000a002; 4751541Srgrimes sc->fc.config_rom[3] = OREAD(sc, OHCI_EUID_HI); 4761541Srgrimes sc->fc.config_rom[4] = OREAD(sc, OHCI_EUID_LO); 4771541Srgrimes sc->fc.config_rom[5] = 0; 4781541Srgrimes sc->fc.config_rom[0] = (4 << 24) | (5 << 16); 4791541Srgrimes 4801541Srgrimes sc->fc.config_rom[0] |= fw_crc16(&sc->fc.config_rom[1], 5*4); 4811549Srgrimes 4829336Sdfr 4839336Sdfr fw_init(&sc->fc); 4849336Sdfr 4859336Sdfr/* Disable interrupt */ 4869336Sdfr OWRITE(sc, FWOHCI_INTMASKCLR, ~0); 4871541Srgrimes 4889336Sdfr/* Now stopping all DMA channel */ 48928270Swollman OWRITE(sc, OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN); 4909336Sdfr OWRITE(sc, OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN); 4919336Sdfr OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN); 4921541Srgrimes OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN); 4931541Srgrimes 4941541Srgrimes OWRITE(sc, OHCI_IR_MASKCLR, ~0); 4951541Srgrimes for( i = 0 ; i < sc->fc.nisodma ; i ++ ){ 4961541Srgrimes OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN); 4971541Srgrimes OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN); 4989336Sdfr } 4999336Sdfr 5001541Srgrimes/* FLUSH FIFO and reset Transmitter/Reciever */ 5019336Sdfr OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_RESET); 5021541Srgrimes if (bootverbose) 5039336Sdfr device_printf(dev, "resetting OHCI..."); 5049336Sdfr i = 0; 5051541Srgrimes while(OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_RESET) { 5061541Srgrimes if (i++ > 100) break; 5071541Srgrimes DELAY(1000); 5081541Srgrimes } 5099336Sdfr if (bootverbose) 5109336Sdfr printf("done (loop=%d)\n", i); 5119336Sdfr 5121541Srgrimes reg = OREAD(sc, OHCI_BUS_OPT); 5131541Srgrimes reg2 = reg | OHCI_BUSFNC; 5141541Srgrimes /* XXX */ 5151541Srgrimes if (((reg & 0x0000f000) >> 12) < 10) 5161541Srgrimes reg2 = (reg2 & 0xffff0fff) | (10 << 12); 5171541Srgrimes if (bootverbose) 5181541Srgrimes device_printf(dev, "BUS_OPT 0x%x -> 0x%x\n", reg, reg2); 5191541Srgrimes OWRITE(sc, OHCI_BUS_OPT, reg2); 5201541Srgrimes 5211541Srgrimes OWRITE(sc, OHCI_CROMHDR, sc->fc.config_rom[0]); 5221541Srgrimes OWRITE(sc, OHCI_CROMPTR, vtophys(&sc->fc.config_rom[0])); 5231541Srgrimes OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_BIGEND); 5241541Srgrimes OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_POSTWR); 5251541Srgrimes 5261541Srgrimes/* 5271541Srgrimes * probe PHY parameters 5281541Srgrimes * 0. to prove PHY version, whether compliance of 1394a. 5291541Srgrimes * 1. to probe maximum speed supported by the PHY and 5301541Srgrimes * number of port supported by core-logic. 5311541Srgrimes * It is not actually available port on your PC . 5321541Srgrimes */ 5331541Srgrimes OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LPS); 5341541Srgrimes#if 0 5351541Srgrimes /* XXX wait for SCLK. */ 5361541Srgrimes DELAY(100000); 5371541Srgrimes#endif 5381541Srgrimes reg = fwphy_rddata(sc, FW_PHY_SPD_REG); 5391541Srgrimes 5401541Srgrimes if((reg >> 5) != 7 ){ 5411541Srgrimes sc->fc.mode &= ~FWPHYASYST; 5421541Srgrimes sc->fc.nport = reg & FW_PHY_NP; 54336503Speter sc->fc.speed = reg & FW_PHY_SPD >> 6; 54436503Speter if (sc->fc.speed > MAX_SPEED) { 54536503Speter device_printf(dev, "invalid speed %d (fixed to %d).\n", 5461541Srgrimes sc->fc.speed, MAX_SPEED); 5479336Sdfr sc->fc.speed = MAX_SPEED; 5489336Sdfr } 5499336Sdfr sc->fc.maxrec = maxrec[sc->fc.speed]; 5501541Srgrimes device_printf(dev, 5511541Srgrimes "Link 1394 only %s, %d ports, maxrec %d bytes.\n", 5529336Sdfr linkspeed[sc->fc.speed], sc->fc.nport, sc->fc.maxrec); 5539336Sdfr }else{ 5549336Sdfr reg2 = fwphy_rddata(sc, FW_PHY_ESPD_REG); 5559336Sdfr sc->fc.mode |= FWPHYASYST; 5561541Srgrimes sc->fc.nport = reg & FW_PHY_NP; 5571541Srgrimes sc->fc.speed = (reg2 & FW_PHY_ESPD) >> 5; 5589336Sdfr if (sc->fc.speed > MAX_SPEED) { 5591541Srgrimes device_printf(dev, "invalid speed %d (fixed to %d).\n", 5601541Srgrimes sc->fc.speed, MAX_SPEED); 5619336Sdfr sc->fc.speed = MAX_SPEED; 56217761Sdyson } 5631541Srgrimes sc->fc.maxrec = maxrec[sc->fc.speed]; 5641541Srgrimes device_printf(dev, 5659336Sdfr "Link 1394a available %s, %d ports, maxrec %d bytes.\n", 5669336Sdfr linkspeed[sc->fc.speed], sc->fc.nport, sc->fc.maxrec); 5679336Sdfr 5689336Sdfr /* check programPhyEnable */ 5699336Sdfr reg2 = fwphy_rddata(sc, 5); 5709336Sdfr#if 0 5711541Srgrimes if (e1394a && (OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_PRPHY)) { 5721541Srgrimes#else /* XXX force to enable 1394a */ 5731541Srgrimes if (e1394a) { 5741541Srgrimes#endif 5751541Srgrimes if (bootverbose) 5761541Srgrimes device_printf(dev, 5771541Srgrimes "Enable 1394a Enhancements\n"); 5781541Srgrimes /* enable EAA EMC */ 5791541Srgrimes reg2 |= 0x03; 5801541Srgrimes /* set aPhyEnhanceEnable */ 5811541Srgrimes OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_PHYEN); 5821541Srgrimes OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_PRPHY); 5831541Srgrimes } else { 5841541Srgrimes /* for safe */ 5851549Srgrimes reg2 &= ~0x83; 5869336Sdfr } 5879336Sdfr reg2 = fwphy_wrdata(sc, 5, reg2); 5889336Sdfr } 5899336Sdfr 5909336Sdfr reg = fwphy_rddata(sc, FW_PHY_SPD_REG); 5911541Srgrimes if((reg >> 5) == 7 ){ 5929336Sdfr reg = fwphy_rddata(sc, 4); 59328270Swollman reg |= 1 << 6; 5949336Sdfr fwphy_wrdata(sc, 4, reg); 5959336Sdfr reg = fwphy_rddata(sc, 4); 5961541Srgrimes } 5971541Srgrimes 5981541Srgrimes/* SID recieve buffer must allign 2^11 */ 5999336Sdfr#define OHCI_SIDSIZE (1 << 11) 6001541Srgrimes sc->fc.sid_buf = (u_int32_t *) vm_page_alloc_contig( OHCI_SIDSIZE, 6011541Srgrimes 0x10000, 0xffffffff, OHCI_SIDSIZE); 6029336Sdfr if (sc->fc.sid_buf == NULL) { 6031541Srgrimes device_printf(dev, "sid_buf alloc failed.\n"); 6049336Sdfr return ENOMEM; 6059336Sdfr } 6061541Srgrimes 6071541Srgrimes OWRITE(sc, OHCI_SID_BUF, vtophys(sc->fc.sid_buf)); 6081541Srgrimes sc->fc.sid_buf++; 6091541Srgrimes OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_SID); 6109336Sdfr 6111541Srgrimes fwohci_db_init(&sc->arrq); 6121541Srgrimes if ((sc->arrq.flags & FWOHCI_DBCH_INIT) == 0) 6131541Srgrimes return ENOMEM; 6141541Srgrimes 6151541Srgrimes fwohci_db_init(&sc->arrs); 6161541Srgrimes if ((sc->arrs.flags & FWOHCI_DBCH_INIT) == 0) 6171541Srgrimes return ENOMEM; 6181541Srgrimes 6199336Sdfr fwohci_db_init(&sc->atrq); 6209336Sdfr if ((sc->atrq.flags & FWOHCI_DBCH_INIT) == 0) 6219336Sdfr return ENOMEM; 6229336Sdfr 6231541Srgrimes fwohci_db_init(&sc->atrs); 6241541Srgrimes if ((sc->atrs.flags & FWOHCI_DBCH_INIT) == 0) 6251541Srgrimes return ENOMEM; 6269336Sdfr 62736503Speter reg = OREAD(sc, FWOHCIGUID_H); 62836503Speter for( i = 0 ; i < 4 ; i ++){ 62936503Speter sc->fc.eui[3 - i] = reg & 0xff; 6309336Sdfr reg = reg >> 8; 6319336Sdfr } 6329336Sdfr reg = OREAD(sc, FWOHCIGUID_L); 6339336Sdfr for( i = 0 ; i < 4 ; i ++){ 6341541Srgrimes sc->fc.eui[7 - i] = reg & 0xff; 6359336Sdfr reg = reg >> 8; 6369336Sdfr } 6379336Sdfr device_printf(dev, "EUI64 %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", 6389336Sdfr sc->fc.eui[0], sc->fc.eui[1], sc->fc.eui[2], sc->fc.eui[3], 6391541Srgrimes sc->fc.eui[4], sc->fc.eui[5], sc->fc.eui[6], sc->fc.eui[7]); 6409336Sdfr sc->fc.ioctl = fwohci_ioctl; 6419336Sdfr sc->fc.cyctimer = fwohci_cyctimer; 64236503Speter sc->fc.set_bmr = fwohci_set_bus_manager; 64336251Speter sc->fc.ibr = fwohci_ibr; 6441541Srgrimes sc->fc.irx_enable = fwohci_irx_enable; 6459336Sdfr sc->fc.irx_disable = fwohci_irx_disable; 6469336Sdfr 6479336Sdfr sc->fc.itx_enable = fwohci_itxbuf_enable; 6483305Sphk sc->fc.itx_disable = fwohci_itx_disable; 64917761Sdyson sc->fc.irx_post = fwohci_irx_post; 6509336Sdfr sc->fc.itx_post = NULL; 6519336Sdfr sc->fc.timeout = fwohci_timeout; 6529336Sdfr sc->fc.poll = fwohci_poll; 6531541Srgrimes sc->fc.set_intr = fwohci_set_intr; 6541541Srgrimes 6551541Srgrimes /* enable link */ 6569336Sdfr OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LINKEN); 6571541Srgrimes fw_busreset(&sc->fc); 6589336Sdfr fwohci_rx_enable(sc, &sc->arrq); 6599336Sdfr fwohci_rx_enable(sc, &sc->arrs); 6609336Sdfr 6619336Sdfr for( i = 0, db_tr = sc->atrq.top; i < sc->atrq.ndb ; 6629336Sdfr i ++, db_tr = STAILQ_NEXT(db_tr, link)){ 6639336Sdfr db_tr->xfer = NULL; 6649336Sdfr } 6659336Sdfr for( i = 0, db_tr = sc->atrs.top; i < sc->atrs.ndb ; 6669336Sdfr i ++, db_tr = STAILQ_NEXT(db_tr, link)){ 6679336Sdfr db_tr->xfer = NULL; 6689336Sdfr } 6699336Sdfr 6709336Sdfr OWRITE(sc, FWOHCI_RETRY, 6711541Srgrimes (0xffff << 16 )| (0x0f << 8) | (0x0f << 4) | 0x0f) ; 6721541Srgrimes OWRITE(sc, FWOHCI_INTMASK, 6731541Srgrimes OHCI_INT_ERR | OHCI_INT_PHY_SID 6741541Srgrimes | OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS 6751541Srgrimes | OHCI_INT_DMA_PRRQ | OHCI_INT_DMA_PRRS 6761541Srgrimes | OHCI_INT_PHY_BUS_R | OHCI_INT_PW_ERR); 6771541Srgrimes fwohci_set_intr(&sc->fc, 1); 6781541Srgrimes 6791541Srgrimes OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD); 6801541Srgrimes OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD); 6819336Sdfr 6821541Srgrimes return err; 6831541Srgrimes} 6841541Srgrimes 6851541Srgrimesvoid 6861541Srgrimesfwohci_timeout(void *arg) 6871541Srgrimes{ 6881541Srgrimes struct fwohci_softc *sc; 6891541Srgrimes 6901541Srgrimes sc = (struct fwohci_softc *)arg; 6911541Srgrimes sc->fc.timeouthandle = timeout(fwohci_timeout, 6929336Sdfr (void *)sc, FW_XFERTIMEOUT * hz * 10); 6939336Sdfr} 6949336Sdfr 6959336Sdfru_int32_t 6969336Sdfrfwohci_cyctimer(struct firewire_comm *fc) 6979336Sdfr{ 6989336Sdfr struct fwohci_softc *sc = (struct fwohci_softc *)fc; 6999336Sdfr return(OREAD(sc, OHCI_CYCLETIMER)); 7009336Sdfr} 7019336Sdfr 7029336Sdfr#define LAST_DB(dbtr, db) do { \ 7039336Sdfr struct fwohcidb_tr *_dbtr = (dbtr); \ 7049336Sdfr int _cnt = _dbtr->dbcnt; \ 7059336Sdfr db = &_dbtr->db[ (_cnt > 2) ? (_cnt -1) : 0]; \ 7069336Sdfr} while (0) 7079336Sdfr 7089336Sdfrint 7099336Sdfrfwohci_detach(struct fwohci_softc *sc, device_t dev) 7109336Sdfr{ 7119336Sdfr int i; 7121541Srgrimes 7131541Srgrimes if (sc->fc.sid_buf != NULL) 7141541Srgrimes contigfree((void *)(uintptr_t)sc->fc.sid_buf, 7151541Srgrimes OHCI_SIDSIZE, M_DEVBUF); 7161541Srgrimes if (sc->cromptr != NULL) 7171541Srgrimes contigfree((void *)sc->cromptr, CROMSIZE * 2, M_DEVBUF); 7181541Srgrimes 7191541Srgrimes fwohci_db_free(&sc->arrq); 7209336Sdfr fwohci_db_free(&sc->arrs); 7219336Sdfr 7229336Sdfr fwohci_db_free(&sc->atrq); 7231541Srgrimes fwohci_db_free(&sc->atrs); 72417761Sdyson 7259336Sdfr for( i = 0 ; i < sc->fc.nisodma ; i ++ ){ 7269336Sdfr fwohci_db_free(&sc->it[i]); 7279336Sdfr fwohci_db_free(&sc->ir[i]); 7281541Srgrimes } 7291541Srgrimes 7301541Srgrimes return 0; 73117761Sdyson} 7329336Sdfr 7331541Srgrimesstatic void 7341541Srgrimesfwohci_start(struct fwohci_softc *sc, struct fwohci_dbch *dbch) 7351541Srgrimes{ 7369336Sdfr int i, s; 7379336Sdfr int tcode, hdr_len, hdr_off, len; 7389336Sdfr int fsegment = -1; 7399336Sdfr u_int32_t off; 7409336Sdfr struct fw_xfer *xfer; 7419336Sdfr struct fw_pkt *fp; 7429336Sdfr volatile struct fwohci_txpkthdr *ohcifp; 7439336Sdfr struct fwohcidb_tr *db_tr; 7441541Srgrimes volatile struct fwohcidb *db; 7451541Srgrimes struct mbuf *m; 7461541Srgrimes struct tcode_info *info; 7471541Srgrimes 7481541Srgrimes if(&sc->atrq == dbch){ 7491541Srgrimes off = OHCI_ATQOFF; 7501541Srgrimes }else if(&sc->atrs == dbch){ 7511549Srgrimes off = OHCI_ATSOFF; 7529336Sdfr }else{ 7539336Sdfr return; 7549336Sdfr } 7559336Sdfr 7569336Sdfr if (dbch->flags & FWOHCI_DBCH_FULL) 7571541Srgrimes return; 7589336Sdfr 75928270Swollman s = splfw(); 7609336Sdfr db_tr = dbch->top; 7619336Sdfrtxloop: 7621541Srgrimes xfer = STAILQ_FIRST(&dbch->xferq.q); 7639336Sdfr if(xfer == NULL){ 7641541Srgrimes goto kick; 7659336Sdfr } 7669336Sdfr if(dbch->xferq.queued == 0 ){ 7679336Sdfr device_printf(sc->fc.dev, "TX queue empty\n"); 7681541Srgrimes } 7691541Srgrimes STAILQ_REMOVE_HEAD(&dbch->xferq.q, link); 7701541Srgrimes db_tr->xfer = xfer; 7711541Srgrimes xfer->state = FWXF_START; 77211921Sphk dbch->xferq.packets++; 7739336Sdfr 7749336Sdfr fp = (struct fw_pkt *)(xfer->send.buf + xfer->send.off); 7759336Sdfr tcode = fp->mode.common.tcode; 7761541Srgrimes 7771541Srgrimes ohcifp = (volatile struct fwohci_txpkthdr *) db_tr->db[1].db.immed; 7781541Srgrimes info = &tinfo[tcode]; 7799336Sdfr hdr_len = hdr_off = info->hdr_len; 7801541Srgrimes /* fw_asyreq must pass valid send.len */ 7811541Srgrimes len = xfer->send.len; 7821541Srgrimes for( i = 0 ; i < hdr_off ; i+= 4){ 7831541Srgrimes ohcifp->mode.ld[i/4] = ntohl(fp->mode.ld[i/4]); 7841541Srgrimes } 7859336Sdfr ohcifp->mode.common.spd = xfer->spd; 7869336Sdfr if (tcode == FWTCODE_STREAM ){ 7879336Sdfr hdr_len = 8; 7889336Sdfr ohcifp->mode.stream.len = ntohs(fp->mode.stream.len); 7891541Srgrimes } else if (tcode == FWTCODE_PHY) { 7901541Srgrimes hdr_len = 12; 7919336Sdfr ohcifp->mode.ld[1] = ntohl(fp->mode.ld[1]); 7929336Sdfr ohcifp->mode.ld[2] = ntohl(fp->mode.ld[2]); 7939336Sdfr ohcifp->mode.common.spd = 0; 7949336Sdfr ohcifp->mode.common.tcode = FWOHCITCODE_PHY; 7959336Sdfr } else { 7969336Sdfr ohcifp->mode.asycomm.dst = ntohs(fp->mode.hdr.dst); 7979336Sdfr ohcifp->mode.asycomm.srcbus = OHCI_ASYSRCBUS; 7981541Srgrimes ohcifp->mode.asycomm.tlrt |= FWRETRY_X; 7991541Srgrimes } 80010224Sdg db = &db_tr->db[0]; 80110224Sdg db->db.desc.cmd = OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | hdr_len; 8021541Srgrimes db->db.desc.status = 0; 8039336Sdfr/* Specify bound timer of asy. responce */ 8049336Sdfr if(&sc->atrs == dbch){ 8059336Sdfr db->db.desc.count 8069336Sdfr = (OREAD(sc, OHCI_CYCLETIMER) >> 12) + (1 << 13); 8079336Sdfr } 8089336Sdfr 8099336Sdfr db_tr->dbcnt = 2; 8109336Sdfr db = &db_tr->db[db_tr->dbcnt]; 8119336Sdfr if(len > hdr_off){ 8129336Sdfr if (xfer->mbuf == NULL) { 8139336Sdfr db->db.desc.addr 8149336Sdfr = vtophys(xfer->send.buf + xfer->send.off) + hdr_off; 8159336Sdfr db->db.desc.cmd 8169336Sdfr = OHCI_OUTPUT_MORE | ((len - hdr_off) & 0xffff); 8179336Sdfr db->db.desc.status = 0; 8189336Sdfr 8199336Sdfr db_tr->dbcnt++; 8209336Sdfr } else { 8211541Srgrimes /* XXX we assume mbuf chain is shorter than ndesc */ 8229336Sdfr m = xfer->mbuf; 8239336Sdfr do { 8249336Sdfr db->db.desc.addr 8259336Sdfr = vtophys(mtod(m, caddr_t)); 8269336Sdfr db->db.desc.cmd = OHCI_OUTPUT_MORE | m->m_len; 8279336Sdfr db->db.desc.status = 0; 8289336Sdfr db++; 8299336Sdfr db_tr->dbcnt++; 8309336Sdfr m = m->m_next; 8319336Sdfr } while (m != NULL); 8329336Sdfr } 8339336Sdfr } 8349336Sdfr /* last db */ 8351541Srgrimes LAST_DB(db_tr, db); 8369336Sdfr db->db.desc.cmd |= OHCI_OUTPUT_LAST 8379336Sdfr | OHCI_INTERRUPT_ALWAYS 8389336Sdfr | OHCI_BRANCH_ALWAYS; 8399336Sdfr db->db.desc.depend = vtophys(STAILQ_NEXT(db_tr, link)->db); 8409336Sdfr 8419336Sdfr if(fsegment == -1 ) 84236503Speter fsegment = db_tr->dbcnt; 84336503Speter if (dbch->pdb_tr != NULL) { 84436503Speter LAST_DB(dbch->pdb_tr, db); 8459336Sdfr db->db.desc.depend |= db_tr->dbcnt; 8469336Sdfr } 8479336Sdfr dbch->pdb_tr = db_tr; 8489336Sdfr db_tr = STAILQ_NEXT(db_tr, link); 8499336Sdfr if(db_tr != dbch->bottom){ 8509336Sdfr goto txloop; 8511541Srgrimes } else { 8529336Sdfr device_printf(sc->fc.dev, "fwohci_start: lack of db_trq\n"); 8539336Sdfr dbch->flags |= FWOHCI_DBCH_FULL; 8549336Sdfr } 8559336Sdfrkick: 8561541Srgrimes if (firewire_debug) printf("kick\n"); 8579336Sdfr /* kick asy q */ 8589336Sdfr 85936251Speter if(dbch->xferq.flag & FWXFERQ_RUNNING) { 8609336Sdfr OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_WAKE); 8613305Sphk } else { 86217761Sdyson if (bootverbose) 8639336Sdfr device_printf(sc->fc.dev, "start AT DMA status=%x\n", 8649336Sdfr OREAD(sc, OHCI_DMACTL(off))); 8659336Sdfr OWRITE(sc, OHCI_DMACMD(off), vtophys(dbch->top->db) | fsegment); 8661541Srgrimes OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_RUN); 8679336Sdfr dbch->xferq.flag |= FWXFERQ_RUNNING; 8689336Sdfr } 8699336Sdfr 8709336Sdfr dbch->top = db_tr; 8719336Sdfr splx(s); 8729336Sdfr return; 8739336Sdfr} 8749336Sdfr 8759336Sdfrstatic void 8769336Sdfrfwohci_drain_atq(struct firewire_comm *fc, struct fw_xfer *xfer) 8779336Sdfr{ 8789336Sdfr struct fwohci_softc *sc = (struct fwohci_softc *)fc; 8799336Sdfr fwohci_drain(&sc->fc, xfer, &(sc->atrq)); 8809336Sdfr return; 8819336Sdfr} 8829336Sdfr 8839336Sdfrstatic void 8849336Sdfrfwohci_drain_ats(struct firewire_comm *fc, struct fw_xfer *xfer) 8859336Sdfr{ 8869336Sdfr struct fwohci_softc *sc = (struct fwohci_softc *)fc; 8879336Sdfr fwohci_drain(&sc->fc, xfer, &(sc->atrs)); 8889336Sdfr return; 8899336Sdfr} 8909336Sdfr 8919336Sdfrstatic void 8929336Sdfrfwohci_start_atq(struct firewire_comm *fc) 8939336Sdfr{ 8949336Sdfr struct fwohci_softc *sc = (struct fwohci_softc *)fc; 8959336Sdfr fwohci_start( sc, &(sc->atrq)); 8969336Sdfr return; 8979336Sdfr} 8989336Sdfr 8999336Sdfrstatic void 9009336Sdfrfwohci_start_ats(struct firewire_comm *fc) 9019336Sdfr{ 9029336Sdfr struct fwohci_softc *sc = (struct fwohci_softc *)fc; 9039336Sdfr fwohci_start( sc, &(sc->atrs)); 9049336Sdfr return; 9059336Sdfr} 90617761Sdyson 9079336Sdfrvoid 9089336Sdfrfwohci_txd(struct fwohci_softc *sc, struct fwohci_dbch *dbch) 9099336Sdfr{ 9109336Sdfr int s, err = 0; 9119336Sdfr struct fwohcidb_tr *tr; 9129336Sdfr volatile struct fwohcidb *db; 9139336Sdfr struct fw_xfer *xfer; 9149336Sdfr u_int32_t off; 9159336Sdfr u_int stat; 9169336Sdfr int packets; 91726418Sdfr struct firewire_comm *fc = (struct firewire_comm *)sc; 91826418Sdfr if(&sc->atrq == dbch){ 91926418Sdfr off = OHCI_ATQOFF; 92026418Sdfr }else if(&sc->atrs == dbch){ 9219336Sdfr off = OHCI_ATSOFF; 9229336Sdfr }else{ 9239336Sdfr return; 9249336Sdfr } 9259336Sdfr s = splfw(); 9269336Sdfr tr = dbch->bottom; 9279336Sdfr packets = 0; 9289336Sdfr while(dbch->xferq.queued > 0){ 9299336Sdfr LAST_DB(tr, db); 9309336Sdfr if(!(db->db.desc.status & OHCI_CNTL_DMA_ACTIVE)){ 9319336Sdfr if (fc->status != FWBUSRESET) 9329336Sdfr /* maybe out of order?? */ 9339336Sdfr goto out; 9349336Sdfr } 9359336Sdfr if(db->db.desc.status & OHCI_CNTL_DMA_DEAD) { 9369336Sdfr#ifdef OHCI_DEBUG 9379336Sdfr dump_dma(sc, ch); 9389336Sdfr dump_db(sc, ch); 9399336Sdfr#endif 9409336Sdfr/* Stop DMA */ 9419336Sdfr OWRITE(sc, OHCI_DMACTLCLR(off), OHCI_CNTL_DMA_RUN); 9429336Sdfr device_printf(sc->fc.dev, "force reset AT FIFO\n"); 9439336Sdfr OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_LINKEN); 9449336Sdfr OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LPS | OHCI_HCC_LINKEN); 9459336Sdfr OWRITE(sc, OHCI_DMACTLCLR(off), OHCI_CNTL_DMA_RUN); 9469336Sdfr } 9479336Sdfr stat = db->db.desc.status & FWOHCIEV_MASK; 9489336Sdfr switch(stat){ 9499336Sdfr case FWOHCIEV_ACKCOMPL: 9509336Sdfr case FWOHCIEV_ACKPEND: 9519336Sdfr err = 0; 9529336Sdfr break; 9539336Sdfr case FWOHCIEV_ACKBSA: 9549336Sdfr case FWOHCIEV_ACKBSB: 9559336Sdfr device_printf(sc->fc.dev, "txd err=%2x %s\n", stat, fwohcicode[stat]); 9569336Sdfr case FWOHCIEV_ACKBSX: 9579336Sdfr err = EBUSY; 9589336Sdfr break; 9599336Sdfr case FWOHCIEV_FLUSHED: 9609336Sdfr case FWOHCIEV_ACKTARD: 9619336Sdfr device_printf(sc->fc.dev, "txd err=%2x %s\n", stat, fwohcicode[stat]); 9629336Sdfr err = EAGAIN; 9639336Sdfr break; 9649336Sdfr case FWOHCIEV_MISSACK: 9659336Sdfr case FWOHCIEV_UNDRRUN: 9669336Sdfr case FWOHCIEV_OVRRUN: 9679336Sdfr case FWOHCIEV_DESCERR: 9689336Sdfr case FWOHCIEV_DTRDERR: 9699336Sdfr case FWOHCIEV_TIMEOUT: 9709336Sdfr case FWOHCIEV_TCODERR: 9719336Sdfr case FWOHCIEV_UNKNOWN: 9729336Sdfr case FWOHCIEV_ACKDERR: 9739336Sdfr case FWOHCIEV_ACKTERR: 9749336Sdfr default: 9759336Sdfr device_printf(sc->fc.dev, "txd err=%2x %s\n", 9769336Sdfr stat, fwohcicode[stat]); 9779336Sdfr err = EINVAL; 9789336Sdfr break; 9799336Sdfr } 9809336Sdfr if(tr->xfer != NULL){ 9819336Sdfr xfer = tr->xfer; 9829336Sdfr xfer->state = FWXF_SENT; 9839336Sdfr if(err == EBUSY && fc->status != FWBUSRESET){ 9849336Sdfr xfer->state = FWXF_BUSY; 9859336Sdfr switch(xfer->act_type){ 9869336Sdfr case FWACT_XFER: 9879336Sdfr xfer->resp = err; 98834961Sphk if(xfer->retry_req != NULL){ 98925664Sdfr xfer->retry_req(xfer); 99025664Sdfr } 9919336Sdfr break; 9929336Sdfr default: 9939336Sdfr break; 9949336Sdfr } 9959336Sdfr } else if( stat != FWOHCIEV_ACKPEND){ 9969336Sdfr if (stat != FWOHCIEV_ACKCOMPL) 9979336Sdfr xfer->state = FWXF_SENTERR; 9989336Sdfr xfer->resp = err; 9999336Sdfr switch(xfer->act_type){ 10009336Sdfr case FWACT_XFER: 10019336Sdfr fw_xfer_done(xfer); 10029336Sdfr break; 10039336Sdfr default: 10049336Sdfr break; 100510224Sdg } 100610224Sdg } 10079336Sdfr dbch->xferq.queued --; 10089336Sdfr } 10099336Sdfr tr->xfer = NULL; 10109336Sdfr 10119336Sdfr packets ++; 10129336Sdfr tr = STAILQ_NEXT(tr, link); 10139336Sdfr dbch->bottom = tr; 10149336Sdfr } 10159336Sdfrout: 10169336Sdfr if ((dbch->flags & FWOHCI_DBCH_FULL) && packets > 0) { 10179336Sdfr printf("make free slot\n"); 10189336Sdfr dbch->flags &= ~FWOHCI_DBCH_FULL; 10199336Sdfr fwohci_start(sc, dbch); 10209336Sdfr } 10219336Sdfr splx(s); 10229336Sdfr} 10239336Sdfr 10249336Sdfrstatic void 10259336Sdfrfwohci_drain(struct firewire_comm *fc, struct fw_xfer *xfer, struct fwohci_dbch *dbch) 10269336Sdfr{ 10279336Sdfr int i, s; 10289336Sdfr struct fwohcidb_tr *tr; 10299336Sdfr 10309336Sdfr if(xfer->state != FWXF_START) return; 10319336Sdfr 10329336Sdfr s = splfw(); 10339336Sdfr tr = dbch->bottom; 10349336Sdfr for( i = 0 ; i <= dbch->xferq.queued ; i ++){ 10359336Sdfr if(tr->xfer == xfer){ 10369336Sdfr s = splfw(); 10379336Sdfr tr->xfer = NULL; 10389336Sdfr dbch->xferq.queued --; 10399336Sdfr#if 1 10409336Sdfr /* XXX */ 10419336Sdfr if (tr == dbch->bottom) 10429336Sdfr dbch->bottom = STAILQ_NEXT(tr, link); 10439336Sdfr#endif 10449336Sdfr if (dbch->flags & FWOHCI_DBCH_FULL) { 10459336Sdfr printf("fwohci_drain: make slot\n"); 10469336Sdfr dbch->flags &= ~FWOHCI_DBCH_FULL; 10479336Sdfr fwohci_start((struct fwohci_softc *)fc, dbch); 10489336Sdfr } 10499336Sdfr 10509336Sdfr splx(s); 10519336Sdfr break; 10529336Sdfr } 10539336Sdfr tr = STAILQ_NEXT(tr, link); 10549336Sdfr } 10559336Sdfr splx(s); 10569336Sdfr return; 10579336Sdfr} 10589336Sdfr 10599336Sdfrstatic void 106025663Sdfrfwohci_db_free(struct fwohci_dbch *dbch) 10619336Sdfr{ 10629336Sdfr struct fwohcidb_tr *db_tr; 10639336Sdfr int idb; 10649336Sdfr 10659336Sdfr if ((dbch->flags & FWOHCI_DBCH_INIT) == 0) 10669336Sdfr return; 10679336Sdfr 10689336Sdfr if(!(dbch->xferq.flag & FWXFERQ_EXTBUF)){ 10699336Sdfr for(db_tr = STAILQ_FIRST(&dbch->db_trq), idb = 0; 10709336Sdfr idb < dbch->ndb; 10719336Sdfr db_tr = STAILQ_NEXT(db_tr, link), idb++){ 10729336Sdfr if (db_tr->buf != NULL) { 10739336Sdfr free(db_tr->buf, M_DEVBUF); 10749336Sdfr db_tr->buf = NULL; 10759336Sdfr } 10769336Sdfr } 10779336Sdfr } 10789336Sdfr dbch->ndb = 0; 10799336Sdfr db_tr = STAILQ_FIRST(&dbch->db_trq); 10809336Sdfr contigfree((void *)(uintptr_t)(volatile void *)db_tr->db, 10819336Sdfr sizeof(struct fwohcidb) * dbch->ndesc * dbch->ndb, M_DEVBUF); 10829336Sdfr free(db_tr, M_DEVBUF); 10839336Sdfr STAILQ_INIT(&dbch->db_trq); 10849336Sdfr dbch->flags &= ~FWOHCI_DBCH_INIT; 10859336Sdfr} 10869336Sdfr 10879336Sdfrstatic void 10889336Sdfrfwohci_db_init(struct fwohci_dbch *dbch) 10899336Sdfr{ 10909336Sdfr int idb; 10919336Sdfr struct fwohcidb *db; 10929336Sdfr struct fwohcidb_tr *db_tr; 10939336Sdfr /* allocate DB entries and attach one to each DMA channels */ 10949336Sdfr /* DB entry must start at 16 bytes bounary. */ 10959336Sdfr dbch->frag.buf = NULL; 10969336Sdfr dbch->frag.len = 0; 10979336Sdfr dbch->frag.plen = 0; 10989336Sdfr dbch->xferq.queued = 0; 10991541Srgrimes dbch->pdb_tr = NULL; 11009336Sdfr 11019336Sdfr STAILQ_INIT(&dbch->db_trq); 11021541Srgrimes db_tr = (struct fwohcidb_tr *) 11039336Sdfr malloc(sizeof(struct fwohcidb_tr) * dbch->ndb, 110434961Sphk M_DEVBUF, M_DONTWAIT | M_ZERO); 11059336Sdfr if(db_tr == NULL){ 11069336Sdfr printf("fwochi_db_init: malloc failed\n"); 11079336Sdfr return; 11089336Sdfr } 11099336Sdfr db = (struct fwohcidb *) 11109336Sdfr contigmalloc(sizeof (struct fwohcidb) * dbch->ndesc * dbch->ndb, 11119336Sdfr M_DEVBUF, M_DONTWAIT, 0x10000, 0xffffffff, PAGE_SIZE, 0ul); 111225663Sdfr if(db == NULL){ 11139336Sdfr printf("fwochi_db_init: contigmalloc failed\n"); 11149336Sdfr free(db_tr, M_DEVBUF); 11159336Sdfr return; 11169336Sdfr } 11179336Sdfr bzero(db, sizeof (struct fwohcidb) * dbch->ndesc * dbch->ndb); 11189336Sdfr /* Attach DB to DMA ch. */ 11199336Sdfr for(idb = 0 ; idb < dbch->ndb ; idb++){ 11209336Sdfr db_tr->dbcnt = 0; 11219336Sdfr db_tr->db = &db[idb * dbch->ndesc]; 112227446Sdfr STAILQ_INSERT_TAIL(&dbch->db_trq, db_tr, link); 11239336Sdfr if(!(dbch->xferq.flag & FWXFERQ_PACKET) && 11249336Sdfr (idb % dbch->xferq.bnpacket == 0)){ 11259336Sdfr dbch->xferq.bulkxfer[idb/dbch->xferq.bnpacket].start 11269336Sdfr = (caddr_t)db_tr; 11279336Sdfr } 11289336Sdfr if((!(dbch->xferq.flag & FWXFERQ_PACKET)) && 11291541Srgrimes ((idb + 1)% dbch->xferq.bnpacket == 0)){ 11309336Sdfr dbch->xferq.bulkxfer[idb/dbch->xferq.bnpacket].end 11319336Sdfr = (caddr_t)db_tr; 11329336Sdfr } 11339336Sdfr db_tr++; 11349336Sdfr } 11359336Sdfr STAILQ_LAST(&dbch->db_trq, fwohcidb_tr,link)->link.stqe_next 113636251Speter = STAILQ_FIRST(&dbch->db_trq); 11379336Sdfr dbch->top = STAILQ_FIRST(&dbch->db_trq); 11389336Sdfr dbch->bottom = dbch->top; 11399336Sdfr dbch->flags = FWOHCI_DBCH_INIT; 11409336Sdfr} 11419336Sdfr 11429336Sdfrstatic int 11439336Sdfrfwohci_itx_disable(struct firewire_comm *fc, int dmach) 11449336Sdfr{ 11459336Sdfr struct fwohci_softc *sc = (struct fwohci_softc *)fc; 11469336Sdfr OWRITE(sc, OHCI_ITCTLCLR(dmach), OHCI_CNTL_DMA_RUN); 11479336Sdfr OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach); 11489336Sdfr OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach); 11499336Sdfr fwohci_db_free(&sc->it[dmach]); 11509336Sdfr sc->it[dmach].xferq.flag &= ~FWXFERQ_RUNNING; 11519336Sdfr return 0; 11529336Sdfr} 11539336Sdfr 11549336Sdfrstatic int 11559336Sdfrfwohci_irx_disable(struct firewire_comm *fc, int dmach) 11561541Srgrimes{ 11579336Sdfr struct fwohci_softc *sc = (struct fwohci_softc *)fc; 11589336Sdfr 11599336Sdfr OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN); 11609336Sdfr OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach); 11619336Sdfr OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach); 11629336Sdfr if(sc->ir[dmach].dummy != NULL){ 11639336Sdfr free(sc->ir[dmach].dummy, M_DEVBUF); 11649336Sdfr } 11659336Sdfr sc->ir[dmach].dummy = NULL; 11669336Sdfr fwohci_db_free(&sc->ir[dmach]); 11679336Sdfr sc->ir[dmach].xferq.flag &= ~FWXFERQ_RUNNING; 11689336Sdfr return 0; 11699336Sdfr} 11709336Sdfr 11719336Sdfrstatic void 11729336Sdfrfwohci_irx_post (struct firewire_comm *fc , u_int32_t *qld) 11739336Sdfr{ 11749336Sdfr qld[0] = ntohl(qld[0]); 11759336Sdfr return; 11761541Srgrimes} 11779336Sdfr 11789336Sdfrstatic int 11799336Sdfrfwohci_irxpp_enable(struct firewire_comm *fc, int dmach) 118017761Sdyson{ 11811541Srgrimes struct fwohci_softc *sc = (struct fwohci_softc *)fc; 11829336Sdfr int err = 0; 11839336Sdfr unsigned short tag, ich; 11849336Sdfr 11859336Sdfr tag = (sc->ir[dmach].xferq.flag >> 6) & 3; 11869336Sdfr ich = sc->ir[dmach].xferq.flag & 0x3f; 11879336Sdfr 11889336Sdfr#if 0 118925663Sdfr if(STAILQ_FIRST(&fc->ir[dmach]->q) != NULL){ 11909336Sdfr wakeup(fc->ir[dmach]); 11919336Sdfr return err; 11929336Sdfr } 11939336Sdfr#endif 11949336Sdfr 11959336Sdfr OWRITE(sc, OHCI_IRMATCH(dmach), tagbit[tag] | ich); 11969336Sdfr if(!(sc->ir[dmach].xferq.flag & FWXFERQ_RUNNING)){ 11979336Sdfr sc->ir[dmach].xferq.queued = 0; 11989336Sdfr sc->ir[dmach].ndb = NDB; 11999336Sdfr sc->ir[dmach].xferq.psize = FWPMAX_S400; 12009336Sdfr sc->ir[dmach].ndesc = 1; 12019336Sdfr fwohci_db_init(&sc->ir[dmach]); 12029336Sdfr err = fwohci_rx_enable(sc, &sc->ir[dmach]); 12039336Sdfr } 12049336Sdfr if(err){ 12059336Sdfr device_printf(sc->fc.dev, "err in IRX setting\n"); 12069336Sdfr return err; 12079336Sdfr } 12089336Sdfr if(!(OREAD(sc, OHCI_IRCTL(dmach)) & OHCI_CNTL_DMA_ACTIVE)){ 12099336Sdfr OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN); 12109336Sdfr OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach); 12119336Sdfr OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach); 12129336Sdfr OWRITE(sc, OHCI_IR_MASK, 1 << dmach); 12139336Sdfr OWRITE(sc, OHCI_IRCTLCLR(dmach), 0xf8000000); 12149336Sdfr OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_ISOHDR); 12159336Sdfr OWRITE(sc, OHCI_IRCMD(dmach), 12169336Sdfr vtophys(sc->ir[dmach].top->db) | 1); 12179336Sdfr OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_DMA_RUN); 12189336Sdfr OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IR); 12199336Sdfr } 12209336Sdfr return err; 12219336Sdfr} 12229336Sdfr 12239336Sdfrstatic int 12249336Sdfrfwohci_tx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch) 12259336Sdfr{ 12269336Sdfr int err = 0; 12279336Sdfr int idb, z, i, dmach = 0; 12289336Sdfr u_int32_t off = NULL; 12299336Sdfr struct fwohcidb_tr *db_tr; 12309336Sdfr 12319336Sdfr if(!(dbch->xferq.flag & FWXFERQ_EXTBUF)){ 12329336Sdfr err = EINVAL; 12339336Sdfr return err; 12349336Sdfr } 12359336Sdfr z = dbch->ndesc; 12369336Sdfr for(dmach = 0 ; dmach < sc->fc.nisodma ; dmach++){ 12379336Sdfr if( &sc->it[dmach] == dbch){ 12389336Sdfr off = OHCI_ITOFF(dmach); 12399336Sdfr break; 12409336Sdfr } 12419336Sdfr } 12429336Sdfr if(off == NULL){ 12439336Sdfr err = EINVAL; 12449336Sdfr return err; 12459336Sdfr } 12469336Sdfr if(dbch->xferq.flag & FWXFERQ_RUNNING) 12479336Sdfr return err; 12489336Sdfr dbch->xferq.flag |= FWXFERQ_RUNNING; 124925663Sdfr for( i = 0, dbch->bottom = dbch->top; i < (dbch->ndb - 1); i++){ 12509336Sdfr dbch->bottom = STAILQ_NEXT(dbch->bottom, link); 12519336Sdfr } 12529336Sdfr db_tr = dbch->top; 12539336Sdfr for( idb = 0 ; idb < dbch->ndb ; idb ++){ 12541541Srgrimes fwohci_add_tx_buf(db_tr, 12559336Sdfr dbch->xferq.psize, dbch->xferq.flag, 12569336Sdfr dbch->xferq.buf + dbch->xferq.psize * idb); 12579336Sdfr if(STAILQ_NEXT(db_tr, link) == NULL){ 12589336Sdfr break; 12599336Sdfr } 12609336Sdfr db_tr->db[0].db.desc.depend 12619336Sdfr = vtophys(STAILQ_NEXT(db_tr, link)->db) | z; 12629336Sdfr db_tr->db[db_tr->dbcnt - 1].db.desc.depend 12639336Sdfr = vtophys(STAILQ_NEXT(db_tr, link)->db) | z; 12649336Sdfr if(dbch->xferq.flag & FWXFERQ_EXTBUF){ 12659336Sdfr if(((idb + 1 ) % dbch->xferq.bnpacket) == 0){ 12669336Sdfr db_tr->db[db_tr->dbcnt - 1].db.desc.cmd 126712911Sphk |= OHCI_INTERRUPT_ALWAYS; 12689336Sdfr db_tr->db[0].db.desc.depend &= ~0xf; 12699336Sdfr db_tr->db[db_tr->dbcnt - 1].db.desc.depend &= 12709336Sdfr ~0xf; 12719336Sdfr } 12729336Sdfr } 12739336Sdfr db_tr = STAILQ_NEXT(db_tr, link); 127425663Sdfr } 12759336Sdfr dbch->bottom->db[db_tr->dbcnt - 1].db.desc.depend &= 0xfffffff0; 127625663Sdfr return err; 127725663Sdfr} 12789336Sdfr 12799336Sdfrstatic int 12809336Sdfrfwohci_rx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch) 12819336Sdfr{ 12829336Sdfr int err = 0; 12839336Sdfr int idb, z, i, dmach = 0; 12849336Sdfr u_int32_t off = NULL; 12859336Sdfr struct fwohcidb_tr *db_tr; 12869336Sdfr 12879336Sdfr z = dbch->ndesc; 12889336Sdfr if(&sc->arrq == dbch){ 12899336Sdfr off = OHCI_ARQOFF; 12909336Sdfr }else if(&sc->arrs == dbch){ 12919336Sdfr off = OHCI_ARSOFF; 12929336Sdfr }else{ 12939336Sdfr for(dmach = 0 ; dmach < sc->fc.nisodma ; dmach++){ 12949336Sdfr if( &sc->ir[dmach] == dbch){ 12959336Sdfr off = OHCI_IROFF(dmach); 12969336Sdfr break; 12979336Sdfr } 12989336Sdfr } 12999336Sdfr } 130025663Sdfr if(off == NULL){ 130125663Sdfr err = EINVAL; 130225663Sdfr return err; 130325663Sdfr } 130425663Sdfr if(dbch->xferq.flag & FWXFERQ_STREAM){ 130525663Sdfr if(dbch->xferq.flag & FWXFERQ_RUNNING) 130625663Sdfr return err; 130725663Sdfr }else{ 130825663Sdfr if(dbch->xferq.flag & FWXFERQ_RUNNING){ 130925663Sdfr err = EBUSY; 13109336Sdfr return err; 13119336Sdfr } 13129336Sdfr } 13131541Srgrimes dbch->xferq.flag |= FWXFERQ_RUNNING; 13141541Srgrimes for( i = 0, dbch->bottom = dbch->top; i < (dbch->ndb - 1); i++){ 13151541Srgrimes dbch->bottom = STAILQ_NEXT(dbch->bottom, link); 13161549Srgrimes } 13179336Sdfr db_tr = dbch->top; 13189336Sdfr for( idb = 0 ; idb < dbch->ndb ; idb ++){ 13199336Sdfr if(!(dbch->xferq.flag & FWXFERQ_EXTBUF)){ 13209336Sdfr fwohci_add_rx_buf(db_tr, 13219336Sdfr dbch->xferq.psize, dbch->xferq.flag, 0, NULL); 13221541Srgrimes }else{ 13239336Sdfr fwohci_add_rx_buf(db_tr, 132428270Swollman dbch->xferq.psize, dbch->xferq.flag, 13259336Sdfr dbch->xferq.buf + dbch->xferq.psize * idb, 13269336Sdfr dbch->dummy + sizeof(u_int32_t) * idb); 13279336Sdfr } 13289336Sdfr if(STAILQ_NEXT(db_tr, link) == NULL){ 13291541Srgrimes break; 13301541Srgrimes } 13311541Srgrimes db_tr->db[db_tr->dbcnt - 1].db.desc.depend 13321541Srgrimes = vtophys(STAILQ_NEXT(db_tr, link)->db) | z; 13331541Srgrimes if(dbch->xferq.flag & FWXFERQ_EXTBUF){ 13341541Srgrimes if(((idb + 1 ) % dbch->xferq.bnpacket) == 0){ 13351541Srgrimes db_tr->db[db_tr->dbcnt - 1].db.desc.cmd 13369336Sdfr |= OHCI_INTERRUPT_ALWAYS; 13379336Sdfr db_tr->db[db_tr->dbcnt - 1].db.desc.depend &= 13381541Srgrimes ~0xf; 13391541Srgrimes } 13409336Sdfr } 13419336Sdfr db_tr = STAILQ_NEXT(db_tr, link); 13421541Srgrimes } 13439336Sdfr dbch->bottom->db[db_tr->dbcnt - 1].db.desc.depend &= 0xfffffff0; 13449336Sdfr dbch->buf_offset = 0; 13451541Srgrimes if(dbch->xferq.flag & FWXFERQ_STREAM){ 13469336Sdfr return err; 13479336Sdfr }else{ 13489336Sdfr OWRITE(sc, OHCI_DMACMD(off), vtophys(dbch->top->db) | z); 13491541Srgrimes } 13501541Srgrimes OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_RUN); 13511541Srgrimes return err; 13529336Sdfr} 13531541Srgrimes 13541541Srgrimesstatic int 13551541Srgrimesfwohci_itxbuf_enable(struct firewire_comm *fc, int dmach) 13569336Sdfr{ 135727446Sdfr struct fwohci_softc *sc = (struct fwohci_softc *)fc; 13589336Sdfr int err = 0; 13599336Sdfr unsigned short tag, ich; 13609336Sdfr struct fwohci_dbch *dbch; 13619336Sdfr struct fw_pkt *fp; 13629336Sdfr struct fwohcidb_tr *db_tr; 136317761Sdyson 13649336Sdfr tag = (sc->it[dmach].xferq.flag >> 6) & 3; 13659336Sdfr ich = sc->it[dmach].xferq.flag & 0x3f; 13669336Sdfr dbch = &sc->it[dmach]; 13679336Sdfr if(dbch->ndb == 0){ 13689336Sdfr dbch->xferq.queued = 0; 13699336Sdfr dbch->ndb = dbch->xferq.bnpacket * dbch->xferq.bnchunk; 13709336Sdfr dbch->ndesc = 3; 137117761Sdyson fwohci_db_init(dbch); 13729336Sdfr err = fwohci_tx_enable(sc, dbch); 13739336Sdfr } 13741541Srgrimes if(err) 13759336Sdfr return err; 13769336Sdfr if(OREAD(sc, OHCI_ITCTL(dmach)) & OHCI_CNTL_DMA_ACTIVE){ 13779336Sdfr if(dbch->xferq.stdma2 != NULL){ 13789336Sdfr fwohci_txbufdb(sc, dmach, dbch->xferq.stdma2); 13799336Sdfr ((struct fwohcidb_tr *) 13809336Sdfr (dbch->xferq.stdma->end))->db[dbch->ndesc - 1].db.desc.cmd 13819336Sdfr |= OHCI_BRANCH_ALWAYS; 13829336Sdfr ((struct fwohcidb_tr *) 13839336Sdfr (dbch->xferq.stdma->end))->db[dbch->ndesc - 1].db.desc.depend = 13849336Sdfr vtophys(((struct fwohcidb_tr *)(dbch->xferq.stdma2->start))->db) | dbch->ndesc; 13859336Sdfr ((struct fwohcidb_tr *)(dbch->xferq.stdma->end))->db[0].db.desc.depend = 13869336Sdfr vtophys(((struct fwohcidb_tr *)(dbch->xferq.stdma2->start))->db) | dbch->ndesc; 13879336Sdfr ((struct fwohcidb_tr *)(dbch->xferq.stdma2->end))->db[dbch->ndesc - 1].db.desc.depend &= ~0xf; 13889336Sdfr ((struct fwohcidb_tr *)(dbch->xferq.stdma2->end))->db[0].db.desc.depend &= ~0xf; 13899336Sdfr } 13909336Sdfr }else if(!(OREAD(sc, OHCI_ITCTL(dmach)) & OHCI_CNTL_DMA_ACTIVE)){ 13919336Sdfr fw_tbuf_update(&sc->fc, dmach, 0); 13929336Sdfr if(dbch->xferq.stdma == NULL){ 13939336Sdfr return err; 13949336Sdfr } 13959336Sdfr OWRITE(sc, OHCI_ITCTLCLR(dmach), OHCI_CNTL_DMA_RUN); 13969336Sdfr OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach); 13979336Sdfr OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach); 13989336Sdfr OWRITE(sc, OHCI_IT_MASK, 1 << dmach); 13999336Sdfr OWRITE(sc, OHCI_ITCTLCLR(dmach), 0xf0000000); 14009336Sdfr fwohci_txbufdb(sc, dmach, dbch->xferq.stdma); 14019336Sdfr if(dbch->xferq.stdma2 != NULL){ 14029336Sdfr fwohci_txbufdb(sc, dmach, dbch->xferq.stdma2); 14039336Sdfr ((struct fwohcidb_tr *) 14049336Sdfr (dbch->xferq.stdma->end))->db[dbch->ndesc - 1].db.desc.cmd 14059336Sdfr |= OHCI_BRANCH_ALWAYS; 14069336Sdfr ((struct fwohcidb_tr *)(dbch->xferq.stdma->end))->db[dbch->ndesc - 1].db.desc.depend = 14079336Sdfr vtophys(((struct fwohcidb_tr *)(dbch->xferq.stdma2->start))->db) | dbch->ndesc; 14089336Sdfr ((struct fwohcidb_tr *)(dbch->xferq.stdma->end))->db[0].db.desc.depend = 14099336Sdfr vtophys(((struct fwohcidb_tr *)(dbch->xferq.stdma2->start))->db) | dbch->ndesc; 14109336Sdfr ((struct fwohcidb_tr *)(dbch->xferq.stdma2->end))->db[dbch->ndesc - 1].db.desc.depend &= ~0xf; 14119336Sdfr ((struct fwohcidb_tr *) (dbch->xferq.stdma2->end))->db[0].db.desc.depend &= ~0xf; 14129336Sdfr }else{ 141336503Speter ((struct fwohcidb_tr *) (dbch->xferq.stdma->end))->db[dbch->ndesc - 1].db.desc.depend &= ~0xf; 141436503Speter ((struct fwohcidb_tr *) (dbch->xferq.stdma->end))->db[0].db.desc.depend &= ~0xf; 14159336Sdfr } 14169336Sdfr OWRITE(sc, OHCI_ITCMD(dmach), 14179336Sdfr vtophys(((struct fwohcidb_tr *) 14181541Srgrimes (dbch->xferq.stdma->start))->db) | dbch->ndesc); 14191541Srgrimes if(dbch->xferq.flag & FWXFERQ_DV){ 14201541Srgrimes db_tr = (struct fwohcidb_tr *)dbch->xferq.stdma->start; 14211541Srgrimes fp = (struct fw_pkt *)db_tr->buf; 14221541Srgrimes fp->mode.ld[2] = htonl(0x80000000 + 14231541Srgrimes ((fc->cyctimer(fc) + 0x3000) & 0xf000)); 14241541Srgrimes } 142517761Sdyson 14269336Sdfr OWRITE(sc, OHCI_ITCTL(dmach), OHCI_CNTL_DMA_RUN); 14279336Sdfr OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IT); 142835823Smsmith } 14299336Sdfr return err; 143017761Sdyson} 143129653Sdyson 14329336Sdfrstatic int 14339336Sdfrfwohci_irxbuf_enable(struct firewire_comm *fc, int dmach) 14349336Sdfr{ 14359336Sdfr struct fwohci_softc *sc = (struct fwohci_softc *)fc; 14369336Sdfr int err = 0; 14379336Sdfr unsigned short tag, ich; 14389336Sdfr tag = (sc->ir[dmach].xferq.flag >> 6) & 3; 14399336Sdfr ich = sc->ir[dmach].xferq.flag & 0x3f; 14409336Sdfr OWRITE(sc, OHCI_IRMATCH(dmach), tagbit[tag] | ich); 14411541Srgrimes 14421541Srgrimes if(!(sc->ir[dmach].xferq.flag & FWXFERQ_RUNNING)){ 14431541Srgrimes sc->ir[dmach].xferq.queued = 0; 14441541Srgrimes sc->ir[dmach].ndb = sc->ir[dmach].xferq.bnpacket * 144526637Sbde sc->ir[dmach].xferq.bnchunk; 144626637Sbde sc->ir[dmach].dummy = 144717761Sdyson malloc(sizeof(u_int32_t) * sc->ir[dmach].ndb, 144829653Sdyson M_DEVBUF, M_DONTWAIT); 14499336Sdfr if(sc->ir[dmach].dummy == NULL){ 145017761Sdyson err = ENOMEM; 14511541Srgrimes return err; 14529336Sdfr } 14539336Sdfr sc->ir[dmach].ndesc = 2; 14549336Sdfr fwohci_db_init(&sc->ir[dmach]); 14559336Sdfr err = fwohci_rx_enable(sc, &sc->ir[dmach]); 145635823Smsmith } 145735823Smsmith if(err) 145835823Smsmith return err; 145917761Sdyson 14609336Sdfr if(OREAD(sc, OHCI_IRCTL(dmach)) & OHCI_CNTL_DMA_ACTIVE){ 14611541Srgrimes if(sc->ir[dmach].xferq.stdma2 != NULL){ 14621541Srgrimes ((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[sc->ir[dmach].ndesc - 1].db.desc.depend = 14631541Srgrimes vtophys(((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->start))->db) | sc->ir[dmach].ndesc; 14649336Sdfr ((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[0].db.desc.depend = 14659336Sdfr vtophys(((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->start))->db); 146636503Speter ((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->end))->db[sc->ir[dmach].ndesc - 1].db.desc.depend &= ~0xf; 146729653Sdyson ((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->end))->db[0].db.desc.depend &= ~0xf; 14681541Srgrimes } 14691541Srgrimes }else if(!(OREAD(sc, OHCI_IRCTL(dmach)) & OHCI_CNTL_DMA_ACTIVE) 147017761Sdyson && !(sc->ir[dmach].xferq.flag & FWXFERQ_PACKET)){ 147129653Sdyson fw_rbuf_update(&sc->fc, dmach, 0); 14721541Srgrimes 147317761Sdyson OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN); 147417761Sdyson OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach); 14751541Srgrimes OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach); 14761541Srgrimes OWRITE(sc, OHCI_IR_MASK, 1 << dmach); 14771541Srgrimes OWRITE(sc, OHCI_IRCTLCLR(dmach), 0xf0000000); 14781541Srgrimes OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_ISOHDR); 14791541Srgrimes if(sc->ir[dmach].xferq.stdma2 != NULL){ 148017761Sdyson ((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[sc->ir[dmach].ndesc - 1].db.desc.depend = 148129653Sdyson vtophys(((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->start))->db) | sc->ir[dmach].ndesc; 14821541Srgrimes ((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[0].db.desc.depend = 148317761Sdyson vtophys(((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->start))->db); 14841541Srgrimes ((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->end))->db[sc->ir[dmach].ndesc - 1].db.desc.depend &= ~0xf; 14851541Srgrimes }else{ 14861541Srgrimes ((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[sc->ir[dmach].ndesc - 1].db.desc.depend &= ~0xf; 14871541Srgrimes ((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[0].db.desc.depend &= ~0xf; 148817761Sdyson } 148929653Sdyson OWRITE(sc, OHCI_IRCMD(dmach), 14901541Srgrimes vtophys(((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->start))->db) | sc->ir[dmach].ndesc); 14911541Srgrimes OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_DMA_RUN); 149217761Sdyson } 14931541Srgrimes OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IR); 149417761Sdyson return err; 14951541Srgrimes} 14961541Srgrimes 14973305Sphkstatic int 149836251Speterfwohci_irx_enable(struct firewire_comm *fc, int dmach) 14999336Sdfr{ 15009336Sdfr struct fwohci_softc *sc = (struct fwohci_softc *)fc; 15019336Sdfr int err = 0; 15029336Sdfr 15039336Sdfr if(sc->ir[dmach].xferq.flag & FWXFERQ_PACKET){ 15049336Sdfr err = fwohci_irxpp_enable(fc, dmach); 15059336Sdfr return err; 15061541Srgrimes }else{ 15079336Sdfr err = fwohci_irxbuf_enable(fc, dmach); 150817761Sdyson return err; 15091541Srgrimes } 15101541Srgrimes} 15119336Sdfr 15129336Sdfrint 15139336Sdfrfwohci_shutdown(device_t dev) 15149336Sdfr{ 15159336Sdfr u_int i; 15169336Sdfr struct fwohci_softc *sc = device_get_softc(dev); 151717761Sdyson 15181541Srgrimes/* Now stopping all DMA channel */ 15199336Sdfr OWRITE(sc, OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN); 15209336Sdfr OWRITE(sc, OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN); 15219336Sdfr OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN); 15229336Sdfr OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN); 15239336Sdfr 152417761Sdyson for( i = 0 ; i < sc->fc.nisodma ; i ++ ){ 15259336Sdfr OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN); 15269336Sdfr OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN); 15279336Sdfr } 15289336Sdfr 15299336Sdfr/* FLUSH FIFO and reset Transmitter/Reciever */ 15309336Sdfr OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_RESET); 15319336Sdfr 15329336Sdfr/* Stop interrupt */ 15339336Sdfr OWRITE(sc, FWOHCI_INTMASKCLR, 15349336Sdfr OHCI_INT_EN | OHCI_INT_ERR | OHCI_INT_PHY_SID 15359336Sdfr | OHCI_INT_PHY_INT 15369336Sdfr | OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS 15379336Sdfr | OHCI_INT_DMA_PRRQ | OHCI_INT_DMA_PRRS 15389336Sdfr | OHCI_INT_DMA_ARRQ | OHCI_INT_DMA_ARRS 15391541Srgrimes | OHCI_INT_PHY_BUS_R); 15409336Sdfr return 0; 154117761Sdyson} 15429336Sdfr 154317761Sdyson#define ACK_ALL 154429653Sdysonstatic void 15459336Sdfrfwohci_intr_body(struct fwohci_softc *sc, u_int32_t stat, int count) 15461541Srgrimes{ 15471541Srgrimes u_int32_t irstat, itstat; 154817761Sdyson u_int i; 15491541Srgrimes struct firewire_comm *fc = (struct firewire_comm *)sc; 155017761Sdyson 15511541Srgrimes#ifdef OHCI_DEBUG 155217761Sdyson if(stat & OREAD(sc, FWOHCI_INTMASK)) 15531541Srgrimes 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", 15549336Sdfr stat & OHCI_INT_EN ? "DMA_EN ":"", 15551541Srgrimes stat & OHCI_INT_PHY_REG ? "PHY_REG ":"", 15569336Sdfr stat & OHCI_INT_CYC_LONG ? "CYC_LONG ":"", 15579336Sdfr stat & OHCI_INT_ERR ? "INT_ERR ":"", 15589336Sdfr stat & OHCI_INT_CYC_ERR ? "CYC_ERR ":"", 15599336Sdfr stat & OHCI_INT_CYC_LOST ? "CYC_LOST ":"", 15609336Sdfr stat & OHCI_INT_CYC_64SECOND ? "CYC_64SECOND ":"", 15619336Sdfr stat & OHCI_INT_CYC_START ? "CYC_START ":"", 15629336Sdfr stat & OHCI_INT_PHY_INT ? "PHY_INT ":"", 15639336Sdfr stat & OHCI_INT_PHY_BUS_R ? "BUS_RESET ":"", 15649336Sdfr stat & OHCI_INT_PHY_SID ? "SID ":"", 15659336Sdfr stat & OHCI_INT_LR_ERR ? "DMA_LR_ERR ":"", 15669336Sdfr stat & OHCI_INT_PW_ERR ? "DMA_PW_ERR ":"", 156728270Swollman stat & OHCI_INT_DMA_IR ? "DMA_IR ":"", 15689336Sdfr stat & OHCI_INT_DMA_IT ? "DMA_IT " :"", 15699336Sdfr stat & OHCI_INT_DMA_PRRS ? "DMA_PRRS " :"", 15709336Sdfr stat & OHCI_INT_DMA_PRRQ ? "DMA_PRRQ " :"", 15719336Sdfr stat & OHCI_INT_DMA_ARRS ? "DMA_ARRS " :"", 15729336Sdfr stat & OHCI_INT_DMA_ARRQ ? "DMA_ARRQ " :"", 15739336Sdfr stat & OHCI_INT_DMA_ATRS ? "DMA_ATRS " :"", 15749336Sdfr stat & OHCI_INT_DMA_ATRQ ? "DMA_ATRQ " :"", 15759336Sdfr stat, OREAD(sc, FWOHCI_INTMASK) 157611921Sphk ); 15779336Sdfr#endif 15789336Sdfr/* Bus reset */ 15799336Sdfr if(stat & OHCI_INT_PHY_BUS_R ){ 15809336Sdfr device_printf(fc->dev, "BUS reset\n"); 15819336Sdfr OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST); 15829336Sdfr OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCSRC); 15839336Sdfr 15849336Sdfr OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN); 15859336Sdfr sc->atrq.xferq.flag &= ~FWXFERQ_RUNNING; 15869336Sdfr OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN); 15879336Sdfr sc->atrs.xferq.flag &= ~FWXFERQ_RUNNING; 15889336Sdfr 15899336Sdfr#if 0 15909336Sdfr for( i = 0 ; i < fc->nisodma ; i ++ ){ 15919336Sdfr OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN); 15929336Sdfr OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN); 15939336Sdfr } 159427446Sdfr 15959336Sdfr#endif 15969336Sdfr fw_busreset(fc); 15979336Sdfr 15989336Sdfr /* XXX need to wait DMA to stop */ 15999336Sdfr#ifndef ACK_ALL 16009336Sdfr OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_BUS_R); 160117761Sdyson#endif 16029336Sdfr#if 1 16039336Sdfr /* pending all pre-bus_reset packets */ 16049336Sdfr fwohci_txd(sc, &sc->atrq); 16059336Sdfr fwohci_txd(sc, &sc->atrs); 16069336Sdfr fwohci_arcv(sc, &sc->arrs, -1); 160717761Sdyson fwohci_arcv(sc, &sc->arrq, -1); 160829653Sdyson#endif 16099336Sdfr 16109336Sdfr 161117761Sdyson OWRITE(sc, OHCI_AREQHI, 1 << 31); 16129336Sdfr /* XXX insecure ?? */ 16139336Sdfr OWRITE(sc, OHCI_PREQHI, 0x7fffffff); 16149336Sdfr OWRITE(sc, OHCI_PREQLO, 0xffffffff); 16159336Sdfr OWRITE(sc, OHCI_PREQUPPER, 0x10000); 16169336Sdfr 16179336Sdfr } 16189336Sdfr if((stat & OHCI_INT_DMA_IR )){ 16199336Sdfr#ifndef ACK_ALL 16209336Sdfr OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_IR); 16219336Sdfr#endif 16229336Sdfr irstat = OREAD(sc, OHCI_IR_STAT); 16239336Sdfr OWRITE(sc, OHCI_IR_STATCLR, ~0); 16249336Sdfr for(i = 0; i < fc->nisodma ; i++){ 16259336Sdfr if((irstat & (1 << i)) != 0){ 16269336Sdfr if(sc->ir[i].xferq.flag & FWXFERQ_PACKET){ 162717761Sdyson fwohci_ircv(sc, &sc->ir[i], count); 162829653Sdyson }else{ 16299336Sdfr fwohci_rbuf_update(sc, i); 16309336Sdfr } 163117761Sdyson } 16329336Sdfr } 16339336Sdfr } 16349336Sdfr if((stat & OHCI_INT_DMA_IT )){ 16359336Sdfr#ifndef ACK_ALL 163617761Sdyson OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_IT); 16379336Sdfr#endif 16389336Sdfr itstat = OREAD(sc, OHCI_IT_STAT); 163935823Smsmith OWRITE(sc, OHCI_IT_STATCLR, ~0); 16409336Sdfr for(i = 0; i < fc->nisodma ; i++){ 164129653Sdyson if((itstat & (1 << i)) != 0){ 16429336Sdfr fwohci_tbuf_update(sc, i); 164326637Sbde } 164417761Sdyson } 164529653Sdyson } 16469336Sdfr if((stat & OHCI_INT_DMA_PRRS )){ 164717761Sdyson#ifndef ACK_ALL 16489336Sdfr OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_PRRS); 16499336Sdfr#endif 16509336Sdfr#if 0 165135823Smsmith dump_dma(sc, ARRS_CH); 165235823Smsmith dump_db(sc, ARRS_CH); 165335823Smsmith#endif 165417761Sdyson fwohci_arcv(sc, &sc->arrs, count); 16559336Sdfr } 16569336Sdfr if((stat & OHCI_INT_DMA_PRRQ )){ 16579336Sdfr#ifndef ACK_ALL 16589336Sdfr OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_PRRQ); 16599336Sdfr#endif 16609336Sdfr#if 0 16619336Sdfr dump_dma(sc, ARRQ_CH); 166229653Sdyson dump_db(sc, ARRQ_CH); 16639336Sdfr#endif 16649336Sdfr fwohci_arcv(sc, &sc->arrq, count); 16659336Sdfr } 166617761Sdyson if(stat & OHCI_INT_PHY_SID){ 166717761Sdyson caddr_t buf; 16689336Sdfr int plen; 16699336Sdfr 16709336Sdfr#ifndef ACK_ALL 16719336Sdfr OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_SID); 16721541Srgrimes#endif 16739336Sdfr/* 16749336Sdfr** Checking whether the node is root or not. If root, turn on 16759336Sdfr** cycle master. 16769336Sdfr*/ 16779336Sdfr device_printf(fc->dev, "node_id = 0x%08x, ", OREAD(sc, FWOHCI_NODEID)); 16789336Sdfr if(!(OREAD(sc, FWOHCI_NODEID) & OHCI_NODE_VALID)){ 16799336Sdfr printf("Bus reset failure\n"); 168017761Sdyson goto sidout; 16819336Sdfr } 16829336Sdfr if( OREAD(sc, FWOHCI_NODEID) & OHCI_NODE_ROOT ){ 168317761Sdyson printf("CYCLEMASTER mode\n"); 16849336Sdfr OWRITE(sc, OHCI_LNKCTL, 16859336Sdfr OHCI_CNTL_CYCMTR | OHCI_CNTL_CYCTIMER); 16869336Sdfr }else{ 16879336Sdfr printf("non CYCLEMASTER mode\n"); 16889336Sdfr OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCMTR); 16899336Sdfr OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_CYCTIMER); 16901549Srgrimes } 16919336Sdfr fc->nodeid = OREAD(sc, FWOHCI_NODEID) & 0x3f; 16929336Sdfr 169317761Sdyson plen = OREAD(sc, OHCI_SID_CNT) & OHCI_SID_CNT_MASK; 16949336Sdfr plen -= 4; /* chop control info */ 169517761Sdyson buf = malloc( FWPMAX_S400, M_DEVBUF, M_NOWAIT); 169629653Sdyson if(buf == NULL) goto sidout; 16979336Sdfr bcopy((void *)(uintptr_t)(volatile void *)fc->sid_buf, 16989336Sdfr buf, plen); 16999336Sdfr fw_sidrcv(fc, buf, plen, 0); 170017761Sdyson } 17019336Sdfrsidout: 170217761Sdyson if((stat & OHCI_INT_DMA_ATRQ )){ 17039336Sdfr#ifndef ACK_ALL 170417761Sdyson OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_ATRQ); 17059336Sdfr#endif 17061541Srgrimes fwohci_txd(sc, &(sc->atrq)); 17071541Srgrimes } 17081541Srgrimes if((stat & OHCI_INT_DMA_ATRS )){ 17091541Srgrimes#ifndef ACK_ALL 17101541Srgrimes OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_ATRS); 17111549Srgrimes#endif 17129336Sdfr fwohci_txd(sc, &(sc->atrs)); 17139336Sdfr } 17149336Sdfr if((stat & OHCI_INT_PW_ERR )){ 17159336Sdfr#ifndef ACK_ALL 17169336Sdfr OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PW_ERR); 17171541Srgrimes#endif 17189336Sdfr device_printf(fc->dev, "posted write error\n"); 171928270Swollman } 17209336Sdfr if((stat & OHCI_INT_ERR )){ 17219336Sdfr#ifndef ACK_ALL 17221541Srgrimes OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_ERR); 17231541Srgrimes#endif 17241541Srgrimes device_printf(fc->dev, "unrecoverable error\n"); 17251541Srgrimes } 17269336Sdfr if((stat & OHCI_INT_PHY_INT)) { 17279336Sdfr#ifndef ACK_ALL 17281541Srgrimes OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_INT); 172911921Sphk#endif 17309336Sdfr device_printf(fc->dev, "phy int\n"); 17319336Sdfr } 17329336Sdfr 17331541Srgrimes return; 17341541Srgrimes} 17351541Srgrimes 17369336Sdfrvoid 17379336Sdfrfwohci_intr(void *arg) 17389336Sdfr{ 17391541Srgrimes struct fwohci_softc *sc = (struct fwohci_softc *)arg; 17401541Srgrimes u_int32_t stat; 17419336Sdfr 17421541Srgrimes if (!(sc->intmask & OHCI_INT_EN)) { 17431541Srgrimes /* polling mode */ 17441541Srgrimes return; 17459336Sdfr } 174627446Sdfr 17479336Sdfr while ((stat = OREAD(sc, FWOHCI_INTSTAT)) != 0) { 17489336Sdfr if (stat == 0xffffffff) { 17499336Sdfr device_printf(sc->fc.dev, 17509336Sdfr "device physically ejected?\n"); 17519336Sdfr return; 175217761Sdyson } 17531541Srgrimes#ifdef ACK_ALL 17549336Sdfr OWRITE(sc, FWOHCI_INTSTATCLR, stat); 17559336Sdfr#endif 175624249Speter fwohci_intr_body(sc, stat, -1); 175724249Speter } 17589336Sdfr} 175924249Speter 17609336Sdfrstatic void 17619336Sdfrfwohci_poll(struct firewire_comm *fc, int quick, int count) 17629336Sdfr{ 17639336Sdfr int s; 17649336Sdfr u_int32_t stat; 17659336Sdfr struct fwohci_softc *sc; 17669336Sdfr 17671541Srgrimes 17689336Sdfr sc = (struct fwohci_softc *)fc; 17699336Sdfr stat = OHCI_INT_DMA_IR | OHCI_INT_DMA_IT | 17709336Sdfr OHCI_INT_DMA_PRRS | OHCI_INT_DMA_PRRQ | 17719336Sdfr OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS; 17729336Sdfr#if 0 17739336Sdfr if (!quick) { 177435823Smsmith#else 177535823Smsmith if (1) { 177635823Smsmith#endif 177735823Smsmith stat = OREAD(sc, FWOHCI_INTSTAT); 177835823Smsmith if (stat == 0) 177935823Smsmith return; 178017761Sdyson if (stat == 0xffffffff) { 17811541Srgrimes device_printf(sc->fc.dev, 17829336Sdfr "device physically ejected?\n"); 17839336Sdfr return; 178417761Sdyson } 17859336Sdfr#ifdef ACK_ALL 17869336Sdfr OWRITE(sc, FWOHCI_INTSTATCLR, stat); 17879336Sdfr#endif 17889336Sdfr } 17899336Sdfr s = splfw(); 17909336Sdfr fwohci_intr_body(sc, stat, count); 17911541Srgrimes splx(s); 17921541Srgrimes} 17931541Srgrimes 17941541Srgrimesstatic void 17951541Srgrimesfwohci_set_intr(struct firewire_comm *fc, int enable) 17961541Srgrimes{ 17971549Srgrimes struct fwohci_softc *sc; 17989336Sdfr 17999336Sdfr sc = (struct fwohci_softc *)fc; 18009336Sdfr if (bootverbose) 18019336Sdfr device_printf(sc->fc.dev, "fwochi_set_intr: %d\n", enable); 18029336Sdfr if (enable) { 18031541Srgrimes sc->intmask |= OHCI_INT_EN; 18049336Sdfr OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_EN); 180528270Swollman } else { 18069336Sdfr sc->intmask &= ~OHCI_INT_EN; 18079336Sdfr OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_EN); 18081541Srgrimes } 18091541Srgrimes} 18101541Srgrimes 18119336Sdfrstatic void 18129336Sdfrfwohci_tbuf_update(struct fwohci_softc *sc, int dmach) 18139336Sdfr{ 18141541Srgrimes int stat; 181511921Sphk struct firewire_comm *fc = &sc->fc; 18161541Srgrimes struct fw_pkt *fp; 18179336Sdfr struct fwohci_dbch *dbch; 18189336Sdfr struct fwohcidb_tr *db_tr; 18199336Sdfr 18209336Sdfr dbch = &sc->it[dmach]; 18211541Srgrimes if((dbch->xferq.flag & FWXFERQ_DV) && (dbch->xferq.stdma2 != NULL)){ 18221541Srgrimes db_tr = (struct fwohcidb_tr *)dbch->xferq.stdma2->start; 18231541Srgrimes/* 18241541Srgrimes * Overwrite highest significant 4 bits timestamp information 18259336Sdfr */ 18269336Sdfr fp = (struct fw_pkt *)db_tr->buf; 18279336Sdfr fp->mode.ld[2] |= htonl(0x80000000 | 18281541Srgrimes ((fc->cyctimer(fc) + 0x4000) & 0xf000)); 18291541Srgrimes } 18301541Srgrimes stat = OREAD(sc, OHCI_ITCTL(dmach)) & 0x1f; 18311541Srgrimes switch(stat){ 18321541Srgrimes case FWOHCIEV_ACKCOMPL: 18339336Sdfr fw_tbuf_update(fc, dmach, 1); 18341541Srgrimes break; 18351541Srgrimes default: 18361541Srgrimes fw_tbuf_update(fc, dmach, 0); 18371541Srgrimes break; 18381541Srgrimes } 18391541Srgrimes fwohci_itxbuf_enable(&sc->fc, dmach); 18401541Srgrimes} 18411541Srgrimes 18429336Sdfrstatic void 184327446Sdfrfwohci_rbuf_update(struct fwohci_softc *sc, int dmach) 18449336Sdfr{ 18459336Sdfr int stat; 18469336Sdfr stat = OREAD(sc, OHCI_IRCTL(dmach)) & 0x1f; 18479336Sdfr switch(stat){ 18489336Sdfr case FWOHCIEV_ACKCOMPL: 184917761Sdyson fw_rbuf_update(&sc->fc, dmach, 1); 18509336Sdfr wakeup(sc->fc.ir[dmach]); 18519336Sdfr fwohci_irx_enable(&sc->fc, dmach); 18529336Sdfr break; 18539336Sdfr default: 18549336Sdfr break; 18559336Sdfr } 18569336Sdfr} 18579336Sdfr 185817761Sdysonvoid 18599336Sdfrdump_dma(struct fwohci_softc *sc, u_int32_t ch) 18609336Sdfr{ 18611541Srgrimes u_int32_t off, cntl, stat, cmd, match; 18621541Srgrimes 18631541Srgrimes if(ch == 0){ 18641541Srgrimes off = OHCI_ATQOFF; 18651541Srgrimes }else if(ch == 1){ 18661541Srgrimes off = OHCI_ATSOFF; 18671541Srgrimes }else if(ch == 2){ 18689336Sdfr off = OHCI_ARQOFF; 186927446Sdfr }else if(ch == 3){ 18709336Sdfr off = OHCI_ARSOFF; 18719336Sdfr }else if(ch < IRX_CH){ 18729336Sdfr off = OHCI_ITCTL(ch - ITX_CH); 18739336Sdfr }else{ 18749336Sdfr off = OHCI_IRCTL(ch - IRX_CH); 187517761Sdyson } 18769336Sdfr cntl = stat = OREAD(sc, off); 18779336Sdfr cmd = OREAD(sc, off + 0xc); 18789336Sdfr match = OREAD(sc, off + 0x10); 18793305Sphk 18801541Srgrimes device_printf(sc->fc.dev, "dma ch %1x:dma regs 0x%08x 0x%08x 0x%08x 0x%08x \n", 188117761Sdyson ch, 188217761Sdyson cntl, 18831541Srgrimes stat, 18841541Srgrimes cmd, 18851541Srgrimes match); 18861541Srgrimes stat &= 0xffff ; 18871541Srgrimes if(stat & 0xff00){ 18881541Srgrimes device_printf(sc->fc.dev, "dma %d ch:%s%s%s%s%s%s %s(%x)\n", 18899336Sdfr ch, 18909336Sdfr stat & OHCI_CNTL_DMA_RUN ? "RUN," : "", 18919336Sdfr stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "", 18929336Sdfr stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "", 18931541Srgrimes stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "", 18941541Srgrimes stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "", 18959336Sdfr stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "", 18969336Sdfr fwohcicode[stat & 0x1f], 18979336Sdfr stat & 0x1f 18989336Sdfr ); 18991541Srgrimes }else{ 19001541Srgrimes device_printf(sc->fc.dev, "dma %d ch: Nostat\n", ch); 19011541Srgrimes } 19029336Sdfr} 19039336Sdfr 19049336Sdfrvoid 19059336Sdfrdump_db(struct fwohci_softc *sc, u_int32_t ch) 19061541Srgrimes{ 19071541Srgrimes struct fwohci_dbch *dbch; 19081541Srgrimes struct fwohcidb_tr *cp = NULL, *pp, *np; 19091541Srgrimes volatile struct fwohcidb *curr = NULL, *prev, *next = NULL; 19109336Sdfr int idb, jdb; 19119336Sdfr u_int32_t cmd, off; 19129336Sdfr if(ch == 0){ 19139336Sdfr off = OHCI_ATQOFF; 19141541Srgrimes dbch = &sc->atrq; 19151541Srgrimes }else if(ch == 1){ 19161541Srgrimes off = OHCI_ATSOFF; 19179336Sdfr dbch = &sc->atrs; 19189336Sdfr }else if(ch == 2){ 19199336Sdfr off = OHCI_ARQOFF; 19209336Sdfr dbch = &sc->arrq; 19211541Srgrimes }else if(ch == 3){ 19221541Srgrimes off = OHCI_ARSOFF; 19231541Srgrimes dbch = &sc->arrs; 19249336Sdfr }else if(ch < IRX_CH){ 19259336Sdfr off = OHCI_ITCTL(ch - ITX_CH); 19269336Sdfr dbch = &sc->it[ch - ITX_CH]; 19279336Sdfr }else { 19281541Srgrimes off = OHCI_IRCTL(ch - IRX_CH); 19291541Srgrimes dbch = &sc->ir[ch - IRX_CH]; 19301541Srgrimes } 19311541Srgrimes cmd = OREAD(sc, off + 0xc); 19321541Srgrimes 19331541Srgrimes if( dbch->ndb == 0 ){ 19341541Srgrimes device_printf(sc->fc.dev, "No DB is attached ch=%d\n", ch); 19351541Srgrimes return; 19361541Srgrimes } 19371541Srgrimes pp = dbch->top; 19381541Srgrimes prev = pp->db; 19391541Srgrimes for(idb = 0 ; idb < dbch->ndb ; idb ++ ){ 19409336Sdfr if(pp == NULL){ 19419336Sdfr curr = NULL; 19428832Sdg goto outdb; 19439336Sdfr } 19448832Sdg cp = STAILQ_NEXT(pp, link); 19451541Srgrimes if(cp == NULL){ 19461541Srgrimes curr = NULL; 19471541Srgrimes goto outdb; 19481541Srgrimes } 19491541Srgrimes np = STAILQ_NEXT(cp, link); 195017761Sdyson if(cp == NULL) break; 19511541Srgrimes for(jdb = 0 ; jdb < dbch->ndesc ; jdb ++ ){ 195217761Sdyson if((cmd & 0xfffffff0) 19531541Srgrimes == vtophys(&(cp->db[jdb]))){ 195417761Sdyson curr = cp->db; 19551541Srgrimes if(np != NULL){ 195617761Sdyson next = np->db; 195717761Sdyson }else{ 19589336Sdfr next = NULL; 19599336Sdfr } 19601541Srgrimes goto outdb; 196117761Sdyson } 196229653Sdyson } 19631541Srgrimes pp = STAILQ_NEXT(pp, link); 19649336Sdfr prev = pp->db; 19659336Sdfr } 196617761Sdysonoutdb: 19679336Sdfr if( curr != NULL){ 19689336Sdfr printf("Prev DB %d\n", ch); 19699336Sdfr print_db(prev, ch, dbch->ndesc); 197017761Sdyson printf("Current DB %d\n", ch); 19719336Sdfr print_db(curr, ch, dbch->ndesc); 197217761Sdyson printf("Next DB %d\n", ch); 197329653Sdyson print_db(next, ch, dbch->ndesc); 19749336Sdfr }else{ 19759336Sdfr printf("dbdump err ch = %d cmd = 0x%08x\n", ch, cmd); 19769336Sdfr } 19779336Sdfr return; 19789336Sdfr} 19799336Sdfr 19801541Srgrimesvoid 19811541Srgrimesprint_db(volatile struct fwohcidb *db, u_int32_t ch, u_int32_t max) 19829336Sdfr{ 198317761Sdyson fwohcireg_t stat; 19849336Sdfr int i, key; 198517761Sdyson 19869336Sdfr if(db == NULL){ 198717761Sdyson printf("No Descriptor is found\n"); 198829653Sdyson return; 19891541Srgrimes } 19909336Sdfr 199117761Sdyson printf("ch = %d\n%8s %s %s %s %s %4s %8s %8s %4s:%4s\n", 199229653Sdyson ch, 19931541Srgrimes "Current", 199417761Sdyson "OP ", 199517761Sdyson "KEY", 19961541Srgrimes "INT", 19971541Srgrimes "BR ", 19981541Srgrimes "len", 19991541Srgrimes "Addr", 20001541Srgrimes "Depend", 20011541Srgrimes "Stat", 20021541Srgrimes "Cnt"); 20031549Srgrimes for( i = 0 ; i <= max ; i ++){ 20049336Sdfr key = db[i].db.desc.cmd & OHCI_KEY_MASK; 20059336Sdfr printf("%08tx %s %s %s %s %5d %08x %08x %04x:%04x", 20069336Sdfr vtophys(&db[i]), 20079336Sdfr dbcode[(db[i].db.desc.cmd >> 28) & 0xf], 20089336Sdfr dbkey[(db[i].db.desc.cmd >> 24) & 0x7], 20091541Srgrimes dbcond[(db[i].db.desc.cmd >> 20) & 0x3], 20109336Sdfr dbcond[(db[i].db.desc.cmd >> 18) & 0x3], 201128270Swollman db[i].db.desc.cmd & 0xffff, 20129336Sdfr db[i].db.desc.addr, 20139336Sdfr db[i].db.desc.depend, 20141541Srgrimes db[i].db.desc.status, 20151541Srgrimes db[i].db.desc.count); 20161541Srgrimes stat = db[i].db.desc.status; 20171541Srgrimes if(stat & 0xff00){ 20189336Sdfr printf(" %s%s%s%s%s%s %s(%x)\n", 20199336Sdfr stat & OHCI_CNTL_DMA_RUN ? "RUN," : "", 20201541Srgrimes stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "", 202111921Sphk stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "", 20229336Sdfr stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "", 20239336Sdfr stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "", 20249336Sdfr stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "", 20251541Srgrimes fwohcicode[stat & 0x1f], 20261541Srgrimes stat & 0x1f 20271541Srgrimes ); 20281541Srgrimes }else{ 20291541Srgrimes printf(" Nostat\n"); 20301541Srgrimes } 20311541Srgrimes if(key == OHCI_KEY_ST2 ){ 20329336Sdfr printf("0x%08x 0x%08x 0x%08x 0x%08x\n", 203336503Speter db[i+1].db.immed[0], 203436503Speter db[i+1].db.immed[1], 203536503Speter db[i+1].db.immed[2], 20369336Sdfr db[i+1].db.immed[3]); 20379336Sdfr } 20389336Sdfr if(key == OHCI_KEY_DEVICE){ 20399336Sdfr return; 20409336Sdfr } 204124249Speter if((db[i].db.desc.cmd & OHCI_BRANCH_MASK) 204224249Speter == OHCI_BRANCH_ALWAYS){ 20431541Srgrimes return; 204424249Speter } 20451541Srgrimes if((db[i].db.desc.cmd & OHCI_CMD_MASK) 20461541Srgrimes == OHCI_OUTPUT_LAST){ 20471541Srgrimes return; 20489336Sdfr } 204927446Sdfr if((db[i].db.desc.cmd & OHCI_CMD_MASK) 20509336Sdfr == OHCI_INPUT_LAST){ 20519336Sdfr return; 20529336Sdfr } 20539336Sdfr if(key == OHCI_KEY_ST2 ){ 20549336Sdfr i++; 205517761Sdyson } 20569336Sdfr } 20579336Sdfr return; 20589336Sdfr} 20593305Sphk 20601541Srgrimesvoid 20611541Srgrimesfwohci_ibr(struct firewire_comm *fc) 20621541Srgrimes{ 20631541Srgrimes struct fwohci_softc *sc; 20641541Srgrimes u_int32_t fun; 20651541Srgrimes 20661541Srgrimes sc = (struct fwohci_softc *)fc; 20671541Srgrimes 20681541Srgrimes /* 20691541Srgrimes * Set root hold-off bit so that non cyclemaster capable node 20701541Srgrimes * shouldn't became the root node. 20719336Sdfr */ 20729336Sdfr fun = fwphy_rddata(sc, FW_PHY_RHB_REG); 207324250Speter fun |= FW_PHY_RHB; 207435823Smsmith fun = fwphy_wrdata(sc, FW_PHY_RHB_REG, fun); 20751541Srgrimes#if 1 20761541Srgrimes fun = fwphy_rddata(sc, FW_PHY_IBR_REG); 20771541Srgrimes fun |= FW_PHY_IBR; 207817761Sdyson fun = fwphy_wrdata(sc, FW_PHY_IBR_REG, fun); 20791541Srgrimes#else 208017761Sdyson fun = fwphy_rddata(sc, FW_PHY_ISBR_REG); 20811541Srgrimes fun |= FW_PHY_ISBR; 208217761Sdyson fun = fwphy_wrdata(sc, FW_PHY_ISBR_REG, fun); 20831541Srgrimes#endif 20841541Srgrimes} 20859336Sdfr 20869336Sdfrvoid 20879336Sdfrfwohci_txbufdb(struct fwohci_softc *sc, int dmach, struct fw_bulkxfer *bulkxfer) 20889336Sdfr{ 208917761Sdyson struct fwohcidb_tr *db_tr, *fdb_tr; 20909336Sdfr struct fwohci_dbch *dbch; 209117761Sdyson struct fw_pkt *fp; 20929336Sdfr volatile struct fwohci_txpkthdr *ohcifp; 20939336Sdfr unsigned short chtag; 20949336Sdfr int idb; 20959336Sdfr 20969336Sdfr dbch = &sc->it[dmach]; 20979336Sdfr chtag = sc->it[dmach].xferq.flag & 0xff; 20981541Srgrimes 20991541Srgrimes db_tr = (struct fwohcidb_tr *)(bulkxfer->start); 21001541Srgrimes fdb_tr = (struct fwohcidb_tr *)(bulkxfer->end); 21011541Srgrimes/* 21021541Srgrimesdevice_printf(sc->fc.dev, "DB %08x %08x %08x\n", bulkxfer, vtophys(db_tr->db), vtophys(fdb_tr->db)); 21031541Srgrimes*/ 21041549Srgrimes if(bulkxfer->flag != 0){ 21059336Sdfr return; 21069336Sdfr } 21079336Sdfr bulkxfer->flag = 1; 21089336Sdfr for( idb = 0 ; idb < bulkxfer->npacket ; idb ++){ 21099336Sdfr db_tr->db[0].db.desc.cmd 21101541Srgrimes = OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | 8; 21119336Sdfr fp = (struct fw_pkt *)db_tr->buf; 211228270Swollman ohcifp = (volatile struct fwohci_txpkthdr *) 21139336Sdfr db_tr->db[1].db.immed; 21149336Sdfr ohcifp->mode.ld[0] = ntohl(fp->mode.ld[0]); 21159336Sdfr ohcifp->mode.stream.len = ntohs(fp->mode.stream.len); 21161541Srgrimes ohcifp->mode.stream.chtag = chtag; 21171541Srgrimes ohcifp->mode.stream.tcode = 0xa; 21181541Srgrimes ohcifp->mode.stream.spd = 4; 21191541Srgrimes ohcifp->mode.ld[2] = ntohl(fp->mode.ld[1]); 21201541Srgrimes ohcifp->mode.ld[3] = ntohl(fp->mode.ld[2]); 212111921Sphk 21221541Srgrimes db_tr->db[2].db.desc.cmd 21231541Srgrimes = OHCI_OUTPUT_LAST 21249336Sdfr | OHCI_UPDATE 21259336Sdfr | OHCI_BRANCH_ALWAYS 21269336Sdfr | ((ntohs(fp->mode.stream.len) ) & 0xffff); 21279336Sdfr db_tr->db[2].db.desc.status = 0; 21289336Sdfr db_tr->db[2].db.desc.count = 0; 21291541Srgrimes if(dbch->xferq.flag & FWXFERQ_DV){ 21301541Srgrimes db_tr->db[0].db.desc.depend 21311541Srgrimes = vtophys(STAILQ_NEXT(db_tr, link)->db) | dbch->ndesc; 21329336Sdfr db_tr->db[dbch->ndesc - 1].db.desc.depend 21331541Srgrimes = vtophys(STAILQ_NEXT(db_tr, link)->db) | dbch->ndesc; 21341541Srgrimes }else{ 21359336Sdfr db_tr->db[0].db.desc.depend 21361541Srgrimes = vtophys(STAILQ_NEXT(db_tr, link)->db) | dbch->ndesc; 21371541Srgrimes db_tr->db[dbch->ndesc - 1].db.desc.depend 21389336Sdfr = vtophys(STAILQ_NEXT(db_tr, link)->db) | dbch->ndesc; 21399336Sdfr } 214027446Sdfr bulkxfer->end = (caddr_t)db_tr; 21419336Sdfr db_tr = STAILQ_NEXT(db_tr, link); 21429336Sdfr } 21439336Sdfr db_tr = (struct fwohcidb_tr *)bulkxfer->end; 21449336Sdfr db_tr->db[0].db.desc.depend &= ~0xf; 21459336Sdfr db_tr->db[dbch->ndesc - 1].db.desc.depend &= ~0xf; 214617761Sdyson/**/ 21479336Sdfr db_tr->db[dbch->ndesc - 1].db.desc.cmd &= ~OHCI_BRANCH_ALWAYS; 21489336Sdfr db_tr->db[dbch->ndesc - 1].db.desc.cmd |= OHCI_BRANCH_NEVER; 21499336Sdfr/**/ 21503305Sphk db_tr->db[dbch->ndesc - 1].db.desc.cmd |= OHCI_INTERRUPT_ALWAYS; 21511541Srgrimes 21529336Sdfr db_tr = (struct fwohcidb_tr *)bulkxfer->start; 21539336Sdfr fdb_tr = (struct fwohcidb_tr *)bulkxfer->end; 21549336Sdfr/* 21551541Srgrimesdevice_printf(sc->fc.dev, "DB %08x %3d %08x %08x\n", bulkxfer, bulkxfer->npacket, vtophys(db_tr->db), vtophys(fdb_tr->db)); 21561541Srgrimes*/ 21571541Srgrimes return; 21581541Srgrimes} 21591541Srgrimes 21601541Srgrimesstatic int 21611541Srgrimesfwohci_add_tx_buf(struct fwohcidb_tr *db_tr, unsigned short size, 21621541Srgrimes int mode, void *buf) 21631541Srgrimes{ 21641541Srgrimes volatile struct fwohcidb *db = db_tr->db; 21651541Srgrimes int err = 0; 21661541Srgrimes if(buf == 0){ 21679336Sdfr err = EINVAL; 21689336Sdfr return err; 21699336Sdfr } 21709336Sdfr db_tr->buf = buf; 21711541Srgrimes db_tr->dbcnt = 3; 21721541Srgrimes db_tr->dummy = NULL; 217317761Sdyson 217429653Sdyson db[0].db.desc.cmd = OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | 8; 21751541Srgrimes 21761541Srgrimes db[2].db.desc.depend = 0; 217717761Sdyson db[2].db.desc.addr = vtophys(buf) + sizeof(u_int32_t); 21781541Srgrimes db[2].db.desc.cmd = OHCI_OUTPUT_MORE; 217917761Sdyson 218017761Sdyson db[0].db.desc.status = 0; 21811541Srgrimes db[0].db.desc.count = 0; 21821541Srgrimes 21831541Srgrimes db[2].db.desc.status = 0; 21849336Sdfr db[2].db.desc.count = 0; 21851541Srgrimes if( mode & FWXFERQ_STREAM ){ 218635823Smsmith db[2].db.desc.cmd |= OHCI_OUTPUT_LAST; 21879336Sdfr if(mode & FWXFERQ_PACKET ){ 218817761Sdyson db[2].db.desc.cmd 21899336Sdfr |= OHCI_INTERRUPT_ALWAYS; 21909336Sdfr } 21919336Sdfr } 21929336Sdfr db[2].db.desc.cmd |= OHCI_BRANCH_ALWAYS; 21939336Sdfr return 1; 21949336Sdfr} 21959336Sdfr 21969336Sdfrint 21979336Sdfrfwohci_add_rx_buf(struct fwohcidb_tr *db_tr, unsigned short size, int mode, 21989336Sdfr void *buf, void *dummy) 21999336Sdfr{ 22009336Sdfr volatile struct fwohcidb *db = db_tr->db; 22019336Sdfr int i; 22029336Sdfr void *dbuf[2]; 22039336Sdfr int dsiz[2]; 220417761Sdyson 22059336Sdfr if(buf == 0){ 22069336Sdfr buf = malloc(size, M_DEVBUF, M_NOWAIT); 220717761Sdyson if(buf == NULL) return 0; 220829653Sdyson db_tr->buf = buf; 22099336Sdfr db_tr->dbcnt = 1; 22101541Srgrimes db_tr->dummy = NULL; 22111541Srgrimes dsiz[0] = size; 22121541Srgrimes dbuf[0] = buf; 22139336Sdfr }else if(dummy == NULL){ 22149336Sdfr db_tr->buf = buf; 221517761Sdyson db_tr->dbcnt = 1; 22169336Sdfr db_tr->dummy = NULL; 22179336Sdfr dsiz[0] = size; 22189336Sdfr dbuf[0] = buf; 22199336Sdfr }else{ 22209336Sdfr db_tr->buf = buf; 22219336Sdfr db_tr->dbcnt = 2; 22229336Sdfr db_tr->dummy = dummy; 22239336Sdfr dsiz[0] = sizeof(u_int32_t); 22249336Sdfr dsiz[1] = size; 22259336Sdfr dbuf[0] = dummy; 22261541Srgrimes dbuf[1] = buf; 22279336Sdfr } 222817761Sdyson for(i = 0 ; i < db_tr->dbcnt ; i++){ 222929653Sdyson db[i].db.desc.addr = vtophys(dbuf[i]) ; 22309336Sdfr db[i].db.desc.cmd = OHCI_INPUT_MORE | dsiz[i]; 22319336Sdfr if( mode & FWXFERQ_STREAM ){ 223217761Sdyson db[i].db.desc.cmd |= OHCI_UPDATE; 22331541Srgrimes } 22341541Srgrimes db[i].db.desc.status = 0; 223517761Sdyson db[i].db.desc.count = dsiz[i]; 22361541Srgrimes } 223717761Sdyson if( mode & FWXFERQ_STREAM ){ 22381541Srgrimes db[db_tr->dbcnt - 1].db.desc.cmd |= OHCI_INPUT_LAST; 223917761Sdyson if(mode & FWXFERQ_PACKET ){ 22401541Srgrimes db[db_tr->dbcnt - 1].db.desc.cmd 22411541Srgrimes |= OHCI_INTERRUPT_ALWAYS; 22421541Srgrimes } 22431541Srgrimes } 22441541Srgrimes db[db_tr->dbcnt - 1].db.desc.cmd |= OHCI_BRANCH_ALWAYS; 22451541Srgrimes return 1; 22461541Srgrimes} 22471541Srgrimes 22481549Srgrimesstatic void 22499336Sdfrfwohci_ircv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count) 22509336Sdfr{ 22519336Sdfr struct fwohcidb_tr *db_tr = dbch->top, *odb_tr; 22529336Sdfr struct firewire_comm *fc = (struct firewire_comm *)sc; 22539336Sdfr int z = 1; 22541541Srgrimes struct fw_pkt *fp; 22559336Sdfr u_int8_t *ld; 225628270Swollman u_int32_t off = NULL; 22579336Sdfr u_int32_t stat; 22589336Sdfr u_int32_t *qld; 22599336Sdfr u_int32_t reg; 22601541Srgrimes u_int spd; 22619336Sdfr u_int dmach; 22621541Srgrimes int len, i, plen; 22631541Srgrimes caddr_t buf; 22641541Srgrimes 22651541Srgrimes for(dmach = 0 ; dmach < sc->fc.nisodma ; dmach++){ 22661541Srgrimes if( &sc->ir[dmach] == dbch){ 22679336Sdfr off = OHCI_IROFF(dmach); 22689336Sdfr break; 22691541Srgrimes } 22701541Srgrimes } 22719336Sdfr if(off == NULL){ 22729336Sdfr return; 22731541Srgrimes } 22741541Srgrimes if(!(dbch->xferq.flag & FWXFERQ_RUNNING)){ 22751541Srgrimes fwohci_irx_disable(&sc->fc, dmach); 22761541Srgrimes return; 22771541Srgrimes } 22789336Sdfr 22791541Srgrimes odb_tr = NULL; 22801541Srgrimes db_tr = dbch->top; 22811541Srgrimes i = 0; 22829336Sdfr while ((reg = db_tr->db[0].db.desc.status) & 0x1f) { 228327446Sdfr if (count >= 0 && count-- == 0) 22849336Sdfr break; 22859336Sdfr ld = (u_int8_t *)db_tr->buf; 22869336Sdfr if (dbch->xferq.flag & FWXFERQ_PACKET) { 22879336Sdfr /* skip timeStamp */ 22889336Sdfr ld += sizeof(struct fwohci_trailer); 228917761Sdyson } 22909336Sdfr qld = (u_int32_t *)ld; 22919336Sdfr len = dbch->xferq.psize - (db_tr->db[0].db.desc.count); 22929336Sdfr/* 22939336Sdfr{ 22949336Sdfrdevice_printf(sc->fc.dev, "%04x %2x 0x%08x 0x%08x 0x%08x 0x%08x\n", len, 22959336Sdfr db_tr->db[0].db.desc.status & 0x1f, qld[0],qld[1],qld[2],qld[3]); 22969336Sdfr} 229717761Sdyson*/ 22989336Sdfr fp=(struct fw_pkt *)ld; 22999336Sdfr qld[0] = htonl(qld[0]); 23001541Srgrimes plen = sizeof(struct fw_isohdr) 23019336Sdfr + ntohs(fp->mode.stream.len) + sizeof(u_int32_t); 23029336Sdfr ld += plen; 23039336Sdfr len -= plen; 23049336Sdfr buf = db_tr->buf; 23059336Sdfr db_tr->buf = NULL; 23069336Sdfr stat = reg & 0x1f; 23071541Srgrimes spd = reg & 0x3; 23081541Srgrimes switch(stat){ 23091541Srgrimes case FWOHCIEV_ACKCOMPL: 23101541Srgrimes case FWOHCIEV_ACKPEND: 23111541Srgrimes fw_rcv(&sc->fc, buf, plen - sizeof(u_int32_t), dmach, sizeof(u_int32_t), spd); 231217761Sdyson break; 23131541Srgrimes default: 231417761Sdyson free(buf, M_DEVBUF); 231517761Sdyson device_printf(sc->fc.dev, "Isochronous receive err %02x\n", stat); 23161541Srgrimes break; 23179336Sdfr } 23181541Srgrimes i++; 23199336Sdfr fwohci_add_rx_buf(db_tr, dbch->xferq.psize, 23203305Sphk dbch->xferq.flag, 0, NULL); 232135823Smsmith db_tr->db[0].db.desc.depend &= ~0xf; 23229336Sdfr if(dbch->pdb_tr != NULL){ 23239336Sdfr dbch->pdb_tr->db[0].db.desc.depend |= z; 23249336Sdfr } else { 23259336Sdfr /* XXX should be rewritten in better way */ 23269336Sdfr dbch->bottom->db[0].db.desc.depend |= z; 23279336Sdfr } 23289336Sdfr dbch->pdb_tr = db_tr; 232917761Sdyson db_tr = STAILQ_NEXT(db_tr, link); 23301541Srgrimes } 23319336Sdfr dbch->top = db_tr; 23329336Sdfr reg = OREAD(sc, OHCI_DMACTL(off)); 23339336Sdfr if (reg & OHCI_CNTL_DMA_ACTIVE) 233417761Sdyson return; 23359336Sdfr device_printf(sc->fc.dev, "IR DMA %d stopped at %x status=%x (%d)\n", 23369336Sdfr dmach, OREAD(sc, OHCI_DMACMD(off)), reg, i); 23379336Sdfr dbch->top = db_tr; 23389336Sdfr fwohci_irx_enable(fc, dmach); 23399336Sdfr} 23409336Sdfr 23419336Sdfr#define PLEN(x) (((ntohs(x))+0x3) & ~0x3) 23429336Sdfrstatic int 23439336Sdfrfwohci_get_plen(struct fwohci_softc *sc, struct fw_pkt *fp, int hlen) 23449336Sdfr{ 23459336Sdfr int i; 23469336Sdfr 23479336Sdfr for( i = 4; i < hlen ; i+=4){ 23489336Sdfr fp->mode.ld[i/4] = htonl(fp->mode.ld[i/4]); 23491541Srgrimes } 23509336Sdfr 235117761Sdyson switch(fp->mode.common.tcode){ 23521541Srgrimes case FWTCODE_RREQQ: 23531541Srgrimes return sizeof(fp->mode.rreqq) + sizeof(u_int32_t); 235417761Sdyson case FWTCODE_WRES: 23551541Srgrimes return sizeof(fp->mode.wres) + sizeof(u_int32_t); 235617761Sdyson case FWTCODE_WREQQ: 23571541Srgrimes return sizeof(fp->mode.wreqq) + sizeof(u_int32_t); 235817761Sdyson case FWTCODE_RREQB: 23591541Srgrimes return sizeof(fp->mode.rreqb) + sizeof(u_int32_t); 23601541Srgrimes case FWTCODE_RRESQ: 23611541Srgrimes return sizeof(fp->mode.rresq) + sizeof(u_int32_t); 23621541Srgrimes case FWTCODE_WREQB: 23631541Srgrimes return sizeof(struct fw_asyhdr) + PLEN(fp->mode.wreqb.len) 23641541Srgrimes + sizeof(u_int32_t); 23651549Srgrimes case FWTCODE_LREQ: 23669336Sdfr return sizeof(struct fw_asyhdr) + PLEN(fp->mode.lreq.len) 23679336Sdfr + sizeof(u_int32_t); 23689336Sdfr case FWTCODE_RRESB: 23699336Sdfr return sizeof(struct fw_asyhdr) + PLEN(fp->mode.rresb.len) 23709336Sdfr + sizeof(u_int32_t); 23711541Srgrimes case FWTCODE_LRES: 23729336Sdfr return sizeof(struct fw_asyhdr) + PLEN(fp->mode.lres.len) 237328270Swollman + sizeof(u_int32_t); 23749336Sdfr case FWOHCITCODE_PHY: 23759336Sdfr return 16; 23761541Srgrimes } 23771541Srgrimes device_printf(sc->fc.dev, "Unknown tcode %d\n", fp->mode.common.tcode); 23781541Srgrimes return 0; 23799336Sdfr} 23809336Sdfr 23811541Srgrimesstatic void 238211921Sphkfwohci_arcv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count) 23839336Sdfr{ 23849336Sdfr struct fwohcidb_tr *db_tr; 23859336Sdfr int z = 1; 23861541Srgrimes struct fw_pkt *fp; 23871541Srgrimes u_int8_t *ld; 23881541Srgrimes u_int32_t stat, off; 23891541Srgrimes u_int spd; 23901541Srgrimes int len, plen, hlen, pcnt, poff = 0, rlen; 23911541Srgrimes int s; 23929336Sdfr caddr_t buf; 23931541Srgrimes int resCount; 23941541Srgrimes 23951541Srgrimes if(&sc->arrq == dbch){ 23969336Sdfr off = OHCI_ARQOFF; 239727446Sdfr }else if(&sc->arrs == dbch){ 23989336Sdfr off = OHCI_ARSOFF; 23999336Sdfr }else{ 24009336Sdfr return; 24019336Sdfr } 24029336Sdfr 240317761Sdyson s = splfw(); 24049336Sdfr db_tr = dbch->top; 24059336Sdfr pcnt = 0; 24069336Sdfr /* XXX we cannot handle a packet which lies in more than two buf */ 24079336Sdfr while (db_tr->db[0].db.desc.status & OHCI_CNTL_DMA_ACTIVE) { 24089336Sdfr ld = (u_int8_t *)db_tr->buf + dbch->buf_offset; 24099336Sdfr resCount = db_tr->db[0].db.desc.count; 24109336Sdfr len = dbch->xferq.psize - resCount 241117761Sdyson - dbch->buf_offset; 24129336Sdfr while (len > 0 ) { 24139336Sdfr if (count >= 0 && count-- == 0) 24141541Srgrimes goto out; 24151541Srgrimes if(dbch->frag.buf != NULL){ 24161541Srgrimes buf = dbch->frag.buf; 24171541Srgrimes if (dbch->frag.plen < 0) { 24181541Srgrimes /* incomplete header */ 24191541Srgrimes int hlen; 24201541Srgrimes 24211541Srgrimes hlen = - dbch->frag.plen; 24221541Srgrimes rlen = hlen - dbch->frag.len; 24231541Srgrimes bcopy(ld, dbch->frag.buf + dbch->frag.len, rlen); 24241541Srgrimes ld += rlen; 24251541Srgrimes len -= rlen; 24261541Srgrimes dbch->frag.len += rlen; 24271541Srgrimes#if 0 24281541Srgrimes printf("(1)frag.plen=%d frag.len=%d rlen=%d len=%d\n", dbch->frag.plen, dbch->frag.len, rlen, len); 24291541Srgrimes#endif 24301541Srgrimes fp=(struct fw_pkt *)dbch->frag.buf; 24311541Srgrimes dbch->frag.plen 24321541Srgrimes = fwohci_get_plen(sc, fp, hlen); 24339336Sdfr if (dbch->frag.plen == 0) 24349336Sdfr goto out; 24351541Srgrimes } 24361541Srgrimes rlen = dbch->frag.plen - dbch->frag.len; 24371541Srgrimes#if 0 243835823Smsmith printf("(2)frag.plen=%d frag.len=%d rlen=%d len=%d\n", dbch->frag.plen, dbch->frag.len, rlen, len); 243935823Smsmith#endif 244035823Smsmith bcopy(ld, dbch->frag.buf + dbch->frag.len, 244135823Smsmith rlen); 244235823Smsmith ld += rlen; 244335823Smsmith len -= rlen; 244417761Sdyson plen = dbch->frag.plen; 24459336Sdfr dbch->frag.buf = NULL; 24469336Sdfr dbch->frag.plen = 0; 244717761Sdyson dbch->frag.len = 0; 24489336Sdfr poff = 0; 24499336Sdfr }else{ 24509336Sdfr fp=(struct fw_pkt *)ld; 24519336Sdfr fp->mode.ld[0] = htonl(fp->mode.ld[0]); 24529336Sdfr switch(fp->mode.common.tcode){ 24539336Sdfr case FWTCODE_RREQQ: 24541541Srgrimes case FWTCODE_WRES: 24551541Srgrimes case FWTCODE_WREQQ: 24561541Srgrimes case FWTCODE_RRESQ: 24571541Srgrimes case FWOHCITCODE_PHY: 24581541Srgrimes hlen = 12; 24591541Srgrimes break; 24601541Srgrimes case FWTCODE_RREQB: 24611541Srgrimes case FWTCODE_WREQB: 24621541Srgrimes case FWTCODE_LREQ: 24631541Srgrimes case FWTCODE_RRESB: 24641541Srgrimes case FWTCODE_LRES: 24651541Srgrimes hlen = 16; 24661541Srgrimes break; 24671541Srgrimes default: 24681541Srgrimes device_printf(sc->fc.dev, "Unknown tcode %d\n", fp->mode.common.tcode); 24691541Srgrimes goto out; 24701541Srgrimes } 24711541Srgrimes if (len >= hlen) { 24721541Srgrimes plen = fwohci_get_plen(sc, fp, hlen); 24731541Srgrimes if (plen == 0) 24741541Srgrimes goto out; 24751541Srgrimes plen = (plen + 3) & ~3; 24761541Srgrimes len -= plen; 24779336Sdfr } else { 24781541Srgrimes plen = -hlen; 24791541Srgrimes len -= hlen; 24801541Srgrimes } 24811541Srgrimes if(resCount > 0 || len > 0){ 24821541Srgrimes buf = malloc( dbch->xferq.psize, 24831541Srgrimes M_DEVBUF, M_NOWAIT); 24841541Srgrimes if(buf == NULL){ 24851541Srgrimes printf("cannot malloc!\n"); 24861541Srgrimes free(db_tr->buf, M_DEVBUF); 24879336Sdfr goto out; 24889336Sdfr } 24899336Sdfr bcopy(ld, buf, plen); 24909336Sdfr poff = 0; 24919336Sdfr dbch->frag.buf = NULL; 24929336Sdfr dbch->frag.plen = 0; 24931541Srgrimes dbch->frag.len = 0; 24941541Srgrimes }else if(len < 0){ 24951549Srgrimes dbch->frag.buf = db_tr->buf; 24969336Sdfr if (plen < 0) { 24979336Sdfr#if 0 24989336Sdfr printf("plen < 0:" 24999336Sdfr "hlen: %d len: %d\n", 25009336Sdfr hlen, len); 25011541Srgrimes#endif 25029336Sdfr dbch->frag.len = hlen + len; 250328270Swollman dbch->frag.plen = -hlen; 25049336Sdfr } else { 25059336Sdfr dbch->frag.len = plen + len; 25061541Srgrimes dbch->frag.plen = plen; 25071541Srgrimes } 25081541Srgrimes bcopy(ld, db_tr->buf, dbch->frag.len); 25091541Srgrimes buf = NULL; 25101541Srgrimes }else{ 25111541Srgrimes buf = db_tr->buf; 25121541Srgrimes poff = ld - (u_int8_t *)buf; 25131541Srgrimes dbch->frag.buf = NULL; 25141541Srgrimes dbch->frag.plen = 0; 25151541Srgrimes dbch->frag.len = 0; 25169336Sdfr } 25179336Sdfr ld += plen; 25181541Srgrimes } 25191541Srgrimes if( buf != NULL){ 25201541Srgrimes/* DMA result-code will be written at the tail of packet */ 25219336Sdfr stat = ((struct fwohci_trailer *)(ld - sizeof(struct fwohci_trailer)))->stat; 25229336Sdfr spd = (stat >> 5) & 0x3; 25239336Sdfr stat &= 0x1f; 25249336Sdfr switch(stat){ 252522521Sdyson case FWOHCIEV_ACKPEND: 25261541Srgrimes#if 0 25271541Srgrimes printf("fwohci_arcv: ack pending..\n"); 25281541Srgrimes#endif 25299336Sdfr /* fall through */ 25309336Sdfr case FWOHCIEV_ACKCOMPL: 25319336Sdfr if( poff != 0 ) 25329336Sdfr bcopy(buf+poff, buf, plen - 4); 25339336Sdfr fw_rcv(&sc->fc, buf, plen - sizeof(struct fwohci_trailer), 0, 0, spd); 25349336Sdfr break; 25359336Sdfr case FWOHCIEV_BUSRST: 25369336Sdfr free(buf, M_DEVBUF); 25379336Sdfr if (sc->fc.status != FWBUSRESET) 25389336Sdfr printf("got BUSRST packet!?\n"); 25399336Sdfr break; 25401541Srgrimes default: 25419336Sdfr device_printf(sc->fc.dev, "Async DMA Receive error err = %02x %s\n", stat, fwohcicode[stat]); 25429336Sdfr#if 0 /* XXX */ 25439336Sdfr goto out; 25449336Sdfr#endif 25451541Srgrimes break; 254636503Speter } 254736503Speter } 254836503Speter pcnt ++; 25499336Sdfr }; 25509336Sdfrout: 25519336Sdfr if (resCount == 0) { 25529336Sdfr /* done on this buffer */ 25539336Sdfr fwohci_add_rx_buf(db_tr, dbch->xferq.psize, 25549336Sdfr dbch->xferq.flag, 0, NULL); 25559336Sdfr dbch->bottom->db[0].db.desc.depend |= z; 255627608Sdfr dbch->bottom = db_tr; 25579336Sdfr db_tr = STAILQ_NEXT(db_tr, link); 25589336Sdfr dbch->top = db_tr; 25599336Sdfr dbch->buf_offset = 0; 256036251Speter } else { 25613305Sphk dbch->buf_offset = dbch->xferq.psize - resCount; 256217761Sdyson break; 25639336Sdfr } 25649336Sdfr /* XXX make sure DMA is not dead */ 25659336Sdfr } 25661541Srgrimes#if 0 256722521Sdyson if (pcnt < 1) 25681541Srgrimes printf("fwohci_arcv: no packets\n"); 25691541Srgrimes#endif 25701541Srgrimes splx(s); 25711541Srgrimes} 25721541Srgrimes