fwohci.c revision 108276
1/* 2 * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the acknowledgement as bellow: 15 * 16 * This product includes software developed by K. Kobayashi and H. Shimokawa 17 * 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 * 33 * $FreeBSD: head/sys/dev/firewire/fwohci.c 108276 2002-12-26 03:17:59Z simokawa $ 34 * 35 */ 36 37#define ATRQ_CH 0 38#define ATRS_CH 1 39#define ARRQ_CH 2 40#define ARRS_CH 3 41#define ITX_CH 4 42#define IRX_CH 0x24 43 44#include <sys/param.h> 45#include <sys/systm.h> 46#include <sys/types.h> 47#include <sys/mbuf.h> 48#include <sys/mman.h> 49#include <sys/socket.h> 50#include <sys/socketvar.h> 51#include <sys/signalvar.h> 52#include <sys/malloc.h> 53#include <sys/uio.h> 54#include <sys/sockio.h> 55#include <sys/bus.h> 56#include <sys/kernel.h> 57#include <sys/conf.h> 58 59#include <machine/bus.h> 60#include <machine/resource.h> 61#include <sys/rman.h> 62 63#include <machine/cpufunc.h> /* for rdtsc proto for clock.h below */ 64#include <machine/clock.h> 65#include <pci/pcivar.h> 66#include <pci/pcireg.h> 67#include <vm/vm.h> 68#include <vm/vm_extern.h> 69#include <vm/pmap.h> /* for vtophys proto */ 70 71#include <dev/firewire/firewire.h> 72#include <dev/firewire/firewirebusreg.h> 73#include <dev/firewire/firewirereg.h> 74#include <dev/firewire/fwohcireg.h> 75#include <dev/firewire/fwohcivar.h> 76#include <dev/firewire/firewire_phy.h> 77 78#undef OHCI_DEBUG 79 80static char dbcode[16][0x10]={"OUTM", "OUTL","INPM","INPL", 81 "STOR","LOAD","NOP ","STOP",}; 82static char dbkey[8][0x10]={"ST0", "ST1","ST2","ST3", 83 "UNDEF","REG","SYS","DEV"}; 84char fwohcicode[32][0x20]={ 85 "No stat","Undef","long","miss Ack err", 86 "underrun","overrun","desc err", "data read err", 87 "data write err","bus reset","timeout","tcode err", 88 "Undef","Undef","unknown event","flushed", 89 "Undef","ack complete","ack pend","Undef", 90 "ack busy_X","ack busy_A","ack busy_B","Undef", 91 "Undef","Undef","Undef","ack tardy", 92 "Undef","ack data_err","ack type_err",""}; 93#define MAX_SPEED 2 94extern char linkspeed[MAX_SPEED+1][0x10]; 95extern int maxrec[MAX_SPEED+1]; 96static char dbcond[4][0x10]={"NEV","C=1", "C=0", "ALL"}; 97u_int32_t tagbit[4] = { 1 << 28, 1 << 29, 1 << 30, 1 << 31}; 98 99static struct tcode_info tinfo[] = { 100/* hdr_len block flag*/ 101/* 0 WREQQ */ {16, FWTI_REQ | FWTI_TLABEL}, 102/* 1 WREQB */ {16, FWTI_REQ | FWTI_TLABEL | FWTI_BLOCK_ASY}, 103/* 2 WRES */ {12, FWTI_RES}, 104/* 3 XXX */ { 0, 0}, 105/* 4 RREQQ */ {12, FWTI_REQ | FWTI_TLABEL}, 106/* 5 RREQB */ {16, FWTI_REQ | FWTI_TLABEL}, 107/* 6 RRESQ */ {16, FWTI_RES}, 108/* 7 RRESB */ {16, FWTI_RES | FWTI_BLOCK_ASY}, 109/* 8 CYCS */ { 0, 0}, 110/* 9 LREQ */ {16, FWTI_REQ | FWTI_TLABEL | FWTI_BLOCK_ASY}, 111/* a STREAM */ { 4, FWTI_REQ | FWTI_BLOCK_STR}, 112/* b LRES */ {16, FWTI_RES | FWTI_BLOCK_ASY}, 113/* c XXX */ { 0, 0}, 114/* d XXX */ { 0, 0}, 115/* e PHY */ {12, FWTI_REQ}, 116/* f XXX */ { 0, 0} 117}; 118 119#define OHCI_WRITE_SIGMASK 0xffff0000 120#define OHCI_READ_SIGMASK 0xffff0000 121 122#define OWRITE(sc, r, x) bus_space_write_4((sc)->bst, (sc)->bsh, (r), (x)) 123#define OREAD(sc, r) bus_space_read_4((sc)->bst, (sc)->bsh, (r)) 124 125static void fwohci_ibr __P((struct firewire_comm *)); 126static void fwohci_db_init __P((struct fwohci_dbch *)); 127static void fwohci_db_free __P((struct fwohci_dbch *)); 128static void fwohci_arcv __P((struct fwohci_softc *, struct fwohci_dbch *, int)); 129static void fwohci_ircv __P((struct fwohci_softc *, struct fwohci_dbch *, int)); 130static void fwohci_txd __P((struct fwohci_softc *, struct fwohci_dbch *)); 131static void fwohci_start_atq __P((struct firewire_comm *)); 132static void fwohci_start_ats __P((struct firewire_comm *)); 133static void fwohci_start __P((struct fwohci_softc *, struct fwohci_dbch *)); 134static void fwohci_drain_atq __P((struct firewire_comm *, struct fw_xfer *)); 135static void fwohci_drain_ats __P((struct firewire_comm *, struct fw_xfer *)); 136static void fwohci_drain __P((struct firewire_comm *, struct fw_xfer *, struct fwohci_dbch *)); 137static u_int32_t fwphy_wrdata __P(( struct fwohci_softc *, u_int32_t, u_int32_t)); 138static u_int32_t fwphy_rddata __P(( struct fwohci_softc *, u_int32_t)); 139static int fwohci_rx_enable __P((struct fwohci_softc *, struct fwohci_dbch *)); 140static int fwohci_tx_enable __P((struct fwohci_softc *, struct fwohci_dbch *)); 141static int fwohci_irx_enable __P((struct firewire_comm *, int)); 142static int fwohci_irxpp_enable __P((struct firewire_comm *, int)); 143static int fwohci_irxbuf_enable __P((struct firewire_comm *, int)); 144static int fwohci_irx_disable __P((struct firewire_comm *, int)); 145static void fwohci_irx_post __P((struct firewire_comm *, u_int32_t *)); 146static int fwohci_itxbuf_enable __P((struct firewire_comm *, int)); 147static int fwohci_itx_disable __P((struct firewire_comm *, int)); 148static void fwohci_timeout __P((void *)); 149static void fwohci_poll __P((struct firewire_comm *, int, int)); 150static void fwohci_set_intr __P((struct firewire_comm *, int)); 151static int fwohci_add_rx_buf __P((struct fwohcidb_tr *, unsigned short, int, void *, void *)); 152static int fwohci_add_tx_buf __P((struct fwohcidb_tr *, unsigned short, int, void *)); 153static void dump_db __P((struct fwohci_softc *, u_int32_t)); 154static void print_db __P((volatile struct fwohcidb *, u_int32_t , u_int32_t)); 155static void dump_dma __P((struct fwohci_softc *, u_int32_t)); 156static u_int32_t fwohci_cyctimer __P((struct firewire_comm *)); 157static void fwohci_rbuf_update __P((struct fwohci_softc *, int)); 158static void fwohci_tbuf_update __P((struct fwohci_softc *, int)); 159void fwohci_txbufdb __P((struct fwohci_softc *, int , struct fw_bulkxfer *)); 160 161/* 162 * memory allocated for DMA programs 163 */ 164#define DMA_PROG_ALLOC (8 * PAGE_SIZE) 165 166/* #define NDB 1024 */ 167#define NDB FWMAXQUEUE 168#define NDVDB (DVBUF * NDB) 169 170#define OHCI_VERSION 0x00 171#define OHCI_CROMHDR 0x18 172#define OHCI_BUS_OPT 0x20 173#define OHCI_BUSIRMC (1 << 31) 174#define OHCI_BUSCMC (1 << 30) 175#define OHCI_BUSISC (1 << 29) 176#define OHCI_BUSBMC (1 << 28) 177#define OHCI_BUSPMC (1 << 27) 178#define OHCI_BUSFNC OHCI_BUSIRMC | OHCI_BUSCMC | OHCI_BUSISC |\ 179 OHCI_BUSBMC | OHCI_BUSPMC 180 181#define OHCI_EUID_HI 0x24 182#define OHCI_EUID_LO 0x28 183 184#define OHCI_CROMPTR 0x34 185#define OHCI_HCCCTL 0x50 186#define OHCI_HCCCTLCLR 0x54 187#define OHCI_AREQHI 0x100 188#define OHCI_AREQHICLR 0x104 189#define OHCI_AREQLO 0x108 190#define OHCI_AREQLOCLR 0x10c 191#define OHCI_PREQHI 0x110 192#define OHCI_PREQHICLR 0x114 193#define OHCI_PREQLO 0x118 194#define OHCI_PREQLOCLR 0x11c 195#define OHCI_PREQUPPER 0x120 196 197#define OHCI_SID_BUF 0x64 198#define OHCI_SID_CNT 0x68 199#define OHCI_SID_CNT_MASK 0xffc 200 201#define OHCI_IT_STAT 0x90 202#define OHCI_IT_STATCLR 0x94 203#define OHCI_IT_MASK 0x98 204#define OHCI_IT_MASKCLR 0x9c 205 206#define OHCI_IR_STAT 0xa0 207#define OHCI_IR_STATCLR 0xa4 208#define OHCI_IR_MASK 0xa8 209#define OHCI_IR_MASKCLR 0xac 210 211#define OHCI_LNKCTL 0xe0 212#define OHCI_LNKCTLCLR 0xe4 213 214#define OHCI_PHYACCESS 0xec 215#define OHCI_CYCLETIMER 0xf0 216 217#define OHCI_DMACTL(off) (off) 218#define OHCI_DMACTLCLR(off) (off + 4) 219#define OHCI_DMACMD(off) (off + 0xc) 220#define OHCI_DMAMATCH(off) (off + 0x10) 221 222#define OHCI_ATQOFF 0x180 223#define OHCI_ATQCTL OHCI_ATQOFF 224#define OHCI_ATQCTLCLR (OHCI_ATQOFF + 4) 225#define OHCI_ATQCMD (OHCI_ATQOFF + 0xc) 226#define OHCI_ATQMATCH (OHCI_ATQOFF + 0x10) 227 228#define OHCI_ATSOFF 0x1a0 229#define OHCI_ATSCTL OHCI_ATSOFF 230#define OHCI_ATSCTLCLR (OHCI_ATSOFF + 4) 231#define OHCI_ATSCMD (OHCI_ATSOFF + 0xc) 232#define OHCI_ATSMATCH (OHCI_ATSOFF + 0x10) 233 234#define OHCI_ARQOFF 0x1c0 235#define OHCI_ARQCTL OHCI_ARQOFF 236#define OHCI_ARQCTLCLR (OHCI_ARQOFF + 4) 237#define OHCI_ARQCMD (OHCI_ARQOFF + 0xc) 238#define OHCI_ARQMATCH (OHCI_ARQOFF + 0x10) 239 240#define OHCI_ARSOFF 0x1e0 241#define OHCI_ARSCTL OHCI_ARSOFF 242#define OHCI_ARSCTLCLR (OHCI_ARSOFF + 4) 243#define OHCI_ARSCMD (OHCI_ARSOFF + 0xc) 244#define OHCI_ARSMATCH (OHCI_ARSOFF + 0x10) 245 246#define OHCI_ITOFF(CH) (0x200 + 0x10 * (CH)) 247#define OHCI_ITCTL(CH) (OHCI_ITOFF(CH)) 248#define OHCI_ITCTLCLR(CH) (OHCI_ITOFF(CH) + 4) 249#define OHCI_ITCMD(CH) (OHCI_ITOFF(CH) + 0xc) 250 251#define OHCI_IROFF(CH) (0x400 + 0x20 * (CH)) 252#define OHCI_IRCTL(CH) (OHCI_IROFF(CH)) 253#define OHCI_IRCTLCLR(CH) (OHCI_IROFF(CH) + 4) 254#define OHCI_IRCMD(CH) (OHCI_IROFF(CH) + 0xc) 255#define OHCI_IRMATCH(CH) (OHCI_IROFF(CH) + 0x10) 256 257d_ioctl_t fwohci_ioctl; 258 259/* 260 * Communication with PHY device 261 */ 262static u_int32_t 263fwphy_wrdata( struct fwohci_softc *sc, u_int32_t addr, u_int32_t data) 264{ 265 u_int32_t fun; 266 267 addr &= 0xf; 268 data &= 0xff; 269 270 fun = (PHYDEV_WRCMD | (addr << PHYDEV_REGADDR) | (data << PHYDEV_WRDATA)); 271 OWRITE(sc, OHCI_PHYACCESS, fun); 272 DELAY(100); 273 274 return(fwphy_rddata( sc, addr)); 275} 276 277static u_int32_t 278fwohci_set_bus_manager(struct firewire_comm *fc, u_int node) 279{ 280 struct fwohci_softc *sc = (struct fwohci_softc *)fc; 281 int i; 282 u_int32_t bm; 283 284#define OHCI_CSR_DATA 0x0c 285#define OHCI_CSR_COMP 0x10 286#define OHCI_CSR_CONT 0x14 287#define OHCI_BUS_MANAGER_ID 0 288 289 OWRITE(sc, OHCI_CSR_DATA, node); 290 OWRITE(sc, OHCI_CSR_COMP, 0x3f); 291 OWRITE(sc, OHCI_CSR_CONT, OHCI_BUS_MANAGER_ID); 292 for (i = 0; !(OREAD(sc, OHCI_CSR_CONT) & (1<<31)) && (i < 1000); i++) 293 DELAY(100); 294 bm = OREAD(sc, OHCI_CSR_DATA); 295 if((bm & 0x3f) == 0x3f) 296 bm = node; 297 if (bootverbose) 298 device_printf(sc->fc.dev, 299 "fw_set_bus_manager: %d->%d (loop=%d)\n", bm, node, i); 300 301 return(bm); 302} 303 304static u_int32_t 305fwphy_rddata(struct fwohci_softc *sc, u_int addr) 306{ 307 u_int32_t fun; 308 u_int i; 309 310 addr &= 0xf; 311 fun = PHYDEV_RDCMD | (addr << PHYDEV_REGADDR); 312 OWRITE(sc, OHCI_PHYACCESS, fun); 313#if 1 314 /* Make sure that SCLK is started */ 315 for(i = 0; i < 1000; i++) { 316 if ((OREAD(sc, FWOHCI_INTSTAT) & OHCI_INT_REG_FAIL) == 0) 317 break; 318 DELAY(100); 319 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_REG_FAIL); 320 OWRITE(sc, OHCI_PHYACCESS, fun); 321 } 322 if (bootverbose) 323 device_printf(sc->fc.dev, "fwphy_rddata: write loop=%d\n", i); 324#endif 325 for ( i = 0 ; i < 1000 ; i ++ ){ 326 fun = OREAD(sc, OHCI_PHYACCESS); 327 if ((fun & PHYDEV_RDCMD) == 0 && (fun & PHYDEV_RDDONE) != 0) 328 break; 329 DELAY(1000); 330 } 331 if( i >= 1000) 332 device_printf(sc->fc.dev, "cannot read phy\n"); 333 return((fun >> PHYDEV_RDDATA )& 0xff); 334} 335/* Device specific ioctl. */ 336int 337fwohci_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td) 338{ 339 struct firewire_softc *sc; 340 struct fwohci_softc *fc; 341 int unit = DEV2UNIT(dev); 342 int err = 0; 343 struct fw_reg_req_t *reg = (struct fw_reg_req_t *) data; 344 u_int32_t *dmach = (u_int32_t *) data; 345 346 sc = devclass_get_softc(firewire_devclass, unit); 347 if(sc == NULL){ 348 return(EINVAL); 349 } 350 fc = (struct fwohci_softc *)sc->fc; 351 352 if (!data) 353 return(EINVAL); 354 355 switch (cmd) { 356 case FWOHCI_WRREG: 357#define OHCI_MAX_REG 0x800 358 if(reg->addr <= OHCI_MAX_REG){ 359 OWRITE(fc, reg->addr, reg->data); 360 reg->data = OREAD(fc, reg->addr); 361 }else{ 362 err = EINVAL; 363 } 364 break; 365 case FWOHCI_RDREG: 366 if(reg->addr <= OHCI_MAX_REG){ 367 reg->data = OREAD(fc, reg->addr); 368 }else{ 369 err = EINVAL; 370 } 371 break; 372/* Read DMA descriptors for debug */ 373 case DUMPDMA: 374 if(*dmach <= OHCI_MAX_DMA_CH ){ 375 dump_dma(fc, *dmach); 376 dump_db(fc, *dmach); 377 }else{ 378 err = EINVAL; 379 } 380 break; 381 default: 382 break; 383 } 384 return err; 385} 386 387int 388fwohci_init(struct fwohci_softc *sc, device_t dev) 389{ 390 int err = 0; 391 int i; 392 u_int32_t reg, reg2; 393 struct fwohcidb_tr *db_tr; 394 int e1394a = 1; 395 396 reg = OREAD(sc, OHCI_VERSION); 397 device_printf(dev, "OHCI version %x.%x (ROM=%d)\n", 398 (reg>>16) & 0xff, reg & 0xff, (reg>>24) & 1); 399 400/* XXX: Available Isochrounous DMA channel probe */ 401 for( i = 0 ; i < 0x20 ; i ++ ){ 402 OWRITE(sc, OHCI_IRCTL(i), OHCI_CNTL_DMA_RUN); 403 reg = OREAD(sc, OHCI_IRCTL(i)); 404 if(!(reg & OHCI_CNTL_DMA_RUN)) break; 405 OWRITE(sc, OHCI_ITCTL(i), OHCI_CNTL_DMA_RUN); 406 reg = OREAD(sc, OHCI_ITCTL(i)); 407 if(!(reg & OHCI_CNTL_DMA_RUN)) break; 408 } 409 sc->fc.nisodma = i; 410 device_printf(dev, "No. of Isochronous channel is %d.\n", i); 411 412 sc->fc.arq = &sc->arrq.xferq; 413 sc->fc.ars = &sc->arrs.xferq; 414 sc->fc.atq = &sc->atrq.xferq; 415 sc->fc.ats = &sc->atrs.xferq; 416 417 sc->arrq.xferq.start = NULL; 418 sc->arrs.xferq.start = NULL; 419 sc->atrq.xferq.start = fwohci_start_atq; 420 sc->atrs.xferq.start = fwohci_start_ats; 421 422 sc->arrq.xferq.drain = NULL; 423 sc->arrs.xferq.drain = NULL; 424 sc->atrq.xferq.drain = fwohci_drain_atq; 425 sc->atrs.xferq.drain = fwohci_drain_ats; 426 427 sc->arrq.ndesc = 1; 428 sc->arrs.ndesc = 1; 429 sc->atrq.ndesc = 10; 430 sc->atrs.ndesc = 10 / 2; 431 432 sc->arrq.ndb = NDB; 433 sc->arrs.ndb = NDB / 2; 434 sc->atrq.ndb = NDB; 435 sc->atrs.ndb = NDB / 2; 436 437 sc->arrq.dummy = NULL; 438 sc->arrs.dummy = NULL; 439 sc->atrq.dummy = NULL; 440 sc->atrs.dummy = NULL; 441 for( i = 0 ; i < sc->fc.nisodma ; i ++ ){ 442 sc->fc.it[i] = &sc->it[i].xferq; 443 sc->fc.ir[i] = &sc->ir[i].xferq; 444 sc->it[i].ndb = 0; 445 sc->ir[i].ndb = 0; 446 } 447 448 sc->fc.tcode = tinfo; 449 450 sc->cromptr = (u_int32_t *) 451 contigmalloc(CROMSIZE * 2, M_DEVBUF, M_NOWAIT, 0, ~0, 1<<10, 0); 452 453 if(sc->cromptr == NULL){ 454 return ENOMEM; 455 } 456 sc->fc.dev = dev; 457 sc->fc.config_rom = &(sc->cromptr[CROMSIZE/4]); 458 459 sc->fc.config_rom[1] = 0x31333934; 460 sc->fc.config_rom[2] = 0xf000a002; 461 sc->fc.config_rom[3] = OREAD(sc, OHCI_EUID_HI); 462 sc->fc.config_rom[4] = OREAD(sc, OHCI_EUID_LO); 463 sc->fc.config_rom[5] = 0; 464 sc->fc.config_rom[0] = (4 << 24) | (5 << 16); 465 466 sc->fc.config_rom[0] |= fw_crc16(&sc->fc.config_rom[1], 5*4); 467 468 469 fw_init(&sc->fc); 470 471/* Disable interrupt */ 472 OWRITE(sc, FWOHCI_INTMASKCLR, ~0); 473 474/* Now stopping all DMA channel */ 475 OWRITE(sc, OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN); 476 OWRITE(sc, OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN); 477 OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN); 478 OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN); 479 480 OWRITE(sc, OHCI_IR_MASKCLR, ~0); 481 for( i = 0 ; i < sc->fc.nisodma ; i ++ ){ 482 OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN); 483 OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN); 484 } 485 486/* FLUSH FIFO and reset Transmitter/Reciever */ 487 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_RESET); 488 if (bootverbose) 489 device_printf(dev, "resetting OHCI..."); 490 i = 0; 491 while(OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_RESET) { 492 if (i++ > 100) break; 493 DELAY(1000); 494 } 495 if (bootverbose) 496 printf("done (loop=%d)\n", i); 497 498 reg = OREAD(sc, OHCI_BUS_OPT); 499 reg2 = reg | OHCI_BUSFNC; 500 /* XXX */ 501 if (((reg & 0x0000f000) >> 12) < 10) 502 reg2 = (reg2 & 0xffff0fff) | (10 << 12); 503 if (bootverbose) 504 device_printf(dev, "BUS_OPT 0x%x -> 0x%x\n", reg, reg2); 505 OWRITE(sc, OHCI_BUS_OPT, reg2); 506 507 OWRITE(sc, OHCI_CROMHDR, sc->fc.config_rom[0]); 508 OWRITE(sc, OHCI_CROMPTR, vtophys(&sc->fc.config_rom[0])); 509 OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_BIGEND); 510 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_POSTWR); 511 512/* 513 * probe PHY parameters 514 * 0. to prove PHY version, whether compliance of 1394a. 515 * 1. to probe maximum speed supported by the PHY and 516 * number of port supported by core-logic. 517 * It is not actually available port on your PC . 518 */ 519 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LPS); 520#if 0 521 /* XXX wait for SCLK. */ 522 DELAY(100000); 523#endif 524 reg = fwphy_rddata(sc, FW_PHY_SPD_REG); 525 526 if((reg >> 5) != 7 ){ 527 sc->fc.mode &= ~FWPHYASYST; 528 sc->fc.nport = reg & FW_PHY_NP; 529 sc->fc.speed = reg & FW_PHY_SPD >> 6; 530 if (sc->fc.speed > MAX_SPEED) { 531 device_printf(dev, "invalid speed %d (fixed to %d).\n", 532 sc->fc.speed, MAX_SPEED); 533 sc->fc.speed = MAX_SPEED; 534 } 535 sc->fc.maxrec = maxrec[sc->fc.speed]; 536 device_printf(dev, 537 "Link 1394 only %s, %d ports, maxrec %d bytes.\n", 538 linkspeed[sc->fc.speed], sc->fc.nport, sc->fc.maxrec); 539 }else{ 540 reg2 = fwphy_rddata(sc, FW_PHY_ESPD_REG); 541 sc->fc.mode |= FWPHYASYST; 542 sc->fc.nport = reg & FW_PHY_NP; 543 sc->fc.speed = (reg2 & FW_PHY_ESPD) >> 5; 544 if (sc->fc.speed > MAX_SPEED) { 545 device_printf(dev, "invalid speed %d (fixed to %d).\n", 546 sc->fc.speed, MAX_SPEED); 547 sc->fc.speed = MAX_SPEED; 548 } 549 sc->fc.maxrec = maxrec[sc->fc.speed]; 550 device_printf(dev, 551 "Link 1394a available %s, %d ports, maxrec %d bytes.\n", 552 linkspeed[sc->fc.speed], sc->fc.nport, sc->fc.maxrec); 553 554 /* check programPhyEnable */ 555 reg2 = fwphy_rddata(sc, 5); 556#if 0 557 if (e1394a && (OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_PRPHY)) { 558#else /* XXX force to enable 1394a */ 559 if (e1394a) { 560#endif 561 if (bootverbose) 562 device_printf(dev, 563 "Enable 1394a Enhancements\n"); 564 /* enable EAA EMC */ 565 reg2 |= 0x03; 566 /* set aPhyEnhanceEnable */ 567 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_PHYEN); 568 OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_PRPHY); 569 } else { 570 /* for safe */ 571 reg2 &= ~0x83; 572 } 573 reg2 = fwphy_wrdata(sc, 5, reg2); 574 } 575 576 reg = fwphy_rddata(sc, FW_PHY_SPD_REG); 577 if((reg >> 5) == 7 ){ 578 reg = fwphy_rddata(sc, 4); 579 reg |= 1 << 6; 580 fwphy_wrdata(sc, 4, reg); 581 reg = fwphy_rddata(sc, 4); 582 } 583 584/* SID recieve buffer must allign 2^11 */ 585#define OHCI_SIDSIZE (1 << 11) 586 sc->fc.sid_buf = (u_int32_t *) vm_page_alloc_contig( OHCI_SIDSIZE, 587 0x10000, 0xffffffff, OHCI_SIDSIZE); 588 OWRITE(sc, OHCI_SID_BUF, vtophys(sc->fc.sid_buf)); 589 sc->fc.sid_buf++; 590 OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_SID); 591 592 fwohci_db_init(&sc->arrq); 593 fwohci_db_init(&sc->arrs); 594 595 fwohci_db_init(&sc->atrq); 596 fwohci_db_init(&sc->atrs); 597 598 reg = OREAD(sc, FWOHCIGUID_H); 599 for( i = 0 ; i < 4 ; i ++){ 600 sc->fc.eui[3 - i] = reg & 0xff; 601 reg = reg >> 8; 602 } 603 reg = OREAD(sc, FWOHCIGUID_L); 604 for( i = 0 ; i < 4 ; i ++){ 605 sc->fc.eui[7 - i] = reg & 0xff; 606 reg = reg >> 8; 607 } 608 device_printf(dev, "EUI64 %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", 609 sc->fc.eui[0], sc->fc.eui[1], sc->fc.eui[2], sc->fc.eui[3], 610 sc->fc.eui[4], sc->fc.eui[5], sc->fc.eui[6], sc->fc.eui[7]); 611 sc->fc.ioctl = fwohci_ioctl; 612 sc->fc.cyctimer = fwohci_cyctimer; 613 sc->fc.set_bmr = fwohci_set_bus_manager; 614 sc->fc.ibr = fwohci_ibr; 615 sc->fc.irx_enable = fwohci_irx_enable; 616 sc->fc.irx_disable = fwohci_irx_disable; 617 618 sc->fc.itx_enable = fwohci_itxbuf_enable; 619 sc->fc.itx_disable = fwohci_itx_disable; 620 sc->fc.irx_post = fwohci_irx_post; 621 sc->fc.itx_post = NULL; 622 sc->fc.timeout = fwohci_timeout; 623 sc->fc.poll = fwohci_poll; 624 sc->fc.set_intr = fwohci_set_intr; 625 626 /* enable link */ 627 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LINKEN); 628 fw_busreset(&sc->fc); 629 fwohci_rx_enable(sc, &sc->arrq); 630 fwohci_rx_enable(sc, &sc->arrs); 631 632 for( i = 0, db_tr = sc->atrq.top; i < sc->atrq.ndb ; 633 i ++, db_tr = STAILQ_NEXT(db_tr, link)){ 634 db_tr->xfer = NULL; 635 } 636 for( i = 0, db_tr = sc->atrs.top; i < sc->atrs.ndb ; 637 i ++, db_tr = STAILQ_NEXT(db_tr, link)){ 638 db_tr->xfer = NULL; 639 } 640 sc->atrq.flags = sc->atrs.flags = 0; 641 642 OWRITE(sc, FWOHCI_RETRY, 643 (0xffff << 16 )| (0x0f << 8) | (0x0f << 4) | 0x0f) ; 644 OWRITE(sc, FWOHCI_INTMASK, 645 OHCI_INT_ERR | OHCI_INT_PHY_SID 646 | OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS 647 | OHCI_INT_DMA_PRRQ | OHCI_INT_DMA_PRRS 648 | OHCI_INT_PHY_BUS_R | OHCI_INT_PW_ERR); 649 fwohci_set_intr(&sc->fc, 1); 650 651 OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD); 652 OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD); 653 654 return err; 655} 656 657void 658fwohci_timeout(void *arg) 659{ 660 struct fwohci_softc *sc; 661 662 sc = (struct fwohci_softc *)arg; 663 sc->fc.timeouthandle = timeout(fwohci_timeout, 664 (void *)sc, FW_XFERTIMEOUT * hz * 10); 665} 666 667u_int32_t 668fwohci_cyctimer(struct firewire_comm *fc) 669{ 670 struct fwohci_softc *sc = (struct fwohci_softc *)fc; 671 return(OREAD(sc, OHCI_CYCLETIMER)); 672} 673 674#define LAST_DB(dbtr, db) do { \ 675 struct fwohcidb_tr *_dbtr = (dbtr); \ 676 int _cnt = _dbtr->dbcnt; \ 677 db = &_dbtr->db[ (_cnt > 2) ? (_cnt -1) : 0]; \ 678} while (0) 679 680static void 681fwohci_start(struct fwohci_softc *sc, struct fwohci_dbch *dbch) 682{ 683 int i, s; 684 int tcode, hdr_len, hdr_off, len; 685 int fsegment = -1; 686 u_int32_t off; 687 struct fw_xfer *xfer; 688 struct fw_pkt *fp; 689 volatile struct fwohci_txpkthdr *ohcifp; 690 struct fwohcidb_tr *db_tr; 691 volatile struct fwohcidb *db; 692 struct mbuf *m; 693 struct tcode_info *info; 694 695 if(&sc->atrq == dbch){ 696 off = OHCI_ATQOFF; 697 }else if(&sc->atrs == dbch){ 698 off = OHCI_ATSOFF; 699 }else{ 700 return; 701 } 702 703 if (dbch->flags & FWOHCI_DBCH_FULL) 704 return; 705 706 s = splfw(); 707 db_tr = dbch->top; 708txloop: 709 xfer = STAILQ_FIRST(&dbch->xferq.q); 710 if(xfer == NULL){ 711 goto kick; 712 } 713 if(dbch->xferq.queued == 0 ){ 714 device_printf(sc->fc.dev, "TX queue empty\n"); 715 } 716 STAILQ_REMOVE_HEAD(&dbch->xferq.q, link); 717 db_tr->xfer = xfer; 718 xfer->state = FWXF_START; 719 dbch->xferq.packets++; 720 721 fp = (struct fw_pkt *)(xfer->send.buf + xfer->send.off); 722 tcode = fp->mode.common.tcode; 723 724 ohcifp = (volatile struct fwohci_txpkthdr *) db_tr->db[1].db.immed; 725 info = &tinfo[tcode]; 726 hdr_len = hdr_off = info->hdr_len; 727 /* fw_asyreq must pass valid send.len */ 728 len = xfer->send.len; 729 for( i = 0 ; i < hdr_off ; i+= 4){ 730 ohcifp->mode.ld[i/4] = ntohl(fp->mode.ld[i/4]); 731 } 732 ohcifp->mode.common.spd = xfer->spd; 733 if (tcode == FWTCODE_STREAM ){ 734 hdr_len = 8; 735 ohcifp->mode.stream.len = ntohs(fp->mode.stream.len); 736 } else if (tcode == FWTCODE_PHY) { 737 hdr_len = 12; 738 ohcifp->mode.ld[1] = ntohl(fp->mode.ld[1]); 739 ohcifp->mode.ld[2] = ntohl(fp->mode.ld[2]); 740 ohcifp->mode.common.spd = 0; 741 ohcifp->mode.common.tcode = FWOHCITCODE_PHY; 742 } else { 743 ohcifp->mode.asycomm.dst = ntohs(fp->mode.hdr.dst); 744 ohcifp->mode.asycomm.srcbus = OHCI_ASYSRCBUS; 745 ohcifp->mode.asycomm.tlrt |= FWRETRY_X; 746 } 747 db = &db_tr->db[0]; 748 db->db.desc.cmd = OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | hdr_len; 749 db->db.desc.status = 0; 750/* Specify bound timer of asy. responce */ 751 if(&sc->atrs == dbch){ 752 db->db.desc.count 753 = (OREAD(sc, OHCI_CYCLETIMER) >> 12) + (1 << 13); 754 } 755 756 db_tr->dbcnt = 2; 757 db = &db_tr->db[db_tr->dbcnt]; 758 if(len > hdr_off){ 759 if (xfer->mbuf == NULL) { 760 db->db.desc.addr 761 = vtophys(xfer->send.buf + xfer->send.off) + hdr_off; 762 db->db.desc.cmd 763 = OHCI_OUTPUT_MORE | ((len - hdr_off) & 0xffff); 764 db->db.desc.status = 0; 765 766 db_tr->dbcnt++; 767 } else { 768 /* XXX we assume mbuf chain is shorter than ndesc */ 769 m = xfer->mbuf; 770 do { 771 db->db.desc.addr 772 = vtophys(mtod(m, caddr_t)); 773 db->db.desc.cmd = OHCI_OUTPUT_MORE | m->m_len; 774 db->db.desc.status = 0; 775 db++; 776 db_tr->dbcnt++; 777 m = m->m_next; 778 } while (m != NULL); 779 } 780 } 781 /* last db */ 782 LAST_DB(db_tr, db); 783 db->db.desc.cmd |= OHCI_OUTPUT_LAST 784 | OHCI_INTERRUPT_ALWAYS 785 | OHCI_BRANCH_ALWAYS; 786 db->db.desc.depend = vtophys(STAILQ_NEXT(db_tr, link)->db); 787 788 if(fsegment == -1 ) 789 fsegment = db_tr->dbcnt; 790 if (dbch->pdb_tr != NULL) { 791 LAST_DB(dbch->pdb_tr, db); 792 db->db.desc.depend |= db_tr->dbcnt; 793 } 794 dbch->pdb_tr = db_tr; 795 db_tr = STAILQ_NEXT(db_tr, link); 796 if(db_tr != dbch->bottom){ 797 goto txloop; 798 } else { 799 device_printf(sc->fc.dev, "fwohci_start: lack of db_trq\n"); 800 dbch->flags |= FWOHCI_DBCH_FULL; 801 } 802kick: 803 if (firewire_debug) printf("kick\n"); 804 /* kick asy q */ 805 806 if(dbch->xferq.flag & FWXFERQ_RUNNING) { 807 OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_WAKE); 808 } else { 809 if (bootverbose) 810 device_printf(sc->fc.dev, "start AT DMA status=%x\n", 811 OREAD(sc, OHCI_DMACTL(off))); 812 OWRITE(sc, OHCI_DMACMD(off), vtophys(dbch->top->db) | fsegment); 813 OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_RUN); 814 dbch->xferq.flag |= FWXFERQ_RUNNING; 815 } 816 817 dbch->top = db_tr; 818 splx(s); 819 return; 820} 821 822static void 823fwohci_drain_atq(struct firewire_comm *fc, struct fw_xfer *xfer) 824{ 825 struct fwohci_softc *sc = (struct fwohci_softc *)fc; 826 fwohci_drain(&sc->fc, xfer, &(sc->atrq)); 827 return; 828} 829 830static void 831fwohci_drain_ats(struct firewire_comm *fc, struct fw_xfer *xfer) 832{ 833 struct fwohci_softc *sc = (struct fwohci_softc *)fc; 834 fwohci_drain(&sc->fc, xfer, &(sc->atrs)); 835 return; 836} 837 838static void 839fwohci_start_atq(struct firewire_comm *fc) 840{ 841 struct fwohci_softc *sc = (struct fwohci_softc *)fc; 842 fwohci_start( sc, &(sc->atrq)); 843 return; 844} 845 846static void 847fwohci_start_ats(struct firewire_comm *fc) 848{ 849 struct fwohci_softc *sc = (struct fwohci_softc *)fc; 850 fwohci_start( sc, &(sc->atrs)); 851 return; 852} 853 854void 855fwohci_txd(struct fwohci_softc *sc, struct fwohci_dbch *dbch) 856{ 857 int s, err = 0; 858 struct fwohcidb_tr *tr; 859 volatile struct fwohcidb *db; 860 struct fw_xfer *xfer; 861 u_int32_t off; 862 u_int stat; 863 int packets; 864 struct firewire_comm *fc = (struct firewire_comm *)sc; 865 if(&sc->atrq == dbch){ 866 off = OHCI_ATQOFF; 867 }else if(&sc->atrs == dbch){ 868 off = OHCI_ATSOFF; 869 }else{ 870 return; 871 } 872 s = splfw(); 873 tr = dbch->bottom; 874 packets = 0; 875 while(dbch->xferq.queued > 0){ 876 LAST_DB(tr, db); 877 if(!(db->db.desc.status & OHCI_CNTL_DMA_ACTIVE)){ 878 if (fc->status != FWBUSRESET) 879 /* maybe out of order?? */ 880 goto out; 881 } 882 if(db->db.desc.status & OHCI_CNTL_DMA_DEAD) { 883#ifdef OHCI_DEBUG 884 dump_dma(sc, ch); 885 dump_db(sc, ch); 886#endif 887/* Stop DMA */ 888 OWRITE(sc, OHCI_DMACTLCLR(off), OHCI_CNTL_DMA_RUN); 889 device_printf(sc->fc.dev, "force reset AT FIFO\n"); 890 OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_LINKEN); 891 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LPS | OHCI_HCC_LINKEN); 892 OWRITE(sc, OHCI_DMACTLCLR(off), OHCI_CNTL_DMA_RUN); 893 } 894 stat = db->db.desc.status & FWOHCIEV_MASK; 895 switch(stat){ 896 case FWOHCIEV_ACKCOMPL: 897 case FWOHCIEV_ACKPEND: 898 err = 0; 899 break; 900 case FWOHCIEV_ACKBSA: 901 case FWOHCIEV_ACKBSB: 902 device_printf(sc->fc.dev, "txd err=%2x %s\n", stat, fwohcicode[stat]); 903 case FWOHCIEV_ACKBSX: 904 err = EBUSY; 905 break; 906 case FWOHCIEV_FLUSHED: 907 case FWOHCIEV_ACKTARD: 908 device_printf(sc->fc.dev, "txd err=%2x %s\n", stat, fwohcicode[stat]); 909 err = EAGAIN; 910 break; 911 case FWOHCIEV_MISSACK: 912 case FWOHCIEV_UNDRRUN: 913 case FWOHCIEV_OVRRUN: 914 case FWOHCIEV_DESCERR: 915 case FWOHCIEV_DTRDERR: 916 case FWOHCIEV_TIMEOUT: 917 case FWOHCIEV_TCODERR: 918 case FWOHCIEV_UNKNOWN: 919 case FWOHCIEV_ACKDERR: 920 case FWOHCIEV_ACKTERR: 921 default: 922 device_printf(sc->fc.dev, "txd err=%2x %s\n", 923 stat, fwohcicode[stat]); 924 err = EINVAL; 925 break; 926 } 927 if(tr->xfer != NULL){ 928 xfer = tr->xfer; 929 xfer->state = FWXF_SENT; 930 if(err == EBUSY && fc->status != FWBUSRESET){ 931 xfer->state = FWXF_BUSY; 932 switch(xfer->act_type){ 933 case FWACT_XFER: 934 xfer->resp = err; 935 if(xfer->retry_req != NULL){ 936 xfer->retry_req(xfer); 937 } 938 break; 939 default: 940 break; 941 } 942 } else if( stat != FWOHCIEV_ACKPEND){ 943 if (stat != FWOHCIEV_ACKCOMPL) 944 xfer->state = FWXF_SENTERR; 945 xfer->resp = err; 946 switch(xfer->act_type){ 947 case FWACT_XFER: 948 fw_xfer_done(xfer); 949 break; 950 default: 951 break; 952 } 953 } 954 dbch->xferq.queued --; 955 } 956 tr->xfer = NULL; 957 958 packets ++; 959 tr = STAILQ_NEXT(tr, link); 960 dbch->bottom = tr; 961 } 962out: 963 if ((dbch->flags & FWOHCI_DBCH_FULL) && packets > 0) { 964 printf("make free slot\n"); 965 dbch->flags &= ~FWOHCI_DBCH_FULL; 966 fwohci_start(sc, dbch); 967 } 968 splx(s); 969} 970 971static void 972fwohci_drain(struct firewire_comm *fc, struct fw_xfer *xfer, struct fwohci_dbch *dbch) 973{ 974 int i, s; 975 struct fwohcidb_tr *tr; 976 977 if(xfer->state != FWXF_START) return; 978 979 s = splfw(); 980 tr = dbch->bottom; 981 for( i = 0 ; i <= dbch->xferq.queued ; i ++){ 982 if(tr->xfer == xfer){ 983 s = splfw(); 984 tr->xfer = NULL; 985 dbch->xferq.queued --; 986#if 1 987 /* XXX */ 988 if (tr == dbch->bottom) 989 dbch->bottom = STAILQ_NEXT(tr, link); 990#endif 991 if (dbch->flags & FWOHCI_DBCH_FULL) { 992 printf("fwohci_drain: make slot\n"); 993 dbch->flags &= ~FWOHCI_DBCH_FULL; 994 fwohci_start((struct fwohci_softc *)fc, dbch); 995 } 996 997 splx(s); 998 break; 999 } 1000 tr = STAILQ_NEXT(tr, link); 1001 } 1002 splx(s); 1003 return; 1004} 1005 1006static void 1007fwohci_db_free(struct fwohci_dbch *dbch) 1008{ 1009 struct fwohcidb_tr *db_tr; 1010 int idb; 1011 1012 if(!(dbch->xferq.flag & FWXFERQ_EXTBUF)){ 1013 for(db_tr = STAILQ_FIRST(&dbch->db_trq), idb = 0; 1014 idb < dbch->ndb; 1015 db_tr = STAILQ_NEXT(db_tr, link), idb++){ 1016 free(db_tr->buf, M_DEVBUF); 1017 db_tr->buf = NULL; 1018 } 1019 } 1020 dbch->ndb = 0; 1021 db_tr = STAILQ_FIRST(&dbch->db_trq); 1022 contigfree((void *)(uintptr_t)(volatile void *)db_tr->db, 1023 sizeof(struct fwohcidb) * dbch->ndesc * dbch->ndb, M_DEVBUF); 1024 /* Attach DB to DMA ch. */ 1025 free(db_tr, M_DEVBUF); 1026 STAILQ_INIT(&dbch->db_trq); 1027} 1028 1029static void 1030fwohci_db_init(struct fwohci_dbch *dbch) 1031{ 1032 int idb; 1033 struct fwohcidb *db; 1034 struct fwohcidb_tr *db_tr; 1035 /* allocate DB entries and attach one to each DMA channels */ 1036 /* DB entry must start at 16 bytes bounary. */ 1037 dbch->frag.buf = NULL; 1038 dbch->frag.len = 0; 1039 dbch->frag.plen = 0; 1040 dbch->xferq.queued = 0; 1041 dbch->pdb_tr = NULL; 1042 1043 STAILQ_INIT(&dbch->db_trq); 1044 db_tr = (struct fwohcidb_tr *) 1045 malloc(sizeof(struct fwohcidb_tr) * dbch->ndb, 1046 M_DEVBUF, M_DONTWAIT); 1047 if(db_tr == NULL){ 1048 return; 1049 } 1050 db = (struct fwohcidb *) 1051 contigmalloc(sizeof (struct fwohcidb) * dbch->ndesc * dbch->ndb, 1052 M_DEVBUF, M_DONTWAIT, 0x10000, 0xffffffff, PAGE_SIZE, 0ul); 1053 if(db == NULL){ 1054 printf("fwochi_db_init: contigmalloc failed\n"); 1055 return; 1056 } 1057 bzero(db, sizeof (struct fwohcidb) * dbch->ndesc * dbch->ndb); 1058 /* Attach DB to DMA ch. */ 1059 for(idb = 0 ; idb < dbch->ndb ; idb++){ 1060 db_tr->dbcnt = 0; 1061 db_tr->db = &db[idb * dbch->ndesc]; 1062 STAILQ_INSERT_TAIL(&dbch->db_trq, db_tr, link); 1063 if(!(dbch->xferq.flag & FWXFERQ_PACKET) && 1064 (idb % dbch->xferq.bnpacket == 0)){ 1065 dbch->xferq.bulkxfer[idb/dbch->xferq.bnpacket].start 1066 = (caddr_t)db_tr; 1067 } 1068 if((!(dbch->xferq.flag & FWXFERQ_PACKET)) && 1069 ((idb + 1)% dbch->xferq.bnpacket == 0)){ 1070 dbch->xferq.bulkxfer[idb/dbch->xferq.bnpacket].end 1071 = (caddr_t)db_tr; 1072 } 1073 db_tr++; 1074 } 1075 STAILQ_LAST(&dbch->db_trq, fwohcidb_tr,link)->link.stqe_next 1076 = STAILQ_FIRST(&dbch->db_trq); 1077 dbch->top = STAILQ_FIRST(&dbch->db_trq); 1078 dbch->bottom = dbch->top; 1079} 1080 1081static int 1082fwohci_itx_disable(struct firewire_comm *fc, int dmach) 1083{ 1084 struct fwohci_softc *sc = (struct fwohci_softc *)fc; 1085 OWRITE(sc, OHCI_ITCTLCLR(dmach), OHCI_CNTL_DMA_RUN); 1086 OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach); 1087 OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach); 1088 fwohci_db_free(&sc->it[dmach]); 1089 sc->it[dmach].xferq.flag &= ~FWXFERQ_RUNNING; 1090 return 0; 1091} 1092 1093static int 1094fwohci_irx_disable(struct firewire_comm *fc, int dmach) 1095{ 1096 struct fwohci_softc *sc = (struct fwohci_softc *)fc; 1097 1098 OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN); 1099 OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach); 1100 OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach); 1101 if(sc->ir[dmach].dummy != NULL){ 1102 free(sc->ir[dmach].dummy, M_DEVBUF); 1103 } 1104 sc->ir[dmach].dummy = NULL; 1105 fwohci_db_free(&sc->ir[dmach]); 1106 sc->ir[dmach].xferq.flag &= ~FWXFERQ_RUNNING; 1107 return 0; 1108} 1109 1110static void 1111fwohci_irx_post (struct firewire_comm *fc , u_int32_t *qld) 1112{ 1113 qld[0] = ntohl(qld[0]); 1114 return; 1115} 1116 1117static int 1118fwohci_irxpp_enable(struct firewire_comm *fc, int dmach) 1119{ 1120 struct fwohci_softc *sc = (struct fwohci_softc *)fc; 1121 int err = 0; 1122 unsigned short tag, ich; 1123 1124 tag = (sc->ir[dmach].xferq.flag >> 6) & 3; 1125 ich = sc->ir[dmach].xferq.flag & 0x3f; 1126 1127#if 0 1128 if(STAILQ_FIRST(&fc->ir[dmach]->q) != NULL){ 1129 wakeup(fc->ir[dmach]); 1130 return err; 1131 } 1132#endif 1133 1134 OWRITE(sc, OHCI_IRMATCH(dmach), tagbit[tag] | ich); 1135 if(!(sc->ir[dmach].xferq.flag & FWXFERQ_RUNNING)){ 1136 sc->ir[dmach].xferq.queued = 0; 1137 sc->ir[dmach].ndb = NDB; 1138 sc->ir[dmach].xferq.psize = FWPMAX_S400; 1139 sc->ir[dmach].ndesc = 1; 1140 fwohci_db_init(&sc->ir[dmach]); 1141 err = fwohci_rx_enable(sc, &sc->ir[dmach]); 1142 } 1143 if(err){ 1144 device_printf(sc->fc.dev, "err in IRX setting\n"); 1145 return err; 1146 } 1147 if(!(OREAD(sc, OHCI_IRCTL(dmach)) & OHCI_CNTL_DMA_ACTIVE)){ 1148 OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN); 1149 OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach); 1150 OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach); 1151 OWRITE(sc, OHCI_IR_MASK, 1 << dmach); 1152 OWRITE(sc, OHCI_IRCTLCLR(dmach), 0xf8000000); 1153 OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_ISOHDR); 1154 OWRITE(sc, OHCI_IRCMD(dmach), 1155 vtophys(sc->ir[dmach].top->db) | 1); 1156 OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_DMA_RUN); 1157 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IR); 1158 } 1159 return err; 1160} 1161 1162static int 1163fwohci_tx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch) 1164{ 1165 int err = 0; 1166 int idb, z, i, dmach = 0; 1167 u_int32_t off = NULL; 1168 struct fwohcidb_tr *db_tr; 1169 1170 if(!(dbch->xferq.flag & FWXFERQ_EXTBUF)){ 1171 err = EINVAL; 1172 return err; 1173 } 1174 z = dbch->ndesc; 1175 for(dmach = 0 ; dmach < sc->fc.nisodma ; dmach++){ 1176 if( &sc->it[dmach] == dbch){ 1177 off = OHCI_ITOFF(dmach); 1178 break; 1179 } 1180 } 1181 if(off == NULL){ 1182 err = EINVAL; 1183 return err; 1184 } 1185 if(dbch->xferq.flag & FWXFERQ_RUNNING) 1186 return err; 1187 dbch->xferq.flag |= FWXFERQ_RUNNING; 1188 for( i = 0, dbch->bottom = dbch->top; i < (dbch->ndb - 1); i++){ 1189 dbch->bottom = STAILQ_NEXT(dbch->bottom, link); 1190 } 1191 db_tr = dbch->top; 1192 for( idb = 0 ; idb < dbch->ndb ; idb ++){ 1193 fwohci_add_tx_buf(db_tr, 1194 dbch->xferq.psize, dbch->xferq.flag, 1195 dbch->xferq.buf + dbch->xferq.psize * idb); 1196 if(STAILQ_NEXT(db_tr, link) == NULL){ 1197 break; 1198 } 1199 db_tr->db[0].db.desc.depend 1200 = vtophys(STAILQ_NEXT(db_tr, link)->db) | z; 1201 db_tr->db[db_tr->dbcnt - 1].db.desc.depend 1202 = vtophys(STAILQ_NEXT(db_tr, link)->db) | z; 1203 if(dbch->xferq.flag & FWXFERQ_EXTBUF){ 1204 if(((idb + 1 ) % dbch->xferq.bnpacket) == 0){ 1205 db_tr->db[db_tr->dbcnt - 1].db.desc.cmd 1206 |= OHCI_INTERRUPT_ALWAYS; 1207 db_tr->db[0].db.desc.depend &= ~0xf; 1208 db_tr->db[db_tr->dbcnt - 1].db.desc.depend &= 1209 ~0xf; 1210 } 1211 } 1212 db_tr = STAILQ_NEXT(db_tr, link); 1213 } 1214 dbch->bottom->db[db_tr->dbcnt - 1].db.desc.depend &= 0xfffffff0; 1215 return err; 1216} 1217 1218static int 1219fwohci_rx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch) 1220{ 1221 int err = 0; 1222 int idb, z, i, dmach = 0; 1223 u_int32_t off = NULL; 1224 struct fwohcidb_tr *db_tr; 1225 1226 z = dbch->ndesc; 1227 if(&sc->arrq == dbch){ 1228 off = OHCI_ARQOFF; 1229 }else if(&sc->arrs == dbch){ 1230 off = OHCI_ARSOFF; 1231 }else{ 1232 for(dmach = 0 ; dmach < sc->fc.nisodma ; dmach++){ 1233 if( &sc->ir[dmach] == dbch){ 1234 off = OHCI_IROFF(dmach); 1235 break; 1236 } 1237 } 1238 } 1239 if(off == NULL){ 1240 err = EINVAL; 1241 return err; 1242 } 1243 if(dbch->xferq.flag & FWXFERQ_STREAM){ 1244 if(dbch->xferq.flag & FWXFERQ_RUNNING) 1245 return err; 1246 }else{ 1247 if(dbch->xferq.flag & FWXFERQ_RUNNING){ 1248 err = EBUSY; 1249 return err; 1250 } 1251 } 1252 dbch->xferq.flag |= FWXFERQ_RUNNING; 1253 for( i = 0, dbch->bottom = dbch->top; i < (dbch->ndb - 1); i++){ 1254 dbch->bottom = STAILQ_NEXT(dbch->bottom, link); 1255 } 1256 db_tr = dbch->top; 1257 for( idb = 0 ; idb < dbch->ndb ; idb ++){ 1258 if(!(dbch->xferq.flag & FWXFERQ_EXTBUF)){ 1259 fwohci_add_rx_buf(db_tr, 1260 dbch->xferq.psize, dbch->xferq.flag, 0, NULL); 1261 }else{ 1262 fwohci_add_rx_buf(db_tr, 1263 dbch->xferq.psize, dbch->xferq.flag, 1264 dbch->xferq.buf + dbch->xferq.psize * idb, 1265 dbch->dummy + sizeof(u_int32_t) * idb); 1266 } 1267 if(STAILQ_NEXT(db_tr, link) == NULL){ 1268 break; 1269 } 1270 db_tr->db[db_tr->dbcnt - 1].db.desc.depend 1271 = vtophys(STAILQ_NEXT(db_tr, link)->db) | z; 1272 if(dbch->xferq.flag & FWXFERQ_EXTBUF){ 1273 if(((idb + 1 ) % dbch->xferq.bnpacket) == 0){ 1274 db_tr->db[db_tr->dbcnt - 1].db.desc.cmd 1275 |= OHCI_INTERRUPT_ALWAYS; 1276 db_tr->db[db_tr->dbcnt - 1].db.desc.depend &= 1277 ~0xf; 1278 } 1279 } 1280 db_tr = STAILQ_NEXT(db_tr, link); 1281 } 1282 dbch->bottom->db[db_tr->dbcnt - 1].db.desc.depend &= 0xfffffff0; 1283 dbch->buf_offset = 0; 1284 if(dbch->xferq.flag & FWXFERQ_STREAM){ 1285 return err; 1286 }else{ 1287 OWRITE(sc, OHCI_DMACMD(off), vtophys(dbch->top->db) | z); 1288 } 1289 OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_RUN); 1290 return err; 1291} 1292 1293static int 1294fwohci_itxbuf_enable(struct firewire_comm *fc, int dmach) 1295{ 1296 struct fwohci_softc *sc = (struct fwohci_softc *)fc; 1297 int err = 0; 1298 unsigned short tag, ich; 1299 struct fwohci_dbch *dbch; 1300 struct fw_pkt *fp; 1301 struct fwohcidb_tr *db_tr; 1302 1303 tag = (sc->it[dmach].xferq.flag >> 6) & 3; 1304 ich = sc->it[dmach].xferq.flag & 0x3f; 1305 dbch = &sc->it[dmach]; 1306 if(dbch->ndb == 0){ 1307 dbch->xferq.queued = 0; 1308 dbch->ndb = dbch->xferq.bnpacket * dbch->xferq.bnchunk; 1309 dbch->ndesc = 3; 1310 fwohci_db_init(dbch); 1311 err = fwohci_tx_enable(sc, dbch); 1312 } 1313 if(err) 1314 return err; 1315 if(OREAD(sc, OHCI_ITCTL(dmach)) & OHCI_CNTL_DMA_ACTIVE){ 1316 if(dbch->xferq.stdma2 != NULL){ 1317 fwohci_txbufdb(sc, dmach, dbch->xferq.stdma2); 1318 ((struct fwohcidb_tr *) 1319 (dbch->xferq.stdma->end))->db[dbch->ndesc - 1].db.desc.cmd 1320 |= OHCI_BRANCH_ALWAYS; 1321 ((struct fwohcidb_tr *) 1322 (dbch->xferq.stdma->end))->db[dbch->ndesc - 1].db.desc.depend = 1323 vtophys(((struct fwohcidb_tr *)(dbch->xferq.stdma2->start))->db) | dbch->ndesc; 1324 ((struct fwohcidb_tr *)(dbch->xferq.stdma->end))->db[0].db.desc.depend = 1325 vtophys(((struct fwohcidb_tr *)(dbch->xferq.stdma2->start))->db) | dbch->ndesc; 1326 ((struct fwohcidb_tr *)(dbch->xferq.stdma2->end))->db[dbch->ndesc - 1].db.desc.depend &= ~0xf; 1327 ((struct fwohcidb_tr *)(dbch->xferq.stdma2->end))->db[0].db.desc.depend &= ~0xf; 1328 } 1329 }else if(!(OREAD(sc, OHCI_ITCTL(dmach)) & OHCI_CNTL_DMA_ACTIVE)){ 1330 fw_tbuf_update(&sc->fc, dmach, 0); 1331 if(dbch->xferq.stdma == NULL){ 1332 return err; 1333 } 1334 OWRITE(sc, OHCI_ITCTLCLR(dmach), OHCI_CNTL_DMA_RUN); 1335 OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach); 1336 OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach); 1337 OWRITE(sc, OHCI_IT_MASK, 1 << dmach); 1338 OWRITE(sc, OHCI_ITCTLCLR(dmach), 0xf0000000); 1339 fwohci_txbufdb(sc, dmach, dbch->xferq.stdma); 1340 if(dbch->xferq.stdma2 != NULL){ 1341 fwohci_txbufdb(sc, dmach, dbch->xferq.stdma2); 1342 ((struct fwohcidb_tr *) 1343 (dbch->xferq.stdma->end))->db[dbch->ndesc - 1].db.desc.cmd 1344 |= OHCI_BRANCH_ALWAYS; 1345 ((struct fwohcidb_tr *)(dbch->xferq.stdma->end))->db[dbch->ndesc - 1].db.desc.depend = 1346 vtophys(((struct fwohcidb_tr *)(dbch->xferq.stdma2->start))->db) | dbch->ndesc; 1347 ((struct fwohcidb_tr *)(dbch->xferq.stdma->end))->db[0].db.desc.depend = 1348 vtophys(((struct fwohcidb_tr *)(dbch->xferq.stdma2->start))->db) | dbch->ndesc; 1349 ((struct fwohcidb_tr *)(dbch->xferq.stdma2->end))->db[dbch->ndesc - 1].db.desc.depend &= ~0xf; 1350 ((struct fwohcidb_tr *) (dbch->xferq.stdma2->end))->db[0].db.desc.depend &= ~0xf; 1351 }else{ 1352 ((struct fwohcidb_tr *) (dbch->xferq.stdma->end))->db[dbch->ndesc - 1].db.desc.depend &= ~0xf; 1353 ((struct fwohcidb_tr *) (dbch->xferq.stdma->end))->db[0].db.desc.depend &= ~0xf; 1354 } 1355 OWRITE(sc, OHCI_ITCMD(dmach), 1356 vtophys(((struct fwohcidb_tr *) 1357 (dbch->xferq.stdma->start))->db) | dbch->ndesc); 1358 if(dbch->xferq.flag & FWXFERQ_DV){ 1359 db_tr = (struct fwohcidb_tr *)dbch->xferq.stdma->start; 1360 fp = (struct fw_pkt *)db_tr->buf; 1361 fp->mode.ld[2] = htonl(0x80000000 + 1362 ((fc->cyctimer(fc) + 0x3000) & 0xf000)); 1363 } 1364 1365 OWRITE(sc, OHCI_ITCTL(dmach), OHCI_CNTL_DMA_RUN); 1366 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IT); 1367 } 1368 return err; 1369} 1370 1371static int 1372fwohci_irxbuf_enable(struct firewire_comm *fc, int dmach) 1373{ 1374 struct fwohci_softc *sc = (struct fwohci_softc *)fc; 1375 int err = 0; 1376 unsigned short tag, ich; 1377 tag = (sc->ir[dmach].xferq.flag >> 6) & 3; 1378 ich = sc->ir[dmach].xferq.flag & 0x3f; 1379 OWRITE(sc, OHCI_IRMATCH(dmach), tagbit[tag] | ich); 1380 1381 if(!(sc->ir[dmach].xferq.flag & FWXFERQ_RUNNING)){ 1382 sc->ir[dmach].xferq.queued = 0; 1383 sc->ir[dmach].ndb = sc->ir[dmach].xferq.bnpacket * 1384 sc->ir[dmach].xferq.bnchunk; 1385 sc->ir[dmach].dummy = 1386 malloc(sizeof(u_int32_t) * sc->ir[dmach].ndb, 1387 M_DEVBUF, M_DONTWAIT); 1388 if(sc->ir[dmach].dummy == NULL){ 1389 err = ENOMEM; 1390 return err; 1391 } 1392 sc->ir[dmach].ndesc = 2; 1393 fwohci_db_init(&sc->ir[dmach]); 1394 err = fwohci_rx_enable(sc, &sc->ir[dmach]); 1395 } 1396 if(err) 1397 return err; 1398 1399 if(OREAD(sc, OHCI_IRCTL(dmach)) & OHCI_CNTL_DMA_ACTIVE){ 1400 if(sc->ir[dmach].xferq.stdma2 != NULL){ 1401 ((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[sc->ir[dmach].ndesc - 1].db.desc.depend = 1402 vtophys(((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->start))->db) | sc->ir[dmach].ndesc; 1403 ((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[0].db.desc.depend = 1404 vtophys(((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->start))->db); 1405 ((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->end))->db[sc->ir[dmach].ndesc - 1].db.desc.depend &= ~0xf; 1406 ((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->end))->db[0].db.desc.depend &= ~0xf; 1407 } 1408 }else if(!(OREAD(sc, OHCI_IRCTL(dmach)) & OHCI_CNTL_DMA_ACTIVE) 1409 && !(sc->ir[dmach].xferq.flag & FWXFERQ_PACKET)){ 1410 fw_rbuf_update(&sc->fc, dmach, 0); 1411 1412 OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN); 1413 OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach); 1414 OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach); 1415 OWRITE(sc, OHCI_IR_MASK, 1 << dmach); 1416 OWRITE(sc, OHCI_IRCTLCLR(dmach), 0xf0000000); 1417 OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_ISOHDR); 1418 if(sc->ir[dmach].xferq.stdma2 != NULL){ 1419 ((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[sc->ir[dmach].ndesc - 1].db.desc.depend = 1420 vtophys(((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->start))->db) | sc->ir[dmach].ndesc; 1421 ((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[0].db.desc.depend = 1422 vtophys(((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->start))->db); 1423 ((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->end))->db[sc->ir[dmach].ndesc - 1].db.desc.depend &= ~0xf; 1424 }else{ 1425 ((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[sc->ir[dmach].ndesc - 1].db.desc.depend &= ~0xf; 1426 ((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[0].db.desc.depend &= ~0xf; 1427 } 1428 OWRITE(sc, OHCI_IRCMD(dmach), 1429 vtophys(((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->start))->db) | sc->ir[dmach].ndesc); 1430 OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_DMA_RUN); 1431 } 1432 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IR); 1433 return err; 1434} 1435 1436static int 1437fwohci_irx_enable(struct firewire_comm *fc, int dmach) 1438{ 1439 struct fwohci_softc *sc = (struct fwohci_softc *)fc; 1440 int err = 0; 1441 1442 if(sc->ir[dmach].xferq.flag & FWXFERQ_PACKET){ 1443 err = fwohci_irxpp_enable(fc, dmach); 1444 return err; 1445 }else{ 1446 err = fwohci_irxbuf_enable(fc, dmach); 1447 return err; 1448 } 1449} 1450 1451int 1452fwohci_shutdown(device_t dev) 1453{ 1454 u_int i; 1455 struct fwohci_softc *sc = device_get_softc(dev); 1456 1457/* Now stopping all DMA channel */ 1458 OWRITE(sc, OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN); 1459 OWRITE(sc, OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN); 1460 OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN); 1461 OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN); 1462 1463 for( i = 0 ; i < sc->fc.nisodma ; i ++ ){ 1464 OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN); 1465 OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN); 1466 } 1467 1468/* FLUSH FIFO and reset Transmitter/Reciever */ 1469 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_RESET); 1470 1471/* Stop interrupt */ 1472 OWRITE(sc, FWOHCI_INTMASKCLR, 1473 OHCI_INT_EN | OHCI_INT_ERR | OHCI_INT_PHY_SID 1474 | OHCI_INT_PHY_INT 1475 | OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS 1476 | OHCI_INT_DMA_PRRQ | OHCI_INT_DMA_PRRS 1477 | OHCI_INT_DMA_ARRQ | OHCI_INT_DMA_ARRS 1478 | OHCI_INT_PHY_BUS_R); 1479 return 0; 1480} 1481 1482#define ACK_ALL 1483static void 1484fwohci_intr_body(struct fwohci_softc *sc, u_int32_t stat, int count) 1485{ 1486 u_int32_t irstat, itstat; 1487 u_int i; 1488 struct firewire_comm *fc = (struct firewire_comm *)sc; 1489 1490#ifdef OHCI_DEBUG 1491 if(stat & OREAD(sc, FWOHCI_INTMASK)) 1492 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", 1493 stat & OHCI_INT_EN ? "DMA_EN ":"", 1494 stat & OHCI_INT_PHY_REG ? "PHY_REG ":"", 1495 stat & OHCI_INT_CYC_LONG ? "CYC_LONG ":"", 1496 stat & OHCI_INT_ERR ? "INT_ERR ":"", 1497 stat & OHCI_INT_CYC_ERR ? "CYC_ERR ":"", 1498 stat & OHCI_INT_CYC_LOST ? "CYC_LOST ":"", 1499 stat & OHCI_INT_CYC_64SECOND ? "CYC_64SECOND ":"", 1500 stat & OHCI_INT_CYC_START ? "CYC_START ":"", 1501 stat & OHCI_INT_PHY_INT ? "PHY_INT ":"", 1502 stat & OHCI_INT_PHY_BUS_R ? "BUS_RESET ":"", 1503 stat & OHCI_INT_PHY_SID ? "SID ":"", 1504 stat & OHCI_INT_LR_ERR ? "DMA_LR_ERR ":"", 1505 stat & OHCI_INT_PW_ERR ? "DMA_PW_ERR ":"", 1506 stat & OHCI_INT_DMA_IR ? "DMA_IR ":"", 1507 stat & OHCI_INT_DMA_IT ? "DMA_IT " :"", 1508 stat & OHCI_INT_DMA_PRRS ? "DMA_PRRS " :"", 1509 stat & OHCI_INT_DMA_PRRQ ? "DMA_PRRQ " :"", 1510 stat & OHCI_INT_DMA_ARRS ? "DMA_ARRS " :"", 1511 stat & OHCI_INT_DMA_ARRQ ? "DMA_ARRQ " :"", 1512 stat & OHCI_INT_DMA_ATRS ? "DMA_ATRS " :"", 1513 stat & OHCI_INT_DMA_ATRQ ? "DMA_ATRQ " :"", 1514 stat, OREAD(sc, FWOHCI_INTMASK) 1515 ); 1516#endif 1517/* Bus reset */ 1518 if(stat & OHCI_INT_PHY_BUS_R ){ 1519 device_printf(fc->dev, "BUS reset\n"); 1520 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST); 1521 OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCSRC); 1522 1523 OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN); 1524 sc->atrq.xferq.flag &= ~FWXFERQ_RUNNING; 1525 OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN); 1526 sc->atrs.xferq.flag &= ~FWXFERQ_RUNNING; 1527 1528#if 0 1529 for( i = 0 ; i < fc->nisodma ; i ++ ){ 1530 OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN); 1531 OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN); 1532 } 1533 1534#endif 1535 fw_busreset(fc); 1536 1537 /* XXX need to wait DMA to stop */ 1538#ifndef ACK_ALL 1539 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_BUS_R); 1540#endif 1541#if 1 1542 /* pending all pre-bus_reset packets */ 1543 fwohci_txd(sc, &sc->atrq); 1544 fwohci_txd(sc, &sc->atrs); 1545 fwohci_arcv(sc, &sc->arrs, -1); 1546 fwohci_arcv(sc, &sc->arrq, -1); 1547#endif 1548 1549 1550 OWRITE(sc, OHCI_AREQHI, 1 << 31); 1551 /* XXX insecure ?? */ 1552 OWRITE(sc, OHCI_PREQHI, 0x7fffffff); 1553 OWRITE(sc, OHCI_PREQLO, 0xffffffff); 1554 OWRITE(sc, OHCI_PREQUPPER, 0x10000); 1555 1556 } 1557 if((stat & OHCI_INT_DMA_IR )){ 1558#ifndef ACK_ALL 1559 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_IR); 1560#endif 1561 irstat = OREAD(sc, OHCI_IR_STAT); 1562 OWRITE(sc, OHCI_IR_STATCLR, ~0); 1563 for(i = 0; i < fc->nisodma ; i++){ 1564 if((irstat & (1 << i)) != 0){ 1565 if(sc->ir[i].xferq.flag & FWXFERQ_PACKET){ 1566 fwohci_ircv(sc, &sc->ir[i], count); 1567 }else{ 1568 fwohci_rbuf_update(sc, i); 1569 } 1570 } 1571 } 1572 } 1573 if((stat & OHCI_INT_DMA_IT )){ 1574#ifndef ACK_ALL 1575 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_IT); 1576#endif 1577 itstat = OREAD(sc, OHCI_IT_STAT); 1578 OWRITE(sc, OHCI_IT_STATCLR, ~0); 1579 for(i = 0; i < fc->nisodma ; i++){ 1580 if((itstat & (1 << i)) != 0){ 1581 fwohci_tbuf_update(sc, i); 1582 } 1583 } 1584 } 1585 if((stat & OHCI_INT_DMA_PRRS )){ 1586#ifndef ACK_ALL 1587 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_PRRS); 1588#endif 1589#if 0 1590 dump_dma(sc, ARRS_CH); 1591 dump_db(sc, ARRS_CH); 1592#endif 1593 fwohci_arcv(sc, &sc->arrs, count); 1594 } 1595 if((stat & OHCI_INT_DMA_PRRQ )){ 1596#ifndef ACK_ALL 1597 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_PRRQ); 1598#endif 1599#if 0 1600 dump_dma(sc, ARRQ_CH); 1601 dump_db(sc, ARRQ_CH); 1602#endif 1603 fwohci_arcv(sc, &sc->arrq, count); 1604 } 1605 if(stat & OHCI_INT_PHY_SID){ 1606 caddr_t buf; 1607 int plen; 1608 1609#ifndef ACK_ALL 1610 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_SID); 1611#endif 1612/* 1613** Checking whether the node is root or not. If root, turn on 1614** cycle master. 1615*/ 1616 device_printf(fc->dev, "node_id = 0x%08x, ", OREAD(sc, FWOHCI_NODEID)); 1617 if(!(OREAD(sc, FWOHCI_NODEID) & OHCI_NODE_VALID)){ 1618 printf("Bus reset failure\n"); 1619 goto sidout; 1620 } 1621 if( OREAD(sc, FWOHCI_NODEID) & OHCI_NODE_ROOT ){ 1622 printf("CYCLEMASTER mode\n"); 1623 OWRITE(sc, OHCI_LNKCTL, 1624 OHCI_CNTL_CYCMTR | OHCI_CNTL_CYCTIMER); 1625 }else{ 1626 printf("non CYCLEMASTER mode\n"); 1627 OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCMTR); 1628 OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_CYCTIMER); 1629 } 1630 fc->nodeid = OREAD(sc, FWOHCI_NODEID) & 0x3f; 1631 1632 plen = OREAD(sc, OHCI_SID_CNT) & OHCI_SID_CNT_MASK; 1633 plen -= 4; /* chop control info */ 1634 buf = malloc( FWPMAX_S400, M_DEVBUF, M_NOWAIT); 1635 if(buf == NULL) goto sidout; 1636 bcopy((void *)(uintptr_t)(volatile void *)fc->sid_buf, 1637 buf, plen); 1638 fw_sidrcv(fc, buf, plen, 0); 1639 } 1640sidout: 1641 if((stat & OHCI_INT_DMA_ATRQ )){ 1642#ifndef ACK_ALL 1643 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_ATRQ); 1644#endif 1645 fwohci_txd(sc, &(sc->atrq)); 1646 } 1647 if((stat & OHCI_INT_DMA_ATRS )){ 1648#ifndef ACK_ALL 1649 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_ATRS); 1650#endif 1651 fwohci_txd(sc, &(sc->atrs)); 1652 } 1653 if((stat & OHCI_INT_PW_ERR )){ 1654#ifndef ACK_ALL 1655 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PW_ERR); 1656#endif 1657 device_printf(fc->dev, "posted write error\n"); 1658 } 1659 if((stat & OHCI_INT_ERR )){ 1660#ifndef ACK_ALL 1661 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_ERR); 1662#endif 1663 device_printf(fc->dev, "unrecoverable error\n"); 1664 } 1665 if((stat & OHCI_INT_PHY_INT)) { 1666#ifndef ACK_ALL 1667 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_INT); 1668#endif 1669 device_printf(fc->dev, "phy int\n"); 1670 } 1671 1672 return; 1673} 1674 1675void 1676fwohci_intr(void *arg) 1677{ 1678 struct fwohci_softc *sc = (struct fwohci_softc *)arg; 1679 u_int32_t stat; 1680 1681 if (!(sc->intmask & OHCI_INT_EN)) { 1682 /* polling mode */ 1683 return; 1684 } 1685 1686 while ((stat = OREAD(sc, FWOHCI_INTSTAT)) != 0) { 1687 if (stat == 0xffffffff) { 1688 device_printf(sc->fc.dev, 1689 "device physically ejected?\n"); 1690 return; 1691 } 1692#ifdef ACK_ALL 1693 OWRITE(sc, FWOHCI_INTSTATCLR, stat); 1694#endif 1695 fwohci_intr_body(sc, stat, -1); 1696 } 1697} 1698 1699static void 1700fwohci_poll(struct firewire_comm *fc, int quick, int count) 1701{ 1702 int s; 1703 u_int32_t stat; 1704 struct fwohci_softc *sc; 1705 1706 1707 sc = (struct fwohci_softc *)fc; 1708 stat = OHCI_INT_DMA_IR | OHCI_INT_DMA_IT | 1709 OHCI_INT_DMA_PRRS | OHCI_INT_DMA_PRRQ | 1710 OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS; 1711#if 0 1712 if (!quick) { 1713#else 1714 if (1) { 1715#endif 1716 stat = OREAD(sc, FWOHCI_INTSTAT); 1717 if (stat == 0) 1718 return; 1719 if (stat == 0xffffffff) { 1720 device_printf(sc->fc.dev, 1721 "device physically ejected?\n"); 1722 return; 1723 } 1724#ifdef ACK_ALL 1725 OWRITE(sc, FWOHCI_INTSTATCLR, stat); 1726#endif 1727 } 1728 s = splfw(); 1729 fwohci_intr_body(sc, stat, count); 1730 splx(s); 1731} 1732 1733static void 1734fwohci_set_intr(struct firewire_comm *fc, int enable) 1735{ 1736 struct fwohci_softc *sc; 1737 1738 sc = (struct fwohci_softc *)fc; 1739 if (bootverbose) 1740 device_printf(sc->fc.dev, "fwochi_set_intr: %d\n", enable); 1741 if (enable) { 1742 sc->intmask |= OHCI_INT_EN; 1743 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_EN); 1744 } else { 1745 sc->intmask &= ~OHCI_INT_EN; 1746 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_EN); 1747 } 1748} 1749 1750static void 1751fwohci_tbuf_update(struct fwohci_softc *sc, int dmach) 1752{ 1753 int stat; 1754 struct firewire_comm *fc = &sc->fc; 1755 struct fw_pkt *fp; 1756 struct fwohci_dbch *dbch; 1757 struct fwohcidb_tr *db_tr; 1758 1759 dbch = &sc->it[dmach]; 1760 if((dbch->xferq.flag & FWXFERQ_DV) && (dbch->xferq.stdma2 != NULL)){ 1761 db_tr = (struct fwohcidb_tr *)dbch->xferq.stdma2->start; 1762/* 1763 * Overwrite highest significant 4 bits timestamp information 1764 */ 1765 fp = (struct fw_pkt *)db_tr->buf; 1766 fp->mode.ld[2] |= htonl(0x80000000 | 1767 ((fc->cyctimer(fc) + 0x4000) & 0xf000)); 1768 } 1769 stat = OREAD(sc, OHCI_ITCTL(dmach)) & 0x1f; 1770 switch(stat){ 1771 case FWOHCIEV_ACKCOMPL: 1772 fw_tbuf_update(fc, dmach, 1); 1773 break; 1774 default: 1775 fw_tbuf_update(fc, dmach, 0); 1776 break; 1777 } 1778 fwohci_itxbuf_enable(&sc->fc, dmach); 1779} 1780 1781static void 1782fwohci_rbuf_update(struct fwohci_softc *sc, int dmach) 1783{ 1784 int stat; 1785 stat = OREAD(sc, OHCI_IRCTL(dmach)) & 0x1f; 1786 switch(stat){ 1787 case FWOHCIEV_ACKCOMPL: 1788 fw_rbuf_update(&sc->fc, dmach, 1); 1789 wakeup(sc->fc.ir[dmach]); 1790 fwohci_irx_enable(&sc->fc, dmach); 1791 break; 1792 default: 1793 break; 1794 } 1795} 1796 1797void 1798dump_dma(struct fwohci_softc *sc, u_int32_t ch) 1799{ 1800 u_int32_t off, cntl, stat, cmd, match; 1801 1802 if(ch == 0){ 1803 off = OHCI_ATQOFF; 1804 }else if(ch == 1){ 1805 off = OHCI_ATSOFF; 1806 }else if(ch == 2){ 1807 off = OHCI_ARQOFF; 1808 }else if(ch == 3){ 1809 off = OHCI_ARSOFF; 1810 }else if(ch < IRX_CH){ 1811 off = OHCI_ITCTL(ch - ITX_CH); 1812 }else{ 1813 off = OHCI_IRCTL(ch - IRX_CH); 1814 } 1815 cntl = stat = OREAD(sc, off); 1816 cmd = OREAD(sc, off + 0xc); 1817 match = OREAD(sc, off + 0x10); 1818 1819 device_printf(sc->fc.dev, "dma ch %1x:dma regs 0x%08x 0x%08x 0x%08x 0x%08x \n", 1820 ch, 1821 cntl, 1822 stat, 1823 cmd, 1824 match); 1825 stat &= 0xffff ; 1826 if(stat & 0xff00){ 1827 device_printf(sc->fc.dev, "dma %d ch:%s%s%s%s%s%s %s(%x)\n", 1828 ch, 1829 stat & OHCI_CNTL_DMA_RUN ? "RUN," : "", 1830 stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "", 1831 stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "", 1832 stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "", 1833 stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "", 1834 stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "", 1835 fwohcicode[stat & 0x1f], 1836 stat & 0x1f 1837 ); 1838 }else{ 1839 device_printf(sc->fc.dev, "dma %d ch: Nostat\n", ch); 1840 } 1841} 1842 1843void 1844dump_db(struct fwohci_softc *sc, u_int32_t ch) 1845{ 1846 struct fwohci_dbch *dbch; 1847 struct fwohcidb_tr *cp = NULL, *pp, *np; 1848 volatile struct fwohcidb *curr = NULL, *prev, *next = NULL; 1849 int idb, jdb; 1850 u_int32_t cmd, off; 1851 if(ch == 0){ 1852 off = OHCI_ATQOFF; 1853 dbch = &sc->atrq; 1854 }else if(ch == 1){ 1855 off = OHCI_ATSOFF; 1856 dbch = &sc->atrs; 1857 }else if(ch == 2){ 1858 off = OHCI_ARQOFF; 1859 dbch = &sc->arrq; 1860 }else if(ch == 3){ 1861 off = OHCI_ARSOFF; 1862 dbch = &sc->arrs; 1863 }else if(ch < IRX_CH){ 1864 off = OHCI_ITCTL(ch - ITX_CH); 1865 dbch = &sc->it[ch - ITX_CH]; 1866 }else { 1867 off = OHCI_IRCTL(ch - IRX_CH); 1868 dbch = &sc->ir[ch - IRX_CH]; 1869 } 1870 cmd = OREAD(sc, off + 0xc); 1871 1872 if( dbch->ndb == 0 ){ 1873 device_printf(sc->fc.dev, "No DB is attached ch=%d\n", ch); 1874 return; 1875 } 1876 pp = dbch->top; 1877 prev = pp->db; 1878 for(idb = 0 ; idb < dbch->ndb ; idb ++ ){ 1879 if(pp == NULL){ 1880 curr = NULL; 1881 goto outdb; 1882 } 1883 cp = STAILQ_NEXT(pp, link); 1884 if(cp == NULL){ 1885 curr = NULL; 1886 goto outdb; 1887 } 1888 np = STAILQ_NEXT(cp, link); 1889 if(cp == NULL) break; 1890 for(jdb = 0 ; jdb < dbch->ndesc ; jdb ++ ){ 1891 if((cmd & 0xfffffff0) 1892 == vtophys(&(cp->db[jdb]))){ 1893 curr = cp->db; 1894 if(np != NULL){ 1895 next = np->db; 1896 }else{ 1897 next = NULL; 1898 } 1899 goto outdb; 1900 } 1901 } 1902 pp = STAILQ_NEXT(pp, link); 1903 prev = pp->db; 1904 } 1905outdb: 1906 if( curr != NULL){ 1907 printf("Prev DB %d\n", ch); 1908 print_db(prev, ch, dbch->ndesc); 1909 printf("Current DB %d\n", ch); 1910 print_db(curr, ch, dbch->ndesc); 1911 printf("Next DB %d\n", ch); 1912 print_db(next, ch, dbch->ndesc); 1913 }else{ 1914 printf("dbdump err ch = %d cmd = 0x%08x\n", ch, cmd); 1915 } 1916 return; 1917} 1918 1919void 1920print_db(volatile struct fwohcidb *db, u_int32_t ch, u_int32_t max) 1921{ 1922 fwohcireg_t stat; 1923 int i, key; 1924 1925 if(db == NULL){ 1926 printf("No Descriptor is found\n"); 1927 return; 1928 } 1929 1930 printf("ch = %d\n%8s %s %s %s %s %4s %8s %8s %4s:%4s\n", 1931 ch, 1932 "Current", 1933 "OP ", 1934 "KEY", 1935 "INT", 1936 "BR ", 1937 "len", 1938 "Addr", 1939 "Depend", 1940 "Stat", 1941 "Cnt"); 1942 for( i = 0 ; i <= max ; i ++){ 1943 key = db[i].db.desc.cmd & OHCI_KEY_MASK; 1944 printf("%08tx %s %s %s %s %5d %08x %08x %04x:%04x", 1945 vtophys(&db[i]), 1946 dbcode[(db[i].db.desc.cmd >> 28) & 0xf], 1947 dbkey[(db[i].db.desc.cmd >> 24) & 0x7], 1948 dbcond[(db[i].db.desc.cmd >> 20) & 0x3], 1949 dbcond[(db[i].db.desc.cmd >> 18) & 0x3], 1950 db[i].db.desc.cmd & 0xffff, 1951 db[i].db.desc.addr, 1952 db[i].db.desc.depend, 1953 db[i].db.desc.status, 1954 db[i].db.desc.count); 1955 stat = db[i].db.desc.status; 1956 if(stat & 0xff00){ 1957 printf(" %s%s%s%s%s%s %s(%x)\n", 1958 stat & OHCI_CNTL_DMA_RUN ? "RUN," : "", 1959 stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "", 1960 stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "", 1961 stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "", 1962 stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "", 1963 stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "", 1964 fwohcicode[stat & 0x1f], 1965 stat & 0x1f 1966 ); 1967 }else{ 1968 printf(" Nostat\n"); 1969 } 1970 if(key == OHCI_KEY_ST2 ){ 1971 printf("0x%08x 0x%08x 0x%08x 0x%08x\n", 1972 db[i+1].db.immed[0], 1973 db[i+1].db.immed[1], 1974 db[i+1].db.immed[2], 1975 db[i+1].db.immed[3]); 1976 } 1977 if(key == OHCI_KEY_DEVICE){ 1978 return; 1979 } 1980 if((db[i].db.desc.cmd & OHCI_BRANCH_MASK) 1981 == OHCI_BRANCH_ALWAYS){ 1982 return; 1983 } 1984 if((db[i].db.desc.cmd & OHCI_CMD_MASK) 1985 == OHCI_OUTPUT_LAST){ 1986 return; 1987 } 1988 if((db[i].db.desc.cmd & OHCI_CMD_MASK) 1989 == OHCI_INPUT_LAST){ 1990 return; 1991 } 1992 if(key == OHCI_KEY_ST2 ){ 1993 i++; 1994 } 1995 } 1996 return; 1997} 1998 1999void 2000fwohci_ibr(struct firewire_comm *fc) 2001{ 2002 struct fwohci_softc *sc; 2003 u_int32_t fun; 2004 2005 sc = (struct fwohci_softc *)fc; 2006 2007 /* 2008 * Set root hold-off bit so that non cyclemaster capable node 2009 * shouldn't became the root node. 2010 */ 2011 fun = fwphy_rddata(sc, FW_PHY_RHB_REG); 2012 fun |= FW_PHY_RHB; 2013 fun = fwphy_wrdata(sc, FW_PHY_RHB_REG, fun); 2014#if 1 2015 fun = fwphy_rddata(sc, FW_PHY_IBR_REG); 2016 fun |= FW_PHY_IBR; 2017 fun = fwphy_wrdata(sc, FW_PHY_IBR_REG, fun); 2018#else 2019 fun = fwphy_rddata(sc, FW_PHY_ISBR_REG); 2020 fun |= FW_PHY_ISBR; 2021 fun = fwphy_wrdata(sc, FW_PHY_ISBR_REG, fun); 2022#endif 2023} 2024 2025void 2026fwohci_txbufdb(struct fwohci_softc *sc, int dmach, struct fw_bulkxfer *bulkxfer) 2027{ 2028 struct fwohcidb_tr *db_tr, *fdb_tr; 2029 struct fwohci_dbch *dbch; 2030 struct fw_pkt *fp; 2031 volatile struct fwohci_txpkthdr *ohcifp; 2032 unsigned short chtag; 2033 int idb; 2034 2035 dbch = &sc->it[dmach]; 2036 chtag = sc->it[dmach].xferq.flag & 0xff; 2037 2038 db_tr = (struct fwohcidb_tr *)(bulkxfer->start); 2039 fdb_tr = (struct fwohcidb_tr *)(bulkxfer->end); 2040/* 2041device_printf(sc->fc.dev, "DB %08x %08x %08x\n", bulkxfer, vtophys(db_tr->db), vtophys(fdb_tr->db)); 2042*/ 2043 if(bulkxfer->flag != 0){ 2044 return; 2045 } 2046 bulkxfer->flag = 1; 2047 for( idb = 0 ; idb < bulkxfer->npacket ; idb ++){ 2048 db_tr->db[0].db.desc.cmd 2049 = OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | 8; 2050 fp = (struct fw_pkt *)db_tr->buf; 2051 ohcifp = (volatile struct fwohci_txpkthdr *) 2052 db_tr->db[1].db.immed; 2053 ohcifp->mode.ld[0] = ntohl(fp->mode.ld[0]); 2054 ohcifp->mode.stream.len = ntohs(fp->mode.stream.len); 2055 ohcifp->mode.stream.chtag = chtag; 2056 ohcifp->mode.stream.tcode = 0xa; 2057 ohcifp->mode.stream.spd = 4; 2058 ohcifp->mode.ld[2] = ntohl(fp->mode.ld[1]); 2059 ohcifp->mode.ld[3] = ntohl(fp->mode.ld[2]); 2060 2061 db_tr->db[2].db.desc.cmd 2062 = OHCI_OUTPUT_LAST 2063 | OHCI_UPDATE 2064 | OHCI_BRANCH_ALWAYS 2065 | ((ntohs(fp->mode.stream.len) ) & 0xffff); 2066 db_tr->db[2].db.desc.status = 0; 2067 db_tr->db[2].db.desc.count = 0; 2068 if(dbch->xferq.flag & FWXFERQ_DV){ 2069 db_tr->db[0].db.desc.depend 2070 = vtophys(STAILQ_NEXT(db_tr, link)->db) | dbch->ndesc; 2071 db_tr->db[dbch->ndesc - 1].db.desc.depend 2072 = vtophys(STAILQ_NEXT(db_tr, link)->db) | dbch->ndesc; 2073 }else{ 2074 db_tr->db[0].db.desc.depend 2075 = vtophys(STAILQ_NEXT(db_tr, link)->db) | dbch->ndesc; 2076 db_tr->db[dbch->ndesc - 1].db.desc.depend 2077 = vtophys(STAILQ_NEXT(db_tr, link)->db) | dbch->ndesc; 2078 } 2079 bulkxfer->end = (caddr_t)db_tr; 2080 db_tr = STAILQ_NEXT(db_tr, link); 2081 } 2082 db_tr = (struct fwohcidb_tr *)bulkxfer->end; 2083 db_tr->db[0].db.desc.depend &= ~0xf; 2084 db_tr->db[dbch->ndesc - 1].db.desc.depend &= ~0xf; 2085/**/ 2086 db_tr->db[dbch->ndesc - 1].db.desc.cmd &= ~OHCI_BRANCH_ALWAYS; 2087 db_tr->db[dbch->ndesc - 1].db.desc.cmd |= OHCI_BRANCH_NEVER; 2088/**/ 2089 db_tr->db[dbch->ndesc - 1].db.desc.cmd |= OHCI_INTERRUPT_ALWAYS; 2090 2091 db_tr = (struct fwohcidb_tr *)bulkxfer->start; 2092 fdb_tr = (struct fwohcidb_tr *)bulkxfer->end; 2093/* 2094device_printf(sc->fc.dev, "DB %08x %3d %08x %08x\n", bulkxfer, bulkxfer->npacket, vtophys(db_tr->db), vtophys(fdb_tr->db)); 2095*/ 2096 return; 2097} 2098 2099static int 2100fwohci_add_tx_buf(struct fwohcidb_tr *db_tr, unsigned short size, 2101 int mode, void *buf) 2102{ 2103 volatile struct fwohcidb *db = db_tr->db; 2104 int err = 0; 2105 if(buf == 0){ 2106 err = EINVAL; 2107 return err; 2108 } 2109 db_tr->buf = buf; 2110 db_tr->dbcnt = 3; 2111 db_tr->dummy = NULL; 2112 2113 db[0].db.desc.cmd = OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | 8; 2114 2115 db[2].db.desc.depend = 0; 2116 db[2].db.desc.addr = vtophys(buf) + sizeof(u_int32_t); 2117 db[2].db.desc.cmd = OHCI_OUTPUT_MORE; 2118 2119 db[0].db.desc.status = 0; 2120 db[0].db.desc.count = 0; 2121 2122 db[2].db.desc.status = 0; 2123 db[2].db.desc.count = 0; 2124 if( mode & FWXFERQ_STREAM ){ 2125 db[2].db.desc.cmd |= OHCI_OUTPUT_LAST; 2126 if(mode & FWXFERQ_PACKET ){ 2127 db[2].db.desc.cmd 2128 |= OHCI_INTERRUPT_ALWAYS; 2129 } 2130 } 2131 db[2].db.desc.cmd |= OHCI_BRANCH_ALWAYS; 2132 return 1; 2133} 2134 2135int 2136fwohci_add_rx_buf(struct fwohcidb_tr *db_tr, unsigned short size, int mode, 2137 void *buf, void *dummy) 2138{ 2139 volatile struct fwohcidb *db = db_tr->db; 2140 int i; 2141 void *dbuf[2]; 2142 int dsiz[2]; 2143 2144 if(buf == 0){ 2145 buf = malloc(size, M_DEVBUF, M_NOWAIT); 2146 if(buf == NULL) return 0; 2147 db_tr->buf = buf; 2148 db_tr->dbcnt = 1; 2149 db_tr->dummy = NULL; 2150 dsiz[0] = size; 2151 dbuf[0] = buf; 2152 }else if(dummy == NULL){ 2153 db_tr->buf = buf; 2154 db_tr->dbcnt = 1; 2155 db_tr->dummy = NULL; 2156 dsiz[0] = size; 2157 dbuf[0] = buf; 2158 }else{ 2159 db_tr->buf = buf; 2160 db_tr->dbcnt = 2; 2161 db_tr->dummy = dummy; 2162 dsiz[0] = sizeof(u_int32_t); 2163 dsiz[1] = size; 2164 dbuf[0] = dummy; 2165 dbuf[1] = buf; 2166 } 2167 for(i = 0 ; i < db_tr->dbcnt ; i++){ 2168 db[i].db.desc.addr = vtophys(dbuf[i]) ; 2169 db[i].db.desc.cmd = OHCI_INPUT_MORE | dsiz[i]; 2170 if( mode & FWXFERQ_STREAM ){ 2171 db[i].db.desc.cmd |= OHCI_UPDATE; 2172 } 2173 db[i].db.desc.status = 0; 2174 db[i].db.desc.count = dsiz[i]; 2175 } 2176 if( mode & FWXFERQ_STREAM ){ 2177 db[db_tr->dbcnt - 1].db.desc.cmd |= OHCI_INPUT_LAST; 2178 if(mode & FWXFERQ_PACKET ){ 2179 db[db_tr->dbcnt - 1].db.desc.cmd 2180 |= OHCI_INTERRUPT_ALWAYS; 2181 } 2182 } 2183 db[db_tr->dbcnt - 1].db.desc.cmd |= OHCI_BRANCH_ALWAYS; 2184 return 1; 2185} 2186 2187static void 2188fwohci_ircv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count) 2189{ 2190 struct fwohcidb_tr *db_tr = dbch->top, *odb_tr; 2191 struct firewire_comm *fc = (struct firewire_comm *)sc; 2192 int z = 1; 2193 struct fw_pkt *fp; 2194 u_int8_t *ld; 2195 u_int32_t off = NULL; 2196 u_int32_t stat; 2197 u_int32_t *qld; 2198 u_int32_t reg; 2199 u_int spd; 2200 u_int dmach; 2201 int len, i, plen; 2202 caddr_t buf; 2203 2204 for(dmach = 0 ; dmach < sc->fc.nisodma ; dmach++){ 2205 if( &sc->ir[dmach] == dbch){ 2206 off = OHCI_IROFF(dmach); 2207 break; 2208 } 2209 } 2210 if(off == NULL){ 2211 return; 2212 } 2213 if(!(dbch->xferq.flag & FWXFERQ_RUNNING)){ 2214 fwohci_irx_disable(&sc->fc, dmach); 2215 return; 2216 } 2217 2218 odb_tr = NULL; 2219 db_tr = dbch->top; 2220 i = 0; 2221 while ((reg = db_tr->db[0].db.desc.status) & 0x1f) { 2222 if (count >= 0 && count-- == 0) 2223 break; 2224 ld = (u_int8_t *)db_tr->buf; 2225 if (dbch->xferq.flag & FWXFERQ_PACKET) { 2226 /* skip timeStamp */ 2227 ld += sizeof(struct fwohci_trailer); 2228 } 2229 qld = (u_int32_t *)ld; 2230 len = dbch->xferq.psize - (db_tr->db[0].db.desc.count); 2231/* 2232{ 2233device_printf(sc->fc.dev, "%04x %2x 0x%08x 0x%08x 0x%08x 0x%08x\n", len, 2234 db_tr->db[0].db.desc.status & 0x1f, qld[0],qld[1],qld[2],qld[3]); 2235} 2236*/ 2237 fp=(struct fw_pkt *)ld; 2238 qld[0] = htonl(qld[0]); 2239 plen = sizeof(struct fw_isohdr) 2240 + ntohs(fp->mode.stream.len) + sizeof(u_int32_t); 2241 ld += plen; 2242 len -= plen; 2243 buf = db_tr->buf; 2244 db_tr->buf = NULL; 2245 stat = reg & 0x1f; 2246 spd = reg & 0x3; 2247 switch(stat){ 2248 case FWOHCIEV_ACKCOMPL: 2249 case FWOHCIEV_ACKPEND: 2250 fw_rcv(&sc->fc, buf, plen - sizeof(u_int32_t), dmach, sizeof(u_int32_t), spd); 2251 break; 2252 default: 2253 free(buf, M_DEVBUF); 2254 device_printf(sc->fc.dev, "Isochronous receive err %02x\n", stat); 2255 break; 2256 } 2257 i++; 2258 fwohci_add_rx_buf(db_tr, dbch->xferq.psize, 2259 dbch->xferq.flag, 0, NULL); 2260 db_tr->db[0].db.desc.depend &= ~0xf; 2261 if(dbch->pdb_tr != NULL){ 2262 dbch->pdb_tr->db[0].db.desc.depend |= z; 2263 } else { 2264 /* XXX should be rewritten in better way */ 2265 dbch->bottom->db[0].db.desc.depend |= z; 2266 } 2267 dbch->pdb_tr = db_tr; 2268 db_tr = STAILQ_NEXT(db_tr, link); 2269 } 2270 dbch->top = db_tr; 2271 reg = OREAD(sc, OHCI_DMACTL(off)); 2272 if (reg & OHCI_CNTL_DMA_ACTIVE) 2273 return; 2274 device_printf(sc->fc.dev, "IR DMA %d stopped at %x status=%x (%d)\n", 2275 dmach, OREAD(sc, OHCI_DMACMD(off)), reg, i); 2276 dbch->top = db_tr; 2277 fwohci_irx_enable(fc, dmach); 2278} 2279 2280#define PLEN(x) (((ntohs(x))+0x3) & ~0x3) 2281static int 2282fwohci_get_plen(struct fwohci_softc *sc, struct fw_pkt *fp, int hlen) 2283{ 2284 int i; 2285 2286 for( i = 4; i < hlen ; i+=4){ 2287 fp->mode.ld[i/4] = htonl(fp->mode.ld[i/4]); 2288 } 2289 2290 switch(fp->mode.common.tcode){ 2291 case FWTCODE_RREQQ: 2292 return sizeof(fp->mode.rreqq) + sizeof(u_int32_t); 2293 case FWTCODE_WRES: 2294 return sizeof(fp->mode.wres) + sizeof(u_int32_t); 2295 case FWTCODE_WREQQ: 2296 return sizeof(fp->mode.wreqq) + sizeof(u_int32_t); 2297 case FWTCODE_RREQB: 2298 return sizeof(fp->mode.rreqb) + sizeof(u_int32_t); 2299 case FWTCODE_RRESQ: 2300 return sizeof(fp->mode.rresq) + sizeof(u_int32_t); 2301 case FWTCODE_WREQB: 2302 return sizeof(struct fw_asyhdr) + PLEN(fp->mode.wreqb.len) 2303 + sizeof(u_int32_t); 2304 case FWTCODE_LREQ: 2305 return sizeof(struct fw_asyhdr) + PLEN(fp->mode.lreq.len) 2306 + sizeof(u_int32_t); 2307 case FWTCODE_RRESB: 2308 return sizeof(struct fw_asyhdr) + PLEN(fp->mode.rresb.len) 2309 + sizeof(u_int32_t); 2310 case FWTCODE_LRES: 2311 return sizeof(struct fw_asyhdr) + PLEN(fp->mode.lres.len) 2312 + sizeof(u_int32_t); 2313 case FWOHCITCODE_PHY: 2314 return 16; 2315 } 2316 device_printf(sc->fc.dev, "Unknown tcode %d\n", fp->mode.common.tcode); 2317 return 0; 2318} 2319 2320static void 2321fwohci_arcv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count) 2322{ 2323 struct fwohcidb_tr *db_tr; 2324 int z = 1; 2325 struct fw_pkt *fp; 2326 u_int8_t *ld; 2327 u_int32_t stat, off; 2328 u_int spd; 2329 int len, plen, hlen, pcnt, poff = 0, rlen; 2330 int s; 2331 caddr_t buf; 2332 int resCount; 2333 2334 if(&sc->arrq == dbch){ 2335 off = OHCI_ARQOFF; 2336 }else if(&sc->arrs == dbch){ 2337 off = OHCI_ARSOFF; 2338 }else{ 2339 return; 2340 } 2341 2342 s = splfw(); 2343 db_tr = dbch->top; 2344 pcnt = 0; 2345 /* XXX we cannot handle a packet which lies in more than two buf */ 2346 while (db_tr->db[0].db.desc.status & OHCI_CNTL_DMA_ACTIVE) { 2347 ld = (u_int8_t *)db_tr->buf + dbch->buf_offset; 2348 resCount = db_tr->db[0].db.desc.count; 2349 len = dbch->xferq.psize - resCount 2350 - dbch->buf_offset; 2351 while (len > 0 ) { 2352 if (count >= 0 && count-- == 0) 2353 goto out; 2354 if(dbch->frag.buf != NULL){ 2355 buf = dbch->frag.buf; 2356 if (dbch->frag.plen < 0) { 2357 /* incomplete header */ 2358 int hlen; 2359 2360 hlen = - dbch->frag.plen; 2361 rlen = hlen - dbch->frag.len; 2362 bcopy(ld, dbch->frag.buf + dbch->frag.len, rlen); 2363 ld += rlen; 2364 len -= rlen; 2365 dbch->frag.len += rlen; 2366#if 0 2367 printf("(1)frag.plen=%d frag.len=%d rlen=%d len=%d\n", dbch->frag.plen, dbch->frag.len, rlen, len); 2368#endif 2369 fp=(struct fw_pkt *)dbch->frag.buf; 2370 dbch->frag.plen 2371 = fwohci_get_plen(sc, fp, hlen); 2372 if (dbch->frag.plen == 0) 2373 goto out; 2374 } 2375 rlen = dbch->frag.plen - dbch->frag.len; 2376#if 0 2377 printf("(2)frag.plen=%d frag.len=%d rlen=%d len=%d\n", dbch->frag.plen, dbch->frag.len, rlen, len); 2378#endif 2379 bcopy(ld, dbch->frag.buf + dbch->frag.len, 2380 rlen); 2381 ld += rlen; 2382 len -= rlen; 2383 plen = dbch->frag.plen; 2384 dbch->frag.buf = NULL; 2385 dbch->frag.plen = 0; 2386 dbch->frag.len = 0; 2387 poff = 0; 2388 }else{ 2389 fp=(struct fw_pkt *)ld; 2390 fp->mode.ld[0] = htonl(fp->mode.ld[0]); 2391 switch(fp->mode.common.tcode){ 2392 case FWTCODE_RREQQ: 2393 case FWTCODE_WRES: 2394 case FWTCODE_WREQQ: 2395 case FWTCODE_RRESQ: 2396 case FWOHCITCODE_PHY: 2397 hlen = 12; 2398 break; 2399 case FWTCODE_RREQB: 2400 case FWTCODE_WREQB: 2401 case FWTCODE_LREQ: 2402 case FWTCODE_RRESB: 2403 case FWTCODE_LRES: 2404 hlen = 16; 2405 break; 2406 default: 2407 device_printf(sc->fc.dev, "Unknown tcode %d\n", fp->mode.common.tcode); 2408 goto out; 2409 } 2410 if (len >= hlen) { 2411 plen = fwohci_get_plen(sc, fp, hlen); 2412 if (plen == 0) 2413 goto out; 2414 plen = (plen + 3) & ~3; 2415 len -= plen; 2416 } else { 2417 plen = -hlen; 2418 len -= hlen; 2419 } 2420 if(resCount > 0 || len > 0){ 2421 buf = malloc( dbch->xferq.psize, 2422 M_DEVBUF, M_NOWAIT); 2423 if(buf == NULL){ 2424 printf("cannot malloc!\n"); 2425 free(db_tr->buf, M_DEVBUF); 2426 goto out; 2427 } 2428 bcopy(ld, buf, plen); 2429 poff = 0; 2430 dbch->frag.buf = NULL; 2431 dbch->frag.plen = 0; 2432 dbch->frag.len = 0; 2433 }else if(len < 0){ 2434 dbch->frag.buf = db_tr->buf; 2435 if (plen < 0) { 2436#if 0 2437 printf("plen < 0:" 2438 "hlen: %d len: %d\n", 2439 hlen, len); 2440#endif 2441 dbch->frag.len = hlen + len; 2442 dbch->frag.plen = -hlen; 2443 } else { 2444 dbch->frag.len = plen + len; 2445 dbch->frag.plen = plen; 2446 } 2447 bcopy(ld, db_tr->buf, dbch->frag.len); 2448 buf = NULL; 2449 }else{ 2450 buf = db_tr->buf; 2451 poff = ld - (u_int8_t *)buf; 2452 dbch->frag.buf = NULL; 2453 dbch->frag.plen = 0; 2454 dbch->frag.len = 0; 2455 } 2456 ld += plen; 2457 } 2458 if( buf != NULL){ 2459/* DMA result-code will be written at the tail of packet */ 2460 stat = ((struct fwohci_trailer *)(ld - sizeof(struct fwohci_trailer)))->stat; 2461 spd = (stat >> 5) & 0x3; 2462 stat &= 0x1f; 2463 switch(stat){ 2464 case FWOHCIEV_ACKPEND: 2465#if 0 2466 printf("fwohci_arcv: ack pending..\n"); 2467#endif 2468 /* fall through */ 2469 case FWOHCIEV_ACKCOMPL: 2470 if( poff != 0 ) 2471 bcopy(buf+poff, buf, plen - 4); 2472 fw_rcv(&sc->fc, buf, plen - sizeof(struct fwohci_trailer), 0, 0, spd); 2473 break; 2474 case FWOHCIEV_BUSRST: 2475 free(buf, M_DEVBUF); 2476 if (sc->fc.status != FWBUSRESET) 2477 printf("got BUSRST packet!?\n"); 2478 break; 2479 default: 2480 device_printf(sc->fc.dev, "Async DMA Receive error err = %02x %s\n", stat, fwohcicode[stat]); 2481#if 0 /* XXX */ 2482 goto out; 2483#endif 2484 break; 2485 } 2486 } 2487 pcnt ++; 2488 }; 2489out: 2490 if (resCount == 0) { 2491 /* done on this buffer */ 2492 fwohci_add_rx_buf(db_tr, dbch->xferq.psize, 2493 dbch->xferq.flag, 0, NULL); 2494 dbch->bottom->db[0].db.desc.depend |= z; 2495 dbch->bottom = db_tr; 2496 db_tr = STAILQ_NEXT(db_tr, link); 2497 dbch->top = db_tr; 2498 dbch->buf_offset = 0; 2499 } else { 2500 dbch->buf_offset = dbch->xferq.psize - resCount; 2501 break; 2502 } 2503 /* XXX make sure DMA is not dead */ 2504 } 2505#if 0 2506 if (pcnt < 1) 2507 printf("fwohci_arcv: no packets\n"); 2508#endif 2509 splx(s); 2510} 2511