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