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