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