1 /* $NetBSD: fwohci.c,v 1.125 2010/04/29 06:53:13 kiyohara 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.125 2010/04/29 06:53:13 kiyohara 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 int sleepch; 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 tsleep((void *)&sleepch, FWPRI, "fwirxd", hz); 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 int sleepch; 1020 1021 OWRITE(sc, OHCI_ITCTLCLR(dmach), 1022 OHCI_CNTL_DMA_RUN | OHCI_CNTL_CYCMATCH_S); 1023 OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach); 1024 OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach); 1025 /* XXX we cannot free buffers until the DMA really stops */ 1026 tsleep((void *)&sleepch, FWPRI, "fwitxd", hz); 1027 fwohci_db_free(sc, &sc->it[dmach]); 1028 sc->it[dmach].xferq.flag &= ~FWXFERQ_RUNNING; 1029 return 0; 1030 } 1031 1032 static void 1033 fwohci_timeout(struct firewire_comm *fc) 1034 { 1035 #if 0 1036 struct fwohci_softc *sc = (struct fwohci_softc *)fc; 1037 #endif 1038 /* nothing? */ 1039 } 1040 1041 #if BYTE_ORDER == BIG_ENDIAN 1042 static void 1043 fwohci_irx_post (struct firewire_comm *fc, uint32_t *qld) 1044 { 1045 1046 qld[0] = FWOHCI_DMA_READ(qld[0]); 1047 return; 1048 } 1049 #endif 1050 1051 static void 1052 fwohci_set_intr(struct firewire_comm *fc, int enable) 1053 { 1054 struct fwohci_softc *sc = (struct fwohci_softc *)fc; 1055 1056 if (firewire_debug) 1057 printf("fwohci_set_intr: %d\n", enable); 1058 if (enable) { 1059 sc->intmask |= OHCI_INT_EN; 1060 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_EN); 1061 } else { 1062 sc->intmask &= ~OHCI_INT_EN; 1063 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_EN); 1064 } 1065 } 1066 1067 /* 1068 * Communication with PHY device 1069 */ 1070 /* XXX need lock for phy access */ 1071 static uint32_t 1072 fwphy_rddata(struct fwohci_softc *sc, u_int addr) 1073 { 1074 uint32_t fun, stat; 1075 u_int i, retry = 0; 1076 1077 addr &= 0xf; 1078 #define MAX_RETRY 100 1079 again: 1080 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_REG_FAIL); 1081 fun = PHYDEV_RDCMD | (addr << PHYDEV_REGADDR); 1082 OWRITE(sc, OHCI_PHYACCESS, fun); 1083 for (i = 0; i < MAX_RETRY; i++) { 1084 fun = OREAD(sc, OHCI_PHYACCESS); 1085 if ((fun & PHYDEV_RDCMD) == 0 && (fun & PHYDEV_RDDONE) != 0) 1086 break; 1087 DELAY(100); 1088 } 1089 if (i >= MAX_RETRY) { 1090 if (firewire_debug) 1091 printf("phy read failed(1).\n"); 1092 if (++retry < MAX_RETRY) { 1093 DELAY(100); 1094 goto again; 1095 } 1096 } 1097 /* Make sure that SCLK is started */ 1098 stat = OREAD(sc, FWOHCI_INTSTAT); 1099 if ((stat & OHCI_INT_REG_FAIL) != 0 || 1100 ((fun >> PHYDEV_REGADDR) & 0xf) != addr) { 1101 if (firewire_debug) 1102 printf("phy read failed(2).\n"); 1103 if (++retry < MAX_RETRY) { 1104 DELAY(100); 1105 goto again; 1106 } 1107 } 1108 if (firewire_debug || retry >= MAX_RETRY) 1109 aprint_error_dev(sc->fc.dev, 1110 "fwphy_rddata: 0x%x loop=%d, retry=%d\n", 1111 addr, i, retry); 1112 #undef MAX_RETRY 1113 return (fun >> PHYDEV_RDDATA) & 0xff; 1114 } 1115 1116 static uint32_t 1117 fwphy_wrdata(struct fwohci_softc *sc, uint32_t addr, uint32_t data) 1118 { 1119 uint32_t fun; 1120 1121 addr &= 0xf; 1122 data &= 0xff; 1123 1124 fun = 1125 (PHYDEV_WRCMD | (addr << PHYDEV_REGADDR) | (data << PHYDEV_WRDATA)); 1126 OWRITE(sc, OHCI_PHYACCESS, fun); 1127 DELAY(100); 1128 1129 return fwphy_rddata(sc, addr); 1130 } 1131 1132 static int 1133 fwohci_probe_phy(struct fwohci_softc *sc) 1134 { 1135 uint32_t reg, reg2; 1136 int e1394a = 1; 1137 1138 /* 1139 * probe PHY parameters 1140 * 0. to prove PHY version, whether compliance of 1394a. 1141 * 1. to probe maximum speed supported by the PHY and 1142 * number of port supported by core-logic. 1143 * It is not actually available port on your PC . 1144 */ 1145 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LPS); 1146 DELAY(500); 1147 1148 reg = fwphy_rddata(sc, FW_PHY_SPD_REG); 1149 1150 if ((reg >> 5) != 7) { 1151 sc->fc.mode &= ~FWPHYASYST; 1152 sc->fc.nport = reg & FW_PHY_NP; 1153 sc->fc.speed = reg & FW_PHY_SPD >> 6; 1154 if (sc->fc.speed > MAX_SPEED) { 1155 aprint_error_dev(sc->fc.dev, 1156 "invalid speed %d (fixed to %d).\n", 1157 sc->fc.speed, MAX_SPEED); 1158 sc->fc.speed = MAX_SPEED; 1159 } 1160 aprint_normal_dev(sc->fc.dev, "Phy 1394 only %s, %d ports.\n", 1161 fw_linkspeed[sc->fc.speed], sc->fc.nport); 1162 } else { 1163 reg2 = fwphy_rddata(sc, FW_PHY_ESPD_REG); 1164 sc->fc.mode |= FWPHYASYST; 1165 sc->fc.nport = reg & FW_PHY_NP; 1166 sc->fc.speed = (reg2 & FW_PHY_ESPD) >> 5; 1167 if (sc->fc.speed > MAX_SPEED) { 1168 aprint_error_dev(sc->fc.dev, 1169 "invalid speed %d (fixed to %d).\n", 1170 sc->fc.speed, MAX_SPEED); 1171 sc->fc.speed = MAX_SPEED; 1172 } 1173 aprint_normal_dev(sc->fc.dev, 1174 "Phy 1394a available %s, %d ports.\n", 1175 fw_linkspeed[sc->fc.speed], sc->fc.nport); 1176 1177 /* check programPhyEnable */ 1178 reg2 = fwphy_rddata(sc, 5); 1179 #if 0 1180 if (e1394a && (OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_PRPHY)) { 1181 #else /* XXX force to enable 1394a */ 1182 if (e1394a) { 1183 #endif 1184 if (firewire_debug) 1185 printf("Enable 1394a Enhancements\n"); 1186 /* enable EAA EMC */ 1187 reg2 |= 0x03; 1188 /* set aPhyEnhanceEnable */ 1189 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_PHYEN); 1190 OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_PRPHY); 1191 } 1192 #if 0 1193 else { 1194 /* for safe */ 1195 reg2 &= ~0x83; 1196 } 1197 #endif 1198 reg2 = fwphy_wrdata(sc, 5, reg2); 1199 } 1200 1201 reg = fwphy_rddata(sc, FW_PHY_SPD_REG); 1202 if ((reg >> 5) == 7) { 1203 reg = fwphy_rddata(sc, 4); 1204 reg |= 1 << 6; 1205 fwphy_wrdata(sc, 4, reg); 1206 reg = fwphy_rddata(sc, 4); 1207 } 1208 return 0; 1209 } 1210 1211 static void 1212 fwohci_reset(struct fwohci_softc *sc) 1213 { 1214 struct fwohcidb_tr *db_tr; 1215 uint32_t reg, reg2; 1216 int i, max_rec, speed; 1217 1218 /* Disable interrupts */ 1219 OWRITE(sc, FWOHCI_INTMASKCLR, ~0); 1220 1221 /* Now stopping all DMA channels */ 1222 OWRITE(sc, OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN); 1223 OWRITE(sc, OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN); 1224 OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN); 1225 OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN); 1226 1227 OWRITE(sc, OHCI_IR_MASKCLR, ~0); 1228 for (i = 0; i < sc->fc.nisodma; i++) { 1229 OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN); 1230 OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN); 1231 } 1232 1233 /* FLUSH FIFO and reset Transmitter/Reciever */ 1234 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_RESET); 1235 if (firewire_debug) 1236 printf("resetting OHCI..."); 1237 i = 0; 1238 while (OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_RESET) { 1239 if (i++ > 100) 1240 break; 1241 DELAY(1000); 1242 } 1243 if (firewire_debug) 1244 printf("done (loop=%d)\n", i); 1245 1246 /* Probe phy */ 1247 fwohci_probe_phy(sc); 1248 1249 /* Probe link */ 1250 reg = OREAD(sc, OHCI_BUS_OPT); 1251 reg2 = reg | OHCI_BUSFNC; 1252 max_rec = (reg & 0x0000f000) >> 12; 1253 speed = (reg & 0x00000007); 1254 aprint_normal_dev(sc->fc.dev, "Link %s, max_rec %d bytes.\n", 1255 fw_linkspeed[speed], MAXREC(max_rec)); 1256 /* XXX fix max_rec */ 1257 sc->fc.maxrec = sc->fc.speed + 8; 1258 if (max_rec != sc->fc.maxrec) { 1259 reg2 = (reg2 & 0xffff0fff) | (sc->fc.maxrec << 12); 1260 aprint_normal_dev(sc->fc.dev, "max_rec %d -> %d\n", 1261 MAXREC(max_rec), MAXREC(sc->fc.maxrec)); 1262 } 1263 if (firewire_debug) 1264 printf("BUS_OPT 0x%x -> 0x%x\n", reg, reg2); 1265 OWRITE(sc, OHCI_BUS_OPT, reg2); 1266 1267 /* Initialize registers */ 1268 OWRITE(sc, OHCI_CROMHDR, sc->fc.config_rom[0]); 1269 OWRITE(sc, OHCI_CROMPTR, sc->crom_dma.bus_addr); 1270 OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_BIGEND); 1271 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_POSTWR); 1272 OWRITE(sc, OHCI_SID_BUF, sc->sid_dma.bus_addr); 1273 OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_SID); 1274 1275 /* Enable link */ 1276 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LINKEN); 1277 1278 /* Force to start async RX DMA */ 1279 sc->arrq.xferq.flag &= ~FWXFERQ_RUNNING; 1280 sc->arrs.xferq.flag &= ~FWXFERQ_RUNNING; 1281 fwohci_rx_enable(sc, &sc->arrq); 1282 fwohci_rx_enable(sc, &sc->arrs); 1283 1284 /* Initialize async TX */ 1285 OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD); 1286 OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD); 1287 1288 /* AT Retries */ 1289 OWRITE(sc, FWOHCI_RETRY, 1290 /* CycleLimit PhyRespRetries ATRespRetries ATReqRetries */ 1291 (0xffff << 16) | (0x0f << 8) | (0x0f << 4) | 0x0f); 1292 1293 sc->atrq.top = STAILQ_FIRST(&sc->atrq.db_trq); 1294 sc->atrs.top = STAILQ_FIRST(&sc->atrs.db_trq); 1295 sc->atrq.bottom = sc->atrq.top; 1296 sc->atrs.bottom = sc->atrs.top; 1297 1298 for (i = 0, db_tr = sc->atrq.top; i < sc->atrq.ndb; 1299 i++, db_tr = STAILQ_NEXT(db_tr, link)) 1300 db_tr->xfer = NULL; 1301 for (i = 0, db_tr = sc->atrs.top; i < sc->atrs.ndb; 1302 i++, db_tr = STAILQ_NEXT(db_tr, link)) 1303 db_tr->xfer = NULL; 1304 1305 1306 /* Enable interrupts */ 1307 sc->intmask = (OHCI_INT_ERR | OHCI_INT_PHY_SID 1308 | OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS 1309 | OHCI_INT_DMA_PRRQ | OHCI_INT_DMA_PRRS 1310 | OHCI_INT_PHY_BUS_R | OHCI_INT_PW_ERR); 1311 sc->intmask |= OHCI_INT_DMA_IR | OHCI_INT_DMA_IT; 1312 sc->intmask |= OHCI_INT_CYC_LOST | OHCI_INT_PHY_INT; 1313 OWRITE(sc, FWOHCI_INTMASK, sc->intmask); 1314 fwohci_set_intr(&sc->fc, 1); 1315 } 1316 1317 #define LAST_DB(dbtr) \ 1318 &dbtr->db[(dbtr->dbcnt > 2) ? (dbtr->dbcnt - 1) : 0]; 1319 1320 static void 1321 fwohci_execute_db(struct fwohcidb_tr *db_tr, bus_dmamap_t dmamap) 1322 { 1323 struct fwohcidb *db; 1324 bus_dma_segment_t *s; 1325 int i; 1326 1327 db = &db_tr->db[db_tr->dbcnt]; 1328 for (i = 0; i < dmamap->dm_nsegs; i++) { 1329 s = &dmamap->dm_segs[i]; 1330 FWOHCI_DMA_WRITE(db->db.desc.addr, s->ds_addr); 1331 FWOHCI_DMA_WRITE(db->db.desc.cmd, s->ds_len); 1332 FWOHCI_DMA_WRITE(db->db.desc.res, 0); 1333 db++; 1334 db_tr->dbcnt++; 1335 } 1336 } 1337 1338 static void 1339 fwohci_start(struct fwohci_softc *sc, struct fwohci_dbch *dbch) 1340 { 1341 struct fw_xfer *xfer; 1342 struct fw_pkt *fp; 1343 struct fwohci_txpkthdr *ohcifp; 1344 struct fwohcidb_tr *db_tr, *kick; 1345 struct fwohcidb *db; 1346 uint32_t *ld; 1347 int tcode, hdr_len, pl_off, fsegment = -1, i; 1348 const struct tcode_info *info; 1349 static int maxdesc = 0; 1350 1351 KASSERT(mutex_owned(&dbch->xferq.q_mtx)); 1352 1353 #if DIAGNOSTIC 1354 if (dbch->off != OHCI_ATQOFF && 1355 dbch->off != OHCI_ATSOFF) 1356 panic("not async tx"); 1357 #endif 1358 1359 if (dbch->flags & FWOHCI_DBCH_FULL) 1360 return; 1361 1362 db_tr = dbch->top; 1363 kick = db_tr; 1364 if (dbch->pdb_tr != NULL) { 1365 kick = dbch->pdb_tr; 1366 fwdma_sync_multiseg(dbch->am, kick->idx, kick->idx, 1367 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1368 } 1369 txloop: 1370 xfer = STAILQ_FIRST(&dbch->xferq.q); 1371 if (xfer == NULL) 1372 goto kick; 1373 #if 0 1374 if (dbch->xferq.queued == 0) 1375 aprint_error_dev(sc->fc.dev, "TX queue empty\n"); 1376 #endif 1377 STAILQ_REMOVE_HEAD(&dbch->xferq.q, link); 1378 db_tr->xfer = xfer; 1379 xfer->flag = FWXF_START; 1380 1381 fp = &xfer->send.hdr; 1382 tcode = fp->mode.common.tcode; 1383 1384 ohcifp = (struct fwohci_txpkthdr *) db_tr->db[1].db.immed; 1385 info = &tinfo[tcode]; 1386 hdr_len = pl_off = info->hdr_len; 1387 1388 ld = ohcifp->mode.ld; 1389 ld[0] = ld[1] = ld[2] = ld[3] = 0; 1390 for (i = 0; i < pl_off / 4; i++) 1391 ld[i] = fp->mode.ld[i]; 1392 1393 ohcifp->mode.common.spd = xfer->send.spd & 0x7; 1394 if (tcode == FWTCODE_STREAM) { 1395 hdr_len = 8; 1396 ohcifp->mode.stream.len = fp->mode.stream.len; 1397 } else if (tcode == FWTCODE_PHY) { 1398 hdr_len = 12; 1399 ld[1] = fp->mode.ld[1]; 1400 ld[2] = fp->mode.ld[2]; 1401 ohcifp->mode.common.spd = 0; 1402 ohcifp->mode.common.tcode = FWOHCITCODE_PHY; 1403 } else { 1404 ohcifp->mode.asycomm.dst = fp->mode.hdr.dst; 1405 ohcifp->mode.asycomm.srcbus = OHCI_ASYSRCBUS; 1406 ohcifp->mode.asycomm.tlrt |= FWRETRY_X; 1407 } 1408 db = db_tr->db; 1409 FWOHCI_DMA_WRITE(db->db.desc.cmd, 1410 OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | hdr_len); 1411 FWOHCI_DMA_WRITE(db->db.desc.addr, 0); 1412 FWOHCI_DMA_WRITE(db->db.desc.res, 0); 1413 /* Specify bound timer of asy. responce */ 1414 if (dbch->off != OHCI_ATSOFF) 1415 FWOHCI_DMA_WRITE(db->db.desc.res, 1416 (OREAD(sc, OHCI_CYCLETIMER) >> 12) + (1 << 13)); 1417 #if BYTE_ORDER == BIG_ENDIAN 1418 if (tcode == FWTCODE_WREQQ || tcode == FWTCODE_RRESQ) 1419 hdr_len = 12; 1420 for (i = 0; i < hdr_len / 4; i++) 1421 FWOHCI_DMA_WRITE(ld[i], ld[i]); 1422 #endif 1423 1424 again: 1425 db_tr->dbcnt = 2; 1426 db = &db_tr->db[db_tr->dbcnt]; 1427 if (xfer->send.pay_len > 0) { 1428 int err; 1429 /* handle payload */ 1430 if (xfer->mbuf == NULL) 1431 err = bus_dmamap_load(sc->fc.dmat, db_tr->dma_map, 1432 xfer->send.payload, xfer->send.pay_len, NULL, 1433 BUS_DMA_WAITOK); 1434 else { 1435 /* XXX we can handle only 6 (=8-2) mbuf chains */ 1436 err = bus_dmamap_load_mbuf(sc->fc.dmat, db_tr->dma_map, 1437 xfer->mbuf, BUS_DMA_WAITOK); 1438 if (err == EFBIG) { 1439 struct mbuf *m0; 1440 1441 if (firewire_debug) 1442 printf("EFBIG.\n"); 1443 m0 = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); 1444 if (m0 != NULL) { 1445 m_copydata(xfer->mbuf, 0, 1446 xfer->mbuf->m_pkthdr.len, 1447 mtod(m0, void *)); 1448 m0->m_len = m0->m_pkthdr.len = 1449 xfer->mbuf->m_pkthdr.len; 1450 m_freem(xfer->mbuf); 1451 xfer->mbuf = m0; 1452 goto again; 1453 } 1454 aprint_error_dev(sc->fc.dev, 1455 "m_getcl failed.\n"); 1456 } 1457 } 1458 if (!err) 1459 fwohci_execute_db(db_tr, db_tr->dma_map); 1460 else 1461 aprint_error_dev(sc->fc.dev, 1462 "dmamap_load: err=%d\n", err); 1463 bus_dmamap_sync(sc->fc.dmat, db_tr->dma_map, 1464 0, db_tr->dma_map->dm_mapsize, BUS_DMASYNC_PREWRITE); 1465 #if 0 /* OHCI_OUTPUT_MODE == 0 */ 1466 for (i = 2; i < db_tr->dbcnt; i++) 1467 FWOHCI_DMA_SET(db_tr->db[i].db.desc.cmd, 1468 OHCI_OUTPUT_MORE); 1469 #endif 1470 } 1471 if (maxdesc < db_tr->dbcnt) { 1472 maxdesc = db_tr->dbcnt; 1473 if (firewire_debug) 1474 printf("maxdesc: %d\n", maxdesc); 1475 } 1476 /* last db */ 1477 db = LAST_DB(db_tr); 1478 FWOHCI_DMA_SET(db->db.desc.cmd, 1479 OHCI_OUTPUT_LAST | OHCI_INTERRUPT_ALWAYS | OHCI_BRANCH_ALWAYS); 1480 FWOHCI_DMA_WRITE(db->db.desc.depend, 1481 STAILQ_NEXT(db_tr, link)->bus_addr); 1482 1483 if (fsegment == -1) 1484 fsegment = db_tr->dbcnt; 1485 if (dbch->pdb_tr != NULL) { 1486 db = LAST_DB(dbch->pdb_tr); 1487 FWOHCI_DMA_SET(db->db.desc.depend, db_tr->dbcnt); 1488 } 1489 dbch->xferq.queued++; 1490 dbch->pdb_tr = db_tr; 1491 db_tr = STAILQ_NEXT(db_tr, link); 1492 if (db_tr != dbch->bottom) 1493 goto txloop; 1494 else { 1495 aprint_error_dev(sc->fc.dev, "fwohci_start: lack of db_trq\n"); 1496 dbch->flags |= FWOHCI_DBCH_FULL; 1497 } 1498 kick: 1499 /* kick asy q */ 1500 fwdma_sync_multiseg(dbch->am, kick->idx, dbch->pdb_tr->idx, 1501 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1502 1503 if (dbch->xferq.flag & FWXFERQ_RUNNING) 1504 OWRITE(sc, OHCI_DMACTL(dbch->off), OHCI_CNTL_DMA_WAKE); 1505 else { 1506 if (firewire_debug) 1507 printf("start AT DMA status=%x\n", 1508 OREAD(sc, OHCI_DMACTL(dbch->off))); 1509 OWRITE(sc, OHCI_DMACMD(dbch->off), 1510 dbch->top->bus_addr | fsegment); 1511 OWRITE(sc, OHCI_DMACTL(dbch->off), OHCI_CNTL_DMA_RUN); 1512 dbch->xferq.flag |= FWXFERQ_RUNNING; 1513 } 1514 1515 dbch->top = db_tr; 1516 return; 1517 } 1518 1519 static void 1520 fwohci_start_atq(struct firewire_comm *fc) 1521 { 1522 struct fwohci_softc *sc = (struct fwohci_softc *)fc; 1523 struct fwohci_dbch *dbch = &sc->atrq; 1524 1525 mutex_enter(&dbch->xferq.q_mtx); 1526 fwohci_start(sc, dbch); 1527 mutex_exit(&dbch->xferq.q_mtx); 1528 return; 1529 } 1530 1531 static void 1532 fwohci_start_ats(struct firewire_comm *fc) 1533 { 1534 struct fwohci_softc *sc = (struct fwohci_softc *)fc; 1535 struct fwohci_dbch *dbch = &sc->atrs; 1536 1537 mutex_enter(&dbch->xferq.q_mtx); 1538 fwohci_start(sc, dbch); 1539 mutex_exit(&dbch->xferq.q_mtx); 1540 return; 1541 } 1542 1543 static void 1544 fwohci_txd(struct fwohci_softc *sc, struct fwohci_dbch *dbch) 1545 { 1546 struct firewire_comm *fc = &sc->fc; 1547 struct fwohcidb_tr *tr; 1548 struct fwohcidb *db; 1549 struct fw_xfer *xfer; 1550 u_int stat, status; 1551 int packets = 0, ch, err = 0; 1552 1553 #if DIAGNOSTIC 1554 if (dbch->off != OHCI_ATQOFF && 1555 dbch->off != OHCI_ATSOFF) 1556 panic("not async tx"); 1557 #endif 1558 if (dbch->off == OHCI_ATQOFF) 1559 ch = ATRQ_CH; 1560 else /* OHCI_ATSOFF */ 1561 ch = ATRS_CH; 1562 1563 mutex_enter(&dbch->xferq.q_mtx); 1564 tr = dbch->bottom; 1565 while (dbch->xferq.queued > 0) { 1566 fwdma_sync_multiseg(dbch->am, tr->idx, tr->idx, 1567 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1568 db = LAST_DB(tr); 1569 status = FWOHCI_DMA_READ(db->db.desc.res) >> OHCI_STATUS_SHIFT; 1570 if (!(status & OHCI_CNTL_DMA_ACTIVE)) 1571 if (fc->status != FWBUSINIT) 1572 goto out; 1573 if (tr->xfer->send.pay_len > 0) { 1574 bus_dmamap_sync(fc->dmat, tr->dma_map, 1575 0, tr->dma_map->dm_mapsize, BUS_DMASYNC_POSTWRITE); 1576 bus_dmamap_unload(fc->dmat, tr->dma_map); 1577 } 1578 #if 1 1579 if (firewire_debug > 1) 1580 dump_db(sc, ch); 1581 #endif 1582 if (status & OHCI_CNTL_DMA_DEAD) { 1583 /* Stop DMA */ 1584 OWRITE(sc, OHCI_DMACTLCLR(dbch->off), 1585 OHCI_CNTL_DMA_RUN); 1586 aprint_error_dev(fc->dev, "force reset AT FIFO\n"); 1587 OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_LINKEN); 1588 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LPS | OHCI_HCC_LINKEN); 1589 OWRITE(sc, OHCI_DMACTLCLR(dbch->off), 1590 OHCI_CNTL_DMA_RUN); 1591 } 1592 stat = status & FWOHCIEV_MASK; 1593 switch(stat) { 1594 case FWOHCIEV_ACKPEND: 1595 1596 /* FALLTHROUGH */ 1597 1598 case FWOHCIEV_ACKCOMPL: 1599 err = 0; 1600 break; 1601 1602 case FWOHCIEV_ACKBSA: 1603 case FWOHCIEV_ACKBSB: 1604 case FWOHCIEV_ACKBSX: 1605 aprint_error_dev(fc->dev, "txd err=%2x %s\n", stat, 1606 fwohcicode[stat]); 1607 err = EBUSY; 1608 break; 1609 1610 case FWOHCIEV_FLUSHED: 1611 case FWOHCIEV_ACKTARD: 1612 aprint_error_dev(fc->dev, "txd err=%2x %s\n", stat, 1613 fwohcicode[stat]); 1614 err = EAGAIN; 1615 break; 1616 1617 case FWOHCIEV_MISSACK: 1618 case FWOHCIEV_UNDRRUN: 1619 case FWOHCIEV_OVRRUN: 1620 case FWOHCIEV_DESCERR: 1621 case FWOHCIEV_DTRDERR: 1622 case FWOHCIEV_TIMEOUT: 1623 case FWOHCIEV_TCODERR: 1624 case FWOHCIEV_UNKNOWN: 1625 case FWOHCIEV_ACKDERR: 1626 case FWOHCIEV_ACKTERR: 1627 default: 1628 aprint_error_dev(fc->dev, "txd err=%2x %s\n", stat, 1629 fwohcicode[stat]); 1630 err = EINVAL; 1631 break; 1632 } 1633 dbch->xferq.queued--; 1634 dbch->bottom = STAILQ_NEXT(tr, link); 1635 if (tr->xfer != NULL) { 1636 xfer = tr->xfer; 1637 tr->xfer = NULL; 1638 mutex_exit(&dbch->xferq.q_mtx); 1639 if (xfer->flag & FWXF_RCVD) { 1640 #if 0 1641 if (firewire_debug) 1642 printf("already rcvd\n"); 1643 #endif 1644 fw_xfer_done(xfer); 1645 } else { 1646 microtime(&xfer->tv); 1647 xfer->flag = FWXF_SENT; 1648 if (err == EBUSY) { 1649 xfer->flag = FWXF_BUSY; 1650 xfer->resp = err; 1651 xfer->recv.pay_len = 0; 1652 fw_xfer_done(xfer); 1653 } else if (stat != FWOHCIEV_ACKPEND) { 1654 if (stat != FWOHCIEV_ACKCOMPL) 1655 xfer->flag = FWXF_SENTERR; 1656 xfer->resp = err; 1657 xfer->recv.pay_len = 0; 1658 fw_xfer_done(xfer); 1659 } 1660 } 1661 mutex_enter(&dbch->xferq.q_mtx); 1662 /* 1663 * The watchdog timer takes care of split 1664 * transcation timeout for ACKPEND case. 1665 */ 1666 } else 1667 aprint_error_dev(fc->dev, "this shouldn't happen\n"); 1668 packets++; 1669 if (dbch->bottom == dbch->top) { 1670 /* we reaches the end of context program */ 1671 if (firewire_debug && dbch->xferq.queued > 0) 1672 printf("queued > 0\n"); 1673 break; 1674 } 1675 tr = dbch->bottom; 1676 } 1677 out: 1678 if (dbch->xferq.queued > 0 || packets > 0) 1679 fwdma_sync_multiseg(dbch->am, tr->idx, tr->idx, 1680 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1681 if ((dbch->flags & FWOHCI_DBCH_FULL) && packets > 0) { 1682 aprint_normal_dev(fc->dev, "make free slot\n"); 1683 dbch->flags &= ~FWOHCI_DBCH_FULL; 1684 fwohci_start(sc, dbch); 1685 } 1686 mutex_exit(&dbch->xferq.q_mtx); 1687 } 1688 1689 static void 1690 fwohci_db_free(struct fwohci_softc *sc, struct fwohci_dbch *dbch) 1691 { 1692 struct fwohcidb_tr *db_tr, *last; 1693 1694 if ((dbch->flags & FWOHCI_DBCH_INIT) == 0) 1695 return; 1696 1697 for (last = db_tr = STAILQ_FIRST(&dbch->db_trq); db_tr != last; 1698 db_tr = STAILQ_NEXT(db_tr, link)) { 1699 bus_dmamap_destroy(sc->fc.dmat, db_tr->dma_map); 1700 if ((dbch->xferq.flag & FWXFERQ_EXTBUF) == 0 && 1701 db_tr->buf != NULL) { 1702 fwdma_free(sc->fc.dmat, db_tr->dma_map, db_tr->buf); 1703 db_tr->buf = NULL; 1704 } 1705 } 1706 dbch->ndb = 0; 1707 db_tr = STAILQ_FIRST(&dbch->db_trq); 1708 fwdma_free_multiseg(dbch->am); 1709 free(db_tr, M_FW); 1710 STAILQ_INIT(&dbch->db_trq); 1711 dbch->flags &= ~FWOHCI_DBCH_INIT; 1712 seldestroy(&dbch->xferq.rsel); 1713 } 1714 1715 static void 1716 fwohci_db_init(struct fwohci_softc *sc, struct fwohci_dbch *dbch) 1717 { 1718 struct firewire_comm *fc = &sc->fc; 1719 struct fwohcidb_tr *db_tr, *lastq, *tmpq; 1720 int idb; 1721 const int db_tr_sz = sizeof(struct fwohcidb_tr) * dbch->ndb; 1722 1723 if ((dbch->flags & FWOHCI_DBCH_INIT) != 0) 1724 goto out; 1725 1726 /* allocate DB entries and attach one to each DMA channels */ 1727 /* DB entry must start at 16 bytes bounary. */ 1728 STAILQ_INIT(&dbch->db_trq); 1729 db_tr = (struct fwohcidb_tr *)malloc(db_tr_sz, M_FW, M_WAITOK | M_ZERO); 1730 if (db_tr == NULL) { 1731 aprint_error_dev(fc->dev, "malloc(1) failed\n"); 1732 return; 1733 } 1734 1735 #define DB_SIZE(x) (sizeof(struct fwohcidb) * (x)->ndesc) 1736 dbch->am = fwdma_malloc_multiseg(fc, DB_SIZE(dbch), DB_SIZE(dbch), 1737 #if 0 1738 dbch->ndb, BUS_DMA_WAITOK); 1739 #else /* Ooops, debugging now... */ 1740 dbch->ndb, BUS_DMA_WAITOK | 1741 (dbch->off == OHCI_ARQOFF || dbch->off == OHCI_ARSOFF) ? 1742 BUS_DMA_COHERENT : 0); 1743 #endif 1744 if (dbch->am == NULL) { 1745 aprint_error_dev(fc->dev, "fwdma_malloc_multiseg failed\n"); 1746 free(db_tr, M_FW); 1747 return; 1748 } 1749 /* Attach DB to DMA ch. */ 1750 for (idb = 0; idb < dbch->ndb; idb++) { 1751 db_tr->idx = idb; 1752 db_tr->dbcnt = 0; 1753 db_tr->db = (struct fwohcidb *)fwdma_v_addr(dbch->am, idb); 1754 db_tr->bus_addr = fwdma_bus_addr(dbch->am, idb); 1755 /* create dmamap for buffers */ 1756 #define MAX_REQCOUNT 0xffff 1757 if (bus_dmamap_create(fc->dmat, dbch->xferq.psize, 1758 dbch->ndesc > 3 ? dbch->ndesc - 2 : 1, MAX_REQCOUNT, 0, 1759 0, &db_tr->dma_map) != 0) { 1760 aprint_error_dev(fc->dev, "bus_dmamap_create failed\n"); 1761 dbch->flags = FWOHCI_DBCH_INIT; /* XXX fake */ 1762 fwohci_db_free(sc, dbch); 1763 return; 1764 } 1765 if (dbch->off == OHCI_ARQOFF || 1766 dbch->off == OHCI_ARSOFF) { 1767 db_tr->buf = fwdma_malloc(fc->dev, fc->dmat, 1768 &db_tr->dma_map, dbch->xferq.psize, 1, 1769 BUS_DMA_NOWAIT); 1770 if (db_tr->buf == NULL) { 1771 aprint_error_dev(fc->dev, 1772 "fwdma_malloc failed\n"); 1773 dbch->flags = FWOHCI_DBCH_INIT; /* XXX fake */ 1774 fwohci_db_free(sc, dbch); 1775 return; 1776 } 1777 } 1778 STAILQ_INSERT_TAIL(&dbch->db_trq, db_tr, link); 1779 if (dbch->xferq.flag & FWXFERQ_EXTBUF) { 1780 struct fw_bulkxfer *bulkxfer = 1781 &dbch->xferq.bulkxfer[idb / dbch->xferq.bnpacket]; 1782 1783 if (idb % dbch->xferq.bnpacket == 0) 1784 bulkxfer->start = (void *)db_tr; 1785 if ((idb + 1) % dbch->xferq.bnpacket == 0) 1786 bulkxfer->end = (void *)db_tr; 1787 } 1788 db_tr++; 1789 } 1790 lastq = NULL; 1791 STAILQ_FOREACH(tmpq, &dbch->db_trq, link) 1792 lastq = tmpq; 1793 lastq->link.stqe_next = STAILQ_FIRST(&dbch->db_trq); 1794 out: 1795 dbch->xferq.queued = 0; 1796 dbch->pdb_tr = NULL; 1797 dbch->top = STAILQ_FIRST(&dbch->db_trq); 1798 dbch->bottom = dbch->top; 1799 dbch->flags = FWOHCI_DBCH_INIT; 1800 selinit(&dbch->xferq.rsel); 1801 } 1802 1803 static int 1804 fwohci_tx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch) 1805 { 1806 int err = 0; 1807 int idb, z, i, dmach = 0, ldesc; 1808 struct fwohcidb_tr *db_tr; 1809 struct fwohcidb *db; 1810 1811 if (!(dbch->xferq.flag & FWXFERQ_EXTBUF)) { 1812 err = EINVAL; 1813 return err; 1814 } 1815 z = dbch->ndesc; 1816 for (dmach = 0; dmach < sc->fc.nisodma; dmach++) 1817 if (dbch->off == sc->it[dmach].off) 1818 break; 1819 if (dmach == sc->fc.nisodma) { 1820 err = EINVAL; 1821 return err; 1822 } 1823 if (dbch->xferq.flag & FWXFERQ_RUNNING) 1824 return err; 1825 dbch->xferq.flag |= FWXFERQ_RUNNING; 1826 for (i = 0, dbch->bottom = dbch->top; i < dbch->ndb - 1; i++) 1827 dbch->bottom = STAILQ_NEXT(dbch->bottom, link); 1828 db_tr = dbch->top; 1829 for (idb = 0; idb < dbch->ndb; idb++) { 1830 fwohci_add_tx_buf(dbch, db_tr, idb); 1831 if (STAILQ_NEXT(db_tr, link) == NULL) 1832 break; 1833 db = db_tr->db; 1834 ldesc = db_tr->dbcnt - 1; 1835 FWOHCI_DMA_WRITE(db[0].db.desc.depend, 1836 STAILQ_NEXT(db_tr, link)->bus_addr | z); 1837 db[ldesc].db.desc.depend = db[0].db.desc.depend; 1838 if (dbch->xferq.flag & FWXFERQ_EXTBUF) { 1839 if (((idb + 1) % dbch->xferq.bnpacket) == 0) { 1840 FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, 1841 OHCI_INTERRUPT_ALWAYS); 1842 /* OHCI 1.1 and above */ 1843 FWOHCI_DMA_SET(db[0].db.desc.cmd, 1844 OHCI_INTERRUPT_ALWAYS); 1845 } 1846 } 1847 db_tr = STAILQ_NEXT(db_tr, link); 1848 } 1849 FWOHCI_DMA_CLEAR( 1850 dbch->bottom->db[dbch->bottom->dbcnt - 1].db.desc.depend, 0xf); 1851 return err; 1852 } 1853 1854 static int 1855 fwohci_rx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch) 1856 { 1857 struct fwohcidb_tr *db_tr; 1858 struct fwohcidb *db; 1859 int idb, z, i, ldesc, err = 0; 1860 1861 z = dbch->ndesc; 1862 if (dbch->xferq.flag & FWXFERQ_STREAM) { 1863 if (dbch->xferq.flag & FWXFERQ_RUNNING) 1864 return err; 1865 } else 1866 if (dbch->xferq.flag & FWXFERQ_RUNNING) { 1867 err = EBUSY; 1868 return err; 1869 } 1870 dbch->xferq.flag |= FWXFERQ_RUNNING; 1871 dbch->top = STAILQ_FIRST(&dbch->db_trq); 1872 for (i = 0, dbch->bottom = dbch->top; i < dbch->ndb - 1; i++) 1873 dbch->bottom = STAILQ_NEXT(dbch->bottom, link); 1874 db_tr = dbch->top; 1875 if (db_tr->dbcnt != 0) 1876 goto run; 1877 for (idb = 0; idb < dbch->ndb; idb++) { 1878 if (dbch->off == OHCI_ARQOFF || 1879 dbch->off == OHCI_ARSOFF) 1880 bus_dmamap_sync(sc->fc.dmat, db_tr->dma_map, 1881 0, db_tr->dma_map->dm_mapsize, BUS_DMASYNC_PREREAD); 1882 fwohci_add_rx_buf(dbch, db_tr, idb, &sc->dummy_dma); 1883 if (STAILQ_NEXT(db_tr, link) == NULL) 1884 break; 1885 db = db_tr->db; 1886 ldesc = db_tr->dbcnt - 1; 1887 FWOHCI_DMA_WRITE(db[ldesc].db.desc.depend, 1888 STAILQ_NEXT(db_tr, link)->bus_addr | z); 1889 if (dbch->xferq.flag & FWXFERQ_EXTBUF) { 1890 if (((idb + 1) % dbch->xferq.bnpacket) == 0) { 1891 FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, 1892 OHCI_INTERRUPT_ALWAYS); 1893 FWOHCI_DMA_CLEAR(db[ldesc].db.desc.depend, 0xf); 1894 } 1895 } 1896 db_tr = STAILQ_NEXT(db_tr, link); 1897 } 1898 FWOHCI_DMA_CLEAR(dbch->bottom->db[db_tr->dbcnt - 1].db.desc.depend, 1899 0xf); 1900 dbch->buf_offset = 0; 1901 run: 1902 fwdma_sync_multiseg_all(dbch->am, 1903 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1904 if (!(dbch->xferq.flag & FWXFERQ_STREAM)) { 1905 OWRITE(sc, OHCI_DMACMD(dbch->off), dbch->top->bus_addr | z); 1906 OWRITE(sc, OHCI_DMACTL(dbch->off), OHCI_CNTL_DMA_RUN); 1907 } 1908 return err; 1909 } 1910 1911 static int 1912 fwohci_next_cycle(struct fwohci_softc *sc, int cycle_now) 1913 { 1914 int sec, cycle, cycle_match; 1915 1916 cycle = cycle_now & 0x1fff; 1917 sec = cycle_now >> 13; 1918 #define CYCLE_MOD 0x10 1919 #if 1 1920 #define CYCLE_DELAY 8 /* min delay to start DMA */ 1921 #else 1922 #define CYCLE_DELAY 7000 /* min delay to start DMA */ 1923 #endif 1924 cycle = cycle + CYCLE_DELAY; 1925 if (cycle >= 8000) { 1926 sec++; 1927 cycle -= 8000; 1928 } 1929 cycle = roundup2(cycle, CYCLE_MOD); 1930 if (cycle >= 8000) { 1931 sec++; 1932 if (cycle == 8000) 1933 cycle = 0; 1934 else 1935 cycle = CYCLE_MOD; 1936 } 1937 cycle_match = ((sec << 13) | cycle) & 0x7ffff; 1938 1939 return cycle_match; 1940 } 1941 1942 #ifdef OHCI_DEBUG 1943 static void 1944 fwohci_dump_intr(struct fwohci_softc *sc, uint32_t stat) 1945 { 1946 1947 if (stat & OREAD(sc, FWOHCI_INTMASK)) 1948 print("%s: INTERRUPT" 1949 " < %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s>" 1950 " 0x%08x, 0x%08x\n", 1951 device_xname(fc->dev), 1952 stat & OHCI_INT_EN ? "DMA_EN ":"", 1953 stat & OHCI_INT_PHY_REG ? "PHY_REG ":"", 1954 stat & OHCI_INT_CYC_LONG ? "CYC_LONG ":"", 1955 stat & OHCI_INT_ERR ? "INT_ERR ":"", 1956 stat & OHCI_INT_CYC_ERR ? "CYC_ERR ":"", 1957 stat & OHCI_INT_CYC_LOST ? "CYC_LOST ":"", 1958 stat & OHCI_INT_CYC_64SECOND ? "CYC_64SECOND ":"", 1959 stat & OHCI_INT_CYC_START ? "CYC_START ":"", 1960 stat & OHCI_INT_PHY_INT ? "PHY_INT ":"", 1961 stat & OHCI_INT_PHY_BUS_R ? "BUS_RESET ":"", 1962 stat & OHCI_INT_PHY_SID ? "SID ":"", 1963 stat & OHCI_INT_LR_ERR ? "DMA_LR_ERR ":"", 1964 stat & OHCI_INT_PW_ERR ? "DMA_PW_ERR ":"", 1965 stat & OHCI_INT_DMA_IR ? "DMA_IR ":"", 1966 stat & OHCI_INT_DMA_IT ? "DMA_IT " :"", 1967 stat & OHCI_INT_DMA_PRRS ? "DMA_PRRS " :"", 1968 stat & OHCI_INT_DMA_PRRQ ? "DMA_PRRQ " :"", 1969 stat & OHCI_INT_DMA_ARRS ? "DMA_ARRS " :"", 1970 stat & OHCI_INT_DMA_ARRQ ? "DMA_ARRQ " :"", 1971 stat & OHCI_INT_DMA_ATRS ? "DMA_ATRS " :"", 1972 stat & OHCI_INT_DMA_ATRQ ? "DMA_ATRQ " :"", 1973 stat, OREAD(sc, FWOHCI_INTMASK) 1974 ); 1975 } 1976 #endif 1977 1978 static void 1979 fwohci_intr_core(struct fwohci_softc *sc, uint32_t stat) 1980 { 1981 struct firewire_comm *fc = &sc->fc; 1982 uint32_t node_id, plen; 1983 1984 if ((stat & OHCI_INT_PHY_BUS_R) && (fc->status != FWBUSRESET)) { 1985 fc->status = FWBUSRESET; 1986 /* Disable bus reset interrupt until sid recv. */ 1987 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_PHY_BUS_R); 1988 1989 aprint_normal_dev(fc->dev, "BUS reset\n"); 1990 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST); 1991 OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCSRC); 1992 1993 OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN); 1994 sc->atrq.xferq.flag &= ~FWXFERQ_RUNNING; 1995 OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN); 1996 sc->atrs.xferq.flag &= ~FWXFERQ_RUNNING; 1997 1998 fw_busreset(&sc->fc, FWBUSRESET); 1999 OWRITE(sc, OHCI_CROMHDR, ntohl(sc->fc.config_rom[0])); 2000 OWRITE(sc, OHCI_BUS_OPT, ntohl(sc->fc.config_rom[2])); 2001 } 2002 if (stat & OHCI_INT_PHY_SID) { 2003 /* Enable bus reset interrupt */ 2004 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_BUS_R); 2005 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_PHY_BUS_R); 2006 2007 /* Allow async. request to us */ 2008 OWRITE(sc, OHCI_AREQHI, 1 << 31); 2009 if (firewire_phydma_enable) { 2010 /* allow from all nodes */ 2011 OWRITE(sc, OHCI_PREQHI, 0x7fffffff); 2012 OWRITE(sc, OHCI_PREQLO, 0xffffffff); 2013 /* 0 to 4GB region */ 2014 OWRITE(sc, OHCI_PREQUPPER, 0x10000); 2015 } 2016 /* Set ATRetries register */ 2017 OWRITE(sc, OHCI_ATRETRY, 1<<(13+16) | 0xfff); 2018 2019 /* 2020 * Checking whether the node is root or not. If root, turn on 2021 * cycle master. 2022 */ 2023 node_id = OREAD(sc, FWOHCI_NODEID); 2024 plen = OREAD(sc, OHCI_SID_CNT); 2025 2026 fc->nodeid = node_id & 0x3f; 2027 aprint_normal_dev(fc->dev, "node_id=0x%08x, gen=%d, ", 2028 node_id, (plen >> 16) & 0xff); 2029 if (!(node_id & OHCI_NODE_VALID)) { 2030 aprint_error_dev(fc->dev, "Bus reset failure\n"); 2031 goto sidout; 2032 } 2033 2034 /* cycle timer */ 2035 sc->cycle_lost = 0; 2036 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_CYC_LOST); 2037 if ((node_id & OHCI_NODE_ROOT) && !nocyclemaster) { 2038 aprint_normal("CYCLEMASTER mode\n"); 2039 OWRITE(sc, OHCI_LNKCTL, 2040 OHCI_CNTL_CYCMTR | OHCI_CNTL_CYCTIMER); 2041 } else { 2042 aprint_normal("non CYCLEMASTER mode\n"); 2043 OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCMTR); 2044 OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_CYCTIMER); 2045 } 2046 2047 fc->status = FWBUSINIT; 2048 2049 fwohci_task_sid(sc); 2050 } 2051 sidout: 2052 if ((stat & ~(OHCI_INT_PHY_BUS_R | OHCI_INT_PHY_SID))) 2053 fwohci_task_dma(sc); 2054 } 2055 2056 static void 2057 fwohci_intr_dma(struct fwohci_softc *sc, uint32_t stat) 2058 { 2059 struct firewire_comm *fc = &sc->fc; 2060 uint32_t irstat, itstat; 2061 u_int i; 2062 2063 if (stat & OHCI_INT_DMA_IR) { 2064 irstat = atomic_swap_32(&sc->irstat, 0); 2065 for (i = 0; i < fc->nisodma; i++) 2066 if ((irstat & (1 << i)) != 0) { 2067 struct fwohci_dbch *dbch = &sc->ir[i]; 2068 2069 if ((dbch->xferq.flag & FWXFERQ_OPEN) == 0) { 2070 aprint_error_dev(fc->dev, 2071 "dma(%d) not active\n", i); 2072 continue; 2073 } 2074 fwohci_rbuf_update(sc, i); 2075 } 2076 } 2077 if (stat & OHCI_INT_DMA_IT) { 2078 itstat = atomic_swap_32(&sc->itstat, 0); 2079 for (i = 0; i < fc->nisodma; i++) 2080 if ((itstat & (1 << i)) != 0) 2081 fwohci_tbuf_update(sc, i); 2082 } 2083 if (stat & OHCI_INT_DMA_PRRS) { 2084 #if 0 2085 dump_dma(sc, ARRS_CH); 2086 dump_db(sc, ARRS_CH); 2087 #endif 2088 fwohci_arcv(sc, &sc->arrs); 2089 } 2090 if (stat & OHCI_INT_DMA_PRRQ) { 2091 #if 0 2092 dump_dma(sc, ARRQ_CH); 2093 dump_db(sc, ARRQ_CH); 2094 #endif 2095 fwohci_arcv(sc, &sc->arrq); 2096 } 2097 if (stat & OHCI_INT_CYC_LOST) { 2098 if (sc->cycle_lost >= 0) 2099 sc->cycle_lost++; 2100 if (sc->cycle_lost > 10) { 2101 sc->cycle_lost = -1; 2102 #if 0 2103 OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCTIMER); 2104 #endif 2105 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST); 2106 aprint_error_dev(fc->dev, "too many cycle lost, " 2107 "no cycle master presents?\n"); 2108 } 2109 } 2110 if (stat & OHCI_INT_DMA_ATRQ) 2111 fwohci_txd(sc, &(sc->atrq)); 2112 if (stat & OHCI_INT_DMA_ATRS) 2113 fwohci_txd(sc, &(sc->atrs)); 2114 if (stat & OHCI_INT_PW_ERR) 2115 aprint_error_dev(fc->dev, "posted write error\n"); 2116 if (stat & OHCI_INT_ERR) 2117 aprint_error_dev(fc->dev, "unrecoverable error\n"); 2118 if (stat & OHCI_INT_PHY_INT) 2119 aprint_normal_dev(fc->dev, "phy int\n"); 2120 2121 return; 2122 } 2123 2124 static void 2125 fwohci_task_sid(struct fwohci_softc *sc) 2126 { 2127 struct firewire_comm *fc = &sc->fc; 2128 uint32_t *buf; 2129 int i, plen; 2130 2131 plen = OREAD(sc, OHCI_SID_CNT); 2132 2133 if (plen & OHCI_SID_ERR) { 2134 aprint_error_dev(fc->dev, "SID Error\n"); 2135 return; 2136 } 2137 plen &= OHCI_SID_CNT_MASK; 2138 if (plen < 4 || plen > OHCI_SIDSIZE) { 2139 aprint_error_dev(fc->dev, "invalid SID len = %d\n", plen); 2140 return; 2141 } 2142 plen -= 4; /* chop control info */ 2143 buf = (uint32_t *)malloc(OHCI_SIDSIZE, M_FW, M_NOWAIT); 2144 if (buf == NULL) { 2145 aprint_error_dev(fc->dev, "malloc failed\n"); 2146 return; 2147 } 2148 for (i = 0; i < plen / 4; i++) 2149 buf[i] = FWOHCI_DMA_READ(sc->sid_buf[i + 1]); 2150 #if 1 /* XXX needed?? */ 2151 /* pending all pre-bus_reset packets */ 2152 fwohci_txd(sc, &sc->atrq); 2153 fwohci_txd(sc, &sc->atrs); 2154 fwohci_arcv(sc, &sc->arrs); 2155 fwohci_arcv(sc, &sc->arrq); 2156 fw_drain_txq(fc); 2157 #endif 2158 fw_sidrcv(fc, buf, plen); 2159 free(buf, M_FW); 2160 } 2161 2162 static void 2163 fwohci_task_dma(struct fwohci_softc *sc) 2164 { 2165 uint32_t stat; 2166 2167 again: 2168 stat = atomic_swap_32(&sc->intstat, 0); 2169 if (stat) 2170 fwohci_intr_dma(sc, stat); 2171 else 2172 return; 2173 goto again; 2174 } 2175 2176 static void 2177 fwohci_tbuf_update(struct fwohci_softc *sc, int dmach) 2178 { 2179 struct firewire_comm *fc = &sc->fc; 2180 struct fwohcidb *db; 2181 struct fw_bulkxfer *chunk; 2182 struct fw_xferq *it; 2183 uint32_t stat, count; 2184 int w = 0, ldesc; 2185 2186 it = fc->it[dmach]; 2187 ldesc = sc->it[dmach].ndesc - 1; 2188 mutex_enter(&fc->fc_mtx); 2189 fwdma_sync_multiseg_all(sc->it[dmach].am, BUS_DMASYNC_POSTREAD); 2190 if (firewire_debug) 2191 dump_db(sc, ITX_CH + dmach); 2192 while ((chunk = STAILQ_FIRST(&it->stdma)) != NULL) { 2193 db = ((struct fwohcidb_tr *)(chunk->end))->db; 2194 stat = 2195 FWOHCI_DMA_READ(db[ldesc].db.desc.res) >> OHCI_STATUS_SHIFT; 2196 db = ((struct fwohcidb_tr *)(chunk->start))->db; 2197 /* timestamp */ 2198 count = 2199 FWOHCI_DMA_READ(db[ldesc].db.desc.res) & OHCI_COUNT_MASK; 2200 if (stat == 0) 2201 break; 2202 STAILQ_REMOVE_HEAD(&it->stdma, link); 2203 switch (stat & FWOHCIEV_MASK) { 2204 case FWOHCIEV_ACKCOMPL: 2205 #if 0 2206 printf("0x%08x\n", count); 2207 #endif 2208 break; 2209 default: 2210 aprint_error_dev(fc->dev, 2211 "Isochronous transmit err %02x(%s)\n", 2212 stat, fwohcicode[stat & 0x1f]); 2213 } 2214 STAILQ_INSERT_TAIL(&it->stfree, chunk, link); 2215 w++; 2216 } 2217 mutex_exit(&fc->fc_mtx); 2218 if (w) 2219 wakeup(it); 2220 } 2221 2222 static void 2223 fwohci_rbuf_update(struct fwohci_softc *sc, int dmach) 2224 { 2225 struct firewire_comm *fc = &sc->fc; 2226 struct fwohcidb_tr *db_tr; 2227 struct fw_bulkxfer *chunk; 2228 struct fw_xferq *ir; 2229 uint32_t stat; 2230 int w = 0, ldesc; 2231 2232 ir = fc->ir[dmach]; 2233 ldesc = sc->ir[dmach].ndesc - 1; 2234 2235 #if 0 2236 dump_db(sc, dmach); 2237 #endif 2238 if ((ir->flag & FWXFERQ_HANDLER) == 0) 2239 mutex_enter(&fc->fc_mtx); 2240 fwdma_sync_multiseg_all(sc->ir[dmach].am, BUS_DMASYNC_POSTREAD); 2241 while ((chunk = STAILQ_FIRST(&ir->stdma)) != NULL) { 2242 db_tr = (struct fwohcidb_tr *)chunk->end; 2243 stat = FWOHCI_DMA_READ(db_tr->db[ldesc].db.desc.res) >> 2244 OHCI_STATUS_SHIFT; 2245 if (stat == 0) 2246 break; 2247 2248 if (chunk->mbuf != NULL) { 2249 bus_dmamap_sync(fc->dmat, db_tr->dma_map, 0, 2250 db_tr->dma_map->dm_mapsize, BUS_DMASYNC_POSTREAD); 2251 bus_dmamap_unload(fc->dmat, db_tr->dma_map); 2252 } else if (ir->buf != NULL) 2253 fwdma_sync_multiseg(ir->buf, chunk->poffset, 2254 ir->bnpacket, BUS_DMASYNC_POSTREAD); 2255 else 2256 /* XXX */ 2257 aprint_error_dev(fc->dev, 2258 "fwohci_rbuf_update: this shouldn't happend\n"); 2259 2260 STAILQ_REMOVE_HEAD(&ir->stdma, link); 2261 STAILQ_INSERT_TAIL(&ir->stvalid, chunk, link); 2262 switch (stat & FWOHCIEV_MASK) { 2263 case FWOHCIEV_ACKCOMPL: 2264 chunk->resp = 0; 2265 break; 2266 default: 2267 chunk->resp = EINVAL; 2268 aprint_error_dev(fc->dev, 2269 "Isochronous receive err %02x(%s)\n", 2270 stat, fwohcicode[stat & 0x1f]); 2271 } 2272 w++; 2273 } 2274 if ((ir->flag & FWXFERQ_HANDLER) == 0) 2275 mutex_exit(&fc->fc_mtx); 2276 if (w == 0) 2277 return; 2278 if (ir->flag & FWXFERQ_HANDLER) 2279 ir->hand(ir); 2280 else 2281 wakeup(ir); 2282 } 2283 2284 static void 2285 dump_dma(struct fwohci_softc *sc, uint32_t ch) 2286 { 2287 struct fwohci_dbch *dbch; 2288 uint32_t cntl, stat, cmd, match; 2289 2290 if (ch == ATRQ_CH) 2291 dbch = &sc->atrq; 2292 else if (ch == ATRS_CH) 2293 dbch = &sc->atrs; 2294 else if (ch == ARRQ_CH) 2295 dbch = &sc->arrq; 2296 else if (ch == ARRS_CH) 2297 dbch = &sc->arrs; 2298 else if (ch < IRX_CH) 2299 dbch = &sc->it[ch - ITX_CH]; 2300 else 2301 dbch = &sc->ir[ch - IRX_CH]; 2302 cntl = stat = OREAD(sc, dbch->off); 2303 cmd = OREAD(sc, dbch->off + 0xc); 2304 match = OREAD(sc, dbch->off + 0x10); 2305 2306 aprint_normal_dev(sc->fc.dev, 2307 "ch %1x cntl:0x%08x cmd:0x%08x match:0x%08x\n", 2308 ch, 2309 cntl, 2310 cmd, 2311 match); 2312 stat &= 0xffff; 2313 if (stat) 2314 aprint_normal_dev(sc->fc.dev, "dma %d ch:%s%s%s%s%s%s %s(%x)\n", 2315 ch, 2316 stat & OHCI_CNTL_DMA_RUN ? "RUN," : "", 2317 stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "", 2318 stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "", 2319 stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "", 2320 stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "", 2321 stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "", 2322 fwohcicode[stat & 0x1f], 2323 stat & 0x1f 2324 ); 2325 else 2326 aprint_normal_dev(sc->fc.dev, "dma %d ch: Nostat\n", ch); 2327 } 2328 2329 static void 2330 dump_db(struct fwohci_softc *sc, uint32_t ch) 2331 { 2332 struct fwohci_dbch *dbch; 2333 struct fwohcidb_tr *cp = NULL, *pp, *np = NULL; 2334 struct fwohcidb *curr = NULL, *prev, *next = NULL; 2335 int idb, jdb; 2336 uint32_t cmd; 2337 2338 if (ch == ATRQ_CH) 2339 dbch = &sc->atrq; 2340 else if (ch == ATRS_CH) 2341 dbch = &sc->atrs; 2342 else if (ch == ARRQ_CH) 2343 dbch = &sc->arrq; 2344 else if (ch == ARRS_CH) 2345 dbch = &sc->arrs; 2346 else if (ch < IRX_CH) 2347 dbch = &sc->it[ch - ITX_CH]; 2348 else 2349 dbch = &sc->ir[ch - IRX_CH]; 2350 cmd = OREAD(sc, dbch->off + 0xc); 2351 2352 if (dbch->ndb == 0) { 2353 aprint_error_dev(sc->fc.dev, "No DB is attached ch=%d\n", ch); 2354 return; 2355 } 2356 pp = dbch->top; 2357 prev = pp->db; 2358 for (idb = 0; idb < dbch->ndb; idb++) { 2359 cp = STAILQ_NEXT(pp, link); 2360 if (cp == NULL) { 2361 curr = NULL; 2362 goto outdb; 2363 } 2364 np = STAILQ_NEXT(cp, link); 2365 for (jdb = 0; jdb < dbch->ndesc; jdb++) 2366 if ((cmd & 0xfffffff0) == cp->bus_addr) { 2367 curr = cp->db; 2368 if (np != NULL) 2369 next = np->db; 2370 else 2371 next = NULL; 2372 goto outdb; 2373 } 2374 pp = STAILQ_NEXT(pp, link); 2375 if (pp == NULL) { 2376 curr = NULL; 2377 goto outdb; 2378 } 2379 prev = pp->db; 2380 } 2381 outdb: 2382 if (curr != NULL) { 2383 #if 0 2384 aprint_normal("Prev DB %d\n", ch); 2385 print_db(pp, prev, ch, dbch->ndesc); 2386 #endif 2387 aprint_normal("Current DB %d\n", ch); 2388 print_db(cp, curr, ch, dbch->ndesc); 2389 #if 0 2390 aprint_normal("Next DB %d\n", ch); 2391 print_db(np, next, ch, dbch->ndesc); 2392 #endif 2393 } else 2394 aprint_error("dbdump err ch = %d cmd = 0x%08x\n", ch, cmd); 2395 return; 2396 } 2397 2398 static void 2399 print_db(struct fwohcidb_tr *db_tr, struct fwohcidb *db, uint32_t ch, 2400 uint32_t hogemax) 2401 { 2402 fwohcireg_t stat; 2403 int i, key; 2404 uint32_t cmd, res; 2405 2406 if (db == NULL) { 2407 aprint_error("No Descriptor is found\n"); 2408 return; 2409 } 2410 2411 aprint_normal("ch = %d\n%8s %s %s %s %s %4s %8s %8s %4s:%4s\n", 2412 ch, 2413 "Current", 2414 "OP ", 2415 "KEY", 2416 "INT", 2417 "BR ", 2418 "len", 2419 "Addr", 2420 "Depend", 2421 "Stat", 2422 "Cnt"); 2423 for (i = 0; i <= hogemax; i++) { 2424 cmd = FWOHCI_DMA_READ(db[i].db.desc.cmd); 2425 res = FWOHCI_DMA_READ(db[i].db.desc.res); 2426 key = cmd & OHCI_KEY_MASK; 2427 stat = res >> OHCI_STATUS_SHIFT; 2428 aprint_normal("%08jx %s %s %s %s %5d %08x %08x %04x:%04x", 2429 (uintmax_t)db_tr->bus_addr, 2430 dbcode[(cmd >> 28) & 0xf], 2431 dbkey[(cmd >> 24) & 0x7], 2432 dbcond[(cmd >> 20) & 0x3], 2433 dbcond[(cmd >> 18) & 0x3], 2434 cmd & OHCI_COUNT_MASK, 2435 FWOHCI_DMA_READ(db[i].db.desc.addr), 2436 FWOHCI_DMA_READ(db[i].db.desc.depend), 2437 stat, 2438 res & OHCI_COUNT_MASK); 2439 if (stat & 0xff00) 2440 aprint_normal(" %s%s%s%s%s%s %s(%x)\n", 2441 stat & OHCI_CNTL_DMA_RUN ? "RUN," : "", 2442 stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "", 2443 stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "", 2444 stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "", 2445 stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "", 2446 stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "", 2447 fwohcicode[stat & 0x1f], 2448 stat & 0x1f 2449 ); 2450 else 2451 aprint_normal(" Nostat\n"); 2452 if (key == OHCI_KEY_ST2) 2453 aprint_normal("0x%08x 0x%08x 0x%08x 0x%08x\n", 2454 FWOHCI_DMA_READ(db[i+1].db.immed[0]), 2455 FWOHCI_DMA_READ(db[i+1].db.immed[1]), 2456 FWOHCI_DMA_READ(db[i+1].db.immed[2]), 2457 FWOHCI_DMA_READ(db[i+1].db.immed[3])); 2458 if (key == OHCI_KEY_DEVICE) 2459 return; 2460 if ((cmd & OHCI_BRANCH_MASK) == OHCI_BRANCH_ALWAYS) 2461 return; 2462 if ((cmd & OHCI_CMD_MASK) == OHCI_OUTPUT_LAST) 2463 return; 2464 if ((cmd & OHCI_CMD_MASK) == OHCI_INPUT_LAST) 2465 return; 2466 if (key == OHCI_KEY_ST2) 2467 i++; 2468 } 2469 return; 2470 } 2471 2472 static void 2473 fwohci_txbufdb(struct fwohci_softc *sc, int dmach, struct fw_bulkxfer *bulkxfer) 2474 { 2475 struct fwohcidb_tr *db_tr, *fdb_tr; 2476 struct fwohci_dbch *dbch; 2477 struct fwohcidb *db; 2478 struct fw_pkt *fp; 2479 struct fwohci_txpkthdr *ohcifp; 2480 unsigned short chtag; 2481 int idb; 2482 2483 KASSERT(mutex_owner(&sc->fc.fc_mtx)); 2484 2485 dbch = &sc->it[dmach]; 2486 chtag = sc->it[dmach].xferq.flag & 0xff; 2487 2488 db_tr = (struct fwohcidb_tr *)(bulkxfer->start); 2489 fdb_tr = (struct fwohcidb_tr *)(bulkxfer->end); 2490 /* 2491 aprint_normal(sc->fc.dev, "DB %08x %08x %08x\n", bulkxfer, db_tr->bus_addr, fdb_tr->bus_addr); 2492 */ 2493 for (idb = 0; idb < dbch->xferq.bnpacket; idb++) { 2494 db = db_tr->db; 2495 fp = (struct fw_pkt *)db_tr->buf; 2496 ohcifp = (struct fwohci_txpkthdr *) db[1].db.immed; 2497 ohcifp->mode.ld[0] = fp->mode.ld[0]; 2498 ohcifp->mode.common.spd = 0 & 0x7; 2499 ohcifp->mode.stream.len = fp->mode.stream.len; 2500 ohcifp->mode.stream.chtag = chtag; 2501 ohcifp->mode.stream.tcode = 0xa; 2502 #if BYTE_ORDER == BIG_ENDIAN 2503 FWOHCI_DMA_WRITE(db[1].db.immed[0], db[1].db.immed[0]); 2504 FWOHCI_DMA_WRITE(db[1].db.immed[1], db[1].db.immed[1]); 2505 #endif 2506 2507 FWOHCI_DMA_CLEAR(db[2].db.desc.cmd, OHCI_COUNT_MASK); 2508 FWOHCI_DMA_SET(db[2].db.desc.cmd, fp->mode.stream.len); 2509 FWOHCI_DMA_WRITE(db[2].db.desc.res, 0); 2510 #if 0 /* if bulkxfer->npackets changes */ 2511 db[2].db.desc.cmd = 2512 OHCI_OUTPUT_LAST | OHCI_UPDATE | OHCI_BRANCH_ALWAYS; 2513 db[0].db.desc.depend = db[dbch->ndesc - 1].db.desc.depend = 2514 STAILQ_NEXT(db_tr, link)->bus_addr | dbch->ndesc; 2515 #else 2516 FWOHCI_DMA_SET(db[0].db.desc.depend, dbch->ndesc); 2517 FWOHCI_DMA_SET(db[dbch->ndesc - 1].db.desc.depend, dbch->ndesc); 2518 #endif 2519 bulkxfer->end = (void *)db_tr; 2520 db_tr = STAILQ_NEXT(db_tr, link); 2521 } 2522 db = ((struct fwohcidb_tr *)bulkxfer->end)->db; 2523 FWOHCI_DMA_CLEAR(db[0].db.desc.depend, 0xf); 2524 FWOHCI_DMA_CLEAR(db[dbch->ndesc - 1].db.desc.depend, 0xf); 2525 #if 0 /* if bulkxfer->npackets changes */ 2526 db[dbch->ndesc - 1].db.desc.control |= OHCI_INTERRUPT_ALWAYS; 2527 /* OHCI 1.1 and above */ 2528 db[0].db.desc.control |= OHCI_INTERRUPT_ALWAYS; 2529 #endif 2530 /* 2531 db_tr = (struct fwohcidb_tr *)bulkxfer->start; 2532 fdb_tr = (struct fwohcidb_tr *)bulkxfer->end; 2533 aprint_normal(sc->fc.dev, "DB %08x %3d %08x %08x\n", bulkxfer, bulkxfer->npacket, db_tr->bus_addr, fdb_tr->bus_addr); 2534 */ 2535 return; 2536 } 2537 2538 static int 2539 fwohci_add_tx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr, 2540 int poffset) 2541 { 2542 struct fwohcidb *db = db_tr->db; 2543 struct fw_xferq *it; 2544 int err = 0; 2545 2546 it = &dbch->xferq; 2547 if (it->buf == 0) { 2548 err = EINVAL; 2549 return err; 2550 } 2551 db_tr->buf = fwdma_v_addr(it->buf, poffset); 2552 db_tr->dbcnt = 3; 2553 2554 FWOHCI_DMA_WRITE(db[0].db.desc.cmd, 2555 OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | 8); 2556 FWOHCI_DMA_WRITE(db[0].db.desc.addr, 0); 2557 memset((void *)db[1].db.immed, 0, sizeof(db[1].db.immed)); 2558 FWOHCI_DMA_WRITE(db[2].db.desc.addr, 2559 fwdma_bus_addr(it->buf, poffset) + sizeof(uint32_t)); 2560 2561 FWOHCI_DMA_WRITE(db[2].db.desc.cmd, 2562 OHCI_OUTPUT_LAST | OHCI_UPDATE | OHCI_BRANCH_ALWAYS); 2563 #if 1 2564 FWOHCI_DMA_WRITE(db[0].db.desc.res, 0); 2565 FWOHCI_DMA_WRITE(db[2].db.desc.res, 0); 2566 #endif 2567 return 0; 2568 } 2569 2570 int 2571 fwohci_add_rx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr, 2572 int poffset, struct fwdma_alloc *dummy_dma) 2573 { 2574 struct fwohcidb *db = db_tr->db; 2575 struct fw_xferq *rq; 2576 int i, ldesc; 2577 bus_addr_t dbuf[2]; 2578 int dsiz[2]; 2579 2580 rq = &dbch->xferq; 2581 if (rq->buf == NULL && (dbch->xferq.flag & FWXFERQ_EXTBUF) == 0) { 2582 /* async */ 2583 db_tr->dbcnt = 1; 2584 dsiz[0] = rq->psize; 2585 dbuf[0] = db_tr->dma_map->dm_segs[0].ds_addr; 2586 } else { 2587 /* isoc */ 2588 db_tr->dbcnt = 0; 2589 dsiz[db_tr->dbcnt] = sizeof(uint32_t); 2590 dbuf[db_tr->dbcnt++] = dummy_dma->bus_addr; 2591 dsiz[db_tr->dbcnt] = rq->psize; 2592 if (rq->buf != NULL) { 2593 db_tr->buf = fwdma_v_addr(rq->buf, poffset); 2594 dbuf[db_tr->dbcnt] = fwdma_bus_addr(rq->buf, poffset); 2595 } 2596 db_tr->dbcnt++; 2597 } 2598 for (i = 0; i < db_tr->dbcnt; i++) { 2599 FWOHCI_DMA_WRITE(db[i].db.desc.addr, dbuf[i]); 2600 FWOHCI_DMA_WRITE(db[i].db.desc.cmd, OHCI_INPUT_MORE | dsiz[i]); 2601 if (rq->flag & FWXFERQ_STREAM) 2602 FWOHCI_DMA_SET(db[i].db.desc.cmd, OHCI_UPDATE); 2603 FWOHCI_DMA_WRITE(db[i].db.desc.res, dsiz[i]); 2604 } 2605 ldesc = db_tr->dbcnt - 1; 2606 if (rq->flag & FWXFERQ_STREAM) 2607 FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, OHCI_INPUT_LAST); 2608 FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, OHCI_BRANCH_ALWAYS); 2609 return 0; 2610 } 2611 2612 2613 static int 2614 fwohci_arcv_swap(struct fw_pkt *fp, int len) 2615 { 2616 struct fw_pkt *fp0; 2617 uint32_t ld0; 2618 int slen, hlen; 2619 #if BYTE_ORDER == BIG_ENDIAN 2620 int i; 2621 #endif 2622 2623 ld0 = FWOHCI_DMA_READ(fp->mode.ld[0]); 2624 #if 0 2625 printf("ld0: x%08x\n", ld0); 2626 #endif 2627 fp0 = (struct fw_pkt *)&ld0; 2628 /* determine length to swap */ 2629 switch (fp0->mode.common.tcode) { 2630 case FWTCODE_WRES: 2631 case FWTCODE_RREQQ: 2632 case FWTCODE_WREQQ: 2633 case FWTCODE_RRESQ: 2634 case FWOHCITCODE_PHY: 2635 slen = 12; 2636 break; 2637 2638 case FWTCODE_RREQB: 2639 case FWTCODE_WREQB: 2640 case FWTCODE_LREQ: 2641 case FWTCODE_RRESB: 2642 case FWTCODE_LRES: 2643 slen = 16; 2644 break; 2645 2646 default: 2647 aprint_error("Unknown tcode %d\n", fp0->mode.common.tcode); 2648 return 0; 2649 } 2650 hlen = tinfo[fp0->mode.common.tcode].hdr_len; 2651 if (hlen > len) { 2652 if (firewire_debug) 2653 printf("splitted header\n"); 2654 return len - hlen; 2655 } 2656 #if BYTE_ORDER == BIG_ENDIAN 2657 for (i = 0; i < slen / 4; i++) 2658 fp->mode.ld[i] = FWOHCI_DMA_READ(fp->mode.ld[i]); 2659 #endif 2660 return hlen; 2661 } 2662 2663 static int 2664 fwohci_get_plen(struct fwohci_softc *sc, struct fwohci_dbch *dbch, 2665 struct fw_pkt *fp) 2666 { 2667 const struct tcode_info *info; 2668 int r; 2669 2670 info = &tinfo[fp->mode.common.tcode]; 2671 r = info->hdr_len + sizeof(uint32_t); 2672 if (info->flag & FWTI_BLOCK_ASY) 2673 r += roundup2(fp->mode.wreqb.len, sizeof(uint32_t)); 2674 2675 if (r == sizeof(uint32_t)) { 2676 /* XXX */ 2677 aprint_error_dev(sc->fc.dev, "Unknown tcode %d\n", 2678 fp->mode.common.tcode); 2679 return -1; 2680 } 2681 2682 if (r > dbch->xferq.psize) { 2683 aprint_error_dev(sc->fc.dev, "Invalid packet length %d\n", r); 2684 return -1; 2685 /* panic ? */ 2686 } 2687 2688 return r; 2689 } 2690 2691 static void 2692 fwohci_arcv_free_buf(struct fwohci_softc *sc, struct fwohci_dbch *dbch, 2693 struct fwohcidb_tr *db_tr, int wake) 2694 { 2695 struct fwohcidb *db = db_tr->db; 2696 struct fwohcidb_tr *bdb_tr = dbch->bottom; 2697 2698 FWOHCI_DMA_CLEAR(db->db.desc.depend, 0xf); 2699 FWOHCI_DMA_WRITE(db->db.desc.res, dbch->xferq.psize); 2700 2701 fwdma_sync_multiseg(dbch->am, bdb_tr->idx, bdb_tr->idx, 2702 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 2703 FWOHCI_DMA_SET(bdb_tr->db[0].db.desc.depend, dbch->ndesc); 2704 2705 fwdma_sync_multiseg(dbch->am, bdb_tr->idx, db_tr->idx, 2706 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 2707 dbch->bottom = db_tr; 2708 2709 if (wake) 2710 OWRITE(sc, OHCI_DMACTL(dbch->off), OHCI_CNTL_DMA_WAKE); 2711 } 2712 2713 static void 2714 fwohci_arcv(struct fwohci_softc *sc, struct fwohci_dbch *dbch) 2715 { 2716 struct fwohcidb_tr *db_tr; 2717 struct fw_pkt pktbuf, *fp; 2718 struct iovec vec[2]; 2719 bus_addr_t m; 2720 bus_size_t n; 2721 u_int spd; 2722 uint32_t stat, status, event; 2723 uint8_t *ld; 2724 int nvec, resCount, len, plen, hlen, offset; 2725 const int psize = dbch->xferq.psize; 2726 2727 #if DIAGNOSTIC 2728 if (dbch->off != OHCI_ARQOFF && 2729 dbch->off != OHCI_ARSOFF) 2730 panic("not async rx"); 2731 #endif 2732 2733 mutex_enter(&dbch->xferq.q_mtx); 2734 db_tr = dbch->top; 2735 /* XXX we cannot handle a packet which lies in more than two buf */ 2736 fwdma_sync_multiseg(dbch->am, db_tr->idx, db_tr->idx, 2737 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 2738 status = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) >> OHCI_STATUS_SHIFT; 2739 resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) & OHCI_COUNT_MASK; 2740 while (status & OHCI_CNTL_DMA_ACTIVE) { 2741 #if 0 2742 if (dbch->off == OHCI_ARQOFF) 2743 aprint_normal_dev(sc->fc.dev, 2744 "buf 0x%08x, status 0x%04x, resCount 0x%04x\n", 2745 db_tr->bus_addr, status, resCount); 2746 #endif 2747 n = 0; 2748 len = psize - resCount; 2749 ld = (uint8_t *)db_tr->buf; 2750 if (dbch->pdb_tr == NULL) { 2751 len -= dbch->buf_offset; 2752 ld += dbch->buf_offset; 2753 m = dbch->buf_offset; 2754 } else 2755 m = 0; 2756 if (len > 0) 2757 bus_dmamap_sync(sc->fc.dmat, db_tr->dma_map, 2758 m, len, BUS_DMASYNC_POSTREAD); 2759 while (len > 0) { 2760 if (dbch->pdb_tr != NULL) { 2761 /* we have a fragment in previous buffer */ 2762 int rlen = 0; 2763 void *buf; 2764 2765 if (dbch->buf_offset < 0) { 2766 /* splitted in header, pull up */ 2767 char *p; 2768 2769 rlen -= dbch->buf_offset; 2770 buf = (char *)dbch->pdb_tr->buf + 2771 psize - rlen; 2772 2773 KASSERT(rlen <= sizeof(pktbuf)); 2774 2775 p = (char *)&pktbuf; 2776 memcpy(p, buf, rlen); 2777 p += rlen; 2778 /* this must be too long but harmless */ 2779 rlen = sizeof(pktbuf) - rlen; 2780 memcpy(p, db_tr->buf, rlen); 2781 ld += rlen; 2782 len -= rlen; 2783 hlen = fwohci_arcv_swap(&pktbuf, 2784 sizeof(pktbuf)); 2785 if (hlen <= 0) { 2786 aprint_error_dev(sc->fc.dev, 2787 "hlen should be positive."); 2788 goto err; 2789 } 2790 offset = sizeof(pktbuf); 2791 vec[0].iov_base = (char *)&pktbuf; 2792 vec[0].iov_len = offset; 2793 } else { 2794 /* splitted in payload */ 2795 buf = (char *)dbch->pdb_tr->buf + 2796 dbch->buf_offset; 2797 rlen = psize - dbch->buf_offset; 2798 if (firewire_debug) 2799 printf("rlen=%d, offset=%d\n", 2800 rlen, dbch->buf_offset); 2801 offset = rlen; 2802 vec[0].iov_base = buf; 2803 vec[0].iov_len = rlen; 2804 } 2805 fp = (struct fw_pkt *)vec[0].iov_base; 2806 nvec = 1; 2807 } else { 2808 /* no fragment in previous buffer */ 2809 fp = (struct fw_pkt *)ld; 2810 hlen = fwohci_arcv_swap(fp, len); 2811 if (hlen == 0) 2812 goto err; 2813 if (hlen < 0) { 2814 dbch->pdb_tr = db_tr; 2815 dbch->buf_offset -= psize; 2816 /* sanity check */ 2817 if (resCount != 0) { 2818 aprint_error_dev(sc->fc.dev, 2819 "resCount=%d hlen=%d\n", 2820 resCount, hlen); 2821 goto err; 2822 } 2823 goto out; 2824 } 2825 offset = 0; 2826 nvec = 0; 2827 } 2828 plen = fwohci_get_plen(sc, dbch, fp) - offset; 2829 if (plen < 0) { 2830 /* 2831 * minimum header size + trailer = 2832 * sizeof(fw_pkt) so this shouldn't happens 2833 */ 2834 aprint_error_dev(sc->fc.dev, 2835 "plen(%d) is negative! offset=%d\n", 2836 plen, offset); 2837 goto err; 2838 } 2839 if (plen > 0) { 2840 len -= plen; 2841 if (len < 0) { 2842 dbch->pdb_tr = db_tr; 2843 if (firewire_debug) 2844 printf("splitted payload\n"); 2845 /* sanity check */ 2846 if (resCount != 0) { 2847 aprint_error_dev(sc->fc.dev, 2848 "resCount=%d plen=%d" 2849 " len=%d\n", 2850 resCount, plen, len); 2851 goto err; 2852 } 2853 goto out; 2854 } 2855 vec[nvec].iov_base = ld; 2856 vec[nvec].iov_len = plen; 2857 nvec++; 2858 ld += plen; 2859 } 2860 if (nvec == 0) 2861 aprint_error_dev(sc->fc.dev, "nvec == 0\n"); 2862 2863 /* DMA result-code will be written at the tail of packet */ 2864 stat = FWOHCI_DMA_READ(*(uint32_t *)(ld - 2865 sizeof(struct fwohci_trailer))); 2866 #if 0 2867 aprint_normal("plen: %d, stat %x\n", plen, stat); 2868 #endif 2869 spd = (stat >> 21) & 0x3; 2870 event = (stat >> 16) & 0x1f; 2871 switch (event) { 2872 case FWOHCIEV_ACKPEND: 2873 #if 0 2874 aprint_normal(sc->fc.dev, 2875 "ack pending tcode=0x%x..\n", 2876 fp->mode.common.tcode); 2877 #endif 2878 /* fall through */ 2879 case FWOHCIEV_ACKCOMPL: 2880 { 2881 struct fw_rcv_buf rb; 2882 2883 vec[nvec - 1].iov_len -= 2884 sizeof(struct fwohci_trailer); 2885 if (vec[nvec - 1].iov_len == 0) 2886 nvec--; 2887 rb.fc = &sc->fc; 2888 rb.vec = vec; 2889 rb.nvec = nvec; 2890 rb.spd = spd; 2891 fw_rcv(&rb); 2892 break; 2893 } 2894 case FWOHCIEV_BUSRST: 2895 if ((sc->fc.status != FWBUSRESET) && 2896 (sc->fc.status != FWBUSINIT)) 2897 aprint_error_dev(sc->fc.dev, 2898 "got BUSRST packet!?\n"); 2899 break; 2900 default: 2901 aprint_error_dev(sc->fc.dev, 2902 "Async DMA Receive error err=%02x %s" 2903 " plen=%d offset=%d len=%d status=0x%08x" 2904 " tcode=0x%x, stat=0x%08x\n", 2905 event, fwohcicode[event], plen, 2906 (int)(ld - (uint8_t *)db_tr->buf - plen), 2907 len, OREAD(sc, OHCI_DMACTL(dbch->off)), 2908 fp->mode.common.tcode, stat); 2909 #if 1 /* XXX */ 2910 goto err; 2911 #endif 2912 break; 2913 } 2914 if (dbch->pdb_tr != NULL) { 2915 if (dbch->buf_offset < 0) 2916 bus_dmamap_sync(sc->fc.dmat, 2917 dbch->pdb_tr->dma_map, 2918 psize + dbch->buf_offset, 2919 0 - dbch->buf_offset, 2920 BUS_DMASYNC_PREREAD); 2921 else 2922 bus_dmamap_sync(sc->fc.dmat, 2923 dbch->pdb_tr->dma_map, 2924 dbch->buf_offset, 2925 psize - dbch->buf_offset, 2926 BUS_DMASYNC_PREREAD); 2927 fwohci_arcv_free_buf(sc, dbch, dbch->pdb_tr, 1); 2928 dbch->pdb_tr = NULL; 2929 } 2930 dbch->buf_offset = ld - (uint8_t *)db_tr->buf; 2931 n += (plen + offset); 2932 } 2933 out: 2934 if (n > 0) 2935 bus_dmamap_sync(sc->fc.dmat, db_tr->dma_map, m, n, 2936 BUS_DMASYNC_PREREAD); 2937 2938 if (resCount != 0) { 2939 dbch->buf_offset = psize - resCount; 2940 break; 2941 } 2942 2943 /* done on this buffer */ 2944 2945 if (dbch->pdb_tr == NULL) { 2946 fwohci_arcv_free_buf(sc, dbch, db_tr, 1); 2947 dbch->buf_offset = 0; 2948 } else 2949 if (dbch->pdb_tr != db_tr) 2950 aprint_error_dev(sc->fc.dev, 2951 "pdb_tr != db_tr\n"); 2952 dbch->top = STAILQ_NEXT(db_tr, link); 2953 2954 db_tr = dbch->top; 2955 fwdma_sync_multiseg(dbch->am, db_tr->idx, db_tr->idx, 2956 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 2957 status = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) >> 2958 OHCI_STATUS_SHIFT; 2959 resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) 2960 & OHCI_COUNT_MASK; 2961 2962 /* XXX check buffer overrun */ 2963 2964 /* XXX make sure DMA is not dead */ 2965 } 2966 fwdma_sync_multiseg(dbch->am, db_tr->idx, db_tr->idx, 2967 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 2968 mutex_exit(&dbch->xferq.q_mtx); 2969 return; 2970 2971 err: 2972 aprint_error_dev(sc->fc.dev, "AR DMA status=%x, ", 2973 OREAD(sc, OHCI_DMACTL(dbch->off))); 2974 if (dbch->pdb_tr != NULL) { 2975 if (dbch->buf_offset < 0) 2976 bus_dmamap_sync(sc->fc.dmat, dbch->pdb_tr->dma_map, 2977 psize + dbch->buf_offset, 0 - dbch->buf_offset, 2978 BUS_DMASYNC_PREREAD); 2979 else 2980 bus_dmamap_sync(sc->fc.dmat, dbch->pdb_tr->dma_map, 2981 dbch->buf_offset, psize - dbch->buf_offset, 2982 BUS_DMASYNC_PREREAD); 2983 fwohci_arcv_free_buf(sc, dbch, dbch->pdb_tr, 1); 2984 dbch->pdb_tr = NULL; 2985 } 2986 /* skip until resCount != 0 */ 2987 aprint_error(" skip buffer"); 2988 while (resCount == 0) { 2989 aprint_error(" #"); 2990 fwohci_arcv_free_buf(sc, dbch, db_tr, 0); 2991 db_tr = STAILQ_NEXT(db_tr, link); 2992 resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) 2993 & OHCI_COUNT_MASK; 2994 } 2995 aprint_error(" done\n"); 2996 dbch->top = db_tr; 2997 dbch->buf_offset = psize - resCount; 2998 OWRITE(sc, OHCI_DMACTL(dbch->off), OHCI_CNTL_DMA_WAKE); 2999 fwdma_sync_multiseg(dbch->am, db_tr->idx, db_tr->idx, 3000 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 3001 bus_dmamap_sync(sc->fc.dmat, db_tr->dma_map, 3002 0, db_tr->dma_map->dm_mapsize, BUS_DMASYNC_PREREAD); 3003 mutex_exit(&dbch->xferq.q_mtx); 3004 } 3005