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/Receiver */ 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 receive 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. response */ 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 1251 #define DB_SIZE(x) (sizeof(struct fwohcidb) * (x)->ndesc) 1252 dbch->am = fwdma_malloc_multiseg(&sc->fc, sizeof(struct fwohcidb), 1253 DB_SIZE(dbch), dbch->ndb, BUS_DMA_WAITOK); 1254 if (dbch->am == NULL) { 1255 printf("fwohci_db_init: fwdma_malloc_multiseg failed\n"); 1256 free(db_tr, M_FW); 1257 return; 1258 } 1259 /* Attach DB to DMA ch. */ 1260 for (idb = 0; idb < dbch->ndb; idb++) { 1261 db_tr->dbcnt = 0; 1262 db_tr->db = (struct fwohcidb *)fwdma_v_addr(dbch->am, idb); 1263 db_tr->bus_addr = fwdma_bus_addr(dbch->am, idb); 1264 /* create dmamap for buffers */ 1265 /* XXX do we need 4bytes alignment tag? */ 1266 /* XXX don't alloc dma_map for AR */ 1267 if (bus_dmamap_create(dbch->dmat, 0, &db_tr->dma_map) != 0) { 1268 printf("bus_dmamap_create failed\n"); 1269 dbch->flags = FWOHCI_DBCH_INIT; /* XXX fake */ 1270 fwohci_db_free(dbch); 1271 return; 1272 } 1273 STAILQ_INSERT_TAIL(&dbch->db_trq, db_tr, link); 1274 if (dbch->xferq.flag & FWXFERQ_EXTBUF) { 1275 if (idb % dbch->xferq.bnpacket == 0) 1276 dbch->xferq.bulkxfer[idb / dbch->xferq.bnpacket 1277 ].start = (caddr_t)db_tr; 1278 if ((idb + 1) % dbch->xferq.bnpacket == 0) 1279 dbch->xferq.bulkxfer[idb / dbch->xferq.bnpacket 1280 ].end = (caddr_t)db_tr; 1281 } 1282 db_tr++; 1283 } 1284 STAILQ_LAST(&dbch->db_trq, fwohcidb_tr,link)->link.stqe_next 1285 = STAILQ_FIRST(&dbch->db_trq); 1286 out: 1287 dbch->xferq.queued = 0; 1288 dbch->pdb_tr = NULL; 1289 dbch->top = STAILQ_FIRST(&dbch->db_trq); 1290 dbch->bottom = dbch->top; 1291 dbch->flags = FWOHCI_DBCH_INIT; 1292 } 1293 1294 static int 1295 fwohci_itx_disable(struct firewire_comm *fc, int dmach) 1296 { 1297 struct fwohci_softc *sc = (struct fwohci_softc *)fc; 1298 1299 OWRITE(sc, OHCI_ITCTLCLR(dmach), 1300 OHCI_CNTL_DMA_RUN | OHCI_CNTL_CYCMATCH_S); 1301 OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach); 1302 OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach); 1303 /* XXX we cannot free buffers until the DMA really stops */ 1304 pause("fwitxd", hz); 1305 fwohci_db_free(&sc->it[dmach]); 1306 sc->it[dmach].xferq.flag &= ~FWXFERQ_RUNNING; 1307 return 0; 1308 } 1309 1310 static int 1311 fwohci_irx_disable(struct firewire_comm *fc, int dmach) 1312 { 1313 struct fwohci_softc *sc = (struct fwohci_softc *)fc; 1314 1315 OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN); 1316 OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach); 1317 OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach); 1318 /* XXX we cannot free buffers until the DMA really stops */ 1319 pause("fwirxd", hz); 1320 fwohci_db_free(&sc->ir[dmach]); 1321 sc->ir[dmach].xferq.flag &= ~FWXFERQ_RUNNING; 1322 return 0; 1323 } 1324 1325 #if BYTE_ORDER == BIG_ENDIAN 1326 static void 1327 fwohci_irx_post (struct firewire_comm *fc , uint32_t *qld) 1328 { 1329 qld[0] = FWOHCI_DMA_READ(qld[0]); 1330 return; 1331 } 1332 #endif 1333 1334 static int 1335 fwohci_tx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch) 1336 { 1337 int err = 0; 1338 int idb, z, i, dmach = 0, ldesc; 1339 uint32_t off = 0; 1340 struct fwohcidb_tr *db_tr; 1341 struct fwohcidb *db; 1342 1343 if (!(dbch->xferq.flag & FWXFERQ_EXTBUF)) { 1344 err = EINVAL; 1345 return err; 1346 } 1347 z = dbch->ndesc; 1348 for (dmach = 0; dmach < sc->fc.nisodma; dmach++) { 1349 if (&sc->it[dmach] == dbch) { 1350 off = OHCI_ITOFF(dmach); 1351 break; 1352 } 1353 } 1354 if (off == 0) { 1355 err = EINVAL; 1356 return err; 1357 } 1358 if (dbch->xferq.flag & FWXFERQ_RUNNING) 1359 return err; 1360 dbch->xferq.flag |= FWXFERQ_RUNNING; 1361 for (i = 0, dbch->bottom = dbch->top; i < (dbch->ndb - 1); i++) { 1362 dbch->bottom = STAILQ_NEXT(dbch->bottom, link); 1363 } 1364 db_tr = dbch->top; 1365 for (idb = 0; idb < dbch->ndb; idb++) { 1366 fwohci_add_tx_buf(dbch, db_tr, idb); 1367 if (STAILQ_NEXT(db_tr, link) == NULL) { 1368 break; 1369 } 1370 db = db_tr->db; 1371 ldesc = db_tr->dbcnt - 1; 1372 FWOHCI_DMA_WRITE(db[0].db.desc.depend, 1373 STAILQ_NEXT(db_tr, link)->bus_addr | z); 1374 db[ldesc].db.desc.depend = db[0].db.desc.depend; 1375 if (dbch->xferq.flag & FWXFERQ_EXTBUF) { 1376 if (((idb + 1) % dbch->xferq.bnpacket) == 0) { 1377 FWOHCI_DMA_SET( 1378 db[ldesc].db.desc.cmd, 1379 OHCI_INTERRUPT_ALWAYS); 1380 /* OHCI 1.1 and above */ 1381 FWOHCI_DMA_SET( 1382 db[0].db.desc.cmd, 1383 OHCI_INTERRUPT_ALWAYS); 1384 } 1385 } 1386 db_tr = STAILQ_NEXT(db_tr, link); 1387 } 1388 FWOHCI_DMA_CLEAR( 1389 dbch->bottom->db[dbch->bottom->dbcnt - 1].db.desc.depend, 0xf); 1390 return err; 1391 } 1392 1393 static int 1394 fwohci_rx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch) 1395 { 1396 int err = 0; 1397 int idb, z, i, dmach = 0, ldesc; 1398 uint32_t off = 0; 1399 struct fwohcidb_tr *db_tr; 1400 struct fwohcidb *db; 1401 1402 z = dbch->ndesc; 1403 if (&sc->arrq == dbch) { 1404 off = OHCI_ARQOFF; 1405 } else if (&sc->arrs == dbch) { 1406 off = OHCI_ARSOFF; 1407 } else { 1408 for (dmach = 0; dmach < sc->fc.nisodma; dmach++) { 1409 if (&sc->ir[dmach] == dbch) { 1410 off = OHCI_IROFF(dmach); 1411 break; 1412 } 1413 } 1414 } 1415 if (off == 0) { 1416 err = EINVAL; 1417 return err; 1418 } 1419 if (dbch->xferq.flag & FWXFERQ_STREAM) { 1420 if (dbch->xferq.flag & FWXFERQ_RUNNING) 1421 return err; 1422 } else { 1423 if (dbch->xferq.flag & FWXFERQ_RUNNING) { 1424 err = EBUSY; 1425 return err; 1426 } 1427 } 1428 dbch->xferq.flag |= FWXFERQ_RUNNING; 1429 dbch->top = STAILQ_FIRST(&dbch->db_trq); 1430 for (i = 0, dbch->bottom = dbch->top; i < (dbch->ndb - 1); i++) { 1431 dbch->bottom = STAILQ_NEXT(dbch->bottom, link); 1432 } 1433 db_tr = dbch->top; 1434 for (idb = 0; idb < dbch->ndb; idb++) { 1435 fwohci_add_rx_buf(dbch, db_tr, idb, &sc->dummy_dma); 1436 if (STAILQ_NEXT(db_tr, link) == NULL) 1437 break; 1438 db = db_tr->db; 1439 ldesc = db_tr->dbcnt - 1; 1440 FWOHCI_DMA_WRITE(db[ldesc].db.desc.depend, 1441 STAILQ_NEXT(db_tr, link)->bus_addr | z); 1442 if (dbch->xferq.flag & FWXFERQ_EXTBUF) { 1443 if (((idb + 1) % dbch->xferq.bnpacket) == 0) { 1444 FWOHCI_DMA_SET( 1445 db[ldesc].db.desc.cmd, 1446 OHCI_INTERRUPT_ALWAYS); 1447 FWOHCI_DMA_CLEAR( 1448 db[ldesc].db.desc.depend, 1449 0xf); 1450 } 1451 } 1452 db_tr = STAILQ_NEXT(db_tr, link); 1453 } 1454 FWOHCI_DMA_CLEAR( 1455 dbch->bottom->db[db_tr->dbcnt - 1].db.desc.depend, 0xf); 1456 dbch->buf_offset = 0; 1457 fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREREAD); 1458 fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREWRITE); 1459 if (dbch->xferq.flag & FWXFERQ_STREAM) { 1460 return err; 1461 } else { 1462 OWRITE(sc, OHCI_DMACMD(off), dbch->top->bus_addr | z); 1463 } 1464 OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_RUN); 1465 return err; 1466 } 1467 1468 static int 1469 fwohci_next_cycle(struct firewire_comm *fc, int cycle_now) 1470 { 1471 int sec, cycle, cycle_match; 1472 1473 cycle = cycle_now & 0x1fff; 1474 sec = cycle_now >> 13; 1475 #define CYCLE_MOD 0x10 1476 #if 1 1477 #define CYCLE_DELAY 8 /* min delay to start DMA */ 1478 #else 1479 #define CYCLE_DELAY 7000 /* min delay to start DMA */ 1480 #endif 1481 cycle = cycle + CYCLE_DELAY; 1482 if (cycle >= 8000) { 1483 sec++; 1484 cycle -= 8000; 1485 } 1486 cycle = roundup2(cycle, CYCLE_MOD); 1487 if (cycle >= 8000) { 1488 sec++; 1489 if (cycle == 8000) 1490 cycle = 0; 1491 else 1492 cycle = CYCLE_MOD; 1493 } 1494 cycle_match = ((sec << 13) | cycle) & 0x7ffff; 1495 1496 return (cycle_match); 1497 } 1498 1499 static int 1500 fwohci_itxbuf_enable(struct firewire_comm *fc, int dmach) 1501 { 1502 struct fwohci_softc *sc = (struct fwohci_softc *)fc; 1503 int err = 0; 1504 unsigned short tag, ich; 1505 struct fwohci_dbch *dbch; 1506 int cycle_match, cycle_now, s, ldesc; 1507 uint32_t stat; 1508 struct fw_bulkxfer *first, *chunk, *prev; 1509 struct fw_xferq *it; 1510 1511 dbch = &sc->it[dmach]; 1512 it = &dbch->xferq; 1513 1514 tag = (it->flag >> 6) & 3; 1515 ich = it->flag & 0x3f; 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; 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, *np = NULL; 2295 struct fwohcidb *curr = NULL, *prev, *next = NULL; 2296 int idb, jdb; 2297 uint32_t cmd, off; 2298 2299 if (ch == 0) { 2300 off = OHCI_ATQOFF; 2301 dbch = &sc->atrq; 2302 } else if (ch == 1) { 2303 off = OHCI_ATSOFF; 2304 dbch = &sc->atrs; 2305 } else if (ch == 2) { 2306 off = OHCI_ARQOFF; 2307 dbch = &sc->arrq; 2308 } else if (ch == 3) { 2309 off = OHCI_ARSOFF; 2310 dbch = &sc->arrs; 2311 } else if (ch < IRX_CH) { 2312 off = OHCI_ITCTL(ch - ITX_CH); 2313 dbch = &sc->it[ch - ITX_CH]; 2314 } else { 2315 off = OHCI_IRCTL(ch - IRX_CH); 2316 dbch = &sc->ir[ch - IRX_CH]; 2317 } 2318 cmd = OREAD(sc, off + 0xc); 2319 2320 if (dbch->ndb == 0) { 2321 device_printf(sc->fc.dev, "No DB is attached ch=%d\n", ch); 2322 return; 2323 } 2324 pp = dbch->top; 2325 prev = pp->db; 2326 for (idb = 0; idb < dbch->ndb; idb++) { 2327 cp = STAILQ_NEXT(pp, link); 2328 if (cp == NULL) { 2329 curr = NULL; 2330 goto outdb; 2331 } 2332 np = STAILQ_NEXT(cp, link); 2333 for (jdb = 0; jdb < dbch->ndesc; jdb++) { 2334 if ((cmd & 0xfffffff0) == cp->bus_addr) { 2335 curr = cp->db; 2336 if (np != NULL) { 2337 next = np->db; 2338 } else { 2339 next = NULL; 2340 } 2341 goto outdb; 2342 } 2343 } 2344 pp = STAILQ_NEXT(pp, link); 2345 if (pp == NULL) { 2346 curr = NULL; 2347 goto outdb; 2348 } 2349 prev = pp->db; 2350 } 2351 outdb: 2352 if (curr != NULL) { 2353 #if 0 2354 printf("Prev DB %d\n", ch); 2355 print_db(pp, prev, ch, dbch->ndesc); 2356 #endif 2357 printf("Current DB %d\n", ch); 2358 print_db(cp, curr, ch, dbch->ndesc); 2359 #if 0 2360 printf("Next DB %d\n", ch); 2361 print_db(np, next, ch, dbch->ndesc); 2362 #endif 2363 } else { 2364 printf("dbdump err ch = %d cmd = 0x%08x\n", ch, cmd); 2365 } 2366 return; 2367 } 2368 2369 void 2370 print_db(struct fwohcidb_tr *db_tr, struct fwohcidb *db, 2371 uint32_t ch, uint32_t max) 2372 { 2373 fwohcireg_t stat; 2374 int i, key; 2375 uint32_t cmd, res; 2376 2377 if (db == NULL) { 2378 printf("No Descriptor is found\n"); 2379 return; 2380 } 2381 2382 printf("ch = %d\n%8s %s %s %s %s %4s %8s %8s %4s:%4s\n", 2383 ch, 2384 "Current", 2385 "OP ", 2386 "KEY", 2387 "INT", 2388 "BR ", 2389 "len", 2390 "Addr", 2391 "Depend", 2392 "Stat", 2393 "Cnt"); 2394 for (i = 0; i <= max; i++) { 2395 cmd = FWOHCI_DMA_READ(db[i].db.desc.cmd); 2396 res = FWOHCI_DMA_READ(db[i].db.desc.res); 2397 key = cmd & OHCI_KEY_MASK; 2398 stat = res >> OHCI_STATUS_SHIFT; 2399 printf("%08jx %s %s %s %s %5d %08x %08x %04x:%04x", 2400 (uintmax_t)db_tr->bus_addr, 2401 dbcode[(cmd >> 28) & 0xf], 2402 dbkey[(cmd >> 24) & 0x7], 2403 dbcond[(cmd >> 20) & 0x3], 2404 dbcond[(cmd >> 18) & 0x3], 2405 cmd & OHCI_COUNT_MASK, 2406 FWOHCI_DMA_READ(db[i].db.desc.addr), 2407 FWOHCI_DMA_READ(db[i].db.desc.depend), 2408 stat, 2409 res & OHCI_COUNT_MASK); 2410 if (stat & 0xff00) { 2411 printf(" %s%s%s%s%s%s %s(%x)\n", 2412 stat & OHCI_CNTL_DMA_RUN ? "RUN," : "", 2413 stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "", 2414 stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "", 2415 stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "", 2416 stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "", 2417 stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "", 2418 fwohcicode[stat & 0x1f], 2419 stat & 0x1f 2420 ); 2421 } else { 2422 printf(" Nostat\n"); 2423 } 2424 if (key == OHCI_KEY_ST2) { 2425 printf("0x%08x 0x%08x 0x%08x 0x%08x\n", 2426 FWOHCI_DMA_READ(db[i + 1].db.immed[0]), 2427 FWOHCI_DMA_READ(db[i + 1].db.immed[1]), 2428 FWOHCI_DMA_READ(db[i + 1].db.immed[2]), 2429 FWOHCI_DMA_READ(db[i + 1].db.immed[3])); 2430 } 2431 if (key == OHCI_KEY_DEVICE) { 2432 return; 2433 } 2434 if ((cmd & OHCI_BRANCH_MASK) 2435 == OHCI_BRANCH_ALWAYS) { 2436 return; 2437 } 2438 if ((cmd & OHCI_CMD_MASK) 2439 == OHCI_OUTPUT_LAST) { 2440 return; 2441 } 2442 if ((cmd & OHCI_CMD_MASK) 2443 == OHCI_INPUT_LAST) { 2444 return; 2445 } 2446 if (key == OHCI_KEY_ST2) { 2447 i++; 2448 } 2449 } 2450 return; 2451 } 2452 2453 void 2454 fwohci_ibr(struct firewire_comm *fc) 2455 { 2456 struct fwohci_softc *sc; 2457 uint32_t fun; 2458 2459 device_printf(fc->dev, "Initiate bus reset\n"); 2460 sc = (struct fwohci_softc *)fc; 2461 2462 FW_GLOCK(fc); 2463 /* 2464 * Make sure our cached values from the config rom are 2465 * initialised. 2466 */ 2467 OWRITE(sc, OHCI_CROMHDR, ntohl(sc->fc.config_rom[0])); 2468 OWRITE(sc, OHCI_BUS_OPT, ntohl(sc->fc.config_rom[2])); 2469 2470 /* 2471 * Set root hold-off bit so that non cyclemaster capable node 2472 * shouldn't became the root node. 2473 */ 2474 #if 1 2475 fun = fwphy_rddata(sc, FW_PHY_IBR_REG); 2476 fun |= FW_PHY_IBR | FW_PHY_RHB; 2477 fun = fwphy_wrdata(sc, FW_PHY_IBR_REG, fun); 2478 #else /* Short bus reset */ 2479 fun = fwphy_rddata(sc, FW_PHY_ISBR_REG); 2480 fun |= FW_PHY_ISBR | FW_PHY_RHB; 2481 fun = fwphy_wrdata(sc, FW_PHY_ISBR_REG, fun); 2482 #endif 2483 FW_GUNLOCK(fc); 2484 } 2485 2486 void 2487 fwohci_txbufdb(struct fwohci_softc *sc, int dmach, struct fw_bulkxfer *bulkxfer) 2488 { 2489 struct fwohcidb_tr *db_tr, *fdb_tr; 2490 struct fwohci_dbch *dbch; 2491 struct fwohcidb *db; 2492 struct fw_pkt *fp; 2493 struct fwohci_txpkthdr *ohcifp; 2494 unsigned short chtag; 2495 int idb; 2496 2497 FW_GLOCK_ASSERT(&sc->fc); 2498 2499 dbch = &sc->it[dmach]; 2500 chtag = sc->it[dmach].xferq.flag & 0xff; 2501 2502 db_tr = (struct fwohcidb_tr *)(bulkxfer->start); 2503 fdb_tr = (struct fwohcidb_tr *)(bulkxfer->end); 2504 /* 2505 device_printf(sc->fc.dev, "DB %08x %08x %08x\n", bulkxfer, db_tr->bus_addr, fdb_tr->bus_addr); 2506 */ 2507 for (idb = 0; idb < dbch->xferq.bnpacket; idb++) { 2508 db = db_tr->db; 2509 fp = (struct fw_pkt *)db_tr->buf; 2510 ohcifp = (struct fwohci_txpkthdr *) db[1].db.immed; 2511 ohcifp->mode.ld[0] = fp->mode.ld[0]; 2512 ohcifp->mode.common.spd = 0 & 0x7; 2513 ohcifp->mode.stream.len = fp->mode.stream.len; 2514 ohcifp->mode.stream.chtag = chtag; 2515 ohcifp->mode.stream.tcode = 0xa; 2516 #if BYTE_ORDER == BIG_ENDIAN 2517 FWOHCI_DMA_WRITE(db[1].db.immed[0], db[1].db.immed[0]); 2518 FWOHCI_DMA_WRITE(db[1].db.immed[1], db[1].db.immed[1]); 2519 #endif 2520 2521 FWOHCI_DMA_CLEAR(db[2].db.desc.cmd, OHCI_COUNT_MASK); 2522 FWOHCI_DMA_SET(db[2].db.desc.cmd, fp->mode.stream.len); 2523 FWOHCI_DMA_WRITE(db[2].db.desc.res, 0); 2524 #if 0 /* if bulkxfer->npackets changes */ 2525 db[2].db.desc.cmd = OHCI_OUTPUT_LAST 2526 | OHCI_UPDATE 2527 | OHCI_BRANCH_ALWAYS; 2528 db[0].db.desc.depend = 2529 = db[dbch->ndesc - 1].db.desc.depend 2530 = STAILQ_NEXT(db_tr, link)->bus_addr | dbch->ndesc; 2531 #else 2532 FWOHCI_DMA_SET(db[0].db.desc.depend, dbch->ndesc); 2533 FWOHCI_DMA_SET(db[dbch->ndesc - 1].db.desc.depend, dbch->ndesc); 2534 #endif 2535 bulkxfer->end = (caddr_t)db_tr; 2536 db_tr = STAILQ_NEXT(db_tr, link); 2537 } 2538 db = ((struct fwohcidb_tr *)bulkxfer->end)->db; 2539 FWOHCI_DMA_CLEAR(db[0].db.desc.depend, 0xf); 2540 FWOHCI_DMA_CLEAR(db[dbch->ndesc - 1].db.desc.depend, 0xf); 2541 #if 0 /* if bulkxfer->npackets changes */ 2542 db[dbch->ndesc - 1].db.desc.control |= OHCI_INTERRUPT_ALWAYS; 2543 /* OHCI 1.1 and above */ 2544 db[0].db.desc.control |= OHCI_INTERRUPT_ALWAYS; 2545 #endif 2546 /* 2547 db_tr = (struct fwohcidb_tr *)bulkxfer->start; 2548 fdb_tr = (struct fwohcidb_tr *)bulkxfer->end; 2549 device_printf(sc->fc.dev, "DB %08x %3d %08x %08x\n", bulkxfer, bulkxfer->npacket, db_tr->bus_addr, fdb_tr->bus_addr); 2550 */ 2551 return; 2552 } 2553 2554 static int 2555 fwohci_add_tx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr, 2556 int poffset) 2557 { 2558 struct fwohcidb *db = db_tr->db; 2559 struct fw_xferq *it; 2560 int err = 0; 2561 2562 it = &dbch->xferq; 2563 if (it->buf == 0) { 2564 err = EINVAL; 2565 return err; 2566 } 2567 db_tr->buf = fwdma_v_addr(it->buf, poffset); 2568 db_tr->dbcnt = 3; 2569 2570 FWOHCI_DMA_WRITE(db[0].db.desc.cmd, 2571 OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | 8); 2572 FWOHCI_DMA_WRITE(db[0].db.desc.addr, 0); 2573 bzero((void *)&db[1].db.immed[0], sizeof(db[1].db.immed)); 2574 FWOHCI_DMA_WRITE(db[2].db.desc.addr, 2575 fwdma_bus_addr(it->buf, poffset) + sizeof(uint32_t)); 2576 2577 FWOHCI_DMA_WRITE(db[2].db.desc.cmd, 2578 OHCI_OUTPUT_LAST | OHCI_UPDATE | OHCI_BRANCH_ALWAYS); 2579 #if 1 2580 FWOHCI_DMA_WRITE(db[0].db.desc.res, 0); 2581 FWOHCI_DMA_WRITE(db[2].db.desc.res, 0); 2582 #endif 2583 return 0; 2584 } 2585 2586 int 2587 fwohci_add_rx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr, 2588 int poffset, struct fwdma_alloc *dummy_dma) 2589 { 2590 struct fwohcidb *db = db_tr->db; 2591 struct fw_xferq *ir; 2592 int i, ldesc; 2593 bus_addr_t dbuf[2]; 2594 int dsiz[2]; 2595 2596 ir = &dbch->xferq; 2597 if (ir->buf == NULL && (dbch->xferq.flag & FWXFERQ_EXTBUF) == 0) { 2598 if (db_tr->buf == NULL) { 2599 db_tr->buf = fwdma_malloc_size(dbch->dmat, 2600 &db_tr->dma_map, ir->psize, &dbuf[0], 2601 BUS_DMA_NOWAIT); 2602 if (db_tr->buf == NULL) 2603 return (ENOMEM); 2604 } 2605 db_tr->dbcnt = 1; 2606 dsiz[0] = ir->psize; 2607 bus_dmamap_sync(dbch->dmat, db_tr->dma_map, 2608 BUS_DMASYNC_PREREAD); 2609 } else { 2610 db_tr->dbcnt = 0; 2611 if (dummy_dma != NULL) { 2612 dsiz[db_tr->dbcnt] = sizeof(uint32_t); 2613 dbuf[db_tr->dbcnt++] = dummy_dma->bus_addr; 2614 } 2615 dsiz[db_tr->dbcnt] = ir->psize; 2616 if (ir->buf != NULL) { 2617 db_tr->buf = fwdma_v_addr(ir->buf, poffset); 2618 dbuf[db_tr->dbcnt] = fwdma_bus_addr(ir->buf, poffset); 2619 } 2620 db_tr->dbcnt++; 2621 } 2622 for (i = 0; i < db_tr->dbcnt; i++) { 2623 FWOHCI_DMA_WRITE(db[i].db.desc.addr, dbuf[i]); 2624 FWOHCI_DMA_WRITE(db[i].db.desc.cmd, OHCI_INPUT_MORE | dsiz[i]); 2625 if (ir->flag & FWXFERQ_STREAM) { 2626 FWOHCI_DMA_SET(db[i].db.desc.cmd, OHCI_UPDATE); 2627 } 2628 FWOHCI_DMA_WRITE(db[i].db.desc.res, dsiz[i]); 2629 } 2630 ldesc = db_tr->dbcnt - 1; 2631 if (ir->flag & FWXFERQ_STREAM) { 2632 FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, OHCI_INPUT_LAST); 2633 } 2634 FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, OHCI_BRANCH_ALWAYS); 2635 return 0; 2636 } 2637 2638 2639 static int 2640 fwohci_arcv_swap(struct fw_pkt *fp, int len) 2641 { 2642 struct fw_pkt *fp0; 2643 uint32_t ld0; 2644 int slen, hlen; 2645 #if BYTE_ORDER == BIG_ENDIAN 2646 int i; 2647 #endif 2648 2649 ld0 = FWOHCI_DMA_READ(fp->mode.ld[0]); 2650 #if 0 2651 printf("ld0: x%08x\n", ld0); 2652 #endif 2653 fp0 = (struct fw_pkt *)&ld0; 2654 /* determine length to swap */ 2655 switch (fp0->mode.common.tcode) { 2656 case FWTCODE_RREQQ: 2657 case FWTCODE_WRES: 2658 case FWTCODE_WREQQ: 2659 case FWTCODE_RRESQ: 2660 case FWOHCITCODE_PHY: 2661 slen = 12; 2662 break; 2663 case FWTCODE_RREQB: 2664 case FWTCODE_WREQB: 2665 case FWTCODE_LREQ: 2666 case FWTCODE_RRESB: 2667 case FWTCODE_LRES: 2668 slen = 16; 2669 break; 2670 default: 2671 printf("Unknown tcode %d\n", fp0->mode.common.tcode); 2672 return (0); 2673 } 2674 hlen = tinfo[fp0->mode.common.tcode].hdr_len; 2675 if (hlen > len) { 2676 if (firewire_debug) 2677 printf("splitted header\n"); 2678 return (-hlen); 2679 } 2680 #if BYTE_ORDER == BIG_ENDIAN 2681 for (i = 0; i < slen/4; i++) 2682 fp->mode.ld[i] = FWOHCI_DMA_READ(fp->mode.ld[i]); 2683 #endif 2684 return (hlen); 2685 } 2686 2687 static int 2688 fwohci_get_plen(struct fwohci_softc *sc, struct fwohci_dbch *dbch, struct fw_pkt *fp) 2689 { 2690 struct tcode_info *info; 2691 int r; 2692 2693 info = &tinfo[fp->mode.common.tcode]; 2694 r = info->hdr_len + sizeof(uint32_t); 2695 if ((info->flag & FWTI_BLOCK_ASY) != 0) 2696 r += roundup2(fp->mode.wreqb.len, sizeof(uint32_t)); 2697 2698 if (r == sizeof(uint32_t)) { 2699 /* XXX */ 2700 device_printf(sc->fc.dev, "Unknown tcode %d\n", 2701 fp->mode.common.tcode); 2702 return (-1); 2703 } 2704 2705 if (r > dbch->xferq.psize) { 2706 device_printf(sc->fc.dev, "Invalid packet length %d\n", r); 2707 return (-1); 2708 /* panic ? */ 2709 } 2710 2711 return r; 2712 } 2713 2714 static void 2715 fwohci_arcv_free_buf(struct fwohci_softc *sc, struct fwohci_dbch *dbch, 2716 struct fwohcidb_tr *db_tr, uint32_t off, int wake) 2717 { 2718 struct fwohcidb *db = &db_tr->db[0]; 2719 2720 FWOHCI_DMA_CLEAR(db->db.desc.depend, 0xf); 2721 FWOHCI_DMA_WRITE(db->db.desc.res, dbch->xferq.psize); 2722 FWOHCI_DMA_SET(dbch->bottom->db[0].db.desc.depend, 1); 2723 fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREWRITE); 2724 dbch->bottom = db_tr; 2725 2726 if (wake) 2727 OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_WAKE); 2728 } 2729 2730 static void 2731 fwohci_arcv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count) 2732 { 2733 struct fwohcidb_tr *db_tr; 2734 struct iovec vec[2]; 2735 struct fw_pkt pktbuf; 2736 int nvec; 2737 struct fw_pkt *fp; 2738 uint8_t *ld; 2739 uint32_t stat, off, status, event; 2740 u_int spd; 2741 int len, plen, hlen, pcnt, offset; 2742 int s; 2743 caddr_t buf; 2744 int resCount; 2745 2746 if (&sc->arrq == dbch) { 2747 off = OHCI_ARQOFF; 2748 } else if (&sc->arrs == dbch) { 2749 off = OHCI_ARSOFF; 2750 } else { 2751 return; 2752 } 2753 2754 s = splfw(); 2755 db_tr = dbch->top; 2756 pcnt = 0; 2757 /* XXX we cannot handle a packet which lies in more than two buf */ 2758 fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_POSTREAD); 2759 fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_POSTWRITE); 2760 status = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) >> OHCI_STATUS_SHIFT; 2761 resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) & OHCI_COUNT_MASK; 2762 while (status & OHCI_CNTL_DMA_ACTIVE) { 2763 #if 0 2764 2765 if (off == OHCI_ARQOFF) 2766 printf("buf 0x%08x, status 0x%04x, resCount 0x%04x\n", 2767 db_tr->bus_addr, status, resCount); 2768 #endif 2769 len = dbch->xferq.psize - resCount; 2770 ld = (uint8_t *)db_tr->buf; 2771 if (dbch->pdb_tr == NULL) { 2772 len -= dbch->buf_offset; 2773 ld += dbch->buf_offset; 2774 } 2775 if (len > 0) 2776 bus_dmamap_sync(dbch->dmat, db_tr->dma_map, 2777 BUS_DMASYNC_POSTREAD); 2778 while (len > 0) { 2779 if (count >= 0 && count-- == 0) 2780 goto out; 2781 if (dbch->pdb_tr != NULL) { 2782 /* we have a fragment in previous buffer */ 2783 int rlen; 2784 2785 offset = dbch->buf_offset; 2786 if (offset < 0) 2787 offset = - offset; 2788 buf = dbch->pdb_tr->buf + offset; 2789 rlen = dbch->xferq.psize - offset; 2790 if (firewire_debug) 2791 printf("rlen=%d, offset=%d\n", 2792 rlen, dbch->buf_offset); 2793 if (dbch->buf_offset < 0) { 2794 /* splitted in header, pull up */ 2795 char *p; 2796 2797 p = (char *)&pktbuf; 2798 bcopy(buf, p, rlen); 2799 p += rlen; 2800 /* this must be too long but harmless */ 2801 rlen = sizeof(pktbuf) - rlen; 2802 if (rlen < 0) 2803 printf("why rlen < 0\n"); 2804 bcopy(db_tr->buf, p, rlen); 2805 ld += rlen; 2806 len -= rlen; 2807 hlen = fwohci_arcv_swap(&pktbuf, sizeof(pktbuf)); 2808 if (hlen <= 0) { 2809 printf("hlen should be positive."); 2810 goto err; 2811 } 2812 offset = sizeof(pktbuf); 2813 vec[0].iov_base = (char *)&pktbuf; 2814 vec[0].iov_len = offset; 2815 } else { 2816 /* splitted in payload */ 2817 offset = rlen; 2818 vec[0].iov_base = buf; 2819 vec[0].iov_len = rlen; 2820 } 2821 fp=(struct fw_pkt *)vec[0].iov_base; 2822 nvec = 1; 2823 } else { 2824 /* no fragment in previous buffer */ 2825 fp=(struct fw_pkt *)ld; 2826 hlen = fwohci_arcv_swap(fp, len); 2827 if (hlen == 0) 2828 goto err; 2829 if (hlen < 0) { 2830 dbch->pdb_tr = db_tr; 2831 dbch->buf_offset = - dbch->buf_offset; 2832 /* sanity check */ 2833 if (resCount != 0) { 2834 printf("resCount=%d hlen=%d\n", 2835 resCount, hlen); 2836 goto err; 2837 } 2838 goto out; 2839 } 2840 offset = 0; 2841 nvec = 0; 2842 } 2843 plen = fwohci_get_plen(sc, dbch, fp) - offset; 2844 if (plen < 0) { 2845 /* minimum header size + trailer 2846 = sizeof(fw_pkt) so this shouldn't happens */ 2847 printf("plen(%d) is negative! offset=%d\n", 2848 plen, offset); 2849 goto err; 2850 } 2851 if (plen > 0) { 2852 len -= plen; 2853 if (len < 0) { 2854 dbch->pdb_tr = db_tr; 2855 if (firewire_debug) 2856 printf("splitted payload\n"); 2857 /* sanity check */ 2858 if (resCount != 0) { 2859 printf("resCount=%d plen=%d" 2860 " len=%d\n", 2861 resCount, plen, len); 2862 goto err; 2863 } 2864 goto out; 2865 } 2866 vec[nvec].iov_base = ld; 2867 vec[nvec].iov_len = plen; 2868 nvec++; 2869 ld += plen; 2870 } 2871 dbch->buf_offset = ld - (uint8_t *)db_tr->buf; 2872 if (nvec == 0) 2873 printf("nvec == 0\n"); 2874 2875 /* DMA result-code will be written at the tail of packet */ 2876 stat = FWOHCI_DMA_READ(*(uint32_t *)(ld - sizeof(struct fwohci_trailer))); 2877 #if 0 2878 printf("plen: %d, stat %x\n", 2879 plen ,stat); 2880 #endif 2881 spd = (stat >> 21) & 0x3; 2882 event = (stat >> 16) & 0x1f; 2883 switch (event) { 2884 case FWOHCIEV_ACKPEND: 2885 #if 0 2886 printf("fwohci_arcv: ack pending tcode=0x%x..\n", fp->mode.common.tcode); 2887 #endif 2888 /* fall through */ 2889 case FWOHCIEV_ACKCOMPL: 2890 { 2891 struct fw_rcv_buf rb; 2892 2893 if ((vec[nvec-1].iov_len -= 2894 sizeof(struct fwohci_trailer)) == 0) 2895 nvec--; 2896 rb.fc = &sc->fc; 2897 rb.vec = vec; 2898 rb.nvec = nvec; 2899 rb.spd = spd; 2900 fw_rcv(&rb); 2901 break; 2902 } 2903 case FWOHCIEV_BUSRST: 2904 if ((sc->fc.status != FWBUSRESET) && 2905 (sc->fc.status != FWBUSINIT)) 2906 printf("got BUSRST packet!?\n"); 2907 break; 2908 default: 2909 device_printf(sc->fc.dev, 2910 "Async DMA Receive error err=%02x %s" 2911 " plen=%d offset=%d len=%d status=0x%08x" 2912 " tcode=0x%x, stat=0x%08x\n", 2913 event, fwohcicode[event], plen, 2914 dbch->buf_offset, len, 2915 OREAD(sc, OHCI_DMACTL(off)), 2916 fp->mode.common.tcode, stat); 2917 #if 1 /* XXX */ 2918 goto err; 2919 #endif 2920 break; 2921 } 2922 pcnt++; 2923 if (dbch->pdb_tr != NULL) { 2924 fwohci_arcv_free_buf(sc, dbch, dbch->pdb_tr, 2925 off, 1); 2926 dbch->pdb_tr = NULL; 2927 } 2928 2929 } 2930 out: 2931 if (resCount == 0) { 2932 /* done on this buffer */ 2933 if (dbch->pdb_tr == NULL) { 2934 fwohci_arcv_free_buf(sc, dbch, db_tr, off, 1); 2935 dbch->buf_offset = 0; 2936 } else 2937 if (dbch->pdb_tr != db_tr) 2938 printf("pdb_tr != db_tr\n"); 2939 db_tr = STAILQ_NEXT(db_tr, link); 2940 status = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) 2941 >> OHCI_STATUS_SHIFT; 2942 resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) 2943 & OHCI_COUNT_MASK; 2944 /* XXX check buffer overrun */ 2945 dbch->top = db_tr; 2946 } else { 2947 dbch->buf_offset = dbch->xferq.psize - resCount; 2948 break; 2949 } 2950 /* XXX make sure DMA is not dead */ 2951 } 2952 #if 0 2953 if (pcnt < 1) 2954 printf("fwohci_arcv: no packets\n"); 2955 #endif 2956 splx(s); 2957 return; 2958 2959 err: 2960 device_printf(sc->fc.dev, "AR DMA status=%x, ", 2961 OREAD(sc, OHCI_DMACTL(off))); 2962 dbch->pdb_tr = NULL; 2963 /* skip until resCount != 0 */ 2964 printf(" skip buffer"); 2965 while (resCount == 0) { 2966 printf(" #"); 2967 fwohci_arcv_free_buf(sc, dbch, db_tr, off, 0); 2968 db_tr = STAILQ_NEXT(db_tr, link); 2969 resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) 2970 & OHCI_COUNT_MASK; 2971 } 2972 printf(" done\n"); 2973 dbch->top = db_tr; 2974 dbch->buf_offset = dbch->xferq.psize - resCount; 2975 OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_WAKE); 2976 splx(s); 2977 } 2978