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 #include <machine/md_var.h> 52 53 #include <dev/firewire/firewire.h> 54 #include <dev/firewire/firewirereg.h> 55 #include <dev/firewire/fwdma.h> 56 #include <dev/firewire/fwohcireg.h> 57 #include <dev/firewire/fwohcivar.h> 58 #include <dev/firewire/firewire_phy.h> 59 60 #undef OHCI_DEBUG 61 62 static int nocyclemaster; 63 int firewire_phydma_enable = 1; 64 SYSCTL_DECL(_hw_firewire); 65 SYSCTL_INT(_hw_firewire, OID_AUTO, nocyclemaster, CTLFLAG_RWTUN, 66 &nocyclemaster, 0, "Do not send cycle start packets"); 67 SYSCTL_INT(_hw_firewire, OID_AUTO, phydma_enable, CTLFLAG_RWTUN, 68 &firewire_phydma_enable, 0, "Allow physical request DMA from firewire"); 69 70 static char dbcode[16][0x10] = {"OUTM", "OUTL", "INPM", "INPL", 71 "STOR", "LOAD", "NOP ", "STOP",}; 72 73 static char dbkey[8][0x10] = {"ST0", "ST1", "ST2", "ST3", 74 "UNDEF", "REG", "SYS", "DEV"}; 75 static char dbcond[4][0x10] = {"NEV", "C=1", "C=0", "ALL"}; 76 char fwohcicode[32][0x20]= { 77 "No stat", "Undef", "long", "miss Ack err", 78 "FIFO underrun", "FIFO overrun", "desc err", "data read err", 79 "data write err", "bus reset", "timeout", "tcode err", 80 "Undef", "Undef", "unknown event", "flushed", 81 "Undef" ,"ack complete", "ack pend", "Undef", 82 "ack busy_X", "ack busy_A", "ack busy_B", "Undef", 83 "Undef", "Undef", "Undef", "ack tardy", 84 "Undef", "ack data_err", "ack type_err", ""}; 85 86 #define MAX_SPEED 3 87 extern char *linkspeed[]; 88 uint32_t tagbit[4] = {1 << 28, 1 << 29, 1 << 30, 1 << 31}; 89 90 static struct tcode_info tinfo[] = { 91 /* hdr_len block flag valid_response */ 92 /* 0 WREQQ */ {16, FWTI_REQ | FWTI_TLABEL, FWTCODE_WRES}, 93 /* 1 WREQB */ {16, FWTI_REQ | FWTI_TLABEL | FWTI_BLOCK_ASY, FWTCODE_WRES}, 94 /* 2 WRES */ {12, FWTI_RES, 0xff}, 95 /* 3 XXX */ { 0, 0, 0xff}, 96 /* 4 RREQQ */ {12, FWTI_REQ | FWTI_TLABEL, FWTCODE_RRESQ}, 97 /* 5 RREQB */ {16, FWTI_REQ | FWTI_TLABEL, FWTCODE_RRESB}, 98 /* 6 RRESQ */ {16, FWTI_RES, 0xff}, 99 /* 7 RRESB */ {16, FWTI_RES | FWTI_BLOCK_ASY, 0xff}, 100 /* 8 CYCS */ { 0, 0, 0xff}, 101 /* 9 LREQ */ {16, FWTI_REQ | FWTI_TLABEL | FWTI_BLOCK_ASY, FWTCODE_LRES}, 102 /* a STREAM */ { 4, FWTI_REQ | FWTI_BLOCK_STR, 0xff}, 103 /* b LRES */ {16, FWTI_RES | FWTI_BLOCK_ASY, 0xff}, 104 /* c XXX */ { 0, 0, 0xff}, 105 /* d XXX */ { 0, 0, 0xff}, 106 /* e PHY */ {12, FWTI_REQ, 0xff}, 107 /* f XXX */ { 0, 0, 0xff} 108 }; 109 110 #define ATRQ_CH 0 111 #define ATRS_CH 1 112 #define ARRQ_CH 2 113 #define ARRS_CH 3 114 #define ITX_CH 4 115 #define IRX_CH 0x24 116 117 #define OHCI_WRITE_SIGMASK 0xffff0000 118 #define OHCI_READ_SIGMASK 0xffff0000 119 120 #define OWRITE(sc, r, x) bus_space_write_4((sc)->bst, (sc)->bsh, (r), (x)) 121 #define OREAD(sc, r) bus_space_read_4((sc)->bst, (sc)->bsh, (r)) 122 123 static void fwohci_ibr (struct firewire_comm *); 124 static void fwohci_db_init (struct fwohci_softc *, struct fwohci_dbch *); 125 static void fwohci_db_free (struct fwohci_dbch *); 126 static void fwohci_arcv (struct fwohci_softc *, struct fwohci_dbch *, int); 127 static void fwohci_txd (struct fwohci_softc *, struct fwohci_dbch *); 128 static void fwohci_start_atq (struct firewire_comm *); 129 static void fwohci_start_ats (struct firewire_comm *); 130 static void fwohci_start (struct fwohci_softc *, struct fwohci_dbch *); 131 static uint32_t fwphy_wrdata (struct fwohci_softc *, uint32_t, uint32_t); 132 static uint32_t fwphy_rddata (struct fwohci_softc *, uint32_t); 133 static int fwohci_rx_enable (struct fwohci_softc *, struct fwohci_dbch *); 134 static int fwohci_tx_enable (struct fwohci_softc *, struct fwohci_dbch *); 135 static int fwohci_irx_enable (struct firewire_comm *, int); 136 static int fwohci_irx_disable (struct firewire_comm *, int); 137 #if BYTE_ORDER == BIG_ENDIAN 138 static void fwohci_irx_post (struct firewire_comm *, uint32_t *); 139 #endif 140 static int fwohci_itxbuf_enable (struct firewire_comm *, int); 141 static int fwohci_itx_disable (struct firewire_comm *, int); 142 static void fwohci_timeout (void *); 143 static void fwohci_set_intr (struct firewire_comm *, int); 144 145 static int fwohci_add_rx_buf (struct fwohci_dbch *, struct fwohcidb_tr *, int, struct fwdma_alloc *); 146 static int fwohci_add_tx_buf (struct fwohci_dbch *, struct fwohcidb_tr *, int); 147 static void dump_db (struct fwohci_softc *, uint32_t); 148 static void print_db (struct fwohcidb_tr *, struct fwohcidb *, uint32_t , uint32_t); 149 static void dump_dma (struct fwohci_softc *, uint32_t); 150 static uint32_t fwohci_cyctimer (struct firewire_comm *); 151 static void fwohci_rbuf_update (struct fwohci_softc *, int); 152 static void fwohci_tbuf_update (struct fwohci_softc *, int); 153 void fwohci_txbufdb (struct fwohci_softc *, int , struct fw_bulkxfer *); 154 static void fwohci_task_busreset(void *, int); 155 static void fwohci_task_sid(void *, int); 156 static void fwohci_task_dma(void *, int); 157 158 /* 159 * memory allocated for DMA programs 160 */ 161 #define DMA_PROG_ALLOC (8 * PAGE_SIZE) 162 163 #define NDB FWMAXQUEUE 164 165 #define OHCI_VERSION 0x00 166 #define OHCI_ATRETRY 0x08 167 #define OHCI_CROMHDR 0x18 168 #define OHCI_BUS_OPT 0x20 169 #define OHCI_BUSIRMC (1U << 31) 170 #define OHCI_BUSCMC (1 << 30) 171 #define OHCI_BUSISC (1 << 29) 172 #define OHCI_BUSBMC (1 << 28) 173 #define OHCI_BUSPMC (1 << 27) 174 #define OHCI_BUSFNC OHCI_BUSIRMC | OHCI_BUSCMC | OHCI_BUSISC |\ 175 OHCI_BUSBMC | OHCI_BUSPMC 176 177 #define OHCI_EUID_HI 0x24 178 #define OHCI_EUID_LO 0x28 179 180 #define OHCI_CROMPTR 0x34 181 #define OHCI_HCCCTL 0x50 182 #define OHCI_HCCCTLCLR 0x54 183 #define OHCI_AREQHI 0x100 184 #define OHCI_AREQHICLR 0x104 185 #define OHCI_AREQLO 0x108 186 #define OHCI_AREQLOCLR 0x10c 187 #define OHCI_PREQHI 0x110 188 #define OHCI_PREQHICLR 0x114 189 #define OHCI_PREQLO 0x118 190 #define OHCI_PREQLOCLR 0x11c 191 #define OHCI_PREQUPPER 0x120 192 #define OHCI_PREQUPPER_MAX 0xffff0000 193 194 #define OHCI_SID_BUF 0x64 195 #define OHCI_SID_CNT 0x68 196 #define OHCI_SID_ERR (1U << 31) 197 #define OHCI_SID_CNT_MASK 0xffc 198 199 #define OHCI_IT_STAT 0x90 200 #define OHCI_IT_STATCLR 0x94 201 #define OHCI_IT_MASK 0x98 202 #define OHCI_IT_MASKCLR 0x9c 203 204 #define OHCI_IR_STAT 0xa0 205 #define OHCI_IR_STATCLR 0xa4 206 #define OHCI_IR_MASK 0xa8 207 #define OHCI_IR_MASKCLR 0xac 208 209 #define OHCI_LNKCTL 0xe0 210 #define OHCI_LNKCTLCLR 0xe4 211 212 #define OHCI_PHYACCESS 0xec 213 #define OHCI_CYCLETIMER 0xf0 214 215 #define OHCI_DMACTL(off) (off) 216 #define OHCI_DMACTLCLR(off) (off + 4) 217 #define OHCI_DMACMD(off) (off + 0xc) 218 #define OHCI_DMAMATCH(off) (off + 0x10) 219 220 #define OHCI_ATQOFF 0x180 221 #define OHCI_ATQCTL OHCI_ATQOFF 222 #define OHCI_ATQCTLCLR (OHCI_ATQOFF + 4) 223 #define OHCI_ATQCMD (OHCI_ATQOFF + 0xc) 224 #define OHCI_ATQMATCH (OHCI_ATQOFF + 0x10) 225 226 #define OHCI_ATSOFF 0x1a0 227 #define OHCI_ATSCTL OHCI_ATSOFF 228 #define OHCI_ATSCTLCLR (OHCI_ATSOFF + 4) 229 #define OHCI_ATSCMD (OHCI_ATSOFF + 0xc) 230 #define OHCI_ATSMATCH (OHCI_ATSOFF + 0x10) 231 232 #define OHCI_ARQOFF 0x1c0 233 #define OHCI_ARQCTL OHCI_ARQOFF 234 #define OHCI_ARQCTLCLR (OHCI_ARQOFF + 4) 235 #define OHCI_ARQCMD (OHCI_ARQOFF + 0xc) 236 #define OHCI_ARQMATCH (OHCI_ARQOFF + 0x10) 237 238 #define OHCI_ARSOFF 0x1e0 239 #define OHCI_ARSCTL OHCI_ARSOFF 240 #define OHCI_ARSCTLCLR (OHCI_ARSOFF + 4) 241 #define OHCI_ARSCMD (OHCI_ARSOFF + 0xc) 242 #define OHCI_ARSMATCH (OHCI_ARSOFF + 0x10) 243 244 #define OHCI_ITOFF(CH) (0x200 + 0x10 * (CH)) 245 #define OHCI_ITCTL(CH) (OHCI_ITOFF(CH)) 246 #define OHCI_ITCTLCLR(CH) (OHCI_ITOFF(CH) + 4) 247 #define OHCI_ITCMD(CH) (OHCI_ITOFF(CH) + 0xc) 248 249 #define OHCI_IROFF(CH) (0x400 + 0x20 * (CH)) 250 #define OHCI_IRCTL(CH) (OHCI_IROFF(CH)) 251 #define OHCI_IRCTLCLR(CH) (OHCI_IROFF(CH) + 4) 252 #define OHCI_IRCMD(CH) (OHCI_IROFF(CH) + 0xc) 253 #define OHCI_IRMATCH(CH) (OHCI_IROFF(CH) + 0x10) 254 255 d_ioctl_t fwohci_ioctl; 256 257 /* 258 * Communication with PHY device 259 */ 260 /* XXX need lock for phy access */ 261 static uint32_t 262 fwphy_wrdata(struct fwohci_softc *sc, uint32_t addr, uint32_t data) 263 { 264 uint32_t fun; 265 266 addr &= 0xf; 267 data &= 0xff; 268 269 fun = (PHYDEV_WRCMD | (addr << PHYDEV_REGADDR) | 270 (data << PHYDEV_WRDATA)); 271 OWRITE(sc, OHCI_PHYACCESS, fun); 272 DELAY(100); 273 274 return (fwphy_rddata(sc, addr)); 275 } 276 277 static uint32_t 278 fwohci_set_bus_manager(struct firewire_comm *fc, u_int node) 279 { 280 struct fwohci_softc *sc = (struct fwohci_softc *)fc; 281 int i; 282 uint32_t bm; 283 284 #define OHCI_CSR_DATA 0x0c 285 #define OHCI_CSR_COMP 0x10 286 #define OHCI_CSR_CONT 0x14 287 #define OHCI_BUS_MANAGER_ID 0 288 289 OWRITE(sc, OHCI_CSR_DATA, node); 290 OWRITE(sc, OHCI_CSR_COMP, 0x3f); 291 OWRITE(sc, OHCI_CSR_CONT, OHCI_BUS_MANAGER_ID); 292 for (i = 0; !(OREAD(sc, OHCI_CSR_CONT) & (1<<31)) && (i < 1000); i++) 293 DELAY(10); 294 bm = OREAD(sc, OHCI_CSR_DATA); 295 if ((bm & 0x3f) == 0x3f) 296 bm = node; 297 if (firewire_debug) 298 device_printf(sc->fc.dev, "%s: %d->%d (loop=%d)\n", 299 __func__, bm, node, i); 300 return (bm); 301 } 302 303 static uint32_t 304 fwphy_rddata(struct fwohci_softc *sc, u_int addr) 305 { 306 uint32_t fun, stat; 307 u_int i, retry = 0; 308 309 addr &= 0xf; 310 #define MAX_RETRY 100 311 again: 312 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_REG_FAIL); 313 fun = PHYDEV_RDCMD | (addr << PHYDEV_REGADDR); 314 OWRITE(sc, OHCI_PHYACCESS, fun); 315 for (i = 0; i < MAX_RETRY; i++) { 316 fun = OREAD(sc, OHCI_PHYACCESS); 317 if ((fun & PHYDEV_RDCMD) == 0 && (fun & PHYDEV_RDDONE) != 0) 318 break; 319 DELAY(100); 320 } 321 if (i >= MAX_RETRY) { 322 if (firewire_debug) 323 device_printf(sc->fc.dev, "%s: failed(1).\n", __func__); 324 if (++retry < MAX_RETRY) { 325 DELAY(100); 326 goto again; 327 } 328 } 329 /* Make sure that SCLK is started */ 330 stat = OREAD(sc, FWOHCI_INTSTAT); 331 if ((stat & OHCI_INT_REG_FAIL) != 0 || 332 ((fun >> PHYDEV_REGADDR) & 0xf) != addr) { 333 if (firewire_debug) 334 device_printf(sc->fc.dev, "%s: failed(2).\n", __func__); 335 if (++retry < MAX_RETRY) { 336 DELAY(100); 337 goto again; 338 } 339 } 340 if (firewire_debug > 1 || retry >= MAX_RETRY) 341 device_printf(sc->fc.dev, 342 "%s:: 0x%x loop=%d, retry=%d\n", 343 __func__, addr, i, retry); 344 #undef MAX_RETRY 345 return ((fun >> PHYDEV_RDDATA) & 0xff); 346 } 347 348 /* Device specific ioctl. */ 349 int 350 fwohci_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, fw_proc *td) 351 { 352 struct firewire_softc *sc; 353 struct fwohci_softc *fc; 354 int unit = DEV2UNIT(dev); 355 int err = 0; 356 struct fw_reg_req_t *reg = (struct fw_reg_req_t *) data; 357 uint32_t *dmach = (uint32_t *) data; 358 359 sc = devclass_get_softc(firewire_devclass, unit); 360 if (sc == NULL) 361 return (EINVAL); 362 363 fc = (struct fwohci_softc *)sc->fc; 364 365 if (!data) 366 return (EINVAL); 367 368 switch (cmd) { 369 case FWOHCI_WRREG: 370 #define OHCI_MAX_REG 0x800 371 if (reg->addr <= OHCI_MAX_REG) { 372 OWRITE(fc, reg->addr, reg->data); 373 reg->data = OREAD(fc, reg->addr); 374 } else { 375 err = EINVAL; 376 } 377 break; 378 case FWOHCI_RDREG: 379 if (reg->addr <= OHCI_MAX_REG) { 380 reg->data = OREAD(fc, reg->addr); 381 } else { 382 err = EINVAL; 383 } 384 break; 385 /* Read DMA descriptors for debug */ 386 case DUMPDMA: 387 if (*dmach <= OHCI_MAX_DMA_CH) { 388 dump_dma(fc, *dmach); 389 dump_db(fc, *dmach); 390 } else { 391 err = EINVAL; 392 } 393 break; 394 /* Read/Write Phy registers */ 395 #define OHCI_MAX_PHY_REG 0xf 396 case FWOHCI_RDPHYREG: 397 if (reg->addr <= OHCI_MAX_PHY_REG) 398 reg->data = fwphy_rddata(fc, reg->addr); 399 else 400 err = EINVAL; 401 break; 402 case FWOHCI_WRPHYREG: 403 if (reg->addr <= OHCI_MAX_PHY_REG) 404 reg->data = fwphy_wrdata(fc, reg->addr, reg->data); 405 else 406 err = EINVAL; 407 break; 408 default: 409 err = EINVAL; 410 break; 411 } 412 return err; 413 } 414 415 static int 416 fwohci_probe_phy(struct fwohci_softc *sc, device_t dev) 417 { 418 uint32_t reg, reg2; 419 int e1394a = 1; 420 421 /* 422 * probe PHY parameters 423 * 0. to prove PHY version, whether compliance of 1394a. 424 * 1. to probe maximum speed supported by the PHY and 425 * number of port supported by core-logic. 426 * It is not actually available port on your PC . 427 */ 428 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LPS); 429 DELAY(500); 430 431 reg = fwphy_rddata(sc, FW_PHY_SPD_REG); 432 433 if ((reg >> 5) != 7) { 434 sc->fc.mode &= ~FWPHYASYST; 435 sc->fc.nport = reg & FW_PHY_NP; 436 sc->fc.speed = reg & FW_PHY_SPD >> 6; 437 if (sc->fc.speed > MAX_SPEED) { 438 device_printf(dev, "invalid speed %d (fixed to %d).\n", 439 sc->fc.speed, MAX_SPEED); 440 sc->fc.speed = MAX_SPEED; 441 } 442 device_printf(dev, 443 "Phy 1394 only %s, %d ports.\n", 444 linkspeed[sc->fc.speed], sc->fc.nport); 445 } else { 446 reg2 = fwphy_rddata(sc, FW_PHY_ESPD_REG); 447 sc->fc.mode |= FWPHYASYST; 448 sc->fc.nport = reg & FW_PHY_NP; 449 sc->fc.speed = (reg2 & FW_PHY_ESPD) >> 5; 450 if (sc->fc.speed > MAX_SPEED) { 451 device_printf(dev, "invalid speed %d (fixed to %d).\n", 452 sc->fc.speed, MAX_SPEED); 453 sc->fc.speed = MAX_SPEED; 454 } 455 device_printf(dev, 456 "Phy 1394a available %s, %d ports.\n", 457 linkspeed[sc->fc.speed], sc->fc.nport); 458 459 /* check programPhyEnable */ 460 reg2 = fwphy_rddata(sc, 5); 461 #if 0 462 if (e1394a && (OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_PRPHY)) { 463 #else /* XXX force to enable 1394a */ 464 if (e1394a) { 465 #endif 466 if (firewire_debug) 467 device_printf(dev, 468 "Enable 1394a Enhancements\n"); 469 /* enable EAA EMC */ 470 reg2 |= 0x03; 471 /* set aPhyEnhanceEnable */ 472 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_PHYEN); 473 OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_PRPHY); 474 } else { 475 /* for safe */ 476 reg2 &= ~0x83; 477 } 478 reg2 = fwphy_wrdata(sc, 5, reg2); 479 } 480 481 reg = fwphy_rddata(sc, FW_PHY_SPD_REG); 482 if ((reg >> 5) == 7) { 483 reg = fwphy_rddata(sc, 4); 484 reg |= 1 << 6; 485 fwphy_wrdata(sc, 4, reg); 486 reg = fwphy_rddata(sc, 4); 487 } 488 return 0; 489 } 490 491 492 void 493 fwohci_reset(struct fwohci_softc *sc, device_t dev) 494 { 495 int i, max_rec, speed; 496 uint32_t reg, reg2; 497 struct fwohcidb_tr *db_tr; 498 499 /* Disable interrupts */ 500 OWRITE(sc, FWOHCI_INTMASKCLR, ~0); 501 502 /* Now stopping all DMA channels */ 503 OWRITE(sc, OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN); 504 OWRITE(sc, OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN); 505 OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN); 506 OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN); 507 508 OWRITE(sc, OHCI_IR_MASKCLR, ~0); 509 for (i = 0; i < sc->fc.nisodma; i++) { 510 OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN); 511 OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN); 512 } 513 514 /* FLUSH FIFO and reset Transmitter/Reciever */ 515 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_RESET); 516 if (firewire_debug) 517 device_printf(dev, "resetting OHCI..."); 518 i = 0; 519 while (OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_RESET) { 520 if (i++ > 100) break; 521 DELAY(1000); 522 } 523 if (firewire_debug) 524 printf("done (loop=%d)\n", i); 525 526 /* Probe phy */ 527 fwohci_probe_phy(sc, dev); 528 529 /* Probe link */ 530 reg = OREAD(sc, OHCI_BUS_OPT); 531 reg2 = reg | OHCI_BUSFNC; 532 max_rec = (reg & 0x0000f000) >> 12; 533 speed = (reg & 0x00000007); 534 device_printf(dev, "Link %s, max_rec %d bytes.\n", 535 linkspeed[speed], MAXREC(max_rec)); 536 /* XXX fix max_rec */ 537 sc->fc.maxrec = sc->fc.speed + 8; 538 if (max_rec != sc->fc.maxrec) { 539 reg2 = (reg2 & 0xffff0fff) | (sc->fc.maxrec << 12); 540 device_printf(dev, "max_rec %d -> %d\n", 541 MAXREC(max_rec), MAXREC(sc->fc.maxrec)); 542 } 543 if (firewire_debug) 544 device_printf(dev, "BUS_OPT 0x%x -> 0x%x\n", reg, reg2); 545 OWRITE(sc, OHCI_BUS_OPT, reg2); 546 547 /* Initialize registers */ 548 OWRITE(sc, OHCI_CROMHDR, sc->fc.config_rom[0]); 549 OWRITE(sc, OHCI_CROMPTR, sc->crom_dma.bus_addr); 550 OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_BIGEND); 551 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_POSTWR); 552 OWRITE(sc, OHCI_SID_BUF, sc->sid_dma.bus_addr); 553 OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_SID); 554 555 /* Enable link */ 556 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LINKEN); 557 558 /* Force to start async RX DMA */ 559 sc->arrq.xferq.flag &= ~FWXFERQ_RUNNING; 560 sc->arrs.xferq.flag &= ~FWXFERQ_RUNNING; 561 fwohci_rx_enable(sc, &sc->arrq); 562 fwohci_rx_enable(sc, &sc->arrs); 563 564 /* Initialize async TX */ 565 OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD); 566 OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD); 567 568 /* AT Retries */ 569 OWRITE(sc, FWOHCI_RETRY, 570 /* CycleLimit PhyRespRetries ATRespRetries ATReqRetries */ 571 (0xffff << 16) | (0x0f << 8) | (0x0f << 4) | 0x0f); 572 573 sc->atrq.top = STAILQ_FIRST(&sc->atrq.db_trq); 574 sc->atrs.top = STAILQ_FIRST(&sc->atrs.db_trq); 575 sc->atrq.bottom = sc->atrq.top; 576 sc->atrs.bottom = sc->atrs.top; 577 578 for (i = 0, db_tr = sc->atrq.top; i < sc->atrq.ndb; 579 i++, db_tr = STAILQ_NEXT(db_tr, link)) { 580 db_tr->xfer = NULL; 581 } 582 for (i = 0, db_tr = sc->atrs.top; i < sc->atrs.ndb; 583 i++, db_tr = STAILQ_NEXT(db_tr, link)) { 584 db_tr->xfer = NULL; 585 } 586 587 /* Enable interrupts */ 588 sc->intmask = (OHCI_INT_ERR | OHCI_INT_PHY_SID 589 | OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS 590 | OHCI_INT_DMA_PRRQ | OHCI_INT_DMA_PRRS 591 | OHCI_INT_PHY_BUS_R | OHCI_INT_PW_ERR); 592 sc->intmask |= OHCI_INT_DMA_IR | OHCI_INT_DMA_IT; 593 sc->intmask |= OHCI_INT_CYC_LOST | OHCI_INT_PHY_INT; 594 OWRITE(sc, FWOHCI_INTMASK, sc->intmask); 595 fwohci_set_intr(&sc->fc, 1); 596 } 597 598 int 599 fwohci_init(struct fwohci_softc *sc, device_t dev) 600 { 601 int i, mver; 602 uint32_t reg; 603 uint8_t ui[8]; 604 605 /* OHCI version */ 606 reg = OREAD(sc, OHCI_VERSION); 607 mver = (reg >> 16) & 0xff; 608 device_printf(dev, "OHCI version %x.%x (ROM=%d)\n", 609 mver, reg & 0xff, (reg >> 24) & 1); 610 if (mver < 1 || mver > 9) { 611 device_printf(dev, "invalid OHCI version\n"); 612 return (ENXIO); 613 } 614 615 /* Available Isochronous DMA channel probe */ 616 OWRITE(sc, OHCI_IT_MASK, 0xffffffff); 617 OWRITE(sc, OHCI_IR_MASK, 0xffffffff); 618 reg = OREAD(sc, OHCI_IT_MASK) & OREAD(sc, OHCI_IR_MASK); 619 OWRITE(sc, OHCI_IT_MASKCLR, 0xffffffff); 620 OWRITE(sc, OHCI_IR_MASKCLR, 0xffffffff); 621 for (i = 0; i < 0x20; i++) 622 if ((reg & (1 << i)) == 0) 623 break; 624 sc->fc.nisodma = i; 625 device_printf(dev, "No. of Isochronous channels is %d.\n", i); 626 if (i == 0) 627 return (ENXIO); 628 629 sc->fc.arq = &sc->arrq.xferq; 630 sc->fc.ars = &sc->arrs.xferq; 631 sc->fc.atq = &sc->atrq.xferq; 632 sc->fc.ats = &sc->atrs.xferq; 633 634 sc->arrq.xferq.psize = roundup2(FWPMAX_S400, PAGE_SIZE); 635 sc->arrs.xferq.psize = roundup2(FWPMAX_S400, PAGE_SIZE); 636 sc->atrq.xferq.psize = roundup2(FWPMAX_S400, PAGE_SIZE); 637 sc->atrs.xferq.psize = roundup2(FWPMAX_S400, PAGE_SIZE); 638 639 sc->arrq.xferq.start = NULL; 640 sc->arrs.xferq.start = NULL; 641 sc->atrq.xferq.start = fwohci_start_atq; 642 sc->atrs.xferq.start = fwohci_start_ats; 643 644 sc->arrq.xferq.buf = NULL; 645 sc->arrs.xferq.buf = NULL; 646 sc->atrq.xferq.buf = NULL; 647 sc->atrs.xferq.buf = NULL; 648 649 sc->arrq.xferq.dmach = -1; 650 sc->arrs.xferq.dmach = -1; 651 sc->atrq.xferq.dmach = -1; 652 sc->atrs.xferq.dmach = -1; 653 654 sc->arrq.ndesc = 1; 655 sc->arrs.ndesc = 1; 656 sc->atrq.ndesc = 8; /* equal to maximum of mbuf chains */ 657 sc->atrs.ndesc = 2; 658 659 sc->arrq.ndb = NDB; 660 sc->arrs.ndb = NDB / 2; 661 sc->atrq.ndb = NDB; 662 sc->atrs.ndb = NDB / 2; 663 664 for (i = 0; i < sc->fc.nisodma; i++) { 665 sc->fc.it[i] = &sc->it[i].xferq; 666 sc->fc.ir[i] = &sc->ir[i].xferq; 667 sc->it[i].xferq.dmach = i; 668 sc->ir[i].xferq.dmach = i; 669 sc->it[i].ndb = 0; 670 sc->ir[i].ndb = 0; 671 } 672 673 sc->fc.tcode = tinfo; 674 sc->fc.dev = dev; 675 676 sc->fc.config_rom = fwdma_malloc(&sc->fc, CROMSIZE, CROMSIZE, 677 &sc->crom_dma, BUS_DMA_WAITOK | BUS_DMA_COHERENT); 678 if (sc->fc.config_rom == NULL) { 679 device_printf(dev, "config_rom alloc failed."); 680 return ENOMEM; 681 } 682 683 #if 0 684 bzero(&sc->fc.config_rom[0], CROMSIZE); 685 sc->fc.config_rom[1] = 0x31333934; 686 sc->fc.config_rom[2] = 0xf000a002; 687 sc->fc.config_rom[3] = OREAD(sc, OHCI_EUID_HI); 688 sc->fc.config_rom[4] = OREAD(sc, OHCI_EUID_LO); 689 sc->fc.config_rom[5] = 0; 690 sc->fc.config_rom[0] = (4 << 24) | (5 << 16); 691 692 sc->fc.config_rom[0] |= fw_crc16(&sc->fc.config_rom[1], 5*4); 693 #endif 694 695 /* SID recieve buffer must align 2^11 */ 696 #define OHCI_SIDSIZE (1 << 11) 697 sc->sid_buf = fwdma_malloc(&sc->fc, OHCI_SIDSIZE, OHCI_SIDSIZE, 698 &sc->sid_dma, BUS_DMA_WAITOK | BUS_DMA_COHERENT); 699 if (sc->sid_buf == NULL) { 700 device_printf(dev, "sid_buf alloc failed."); 701 return ENOMEM; 702 } 703 704 fwdma_malloc(&sc->fc, sizeof(uint32_t), sizeof(uint32_t), 705 &sc->dummy_dma, BUS_DMA_WAITOK); 706 707 if (sc->dummy_dma.v_addr == NULL) { 708 device_printf(dev, "dummy_dma alloc failed."); 709 return ENOMEM; 710 } 711 712 fwohci_db_init(sc, &sc->arrq); 713 if ((sc->arrq.flags & FWOHCI_DBCH_INIT) == 0) 714 return ENOMEM; 715 716 fwohci_db_init(sc, &sc->arrs); 717 if ((sc->arrs.flags & FWOHCI_DBCH_INIT) == 0) 718 return ENOMEM; 719 720 fwohci_db_init(sc, &sc->atrq); 721 if ((sc->atrq.flags & FWOHCI_DBCH_INIT) == 0) 722 return ENOMEM; 723 724 fwohci_db_init(sc, &sc->atrs); 725 if ((sc->atrs.flags & FWOHCI_DBCH_INIT) == 0) 726 return ENOMEM; 727 728 sc->fc.eui.hi = OREAD(sc, FWOHCIGUID_H); 729 sc->fc.eui.lo = OREAD(sc, FWOHCIGUID_L); 730 for (i = 0; i < 8; i++) 731 ui[i] = FW_EUI64_BYTE(&sc->fc.eui,i); 732 device_printf(dev, "EUI64 %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", 733 ui[0], ui[1], ui[2], ui[3], ui[4], ui[5], ui[6], ui[7]); 734 735 sc->fc.ioctl = fwohci_ioctl; 736 sc->fc.cyctimer = fwohci_cyctimer; 737 sc->fc.set_bmr = fwohci_set_bus_manager; 738 sc->fc.ibr = fwohci_ibr; 739 sc->fc.irx_enable = fwohci_irx_enable; 740 sc->fc.irx_disable = fwohci_irx_disable; 741 742 sc->fc.itx_enable = fwohci_itxbuf_enable; 743 sc->fc.itx_disable = fwohci_itx_disable; 744 #if BYTE_ORDER == BIG_ENDIAN 745 sc->fc.irx_post = fwohci_irx_post; 746 #else 747 sc->fc.irx_post = NULL; 748 #endif 749 sc->fc.itx_post = NULL; 750 sc->fc.timeout = fwohci_timeout; 751 sc->fc.poll = fwohci_poll; 752 sc->fc.set_intr = fwohci_set_intr; 753 754 sc->intmask = sc->irstat = sc->itstat = 0; 755 756 /* Init task queue */ 757 sc->fc.taskqueue = taskqueue_create_fast("fw_taskq", M_WAITOK, 758 taskqueue_thread_enqueue, &sc->fc.taskqueue); 759 taskqueue_start_threads(&sc->fc.taskqueue, 1, PI_NET, "fw%d_taskq", 760 device_get_unit(dev)); 761 TASK_INIT(&sc->fwohci_task_busreset, 2, fwohci_task_busreset, sc); 762 TASK_INIT(&sc->fwohci_task_sid, 1, fwohci_task_sid, sc); 763 TASK_INIT(&sc->fwohci_task_dma, 0, fwohci_task_dma, sc); 764 765 fw_init(&sc->fc); 766 fwohci_reset(sc, dev); 767 768 return 0; 769 } 770 771 void 772 fwohci_timeout(void *arg) 773 { 774 struct fwohci_softc *sc; 775 776 sc = (struct fwohci_softc *)arg; 777 } 778 779 uint32_t 780 fwohci_cyctimer(struct firewire_comm *fc) 781 { 782 struct fwohci_softc *sc = (struct fwohci_softc *)fc; 783 return (OREAD(sc, OHCI_CYCLETIMER)); 784 } 785 786 int 787 fwohci_detach(struct fwohci_softc *sc, device_t dev) 788 { 789 int i; 790 791 if (sc->sid_buf != NULL) 792 fwdma_free(&sc->fc, &sc->sid_dma); 793 if (sc->fc.config_rom != NULL) 794 fwdma_free(&sc->fc, &sc->crom_dma); 795 796 fwohci_db_free(&sc->arrq); 797 fwohci_db_free(&sc->arrs); 798 799 fwohci_db_free(&sc->atrq); 800 fwohci_db_free(&sc->atrs); 801 802 for (i = 0; i < sc->fc.nisodma; i++) { 803 fwohci_db_free(&sc->it[i]); 804 fwohci_db_free(&sc->ir[i]); 805 } 806 if (sc->fc.taskqueue != NULL) { 807 taskqueue_drain(sc->fc.taskqueue, &sc->fwohci_task_busreset); 808 taskqueue_drain(sc->fc.taskqueue, &sc->fwohci_task_sid); 809 taskqueue_drain(sc->fc.taskqueue, &sc->fwohci_task_dma); 810 taskqueue_drain(sc->fc.taskqueue, &sc->fc.task_timeout); 811 taskqueue_free(sc->fc.taskqueue); 812 sc->fc.taskqueue = NULL; 813 } 814 815 return 0; 816 } 817 818 #define LAST_DB(dbtr, db) do { \ 819 struct fwohcidb_tr *_dbtr = (dbtr); \ 820 int _cnt = _dbtr->dbcnt; \ 821 db = &_dbtr->db[ (_cnt > 2) ? (_cnt -1) : 0]; \ 822 } while (0) 823 824 static void 825 fwohci_execute_db(void *arg, bus_dma_segment_t *segs, int nseg, int error) 826 { 827 struct fwohcidb_tr *db_tr; 828 struct fwohcidb *db; 829 bus_dma_segment_t *s; 830 int i; 831 832 db_tr = (struct fwohcidb_tr *)arg; 833 db = &db_tr->db[db_tr->dbcnt]; 834 if (error) { 835 if (firewire_debug || error != EFBIG) 836 printf("fwohci_execute_db: error=%d\n", error); 837 return; 838 } 839 for (i = 0; i < nseg; i++) { 840 s = &segs[i]; 841 FWOHCI_DMA_WRITE(db->db.desc.addr, s->ds_addr); 842 FWOHCI_DMA_WRITE(db->db.desc.cmd, s->ds_len); 843 FWOHCI_DMA_WRITE(db->db.desc.res, 0); 844 db++; 845 db_tr->dbcnt++; 846 } 847 } 848 849 static void 850 fwohci_execute_db2(void *arg, bus_dma_segment_t *segs, int nseg, 851 bus_size_t size, int error) 852 { 853 fwohci_execute_db(arg, segs, nseg, error); 854 } 855 856 static void 857 fwohci_start(struct fwohci_softc *sc, struct fwohci_dbch *dbch) 858 { 859 int i; 860 int tcode, hdr_len, pl_off; 861 int fsegment = -1; 862 uint32_t off; 863 struct fw_xfer *xfer; 864 struct fw_pkt *fp; 865 struct fwohci_txpkthdr *ohcifp; 866 struct fwohcidb_tr *db_tr; 867 struct fwohcidb *db; 868 uint32_t *ld; 869 struct tcode_info *info; 870 static int maxdesc=0; 871 872 FW_GLOCK_ASSERT(&sc->fc); 873 874 if (&sc->atrq == dbch) { 875 off = OHCI_ATQOFF; 876 } else if (&sc->atrs == dbch) { 877 off = OHCI_ATSOFF; 878 } else { 879 return; 880 } 881 882 if (dbch->flags & FWOHCI_DBCH_FULL) 883 return; 884 885 db_tr = dbch->top; 886 txloop: 887 xfer = STAILQ_FIRST(&dbch->xferq.q); 888 if (xfer == NULL) { 889 goto kick; 890 } 891 #if 0 892 if (dbch->xferq.queued == 0) { 893 device_printf(sc->fc.dev, "TX queue empty\n"); 894 } 895 #endif 896 STAILQ_REMOVE_HEAD(&dbch->xferq.q, link); 897 db_tr->xfer = xfer; 898 xfer->flag = FWXF_START; 899 900 fp = &xfer->send.hdr; 901 tcode = fp->mode.common.tcode; 902 903 ohcifp = (struct fwohci_txpkthdr *) db_tr->db[1].db.immed; 904 info = &tinfo[tcode]; 905 hdr_len = pl_off = info->hdr_len; 906 907 ld = &ohcifp->mode.ld[0]; 908 ld[0] = ld[1] = ld[2] = ld[3] = 0; 909 for (i = 0; i < pl_off; i+= 4) 910 ld[i/4] = fp->mode.ld[i/4]; 911 912 ohcifp->mode.common.spd = xfer->send.spd & 0x7; 913 if (tcode == FWTCODE_STREAM) { 914 hdr_len = 8; 915 ohcifp->mode.stream.len = fp->mode.stream.len; 916 } else if (tcode == FWTCODE_PHY) { 917 hdr_len = 12; 918 ld[1] = fp->mode.ld[1]; 919 ld[2] = fp->mode.ld[2]; 920 ohcifp->mode.common.spd = 0; 921 ohcifp->mode.common.tcode = FWOHCITCODE_PHY; 922 } else { 923 ohcifp->mode.asycomm.dst = fp->mode.hdr.dst; 924 ohcifp->mode.asycomm.srcbus = OHCI_ASYSRCBUS; 925 ohcifp->mode.asycomm.tlrt |= FWRETRY_X; 926 } 927 db = &db_tr->db[0]; 928 FWOHCI_DMA_WRITE(db->db.desc.cmd, 929 OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | hdr_len); 930 FWOHCI_DMA_WRITE(db->db.desc.addr, 0); 931 FWOHCI_DMA_WRITE(db->db.desc.res, 0); 932 /* Specify bound timer of asy. responce */ 933 if (&sc->atrs == dbch) { 934 FWOHCI_DMA_WRITE(db->db.desc.res, 935 (OREAD(sc, OHCI_CYCLETIMER) >> 12) + (1 << 13)); 936 } 937 #if BYTE_ORDER == BIG_ENDIAN 938 if (tcode == FWTCODE_WREQQ || tcode == FWTCODE_RRESQ) 939 hdr_len = 12; 940 for (i = 0; i < hdr_len/4; i++) 941 FWOHCI_DMA_WRITE(ld[i], ld[i]); 942 #endif 943 944 again: 945 db_tr->dbcnt = 2; 946 db = &db_tr->db[db_tr->dbcnt]; 947 if (xfer->send.pay_len > 0) { 948 int err; 949 /* handle payload */ 950 if (xfer->mbuf == NULL) { 951 err = bus_dmamap_load(dbch->dmat, db_tr->dma_map, 952 &xfer->send.payload[0], xfer->send.pay_len, 953 fwohci_execute_db, db_tr, 954 /*flags*/0); 955 } else { 956 /* XXX we can handle only 6 (=8-2) mbuf chains */ 957 err = bus_dmamap_load_mbuf(dbch->dmat, db_tr->dma_map, 958 xfer->mbuf, 959 fwohci_execute_db2, db_tr, 960 /* flags */0); 961 if (err == EFBIG) { 962 struct mbuf *m0; 963 964 if (firewire_debug) 965 device_printf(sc->fc.dev, "EFBIG.\n"); 966 m0 = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); 967 if (m0 != NULL) { 968 m_copydata(xfer->mbuf, 0, 969 xfer->mbuf->m_pkthdr.len, 970 mtod(m0, caddr_t)); 971 m0->m_len = m0->m_pkthdr.len = 972 xfer->mbuf->m_pkthdr.len; 973 m_freem(xfer->mbuf); 974 xfer->mbuf = m0; 975 goto again; 976 } 977 device_printf(sc->fc.dev, "m_getcl failed.\n"); 978 } 979 } 980 if (err) 981 printf("dmamap_load: err=%d\n", err); 982 bus_dmamap_sync(dbch->dmat, db_tr->dma_map, 983 BUS_DMASYNC_PREWRITE); 984 #if 0 /* OHCI_OUTPUT_MODE == 0 */ 985 for (i = 2; i < db_tr->dbcnt; i++) 986 FWOHCI_DMA_SET(db_tr->db[i].db.desc.cmd, 987 OHCI_OUTPUT_MORE); 988 #endif 989 } 990 if (maxdesc < db_tr->dbcnt) { 991 maxdesc = db_tr->dbcnt; 992 if (firewire_debug) 993 device_printf(sc->fc.dev, "%s: maxdesc %d\n", __func__, maxdesc); 994 } 995 /* last db */ 996 LAST_DB(db_tr, db); 997 FWOHCI_DMA_SET(db->db.desc.cmd, 998 OHCI_OUTPUT_LAST | OHCI_INTERRUPT_ALWAYS | OHCI_BRANCH_ALWAYS); 999 FWOHCI_DMA_WRITE(db->db.desc.depend, 1000 STAILQ_NEXT(db_tr, link)->bus_addr); 1001 1002 if (fsegment == -1) 1003 fsegment = db_tr->dbcnt; 1004 if (dbch->pdb_tr != NULL) { 1005 LAST_DB(dbch->pdb_tr, db); 1006 FWOHCI_DMA_SET(db->db.desc.depend, db_tr->dbcnt); 1007 } 1008 dbch->xferq.queued++; 1009 dbch->pdb_tr = db_tr; 1010 db_tr = STAILQ_NEXT(db_tr, link); 1011 if (db_tr != dbch->bottom) { 1012 goto txloop; 1013 } else { 1014 device_printf(sc->fc.dev, "fwohci_start: lack of db_trq\n"); 1015 dbch->flags |= FWOHCI_DBCH_FULL; 1016 } 1017 kick: 1018 /* kick asy q */ 1019 fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREREAD); 1020 fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREWRITE); 1021 1022 if (dbch->xferq.flag & FWXFERQ_RUNNING) { 1023 OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_WAKE); 1024 } else { 1025 if (firewire_debug) 1026 device_printf(sc->fc.dev, "start AT DMA status=%x\n", 1027 OREAD(sc, OHCI_DMACTL(off))); 1028 OWRITE(sc, OHCI_DMACMD(off), dbch->top->bus_addr | fsegment); 1029 OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_RUN); 1030 dbch->xferq.flag |= FWXFERQ_RUNNING; 1031 } 1032 1033 dbch->top = db_tr; 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 uintmax_t prequpper; 1825 uint32_t node_id, plen; 1826 1827 FW_GLOCK_ASSERT(fc); 1828 if ((stat & OHCI_INT_PHY_BUS_R) && (fc->status != FWBUSRESET)) { 1829 fc->status = FWBUSRESET; 1830 /* Disable bus reset interrupt until sid recv. */ 1831 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_PHY_BUS_R); 1832 1833 device_printf(fc->dev, "%s: BUS reset\n", __func__); 1834 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST); 1835 OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCSRC); 1836 1837 OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN); 1838 sc->atrq.xferq.flag &= ~FWXFERQ_RUNNING; 1839 OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN); 1840 sc->atrs.xferq.flag &= ~FWXFERQ_RUNNING; 1841 1842 if (!kdb_active) 1843 taskqueue_enqueue(sc->fc.taskqueue, &sc->fwohci_task_busreset); 1844 } 1845 if (stat & OHCI_INT_PHY_SID) { 1846 /* Enable bus reset interrupt */ 1847 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_BUS_R); 1848 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_PHY_BUS_R); 1849 1850 /* Allow async. request to us */ 1851 OWRITE(sc, OHCI_AREQHI, 1 << 31); 1852 if (firewire_phydma_enable) { 1853 /* allow from all nodes */ 1854 OWRITE(sc, OHCI_PREQHI, 0x7fffffff); 1855 OWRITE(sc, OHCI_PREQLO, 0xffffffff); 1856 prequpper = ((uintmax_t)Maxmem << PAGE_SHIFT) >> 16; 1857 if (prequpper > OHCI_PREQUPPER_MAX) { 1858 device_printf(fc->dev, 1859 "Physical memory size of 0x%jx exceeds " 1860 "fire wire address space. Limiting dma " 1861 "to memory below 0x%jx\n", 1862 (uintmax_t)Maxmem << PAGE_SHIFT, 1863 (uintmax_t)OHCI_PREQUPPER_MAX << 16); 1864 prequpper = OHCI_PREQUPPER_MAX; 1865 } 1866 OWRITE(sc, OHCI_PREQUPPER, prequpper & 0xffffffff); 1867 } 1868 /* Set ATRetries register */ 1869 OWRITE(sc, OHCI_ATRETRY, 1<<(13 + 16) | 0xfff); 1870 1871 /* 1872 * Checking whether the node is root or not. If root, turn on 1873 * cycle master. 1874 */ 1875 node_id = OREAD(sc, FWOHCI_NODEID); 1876 plen = OREAD(sc, OHCI_SID_CNT); 1877 1878 fc->nodeid = node_id & 0x3f; 1879 device_printf(fc->dev, "%s: node_id=0x%08x, SelfID Count=%d, ", 1880 __func__, fc->nodeid, (plen >> 16) & 0xff); 1881 if (!(node_id & OHCI_NODE_VALID)) { 1882 device_printf(fc->dev, "%s: Bus reset failure\n", 1883 __func__); 1884 goto sidout; 1885 } 1886 1887 /* cycle timer */ 1888 sc->cycle_lost = 0; 1889 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_CYC_LOST); 1890 if ((node_id & OHCI_NODE_ROOT) && !nocyclemaster) { 1891 printf("CYCLEMASTER mode\n"); 1892 OWRITE(sc, OHCI_LNKCTL, 1893 OHCI_CNTL_CYCMTR | OHCI_CNTL_CYCTIMER); 1894 } else { 1895 printf("non CYCLEMASTER mode\n"); 1896 OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCMTR); 1897 OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_CYCTIMER); 1898 } 1899 1900 fc->status = FWBUSINIT; 1901 1902 if (!kdb_active) 1903 taskqueue_enqueue(sc->fc.taskqueue, &sc->fwohci_task_sid); 1904 } 1905 sidout: 1906 if ((stat & ~(OHCI_INT_PHY_BUS_R | OHCI_INT_PHY_SID)) && (!kdb_active)) 1907 taskqueue_enqueue(sc->fc.taskqueue, &sc->fwohci_task_dma); 1908 } 1909 1910 static void 1911 fwohci_intr_dma(struct fwohci_softc *sc, uint32_t stat, int count) 1912 { 1913 uint32_t irstat, itstat; 1914 u_int i; 1915 struct firewire_comm *fc = (struct firewire_comm *)sc; 1916 1917 if (stat & OHCI_INT_DMA_IR) { 1918 irstat = atomic_readandclear_int(&sc->irstat); 1919 for (i = 0; i < fc->nisodma; i++) { 1920 struct fwohci_dbch *dbch; 1921 1922 if ((irstat & (1 << i)) != 0) { 1923 dbch = &sc->ir[i]; 1924 if ((dbch->xferq.flag & FWXFERQ_OPEN) == 0) { 1925 device_printf(sc->fc.dev, 1926 "dma(%d) not active\n", i); 1927 continue; 1928 } 1929 fwohci_rbuf_update(sc, i); 1930 } 1931 } 1932 } 1933 if (stat & OHCI_INT_DMA_IT) { 1934 itstat = atomic_readandclear_int(&sc->itstat); 1935 for (i = 0; i < fc->nisodma; i++) { 1936 if ((itstat & (1 << i)) != 0) { 1937 fwohci_tbuf_update(sc, i); 1938 } 1939 } 1940 } 1941 if (stat & OHCI_INT_DMA_PRRS) { 1942 #if 0 1943 dump_dma(sc, ARRS_CH); 1944 dump_db(sc, ARRS_CH); 1945 #endif 1946 fwohci_arcv(sc, &sc->arrs, count); 1947 } 1948 if (stat & OHCI_INT_DMA_PRRQ) { 1949 #if 0 1950 dump_dma(sc, ARRQ_CH); 1951 dump_db(sc, ARRQ_CH); 1952 #endif 1953 fwohci_arcv(sc, &sc->arrq, count); 1954 } 1955 if (stat & OHCI_INT_CYC_LOST) { 1956 if (sc->cycle_lost >= 0) 1957 sc->cycle_lost++; 1958 if (sc->cycle_lost > 10) { 1959 sc->cycle_lost = -1; 1960 #if 0 1961 OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCTIMER); 1962 #endif 1963 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST); 1964 device_printf(fc->dev, "too many cycles lost, " 1965 "no cycle master present?\n"); 1966 } 1967 } 1968 if (stat & OHCI_INT_DMA_ATRQ) { 1969 fwohci_txd(sc, &(sc->atrq)); 1970 } 1971 if (stat & OHCI_INT_DMA_ATRS) { 1972 fwohci_txd(sc, &(sc->atrs)); 1973 } 1974 if (stat & OHCI_INT_PW_ERR) { 1975 device_printf(fc->dev, "posted write error\n"); 1976 } 1977 if (stat & OHCI_INT_ERR) { 1978 device_printf(fc->dev, "unrecoverable error\n"); 1979 } 1980 if (stat & OHCI_INT_PHY_INT) { 1981 device_printf(fc->dev, "phy int\n"); 1982 } 1983 } 1984 1985 static void 1986 fwohci_task_busreset(void *arg, int pending) 1987 { 1988 struct fwohci_softc *sc = (struct fwohci_softc *)arg; 1989 1990 FW_GLOCK(&sc->fc); 1991 fw_busreset(&sc->fc, FWBUSRESET); 1992 OWRITE(sc, OHCI_CROMHDR, ntohl(sc->fc.config_rom[0])); 1993 OWRITE(sc, OHCI_BUS_OPT, ntohl(sc->fc.config_rom[2])); 1994 FW_GUNLOCK(&sc->fc); 1995 } 1996 1997 static void 1998 fwohci_task_sid(void *arg, int pending) 1999 { 2000 struct fwohci_softc *sc = (struct fwohci_softc *)arg; 2001 struct firewire_comm *fc = &sc->fc; 2002 uint32_t *buf; 2003 int i, plen; 2004 2005 2006 /* 2007 * We really should have locking 2008 * here. Not sure why it's not 2009 */ 2010 plen = OREAD(sc, OHCI_SID_CNT); 2011 2012 if (plen & OHCI_SID_ERR) { 2013 device_printf(fc->dev, "SID Error\n"); 2014 return; 2015 } 2016 plen &= OHCI_SID_CNT_MASK; 2017 if (plen < 4 || plen > OHCI_SIDSIZE) { 2018 device_printf(fc->dev, "invalid SID len = %d\n", plen); 2019 return; 2020 } 2021 plen -= 4; /* chop control info */ 2022 buf = (uint32_t *)malloc(OHCI_SIDSIZE, M_FW, M_NOWAIT); 2023 if (buf == NULL) { 2024 device_printf(fc->dev, "malloc failed\n"); 2025 return; 2026 } 2027 for (i = 0; i < plen / 4; i++) 2028 buf[i] = FWOHCI_DMA_READ(sc->sid_buf[i + 1]); 2029 2030 /* pending all pre-bus_reset packets */ 2031 fwohci_txd(sc, &sc->atrq); 2032 fwohci_txd(sc, &sc->atrs); 2033 fwohci_arcv(sc, &sc->arrs, -1); 2034 fwohci_arcv(sc, &sc->arrq, -1); 2035 fw_drain_txq(fc); 2036 fw_sidrcv(fc, buf, plen); 2037 free(buf, M_FW); 2038 } 2039 2040 static void 2041 fwohci_task_dma(void *arg, int pending) 2042 { 2043 struct fwohci_softc *sc = (struct fwohci_softc *)arg; 2044 uint32_t stat; 2045 2046 again: 2047 stat = atomic_readandclear_int(&sc->intstat); 2048 if (stat) 2049 fwohci_intr_dma(sc, stat, -1); 2050 else 2051 return; 2052 goto again; 2053 } 2054 2055 static int 2056 fwohci_check_stat(struct fwohci_softc *sc) 2057 { 2058 uint32_t stat, irstat, itstat; 2059 2060 FW_GLOCK_ASSERT(&sc->fc); 2061 stat = OREAD(sc, FWOHCI_INTSTAT); 2062 if (stat == 0xffffffff) { 2063 if (!bus_child_present(sc->fc.dev)) 2064 return (FILTER_HANDLED); 2065 device_printf(sc->fc.dev, "device physically ejected?\n"); 2066 return (FILTER_STRAY); 2067 } 2068 if (stat) 2069 OWRITE(sc, FWOHCI_INTSTATCLR, stat & ~OHCI_INT_PHY_BUS_R); 2070 2071 stat &= sc->intmask; 2072 if (stat == 0) 2073 return (FILTER_STRAY); 2074 2075 atomic_set_int(&sc->intstat, stat); 2076 if (stat & OHCI_INT_DMA_IR) { 2077 irstat = OREAD(sc, OHCI_IR_STAT); 2078 OWRITE(sc, OHCI_IR_STATCLR, irstat); 2079 atomic_set_int(&sc->irstat, irstat); 2080 } 2081 if (stat & OHCI_INT_DMA_IT) { 2082 itstat = OREAD(sc, OHCI_IT_STAT); 2083 OWRITE(sc, OHCI_IT_STATCLR, itstat); 2084 atomic_set_int(&sc->itstat, itstat); 2085 } 2086 2087 fwohci_intr_core(sc, stat, -1); 2088 return (FILTER_HANDLED); 2089 } 2090 2091 void 2092 fwohci_intr(void *arg) 2093 { 2094 struct fwohci_softc *sc = (struct fwohci_softc *)arg; 2095 2096 FW_GLOCK(&sc->fc); 2097 fwohci_check_stat(sc); 2098 FW_GUNLOCK(&sc->fc); 2099 } 2100 2101 void 2102 fwohci_poll(struct firewire_comm *fc, int quick, int count) 2103 { 2104 struct fwohci_softc *sc = (struct fwohci_softc *)fc; 2105 2106 FW_GLOCK(fc); 2107 fwohci_check_stat(sc); 2108 FW_GUNLOCK(fc); 2109 } 2110 2111 static void 2112 fwohci_set_intr(struct firewire_comm *fc, int enable) 2113 { 2114 struct fwohci_softc *sc; 2115 2116 sc = (struct fwohci_softc *)fc; 2117 if (firewire_debug) 2118 device_printf(sc->fc.dev, "fwohci_set_intr: %d\n", enable); 2119 if (enable) { 2120 sc->intmask |= OHCI_INT_EN; 2121 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_EN); 2122 } else { 2123 sc->intmask &= ~OHCI_INT_EN; 2124 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_EN); 2125 } 2126 } 2127 2128 static void 2129 fwohci_tbuf_update(struct fwohci_softc *sc, int dmach) 2130 { 2131 struct firewire_comm *fc = &sc->fc; 2132 struct fwohcidb *db; 2133 struct fw_bulkxfer *chunk; 2134 struct fw_xferq *it; 2135 uint32_t stat, count; 2136 int s, w=0, ldesc; 2137 2138 it = fc->it[dmach]; 2139 ldesc = sc->it[dmach].ndesc - 1; 2140 s = splfw(); /* unnecessary ? */ 2141 FW_GLOCK(fc); 2142 fwdma_sync_multiseg_all(sc->it[dmach].am, BUS_DMASYNC_POSTREAD); 2143 if (firewire_debug) 2144 dump_db(sc, ITX_CH + dmach); 2145 while ((chunk = STAILQ_FIRST(&it->stdma)) != NULL) { 2146 db = ((struct fwohcidb_tr *)(chunk->end))->db; 2147 stat = FWOHCI_DMA_READ(db[ldesc].db.desc.res) 2148 >> OHCI_STATUS_SHIFT; 2149 db = ((struct fwohcidb_tr *)(chunk->start))->db; 2150 /* timestamp */ 2151 count = FWOHCI_DMA_READ(db[ldesc].db.desc.res) 2152 & OHCI_COUNT_MASK; 2153 if (stat == 0) 2154 break; 2155 STAILQ_REMOVE_HEAD(&it->stdma, link); 2156 switch (stat & FWOHCIEV_MASK) { 2157 case FWOHCIEV_ACKCOMPL: 2158 #if 0 2159 device_printf(fc->dev, "0x%08x\n", count); 2160 #endif 2161 break; 2162 default: 2163 device_printf(fc->dev, 2164 "Isochronous transmit err %02x(%s)\n", 2165 stat, fwohcicode[stat & 0x1f]); 2166 } 2167 STAILQ_INSERT_TAIL(&it->stfree, chunk, link); 2168 w++; 2169 } 2170 FW_GUNLOCK(fc); 2171 splx(s); 2172 if (w) 2173 wakeup(it); 2174 } 2175 2176 static void 2177 fwohci_rbuf_update(struct fwohci_softc *sc, int dmach) 2178 { 2179 struct firewire_comm *fc = &sc->fc; 2180 struct fwohcidb_tr *db_tr; 2181 struct fw_bulkxfer *chunk; 2182 struct fw_xferq *ir; 2183 uint32_t stat; 2184 int w = 0, ldesc; 2185 2186 ir = fc->ir[dmach]; 2187 ldesc = sc->ir[dmach].ndesc - 1; 2188 2189 #if 0 2190 dump_db(sc, dmach); 2191 #endif 2192 if ((ir->flag & FWXFERQ_HANDLER) == 0) 2193 FW_GLOCK(fc); 2194 fwdma_sync_multiseg_all(sc->ir[dmach].am, BUS_DMASYNC_POSTREAD); 2195 while ((chunk = STAILQ_FIRST(&ir->stdma)) != NULL) { 2196 db_tr = (struct fwohcidb_tr *)chunk->end; 2197 stat = FWOHCI_DMA_READ(db_tr->db[ldesc].db.desc.res) 2198 >> OHCI_STATUS_SHIFT; 2199 if (stat == 0) 2200 break; 2201 2202 if (chunk->mbuf != NULL) { 2203 bus_dmamap_sync(sc->ir[dmach].dmat, db_tr->dma_map, 2204 BUS_DMASYNC_POSTREAD); 2205 bus_dmamap_unload(sc->ir[dmach].dmat, db_tr->dma_map); 2206 } else if (ir->buf != NULL) { 2207 fwdma_sync_multiseg(ir->buf, chunk->poffset, 2208 ir->bnpacket, BUS_DMASYNC_POSTREAD); 2209 } else { 2210 /* XXX */ 2211 printf("fwohci_rbuf_update: this shouldn't happend\n"); 2212 } 2213 2214 STAILQ_REMOVE_HEAD(&ir->stdma, link); 2215 STAILQ_INSERT_TAIL(&ir->stvalid, chunk, link); 2216 switch (stat & FWOHCIEV_MASK) { 2217 case FWOHCIEV_ACKCOMPL: 2218 chunk->resp = 0; 2219 break; 2220 default: 2221 chunk->resp = EINVAL; 2222 device_printf(fc->dev, 2223 "Isochronous receive err %02x(%s)\n", 2224 stat, fwohcicode[stat & 0x1f]); 2225 } 2226 w++; 2227 } 2228 if ((ir->flag & FWXFERQ_HANDLER) == 0) 2229 FW_GUNLOCK(fc); 2230 if (w == 0) 2231 return; 2232 2233 if (ir->flag & FWXFERQ_HANDLER) 2234 ir->hand(ir); 2235 else 2236 wakeup(ir); 2237 } 2238 2239 void 2240 dump_dma(struct fwohci_softc *sc, uint32_t ch) 2241 { 2242 uint32_t off, cntl, stat, cmd, match; 2243 2244 if (ch == 0) { 2245 off = OHCI_ATQOFF; 2246 } else if (ch == 1) { 2247 off = OHCI_ATSOFF; 2248 } else if (ch == 2) { 2249 off = OHCI_ARQOFF; 2250 } else if (ch == 3) { 2251 off = OHCI_ARSOFF; 2252 } else if (ch < IRX_CH) { 2253 off = OHCI_ITCTL(ch - ITX_CH); 2254 } else { 2255 off = OHCI_IRCTL(ch - IRX_CH); 2256 } 2257 cntl = stat = OREAD(sc, off); 2258 cmd = OREAD(sc, off + 0xc); 2259 match = OREAD(sc, off + 0x10); 2260 2261 device_printf(sc->fc.dev, "ch %1x cntl:0x%08x cmd:0x%08x match:0x%08x\n", 2262 ch, 2263 cntl, 2264 cmd, 2265 match); 2266 stat &= 0xffff; 2267 if (stat) { 2268 device_printf(sc->fc.dev, "dma %d ch:%s%s%s%s%s%s %s(%x)\n", 2269 ch, 2270 stat & OHCI_CNTL_DMA_RUN ? "RUN," : "", 2271 stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "", 2272 stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "", 2273 stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "", 2274 stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "", 2275 stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "", 2276 fwohcicode[stat & 0x1f], 2277 stat & 0x1f 2278 ); 2279 } else { 2280 device_printf(sc->fc.dev, "dma %d ch: Nostat\n", ch); 2281 } 2282 } 2283 2284 void 2285 dump_db(struct fwohci_softc *sc, uint32_t ch) 2286 { 2287 struct fwohci_dbch *dbch; 2288 struct fwohcidb_tr *cp = NULL, *pp, *np = NULL; 2289 struct fwohcidb *curr = NULL, *prev, *next = NULL; 2290 int idb, jdb; 2291 uint32_t cmd, off; 2292 2293 if (ch == 0) { 2294 off = OHCI_ATQOFF; 2295 dbch = &sc->atrq; 2296 } else if (ch == 1) { 2297 off = OHCI_ATSOFF; 2298 dbch = &sc->atrs; 2299 } else if (ch == 2) { 2300 off = OHCI_ARQOFF; 2301 dbch = &sc->arrq; 2302 } else if (ch == 3) { 2303 off = OHCI_ARSOFF; 2304 dbch = &sc->arrs; 2305 } else if (ch < IRX_CH) { 2306 off = OHCI_ITCTL(ch - ITX_CH); 2307 dbch = &sc->it[ch - ITX_CH]; 2308 } else { 2309 off = OHCI_IRCTL(ch - IRX_CH); 2310 dbch = &sc->ir[ch - IRX_CH]; 2311 } 2312 cmd = OREAD(sc, off + 0xc); 2313 2314 if (dbch->ndb == 0) { 2315 device_printf(sc->fc.dev, "No DB is attached ch=%d\n", ch); 2316 return; 2317 } 2318 pp = dbch->top; 2319 prev = pp->db; 2320 for (idb = 0; idb < dbch->ndb; idb++) { 2321 cp = STAILQ_NEXT(pp, link); 2322 if (cp == NULL) { 2323 curr = NULL; 2324 goto outdb; 2325 } 2326 np = STAILQ_NEXT(cp, link); 2327 for (jdb = 0; jdb < dbch->ndesc; jdb++) { 2328 if ((cmd & 0xfffffff0) == cp->bus_addr) { 2329 curr = cp->db; 2330 if (np != NULL) { 2331 next = np->db; 2332 } else { 2333 next = NULL; 2334 } 2335 goto outdb; 2336 } 2337 } 2338 pp = STAILQ_NEXT(pp, link); 2339 if (pp == NULL) { 2340 curr = NULL; 2341 goto outdb; 2342 } 2343 prev = pp->db; 2344 } 2345 outdb: 2346 if (curr != NULL) { 2347 #if 0 2348 printf("Prev DB %d\n", ch); 2349 print_db(pp, prev, ch, dbch->ndesc); 2350 #endif 2351 printf("Current DB %d\n", ch); 2352 print_db(cp, curr, ch, dbch->ndesc); 2353 #if 0 2354 printf("Next DB %d\n", ch); 2355 print_db(np, next, ch, dbch->ndesc); 2356 #endif 2357 } else { 2358 printf("dbdump err ch = %d cmd = 0x%08x\n", ch, cmd); 2359 } 2360 return; 2361 } 2362 2363 void 2364 print_db(struct fwohcidb_tr *db_tr, struct fwohcidb *db, 2365 uint32_t ch, uint32_t max) 2366 { 2367 fwohcireg_t stat; 2368 int i, key; 2369 uint32_t cmd, res; 2370 2371 if (db == NULL) { 2372 printf("No Descriptor is found\n"); 2373 return; 2374 } 2375 2376 printf("ch = %d\n%8s %s %s %s %s %4s %8s %8s %4s:%4s\n", 2377 ch, 2378 "Current", 2379 "OP ", 2380 "KEY", 2381 "INT", 2382 "BR ", 2383 "len", 2384 "Addr", 2385 "Depend", 2386 "Stat", 2387 "Cnt"); 2388 for (i = 0; i <= max; i++) { 2389 cmd = FWOHCI_DMA_READ(db[i].db.desc.cmd); 2390 res = FWOHCI_DMA_READ(db[i].db.desc.res); 2391 key = cmd & OHCI_KEY_MASK; 2392 stat = res >> OHCI_STATUS_SHIFT; 2393 printf("%08jx %s %s %s %s %5d %08x %08x %04x:%04x", 2394 (uintmax_t)db_tr->bus_addr, 2395 dbcode[(cmd >> 28) & 0xf], 2396 dbkey[(cmd >> 24) & 0x7], 2397 dbcond[(cmd >> 20) & 0x3], 2398 dbcond[(cmd >> 18) & 0x3], 2399 cmd & OHCI_COUNT_MASK, 2400 FWOHCI_DMA_READ(db[i].db.desc.addr), 2401 FWOHCI_DMA_READ(db[i].db.desc.depend), 2402 stat, 2403 res & OHCI_COUNT_MASK); 2404 if (stat & 0xff00) { 2405 printf(" %s%s%s%s%s%s %s(%x)\n", 2406 stat & OHCI_CNTL_DMA_RUN ? "RUN," : "", 2407 stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "", 2408 stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "", 2409 stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "", 2410 stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "", 2411 stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "", 2412 fwohcicode[stat & 0x1f], 2413 stat & 0x1f 2414 ); 2415 } else { 2416 printf(" Nostat\n"); 2417 } 2418 if (key == OHCI_KEY_ST2) { 2419 printf("0x%08x 0x%08x 0x%08x 0x%08x\n", 2420 FWOHCI_DMA_READ(db[i + 1].db.immed[0]), 2421 FWOHCI_DMA_READ(db[i + 1].db.immed[1]), 2422 FWOHCI_DMA_READ(db[i + 1].db.immed[2]), 2423 FWOHCI_DMA_READ(db[i + 1].db.immed[3])); 2424 } 2425 if (key == OHCI_KEY_DEVICE) { 2426 return; 2427 } 2428 if ((cmd & OHCI_BRANCH_MASK) 2429 == OHCI_BRANCH_ALWAYS) { 2430 return; 2431 } 2432 if ((cmd & OHCI_CMD_MASK) 2433 == OHCI_OUTPUT_LAST) { 2434 return; 2435 } 2436 if ((cmd & OHCI_CMD_MASK) 2437 == OHCI_INPUT_LAST) { 2438 return; 2439 } 2440 if (key == OHCI_KEY_ST2) { 2441 i++; 2442 } 2443 } 2444 return; 2445 } 2446 2447 void 2448 fwohci_ibr(struct firewire_comm *fc) 2449 { 2450 struct fwohci_softc *sc; 2451 uint32_t fun; 2452 2453 device_printf(fc->dev, "Initiate bus reset\n"); 2454 sc = (struct fwohci_softc *)fc; 2455 2456 FW_GLOCK(fc); 2457 /* 2458 * Make sure our cached values from the config rom are 2459 * initialised. 2460 */ 2461 OWRITE(sc, OHCI_CROMHDR, ntohl(sc->fc.config_rom[0])); 2462 OWRITE(sc, OHCI_BUS_OPT, ntohl(sc->fc.config_rom[2])); 2463 2464 /* 2465 * Set root hold-off bit so that non cyclemaster capable node 2466 * shouldn't became the root node. 2467 */ 2468 #if 1 2469 fun = fwphy_rddata(sc, FW_PHY_IBR_REG); 2470 fun |= FW_PHY_IBR | FW_PHY_RHB; 2471 fun = fwphy_wrdata(sc, FW_PHY_IBR_REG, fun); 2472 #else /* Short bus reset */ 2473 fun = fwphy_rddata(sc, FW_PHY_ISBR_REG); 2474 fun |= FW_PHY_ISBR | FW_PHY_RHB; 2475 fun = fwphy_wrdata(sc, FW_PHY_ISBR_REG, fun); 2476 #endif 2477 FW_GUNLOCK(fc); 2478 } 2479 2480 void 2481 fwohci_txbufdb(struct fwohci_softc *sc, int dmach, struct fw_bulkxfer *bulkxfer) 2482 { 2483 struct fwohcidb_tr *db_tr, *fdb_tr; 2484 struct fwohci_dbch *dbch; 2485 struct fwohcidb *db; 2486 struct fw_pkt *fp; 2487 struct fwohci_txpkthdr *ohcifp; 2488 unsigned short chtag; 2489 int idb; 2490 2491 FW_GLOCK_ASSERT(&sc->fc); 2492 2493 dbch = &sc->it[dmach]; 2494 chtag = sc->it[dmach].xferq.flag & 0xff; 2495 2496 db_tr = (struct fwohcidb_tr *)(bulkxfer->start); 2497 fdb_tr = (struct fwohcidb_tr *)(bulkxfer->end); 2498 /* 2499 device_printf(sc->fc.dev, "DB %08x %08x %08x\n", bulkxfer, db_tr->bus_addr, fdb_tr->bus_addr); 2500 */ 2501 for (idb = 0; idb < dbch->xferq.bnpacket; idb++) { 2502 db = db_tr->db; 2503 fp = (struct fw_pkt *)db_tr->buf; 2504 ohcifp = (struct fwohci_txpkthdr *) db[1].db.immed; 2505 ohcifp->mode.ld[0] = fp->mode.ld[0]; 2506 ohcifp->mode.common.spd = 0 & 0x7; 2507 ohcifp->mode.stream.len = fp->mode.stream.len; 2508 ohcifp->mode.stream.chtag = chtag; 2509 ohcifp->mode.stream.tcode = 0xa; 2510 #if BYTE_ORDER == BIG_ENDIAN 2511 FWOHCI_DMA_WRITE(db[1].db.immed[0], db[1].db.immed[0]); 2512 FWOHCI_DMA_WRITE(db[1].db.immed[1], db[1].db.immed[1]); 2513 #endif 2514 2515 FWOHCI_DMA_CLEAR(db[2].db.desc.cmd, OHCI_COUNT_MASK); 2516 FWOHCI_DMA_SET(db[2].db.desc.cmd, fp->mode.stream.len); 2517 FWOHCI_DMA_WRITE(db[2].db.desc.res, 0); 2518 #if 0 /* if bulkxfer->npackets changes */ 2519 db[2].db.desc.cmd = OHCI_OUTPUT_LAST 2520 | OHCI_UPDATE 2521 | OHCI_BRANCH_ALWAYS; 2522 db[0].db.desc.depend = 2523 = db[dbch->ndesc - 1].db.desc.depend 2524 = STAILQ_NEXT(db_tr, link)->bus_addr | dbch->ndesc; 2525 #else 2526 FWOHCI_DMA_SET(db[0].db.desc.depend, dbch->ndesc); 2527 FWOHCI_DMA_SET(db[dbch->ndesc - 1].db.desc.depend, dbch->ndesc); 2528 #endif 2529 bulkxfer->end = (caddr_t)db_tr; 2530 db_tr = STAILQ_NEXT(db_tr, link); 2531 } 2532 db = ((struct fwohcidb_tr *)bulkxfer->end)->db; 2533 FWOHCI_DMA_CLEAR(db[0].db.desc.depend, 0xf); 2534 FWOHCI_DMA_CLEAR(db[dbch->ndesc - 1].db.desc.depend, 0xf); 2535 #if 0 /* if bulkxfer->npackets changes */ 2536 db[dbch->ndesc - 1].db.desc.control |= OHCI_INTERRUPT_ALWAYS; 2537 /* OHCI 1.1 and above */ 2538 db[0].db.desc.control |= OHCI_INTERRUPT_ALWAYS; 2539 #endif 2540 /* 2541 db_tr = (struct fwohcidb_tr *)bulkxfer->start; 2542 fdb_tr = (struct fwohcidb_tr *)bulkxfer->end; 2543 device_printf(sc->fc.dev, "DB %08x %3d %08x %08x\n", bulkxfer, bulkxfer->npacket, db_tr->bus_addr, fdb_tr->bus_addr); 2544 */ 2545 return; 2546 } 2547 2548 static int 2549 fwohci_add_tx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr, 2550 int poffset) 2551 { 2552 struct fwohcidb *db = db_tr->db; 2553 struct fw_xferq *it; 2554 int err = 0; 2555 2556 it = &dbch->xferq; 2557 if (it->buf == 0) { 2558 err = EINVAL; 2559 return err; 2560 } 2561 db_tr->buf = fwdma_v_addr(it->buf, poffset); 2562 db_tr->dbcnt = 3; 2563 2564 FWOHCI_DMA_WRITE(db[0].db.desc.cmd, 2565 OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | 8); 2566 FWOHCI_DMA_WRITE(db[0].db.desc.addr, 0); 2567 bzero((void *)&db[1].db.immed[0], sizeof(db[1].db.immed)); 2568 FWOHCI_DMA_WRITE(db[2].db.desc.addr, 2569 fwdma_bus_addr(it->buf, poffset) + sizeof(uint32_t)); 2570 2571 FWOHCI_DMA_WRITE(db[2].db.desc.cmd, 2572 OHCI_OUTPUT_LAST | OHCI_UPDATE | OHCI_BRANCH_ALWAYS); 2573 #if 1 2574 FWOHCI_DMA_WRITE(db[0].db.desc.res, 0); 2575 FWOHCI_DMA_WRITE(db[2].db.desc.res, 0); 2576 #endif 2577 return 0; 2578 } 2579 2580 int 2581 fwohci_add_rx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr, 2582 int poffset, struct fwdma_alloc *dummy_dma) 2583 { 2584 struct fwohcidb *db = db_tr->db; 2585 struct fw_xferq *ir; 2586 int i, ldesc; 2587 bus_addr_t dbuf[2]; 2588 int dsiz[2]; 2589 2590 ir = &dbch->xferq; 2591 if (ir->buf == NULL && (dbch->xferq.flag & FWXFERQ_EXTBUF) == 0) { 2592 if (db_tr->buf == NULL) { 2593 db_tr->buf = fwdma_malloc_size(dbch->dmat, 2594 &db_tr->dma_map, ir->psize, &dbuf[0], 2595 BUS_DMA_NOWAIT); 2596 if (db_tr->buf == NULL) 2597 return (ENOMEM); 2598 } 2599 db_tr->dbcnt = 1; 2600 dsiz[0] = ir->psize; 2601 bus_dmamap_sync(dbch->dmat, db_tr->dma_map, 2602 BUS_DMASYNC_PREREAD); 2603 } else { 2604 db_tr->dbcnt = 0; 2605 if (dummy_dma != NULL) { 2606 dsiz[db_tr->dbcnt] = sizeof(uint32_t); 2607 dbuf[db_tr->dbcnt++] = dummy_dma->bus_addr; 2608 } 2609 dsiz[db_tr->dbcnt] = ir->psize; 2610 if (ir->buf != NULL) { 2611 db_tr->buf = fwdma_v_addr(ir->buf, poffset); 2612 dbuf[db_tr->dbcnt] = fwdma_bus_addr(ir->buf, poffset); 2613 } 2614 db_tr->dbcnt++; 2615 } 2616 for (i = 0; i < db_tr->dbcnt; i++) { 2617 FWOHCI_DMA_WRITE(db[i].db.desc.addr, dbuf[i]); 2618 FWOHCI_DMA_WRITE(db[i].db.desc.cmd, OHCI_INPUT_MORE | dsiz[i]); 2619 if (ir->flag & FWXFERQ_STREAM) { 2620 FWOHCI_DMA_SET(db[i].db.desc.cmd, OHCI_UPDATE); 2621 } 2622 FWOHCI_DMA_WRITE(db[i].db.desc.res, dsiz[i]); 2623 } 2624 ldesc = db_tr->dbcnt - 1; 2625 if (ir->flag & FWXFERQ_STREAM) { 2626 FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, OHCI_INPUT_LAST); 2627 } 2628 FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, OHCI_BRANCH_ALWAYS); 2629 return 0; 2630 } 2631 2632 2633 static int 2634 fwohci_arcv_swap(struct fw_pkt *fp, int len) 2635 { 2636 struct fw_pkt *fp0; 2637 uint32_t ld0; 2638 int slen, hlen; 2639 #if BYTE_ORDER == BIG_ENDIAN 2640 int i; 2641 #endif 2642 2643 ld0 = FWOHCI_DMA_READ(fp->mode.ld[0]); 2644 #if 0 2645 printf("ld0: x%08x\n", ld0); 2646 #endif 2647 fp0 = (struct fw_pkt *)&ld0; 2648 /* determine length to swap */ 2649 switch (fp0->mode.common.tcode) { 2650 case FWTCODE_RREQQ: 2651 case FWTCODE_WRES: 2652 case FWTCODE_WREQQ: 2653 case FWTCODE_RRESQ: 2654 case FWOHCITCODE_PHY: 2655 slen = 12; 2656 break; 2657 case FWTCODE_RREQB: 2658 case FWTCODE_WREQB: 2659 case FWTCODE_LREQ: 2660 case FWTCODE_RRESB: 2661 case FWTCODE_LRES: 2662 slen = 16; 2663 break; 2664 default: 2665 printf("Unknown tcode %d\n", fp0->mode.common.tcode); 2666 return (0); 2667 } 2668 hlen = tinfo[fp0->mode.common.tcode].hdr_len; 2669 if (hlen > len) { 2670 if (firewire_debug) 2671 printf("splitted header\n"); 2672 return (-hlen); 2673 } 2674 #if BYTE_ORDER == BIG_ENDIAN 2675 for (i = 0; i < slen/4; i++) 2676 fp->mode.ld[i] = FWOHCI_DMA_READ(fp->mode.ld[i]); 2677 #endif 2678 return (hlen); 2679 } 2680 2681 static int 2682 fwohci_get_plen(struct fwohci_softc *sc, struct fwohci_dbch *dbch, struct fw_pkt *fp) 2683 { 2684 struct tcode_info *info; 2685 int r; 2686 2687 info = &tinfo[fp->mode.common.tcode]; 2688 r = info->hdr_len + sizeof(uint32_t); 2689 if ((info->flag & FWTI_BLOCK_ASY) != 0) 2690 r += roundup2(fp->mode.wreqb.len, sizeof(uint32_t)); 2691 2692 if (r == sizeof(uint32_t)) { 2693 /* XXX */ 2694 device_printf(sc->fc.dev, "Unknown tcode %d\n", 2695 fp->mode.common.tcode); 2696 return (-1); 2697 } 2698 2699 if (r > dbch->xferq.psize) { 2700 device_printf(sc->fc.dev, "Invalid packet length %d\n", r); 2701 return (-1); 2702 /* panic ? */ 2703 } 2704 2705 return r; 2706 } 2707 2708 static void 2709 fwohci_arcv_free_buf(struct fwohci_softc *sc, struct fwohci_dbch *dbch, 2710 struct fwohcidb_tr *db_tr, uint32_t off, int wake) 2711 { 2712 struct fwohcidb *db = &db_tr->db[0]; 2713 2714 FWOHCI_DMA_CLEAR(db->db.desc.depend, 0xf); 2715 FWOHCI_DMA_WRITE(db->db.desc.res, dbch->xferq.psize); 2716 FWOHCI_DMA_SET(dbch->bottom->db[0].db.desc.depend, 1); 2717 fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREWRITE); 2718 dbch->bottom = db_tr; 2719 2720 if (wake) 2721 OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_WAKE); 2722 } 2723 2724 static void 2725 fwohci_arcv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count) 2726 { 2727 struct fwohcidb_tr *db_tr; 2728 struct iovec vec[2]; 2729 struct fw_pkt pktbuf; 2730 int nvec; 2731 struct fw_pkt *fp; 2732 uint8_t *ld; 2733 uint32_t stat, off, status, event; 2734 u_int spd; 2735 int len, plen, hlen, pcnt, offset; 2736 int s; 2737 caddr_t buf; 2738 int resCount; 2739 2740 if (&sc->arrq == dbch) { 2741 off = OHCI_ARQOFF; 2742 } else if (&sc->arrs == dbch) { 2743 off = OHCI_ARSOFF; 2744 } else { 2745 return; 2746 } 2747 2748 s = splfw(); 2749 db_tr = dbch->top; 2750 pcnt = 0; 2751 /* XXX we cannot handle a packet which lies in more than two buf */ 2752 fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_POSTREAD); 2753 fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_POSTWRITE); 2754 status = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) >> OHCI_STATUS_SHIFT; 2755 resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) & OHCI_COUNT_MASK; 2756 while (status & OHCI_CNTL_DMA_ACTIVE) { 2757 #if 0 2758 2759 if (off == OHCI_ARQOFF) 2760 printf("buf 0x%08x, status 0x%04x, resCount 0x%04x\n", 2761 db_tr->bus_addr, status, resCount); 2762 #endif 2763 len = dbch->xferq.psize - resCount; 2764 ld = (uint8_t *)db_tr->buf; 2765 if (dbch->pdb_tr == NULL) { 2766 len -= dbch->buf_offset; 2767 ld += dbch->buf_offset; 2768 } 2769 if (len > 0) 2770 bus_dmamap_sync(dbch->dmat, db_tr->dma_map, 2771 BUS_DMASYNC_POSTREAD); 2772 while (len > 0) { 2773 if (count >= 0 && count-- == 0) 2774 goto out; 2775 if (dbch->pdb_tr != NULL) { 2776 /* we have a fragment in previous buffer */ 2777 int rlen; 2778 2779 offset = dbch->buf_offset; 2780 if (offset < 0) 2781 offset = - offset; 2782 buf = dbch->pdb_tr->buf + offset; 2783 rlen = dbch->xferq.psize - offset; 2784 if (firewire_debug) 2785 printf("rlen=%d, offset=%d\n", 2786 rlen, dbch->buf_offset); 2787 if (dbch->buf_offset < 0) { 2788 /* splitted in header, pull up */ 2789 char *p; 2790 2791 p = (char *)&pktbuf; 2792 bcopy(buf, p, rlen); 2793 p += rlen; 2794 /* this must be too long but harmless */ 2795 rlen = sizeof(pktbuf) - rlen; 2796 if (rlen < 0) 2797 printf("why rlen < 0\n"); 2798 bcopy(db_tr->buf, p, rlen); 2799 ld += rlen; 2800 len -= rlen; 2801 hlen = fwohci_arcv_swap(&pktbuf, sizeof(pktbuf)); 2802 if (hlen <= 0) { 2803 printf("hlen should be positive."); 2804 goto err; 2805 } 2806 offset = sizeof(pktbuf); 2807 vec[0].iov_base = (char *)&pktbuf; 2808 vec[0].iov_len = offset; 2809 } else { 2810 /* splitted in payload */ 2811 offset = rlen; 2812 vec[0].iov_base = buf; 2813 vec[0].iov_len = rlen; 2814 } 2815 fp=(struct fw_pkt *)vec[0].iov_base; 2816 nvec = 1; 2817 } else { 2818 /* no fragment in previous buffer */ 2819 fp=(struct fw_pkt *)ld; 2820 hlen = fwohci_arcv_swap(fp, len); 2821 if (hlen == 0) 2822 goto err; 2823 if (hlen < 0) { 2824 dbch->pdb_tr = db_tr; 2825 dbch->buf_offset = - dbch->buf_offset; 2826 /* sanity check */ 2827 if (resCount != 0) { 2828 printf("resCount=%d hlen=%d\n", 2829 resCount, hlen); 2830 goto err; 2831 } 2832 goto out; 2833 } 2834 offset = 0; 2835 nvec = 0; 2836 } 2837 plen = fwohci_get_plen(sc, dbch, fp) - offset; 2838 if (plen < 0) { 2839 /* minimum header size + trailer 2840 = sizeof(fw_pkt) so this shouldn't happens */ 2841 printf("plen(%d) is negative! offset=%d\n", 2842 plen, offset); 2843 goto err; 2844 } 2845 if (plen > 0) { 2846 len -= plen; 2847 if (len < 0) { 2848 dbch->pdb_tr = db_tr; 2849 if (firewire_debug) 2850 printf("splitted payload\n"); 2851 /* sanity check */ 2852 if (resCount != 0) { 2853 printf("resCount=%d plen=%d" 2854 " len=%d\n", 2855 resCount, plen, len); 2856 goto err; 2857 } 2858 goto out; 2859 } 2860 vec[nvec].iov_base = ld; 2861 vec[nvec].iov_len = plen; 2862 nvec++; 2863 ld += plen; 2864 } 2865 dbch->buf_offset = ld - (uint8_t *)db_tr->buf; 2866 if (nvec == 0) 2867 printf("nvec == 0\n"); 2868 2869 /* DMA result-code will be written at the tail of packet */ 2870 stat = FWOHCI_DMA_READ(*(uint32_t *)(ld - sizeof(struct fwohci_trailer))); 2871 #if 0 2872 printf("plen: %d, stat %x\n", 2873 plen ,stat); 2874 #endif 2875 spd = (stat >> 21) & 0x3; 2876 event = (stat >> 16) & 0x1f; 2877 switch (event) { 2878 case FWOHCIEV_ACKPEND: 2879 #if 0 2880 printf("fwohci_arcv: ack pending tcode=0x%x..\n", fp->mode.common.tcode); 2881 #endif 2882 /* fall through */ 2883 case FWOHCIEV_ACKCOMPL: 2884 { 2885 struct fw_rcv_buf rb; 2886 2887 if ((vec[nvec-1].iov_len -= 2888 sizeof(struct fwohci_trailer)) == 0) 2889 nvec--; 2890 rb.fc = &sc->fc; 2891 rb.vec = vec; 2892 rb.nvec = nvec; 2893 rb.spd = spd; 2894 fw_rcv(&rb); 2895 break; 2896 } 2897 case FWOHCIEV_BUSRST: 2898 if ((sc->fc.status != FWBUSRESET) && 2899 (sc->fc.status != FWBUSINIT)) 2900 printf("got BUSRST packet!?\n"); 2901 break; 2902 default: 2903 device_printf(sc->fc.dev, 2904 "Async DMA Receive error err=%02x %s" 2905 " plen=%d offset=%d len=%d status=0x%08x" 2906 " tcode=0x%x, stat=0x%08x\n", 2907 event, fwohcicode[event], plen, 2908 dbch->buf_offset, len, 2909 OREAD(sc, OHCI_DMACTL(off)), 2910 fp->mode.common.tcode, stat); 2911 #if 1 /* XXX */ 2912 goto err; 2913 #endif 2914 break; 2915 } 2916 pcnt++; 2917 if (dbch->pdb_tr != NULL) { 2918 fwohci_arcv_free_buf(sc, dbch, dbch->pdb_tr, 2919 off, 1); 2920 dbch->pdb_tr = NULL; 2921 } 2922 2923 } 2924 out: 2925 if (resCount == 0) { 2926 /* done on this buffer */ 2927 if (dbch->pdb_tr == NULL) { 2928 fwohci_arcv_free_buf(sc, dbch, db_tr, off, 1); 2929 dbch->buf_offset = 0; 2930 } else 2931 if (dbch->pdb_tr != db_tr) 2932 printf("pdb_tr != db_tr\n"); 2933 db_tr = STAILQ_NEXT(db_tr, link); 2934 status = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) 2935 >> OHCI_STATUS_SHIFT; 2936 resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) 2937 & OHCI_COUNT_MASK; 2938 /* XXX check buffer overrun */ 2939 dbch->top = db_tr; 2940 } else { 2941 dbch->buf_offset = dbch->xferq.psize - resCount; 2942 break; 2943 } 2944 /* XXX make sure DMA is not dead */ 2945 } 2946 #if 0 2947 if (pcnt < 1) 2948 printf("fwohci_arcv: no packets\n"); 2949 #endif 2950 splx(s); 2951 return; 2952 2953 err: 2954 device_printf(sc->fc.dev, "AR DMA status=%x, ", 2955 OREAD(sc, OHCI_DMACTL(off))); 2956 dbch->pdb_tr = NULL; 2957 /* skip until resCount != 0 */ 2958 printf(" skip buffer"); 2959 while (resCount == 0) { 2960 printf(" #"); 2961 fwohci_arcv_free_buf(sc, dbch, db_tr, off, 0); 2962 db_tr = STAILQ_NEXT(db_tr, link); 2963 resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) 2964 & OHCI_COUNT_MASK; 2965 } 2966 printf(" done\n"); 2967 dbch->top = db_tr; 2968 dbch->buf_offset = dbch->xferq.psize - resCount; 2969 OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_WAKE); 2970 splx(s); 2971 } 2972