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