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