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