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