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