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