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