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