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