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