firewire.c revision 106810
1155228Smjacob/* 2321870Smav * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa 3196008Smjacob * All rights reserved. 4167403Smjacob * 5196008Smjacob * Redistribution and use in source and binary forms, with or without 6167403Smjacob * modification, are permitted provided that the following conditions 7167403Smjacob * are met: 8167403Smjacob * 1. Redistributions of source code must retain the above copyright 9196008Smjacob * notice, this list of conditions and the following disclaimer. 10167403Smjacob * 2. Redistributions in binary form must reproduce the above copyright 11167403Smjacob * notice, this list of conditions and the following disclaimer in the 12167403Smjacob * documentation and/or other materials provided with the distribution. 13167403Smjacob * 3. All advertising materials mentioning features or use of this software 14167403Smjacob * must display the acknowledgement as bellow: 15196008Smjacob * 16167403Smjacob * This product includes software developed by K. Kobayashi and H. Shimokawa 17167403Smjacob * 18167403Smjacob * 4. The name of the author may not be used to endorse or promote products 19167403Smjacob * derived from this software without specific prior written permission. 20167403Smjacob * 21167403Smjacob * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22167403Smjacob * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23167403Smjacob * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24167403Smjacob * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25167403Smjacob * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26167403Smjacob * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27196008Smjacob * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28155228Smjacob * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29160410Smjacob * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 30160410Smjacob * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31160410Smjacob * POSSIBILITY OF SUCH DAMAGE. 32155704Smjacob * 33167403Smjacob * $FreeBSD: head/sys/dev/firewire/firewire.c 106810 2002-11-12 13:49:17Z simokawa $ 34167403Smjacob * 35155704Smjacob */ 36155704Smjacob 37155704Smjacob#include <sys/param.h> 38160410Smjacob#include <sys/systm.h> 39160410Smjacob#include <sys/types.h> 40155228Smjacob#include <sys/mbuf.h> 41155704Smjacob#include <sys/socket.h> 42155704Smjacob#include <sys/socketvar.h> 43155704Smjacob 44155704Smjacob#include <sys/kernel.h> 45155704Smjacob#include <sys/malloc.h> 46155704Smjacob#include <sys/conf.h> 47155704Smjacob#include <sys/uio.h> 48155704Smjacob#include <sys/sysctl.h> 49155704Smjacob#include <sys/poll.h> 50155704Smjacob 51155228Smjacob#include <machine/cpufunc.h> /* for rdtsc proto for clock.h below */ 52196008Smjacob#include <machine/clock.h> 53196008Smjacob#include <pci/pcivar.h> 54196008Smjacob#include <pci/pcireg.h> 55196008Smjacob 56196008Smjacob#include <vm/vm.h> 57196008Smjacob#include <vm/pmap.h> /* for vtophys proto */ 58196008Smjacob#include <vm/vm_extern.h> 59196008Smjacob 60196008Smjacob#include <sys/bus.h> /* used by smbus and newbus */ 61155228Smjacob 62238869Smjacob#include <machine/bus.h> /* used by newbus */ 63196008Smjacob#include <sys/rman.h> /* used by newbus */ 64196008Smjacob#include <machine/resource.h> /* used by newbus */ 65317360Smav 66317360Smav#include <sys/signal.h> 67196008Smjacob#include <sys/mman.h> 68196008Smjacob#include <sys/ioccom.h> 69196008Smjacob 70196008Smjacob#include <dev/firewire/firewire.h> 71196008Smjacob#include <dev/firewire/firewirereg.h> 72196008Smjacob#include <dev/firewire/fwmem.h> 73196008Smjacob#include <dev/firewire/iec13213.h> 74196008Smjacob#include <dev/firewire/iec68113.h> 75196008Smjacob 76196008Smjacobint firewire_debug=0; 77196008SmjacobSYSCTL_NODE(_hw, OID_AUTO, firewire, CTLFLAG_RD, 0, "Firewire Subsystem"); 78196008SmjacobSYSCTL_INT(_debug, OID_AUTO, firewire_debug, CTLFLAG_RW, &firewire_debug, 0, 79196008Smjacob "Firewire driver debug flag"); 80196008Smjacob 81196008Smjacob#define CDEV_MAJOR 127 82196008Smjacob#define FW_MAXASYRTY 4 83196008Smjacob#define FW_MAXDEVRCNT 4 84196008Smjacob#define FWNODE_INVAL 0xffff 85196008Smjacob 86196008Smjacob#define XFER_TIMEOUT 0 87196008Smjacob 88196008Smjacobstatic d_open_t fw_open; 89196008Smjacobstatic d_close_t fw_close; 90196008Smjacobstatic d_ioctl_t fw_ioctl; 91196008Smjacobstatic d_poll_t fw_poll; 92317360Smavstatic d_read_t fw_read; /* for Isochronous packet */ 93317360Smavstatic d_write_t fw_write; 94317360Smavstatic d_mmap_t fw_mmap; 95317360Smav 96317360Smavdevclass_t firewire_devclass; 97317360Smav 98317360Smav 99317360Smavstatic int firewire_match __P((device_t)); 100317360Smavstatic int firewire_attach __P((device_t)); 101317360Smavstatic int firewire_detach __P((device_t)); 102317360Smav#if 0 103317360Smavstatic int firewire_shutdown __P((device_t)); 104196008Smjacob#endif 105317360Smavstatic device_t firewire_add_child __P((device_t, int, const char *, int)); 106317360Smavstatic struct fw_bind *fw_bindlookup __P((struct firewire_comm *, u_int32_t, u_int32_t)); 107196008Smjacobstatic void fw_try_bmr __P((void *)); 108196008Smjacobstatic void fw_try_bmr_callback __P((struct fw_xfer *)); 109196008Smjacobstatic void fw_asystart __P((struct fw_xfer *)); 110196008Smjacobstatic int fw_get_tlabel __P((struct firewire_comm *, struct fw_xfer *)); 111196008Smjacobstatic void fw_bus_probe __P((struct firewire_comm *)); 112196008Smjacobstatic void fw_bus_explore __P((struct firewire_comm *)); 113196008Smjacobstatic void fw_bus_explore_callback __P((struct fw_xfer *)); 114196008Smjacobstatic void fw_attach_dev __P((struct firewire_comm *)); 115196008Smjacob#ifdef FW_VMACCESS 116196008Smjacobstatic void fw_vmaccess __P((struct fw_xfer *)); 117196008Smjacob#endif 118196008Smjacobstruct fw_xfer *asyreqq __P((struct firewire_comm *, u_int8_t, u_int8_t, u_int8_t, 119196008Smjacob u_int32_t, u_int32_t, void (*)__P((struct fw_xfer *)))); 120196008Smjacob 121196008Smjacobstatic device_method_t firewire_methods[] = { 122196008Smjacob /* Device interface */ 123196008Smjacob DEVMETHOD(device_probe, firewire_match), 124196008Smjacob DEVMETHOD(device_attach, firewire_attach), 125196008Smjacob DEVMETHOD(device_detach, firewire_detach), 126196008Smjacob DEVMETHOD(device_shutdown, bus_generic_shutdown), 127196008Smjacob 128196008Smjacob /* Bus interface */ 129196008Smjacob DEVMETHOD(bus_add_child, firewire_add_child), 130196008Smjacob DEVMETHOD(bus_print_child, bus_generic_print_child), 131196008Smjacob 132196008Smjacob { 0, 0 } 133196008Smjacob}; 134196008Smjacobchar linkspeed[7][0x10]={"S100","S200","S400","S800","S1600","S3200","Unknown"}; 135196008Smjacobu_int maxrec[6]={512,1024,2048,4096,8192,0}; 136196008Smjacob 137196008Smjacob#define MAX_GAPHOP 16 138317360Smavu_int gap_cnt[] = {1, 1, 4, 6, 9, 12, 14, 17, 139317360Smav 20, 23, 25, 28, 31, 33, 36, 39, 42}; 140317360Smav/* 141317360Smav * The probe routine. 142317360Smav */ 143317360Smavstruct cdevsw firewire_cdevsw = 144317360Smav{ 145317360Smav fw_open, fw_close, fw_read, fw_write, fw_ioctl, 146317360Smav fw_poll, fw_mmap, nostrategy, "fw", CDEV_MAJOR, nodump, nopsize, D_MEM 147317360Smav}; 148317360Smavstatic driver_t firewire_driver = { 149317360Smav "firewire", 150317360Smav firewire_methods, 151317360Smav sizeof(struct firewire_softc), 152196008Smjacob}; 153196008Smjacob 154196008Smjacobstatic int 155317360Smavfw_open (dev_t dev, int flags, int fmt, fw_proc *td) 156196008Smjacob{ 157317360Smav struct firewire_softc *sc; 158317360Smav int unit = DEV2UNIT(dev); 159196008Smjacob int sub = DEV2DMACH(dev); 160196008Smjacob 161196008Smjacob int err = 0; 162196008Smjacob 163196008Smjacob if (DEV_FWMEM(dev)) 164196008Smjacob return fwmem_open(dev, flags, fmt, td); 165196008Smjacob 166196008Smjacob sc = devclass_get_softc(firewire_devclass, unit); 167196008Smjacob if(sc->fc->ir[sub]->flag & FWXFERQ_OPEN){ 168196008Smjacob err = EBUSY; 169196008Smjacob return err; 170196008Smjacob } 171196008Smjacob if(sc->fc->it[sub]->flag & FWXFERQ_OPEN){ 172261515Smav err = EBUSY; 173261515Smav return err; 174261515Smav } 175196008Smjacob if(sc->fc->ir[sub]->flag & FWXFERQ_MODEMASK){ 176196008Smjacob err = EBUSY; 177196008Smjacob return err; 178196008Smjacob } 179196008Smjacob/* Default is per packet mode */ 180196008Smjacob sc->fc->ir[sub]->flag |= FWXFERQ_OPEN; 181196008Smjacob sc->fc->it[sub]->flag |= FWXFERQ_OPEN; 182196008Smjacob sc->fc->ir[sub]->flag |= FWXFERQ_PACKET; 183196008Smjacob return err; 184196008Smjacob} 185196008Smjacobstatic int 186196008Smjacobfw_close (dev_t dev, int flags, int fmt, fw_proc *td) 187196008Smjacob{ 188196008Smjacob struct firewire_softc *sc; 189196008Smjacob int unit = DEV2UNIT(dev); 190196008Smjacob int sub = DEV2DMACH(dev); 191196008Smjacob struct fw_xfer *xfer; 192317360Smav struct fw_dvbuf *dvbuf; 193317360Smav struct fw_bind *fwb; 194317360Smav int err = 0; 195317360Smav 196196008Smjacob if (DEV_FWMEM(dev)) 197196008Smjacob return fwmem_close(dev, flags, fmt, td); 198196008Smjacob 199196008Smjacob sc = devclass_get_softc(firewire_devclass, unit); 200196008Smjacob if(!(sc->fc->ir[sub]->flag & FWXFERQ_OPEN)){ 201196008Smjacob err = EINVAL; 202196008Smjacob return err; 203196008Smjacob } 204196008Smjacob sc->fc->ir[sub]->flag &= ~FWXFERQ_OPEN; 205196008Smjacob if(!(sc->fc->it[sub]->flag & FWXFERQ_OPEN)){ 206196008Smjacob err = EINVAL; 207196008Smjacob return err; 208297817Smav } 209297817Smav sc->fc->it[sub]->flag &= ~FWXFERQ_OPEN; 210196008Smjacob 211196008Smjacob if(sc->fc->ir[sub]->flag & FWXFERQ_RUNNING){ 212196008Smjacob sc->fc->irx_disable(sc->fc, sub); 213196008Smjacob } 214196008Smjacob if(sc->fc->it[sub]->flag & FWXFERQ_RUNNING){ 215196008Smjacob sc->fc->it[sub]->flag &= ~FWXFERQ_RUNNING; 216196008Smjacob sc->fc->itx_disable(sc->fc, sub); 217196008Smjacob } 218196008Smjacob if(sc->fc->it[sub]->flag & FWXFERQ_DV){ 219317360Smav if((dvbuf = sc->fc->it[sub]->dvproc) != NULL){ 220317360Smav free(dvbuf->buf, M_DEVBUF); 221196008Smjacob sc->fc->it[sub]->dvproc = NULL; 222196008Smjacob } 223196008Smjacob if((dvbuf = sc->fc->it[sub]->dvdma) != NULL){ 224196008Smjacob free(dvbuf->buf, M_DEVBUF); 225196008Smjacob sc->fc->it[sub]->dvdma = NULL; 226196008Smjacob } 227317360Smav while((dvbuf = STAILQ_FIRST(&sc->fc->it[sub]->dvvalid)) != NULL){ 228317360Smav STAILQ_REMOVE_HEAD(&sc->fc->it[sub]->dvvalid, link); 229196008Smjacob free(dvbuf->buf, M_DEVBUF); 230196008Smjacob } 231196008Smjacob while((dvbuf = STAILQ_FIRST(&sc->fc->it[sub]->dvfree)) != NULL){ 232196008Smjacob STAILQ_REMOVE_HEAD(&sc->fc->it[sub]->dvfree, link); 233196008Smjacob free(dvbuf->buf, M_DEVBUF); 234196008Smjacob } 235196008Smjacob free(sc->fc->it[sub]->dvbuf, M_DEVBUF); 236196008Smjacob sc->fc->it[sub]->dvbuf = NULL; 237196008Smjacob } 238196008Smjacob if(sc->fc->ir[sub]->flag & FWXFERQ_EXTBUF){ 239196008Smjacob free(sc->fc->ir[sub]->buf, M_DEVBUF); 240196008Smjacob sc->fc->ir[sub]->buf = NULL; 241196008Smjacob free(sc->fc->ir[sub]->bulkxfer, M_DEVBUF); 242196008Smjacob sc->fc->ir[sub]->bulkxfer = NULL; 243196008Smjacob sc->fc->ir[sub]->flag &= ~FWXFERQ_EXTBUF; 244196008Smjacob sc->fc->ir[sub]->psize = FWPMAX_S400; 245196008Smjacob sc->fc->ir[sub]->maxq = FWMAXQUEUE; 246196008Smjacob } 247196008Smjacob if(sc->fc->it[sub]->flag & FWXFERQ_EXTBUF){ 248196008Smjacob free(sc->fc->it[sub]->buf, M_DEVBUF); 249196008Smjacob sc->fc->it[sub]->buf = NULL; 250196008Smjacob free(sc->fc->it[sub]->bulkxfer, M_DEVBUF); 251196008Smjacob sc->fc->it[sub]->bulkxfer = NULL; 252196008Smjacob sc->fc->it[sub]->dvbuf = NULL; 253196008Smjacob sc->fc->it[sub]->flag &= ~FWXFERQ_EXTBUF; 254196008Smjacob sc->fc->it[sub]->psize = FWPMAX_S400; 255317360Smav sc->fc->it[sub]->maxq = FWMAXQUEUE; 256196008Smjacob } 257196008Smjacob for(xfer = STAILQ_FIRST(&sc->fc->ir[sub]->q); 258196008Smjacob xfer != NULL; xfer = STAILQ_FIRST(&sc->fc->ir[sub]->q)){ 259196008Smjacob sc->fc->ir[sub]->queued--; 260317360Smav STAILQ_REMOVE_HEAD(&sc->fc->ir[sub]->q, link); 261317360Smav 262317360Smav xfer->resp = 0; 263317360Smav switch(xfer->act_type){ 264317360Smav case FWACT_XFER: 265317360Smav fw_xfer_done(xfer); 266317360Smav break; 267317360Smav default: 268317360Smav break; 269317360Smav } 270317360Smav fw_xfer_free(xfer); 271317360Smav } 272317360Smav for(fwb = STAILQ_FIRST(&sc->fc->ir[sub]->binds); fwb != NULL; 273317360Smav fwb = STAILQ_FIRST(&sc->fc->ir[sub]->binds)){ 274317360Smav STAILQ_REMOVE(&sc->fc->binds, fwb, fw_bind, fclist); 275317360Smav STAILQ_REMOVE_HEAD(&sc->fc->ir[sub]->binds, chlist); 276317360Smav free(fwb, M_DEVBUF); 277317360Smav } 278317360Smav sc->fc->ir[sub]->flag &= ~FWXFERQ_MODEMASK; 279317360Smav sc->fc->it[sub]->flag &= ~FWXFERQ_MODEMASK; 280317360Smav return err; 281317360Smav} 282317360Smav/* 283196008Smjacob * read request. 284196008Smjacob */ 285196008Smjacobstatic int 286196008Smjacobfw_read (dev_t dev, struct uio *uio, int ioflag) 287297817Smav{ 288196008Smjacob struct firewire_softc *sc; 289196008Smjacob struct fw_xferq *ir; 290196008Smjacob struct fw_xfer *xfer; 291196008Smjacob int err = 0, s, slept = 0; 292196008Smjacob int unit = DEV2UNIT(dev); 293292725Smav int sub = DEV2DMACH(dev); 294292725Smav struct fw_pkt *fp; 295155228Smjacob 296203444Smjacob if (DEV_FWMEM(dev)) 297155228Smjacob return fwmem_read(dev, uio, ioflag); 298203444Smjacob 299292725Smav sc = devclass_get_softc(firewire_devclass, unit); 300292725Smav 301203444Smjacob ir = sc->fc->ir[sub]; 302203444Smjacob 303203444Smjacob if(ir->flag & FWXFERQ_PACKET){ 304292725Smav ir->stproc = NULL; 305203444Smjacob } 306292725Smavreadloop: 307155228Smjacob xfer = STAILQ_FIRST(&ir->q); 308155228Smjacob if(!(ir->flag & FWXFERQ_PACKET) && ir->stproc == NULL){ 309292725Smav ir->stproc = STAILQ_FIRST(&ir->stvalid); 310163899Smjacob if(ir->stproc != NULL){ 311155228Smjacob s = splfw(); 312292725Smav STAILQ_REMOVE_HEAD(&ir->stvalid, link); 313203444Smjacob splx(s); 314155228Smjacob ir->queued = 0; 315155228Smjacob } 316203444Smjacob } 317155228Smjacob 318155228Smjacob if(xfer == NULL && ir->stproc == NULL){ 319163899Smjacob if(slept == 0){ 320292725Smav slept = 1; 321155228Smjacob if(!(ir->flag & FWXFERQ_RUNNING) 322203444Smjacob && (ir->flag & FWXFERQ_PACKET)){ 323203444Smjacob err = sc->fc->irx_enable(sc->fc, sub); 324155228Smjacob } 325155228Smjacob if(err){ 326203444Smjacob return err; 327203444Smjacob } 328155228Smjacob ir->flag |= FWXFERQ_WAKEUP; 329203444Smjacob err = tsleep((caddr_t)ir, FWPRI, "fw_read", hz); 330203444Smjacob if(err){ 331155228Smjacob ir->flag &= ~FWXFERQ_WAKEUP; 332155228Smjacob return err; 333203444Smjacob } 334155228Smjacob goto readloop; 335155228Smjacob }else{ 336155228Smjacob err = EIO; 337163899Smjacob return err; 338155228Smjacob } 339292725Smav }else if(xfer != NULL){ 340203444Smjacob s = splfw(); 341203444Smjacob ir->queued --; 342203444Smjacob STAILQ_REMOVE_HEAD(&ir->q, link); 343203444Smjacob splx(s); 344203444Smjacob fp = (struct fw_pkt *)(xfer->recv.buf + xfer->recv.off); 345155228Smjacob if(sc->fc->irx_post != NULL) 346155228Smjacob sc->fc->irx_post(sc->fc, fp->mode.ld); 347155228Smjacob err = uiomove(xfer->recv.buf + xfer->recv.off, xfer->recv.len, uio); 348196008Smjacob fw_xfer_free( xfer); 349196008Smjacob }else if(ir->stproc != NULL){ 350196008Smjacob fp = (struct fw_pkt *)(ir->stproc->buf + ir->queued * ir->psize); 351196008Smjacob if(sc->fc->irx_post != NULL) 352196008Smjacob sc->fc->irx_post(sc->fc, fp->mode.ld); 353196008Smjacob if(ntohs(fp->mode.stream.len) == 0){ 354196008Smjacob err = EIO; 355196008Smjacob return err; 356155228Smjacob } 357257916Smav err = uiomove((caddr_t)fp, ntohs(fp->mode.stream.len) + sizeof(u_int32_t), uio); 358257916Smav fp->mode.stream.len = 0; 359257916Smav ir->queued ++; 360257916Smav if(ir->queued >= ir->bnpacket){ 361257916Smav s = splfw(); 362257916Smav ir->stproc->flag = 0; 363257916Smav STAILQ_INSERT_TAIL(&ir->stfree, ir->stproc, link); 364155228Smjacob splx(s); 365196008Smjacob ir->stproc = NULL; 366155228Smjacob } 367155228Smjacob } 368155228Smjacob#if 0 369155228Smjacob if(STAILQ_FIRST(&ir->q) == NULL && 370196008Smjacob (ir->flag & FWXFERQ_RUNNING) && (ir->flag & FWXFERQ_PACKET)){ 371155228Smjacob err = sc->fc->irx_enable(sc->fc, sub); 372155228Smjacob } 373155228Smjacob#endif 374155704Smjacob#if 0 375155228Smjacob if(STAILQ_FIRST(&ir->stvalid) == NULL && 376155228Smjacob (ir->flag & FWXFERQ_RUNNING) && !(ir->flag & FWXFERQ_PACKET)){ 377155228Smjacob err = sc->fc->irx_enable(sc->fc, sub); 378155228Smjacob } 379196008Smjacob#endif 380155228Smjacob return err; 381196008Smjacob} 382155228Smjacobstatic int 383208997Smjacobfw_write (dev_t dev, struct uio *uio, int ioflag) 384155228Smjacob{ 385155228Smjacob int err = 0; 386155228Smjacob struct firewire_softc *sc; 387155228Smjacob int unit = DEV2UNIT(dev); 388167821Smjacob int sub = DEV2DMACH(dev); 389155228Smjacob int tl, s, slept = 0; 390155228Smjacob struct fw_pkt *fp; 391155704Smjacob struct fw_xfer *xfer; 392155228Smjacob struct fw_xferq *xferq; 393155228Smjacob struct firewire_comm *fc; 394155228Smjacob struct fw_xferq *it; 395155228Smjacob 396155228Smjacob if (DEV_FWMEM(dev)) 397155228Smjacob return fwmem_write(dev, uio, ioflag); 398155228Smjacob 399155228Smjacob sc = devclass_get_softc(firewire_devclass, unit); 400155228Smjacob fc = sc->fc; 401155228Smjacob it = sc->fc->it[sub]; 402196008Smjacob 403196008Smjacob fp = (struct fw_pkt *)uio->uio_iov->iov_base; 404155228Smjacob switch(fp->mode.common.tcode){ 405196008Smjacob case FWTCODE_RREQQ: 406155228Smjacob case FWTCODE_RREQB: 407155228Smjacob case FWTCODE_LREQ: 408155228Smjacob err = EINVAL; 409155228Smjacob return err; 410155228Smjacob case FWTCODE_WREQQ: 411155228Smjacob case FWTCODE_WREQB: 412155228Smjacob xferq = fc->atq; 413155228Smjacob break; 414155228Smjacob case FWTCODE_STREAM: 415155228Smjacob if(it->flag & FWXFERQ_PACKET){ 416155228Smjacob xferq = fc->atq; 417155228Smjacob }else{ 418155228Smjacob xferq = NULL; 419155228Smjacob } 420155228Smjacob break; 421155228Smjacob case FWTCODE_WRES: 422155228Smjacob case FWTCODE_RRESQ: 423155228Smjacob case FWTCODE_RRESB: 424155228Smjacob case FWTCODE_LRES: 425196008Smjacob xferq = fc->ats; 426155228Smjacob break; 427291365Smav default: 428291365Smav err = EINVAL; 429155228Smjacob return err; 430291365Smav } 431291365Smav /* Discard unsent buffered stream packet, when sending Asyrequrst */ 432290993Smav if(xferq != NULL && it->stproc != NULL){ 433291365Smav s = splfw(); 434291365Smav it->stproc->flag = 0; 435291365Smav STAILQ_INSERT_TAIL(&it->stfree, it->stproc, link); 436291365Smav splx(s); 437291365Smav it->stproc = NULL; 438291365Smav } 439291365Smav if(xferq == NULL && !(it->flag & FWXFERQ_DV)){ 440291365Smavisoloop: 441291365Smav if(it->stproc == NULL){ 442291365Smav it->stproc = STAILQ_FIRST(&it->stfree); 443291365Smav if(it->stproc != NULL){ 444291365Smav s = splfw(); 445291365Smav STAILQ_REMOVE_HEAD(&it->stfree, link); 446291365Smav splx(s); 447291365Smav it->queued = 0; 448291365Smav }else if(slept == 0){ 449291365Smav slept = 1; 450291365Smav err = sc->fc->itx_enable(sc->fc, sub); 451291365Smav if(err){ 452155228Smjacob return err; 453155228Smjacob } 454164272Smjacob err = tsleep((caddr_t)it, FWPRI, "fw_write", hz); 455196008Smjacob if(err){ 456164272Smjacob return err; 457163899Smjacob } 458196008Smjacob goto isoloop; 459164272Smjacob }else{ 460196008Smjacob err = EIO; 461164272Smjacob return err; 462164272Smjacob } 463164272Smjacob } 464285459Smav fp = (struct fw_pkt *)(it->stproc->buf + it->queued * it->psize); 465164272Smjacob fp->mode.stream.len = htons(uio->uio_resid - sizeof(u_int32_t)); 466164272Smjacob err = uiomove(it->stproc->buf + it->queued * it->psize, 467164272Smjacob uio->uio_resid, uio); 468164272Smjacob it->queued ++; 469164272Smjacob if(it->queued >= it->btpacket){ 470164272Smjacob s = splfw(); 471164272Smjacob STAILQ_INSERT_TAIL(&it->stvalid, it->stproc, link); 472164272Smjacob splx(s); 473164272Smjacob it->stproc = NULL; 474164272Smjacob fw_tbuf_update(sc->fc, sub, 0); 475164272Smjacob err = sc->fc->itx_enable(sc->fc, sub); 476164272Smjacob } 477285459Smav return err; 478164272Smjacob } if(xferq == NULL && it->flag & FWXFERQ_DV){ 479164272Smjacobdvloop: 480238869Smjacob if(it->dvproc == NULL){ 481238869Smjacob it->dvproc = STAILQ_FIRST(&it->dvfree); 482300052Smav if(it->dvproc != NULL){ 483300052Smav s = splfw(); 484196008Smjacob STAILQ_REMOVE_HEAD(&it->dvfree, link); 485164272Smjacob splx(s); 486164272Smjacob it->dvptr = 0; 487164272Smjacob }else if(slept == 0){ 488238869Smjacob slept = 1; 489238869Smjacob err = sc->fc->itx_enable(sc->fc, sub); 490238869Smjacob if(err){ 491238869Smjacob return err; 492238869Smjacob } 493238869Smjacob err = tsleep((caddr_t)it, FWPRI, "fw_write", hz); 494238869Smjacob if(err){ 495238869Smjacob return err; 496238869Smjacob } 497238869Smjacob goto dvloop; 498238869Smjacob }else{ 499238869Smjacob err = EIO; 500238869Smjacob return err; 501238869Smjacob } 502238869Smjacob } 503238869Smjacob fp = (struct fw_pkt *)(it->dvproc->buf + it->queued * it->psize); 504238869Smjacob fp->mode.stream.len = htons(uio->uio_resid - sizeof(u_int32_t)); 505238869Smjacob err = uiomove(it->dvproc->buf + it->dvptr, 506238869Smjacob uio->uio_resid, uio); 507238869Smjacob it->dvptr += it->psize; 508238869Smjacob if(err){ 509238869Smjacob return err; 510238869Smjacob } 511238869Smjacob if(it->dvptr >= it->psize * it->dvpacket){ 512238869Smjacob s = splfw(); 513238869Smjacob STAILQ_INSERT_TAIL(&it->dvvalid, it->dvproc, link); 514238869Smjacob splx(s); 515238869Smjacob it->dvproc = NULL; 516238869Smjacob err = fw_tbuf_update(sc->fc, sub, 0); 517238869Smjacob if(err){ 518238869Smjacob return err; 519238869Smjacob } 520238869Smjacob err = sc->fc->itx_enable(sc->fc, sub); 521238869Smjacob } 522238869Smjacob return err; 523238869Smjacob } 524238869Smjacob if(xferq != NULL){ 525238869Smjacob xfer = fw_xfer_alloc(); 526238869Smjacob if(xfer == NULL){ 527238869Smjacob err = ENOMEM; 528238869Smjacob return err; 529238869Smjacob } 530238869Smjacob xfer->send.buf = malloc(uio->uio_resid, M_DEVBUF, M_NOWAIT); 531238869Smjacob if(xfer->send.buf == NULL){ 532238869Smjacob fw_xfer_free( xfer); 533238869Smjacob err = ENOBUFS; 534238869Smjacob return err; 535238869Smjacob } 536238869Smjacob xfer->dst = ntohs(fp->mode.hdr.dst); 537238869Smjacob 538238869Smjacob switch(fp->mode.common.tcode){ 539238869Smjacob case FWTCODE_WREQQ: 540238869Smjacob case FWTCODE_WREQB: 541238869Smjacob if((tl = fw_get_tlabel(fc, xfer)) == -1 ){ 542238869Smjacob fw_xfer_free( xfer); 543238869Smjacob err = EAGAIN; 544238869Smjacob return err; 545238869Smjacob } 546238869Smjacob fp->mode.hdr.tlrt = tl << 2; 547238869Smjacob default: 548238869Smjacob break; 549238869Smjacob } 550238869Smjacob 551238869Smjacob xfer->tl = fp->mode.hdr.tlrt >> 2; 552238869Smjacob xfer->send.len = uio->uio_resid; 553238869Smjacob xfer->send.off = 0; 554238869Smjacob xfer->tcode = fp->mode.common.tcode; 555196008Smjacob xfer->spd = 0;/* XXX: how to setup it */ 556196008Smjacob xfer->fc = fc; 557196008Smjacob xfer->q = xferq; 558196008Smjacob xfer->act_type = FWACT_XFER; 559196008Smjacob xfer->act.hand = fw_asy_callback; 560290993Smav xfer->retry_req = fw_asybusy; 561196008Smjacob 562196008Smjacob err = uiomove(xfer->send.buf, uio->uio_resid, uio); 563196008Smjacob if(err){ 564196008Smjacob return err; 565196008Smjacob } 566196008Smjacob fw_asystart(xfer); 567196008Smjacob err = tsleep((caddr_t)xfer, FWPRI, "fw_write", hz); 568196008Smjacob if(xfer->resp == EBUSY) 569196008Smjacob return EBUSY; 570196008Smjacob fw_xfer_free( xfer); 571196008Smjacob return err; 572196008Smjacob } 573196008Smjacob return EINVAL; 574196008Smjacob} 575196008Smjacob/* 576291365Smav * transmitter buffer update. 577297991Smav */ 578290993Smavint 579290993Smavfw_tbuf_update(struct firewire_comm *fc, int sub, int flag){ 580290993Smav struct fw_bulkxfer *bulkxfer, *bulkxfer2 = NULL; 581196008Smjacob struct fw_dvbuf *dvbuf = NULL; 582196008Smjacob struct fw_xferq *it; 583196008Smjacob int s, err = 0, i, j, chtag; 584196008Smjacob struct fw_pkt *fp; 585196008Smjacob u_int64_t tmpsync, dvsync; 586196008Smjacob 587196008Smjacob it = fc->it[sub]; 588196008Smjacob 589196008Smjacob s = splfw(); 590196008Smjacob if(it->stdma == NULL){ 591196008Smjacob bulkxfer = STAILQ_FIRST(&it->stvalid); 592196008Smjacob }else if(flag != 0){ 593196008Smjacob bulkxfer = STAILQ_FIRST(&it->stvalid); 594297991Smav if(bulkxfer == it->stdma){ 595196008Smjacob STAILQ_REMOVE_HEAD(&it->stvalid, link); 596196008Smjacob it->stdma->flag = 0; 597196008Smjacob STAILQ_INSERT_TAIL(&it->stfree, it->stdma, link); 598291080Smav if(!(it->flag & FWXFERQ_DV)) 599291080Smav wakeup(it); 600291080Smav } 601291080Smav bulkxfer = STAILQ_FIRST(&it->stvalid); 602291080Smav }else{ 603196008Smjacob bulkxfer = it->stdma; 604196008Smjacob } 605196008Smjacob splx(s); 606196008Smjacob if(bulkxfer != NULL){ 607164272Smjacob s = splfw(); 608196008Smjacob bulkxfer2 = STAILQ_NEXT(bulkxfer, link); 609196008Smjacob#if 0 610203444Smjacob if(it->flag & FWXFERQ_DV && bulkxfer2 == NULL){ 611203444Smjacob bulkxfer2 = STAILQ_FIRST(&it->stfree); 612196008Smjacob STAILQ_REMOVE_HEAD(&it->stfree, link); 613196008Smjacob splx(s); 614196008Smjacob bcopy(bulkxfer->buf, bulkxfer2->buf, 615196008Smjacob it->psize * it->btpacket); 616196008Smjacob s = splfw(); 617203444Smjacob STAILQ_INSERT_TAIL(&it->stvalid, bulkxfer2, link); 618203444Smjacob } 619292739Smav#endif 620292739Smav splx(s); 621292725Smav } 622292725Smav it->stdma = bulkxfer; 623292725Smav it->stdma2 = bulkxfer2; 624292725Smav 625292725Smav if(it->flag & FWXFERQ_DV){ 626292725Smav chtag = it->flag & 0xff; 627292725Smavdvloop: 628292739Smav if(it->dvdma == NULL){ 629292725Smav dvbuf = STAILQ_FIRST(&it->dvvalid); 630292725Smav if(dvbuf != NULL){ 631292739Smav s = splfw(); 632292739Smav STAILQ_REMOVE_HEAD(&it->dvvalid, link); 633292725Smav it->dvdma = dvbuf; 634292739Smav splx(s); 635292725Smav it->queued = 0; 636292725Smav } 637292725Smav } 638292725Smav if(it->dvdma == NULL) 639292725Smav return err; 640292725Smav 641292725Smav it->stproc = STAILQ_FIRST(&it->stfree); 642292725Smav if(it->stproc != NULL){ 643292725Smav s = splfw(); 644292725Smav STAILQ_REMOVE_HEAD(&it->stfree, link); 645292725Smav splx(s); 646292725Smav }else{ 647292725Smav return err; 648292725Smav } 649292725Smav/* 650292739Smav * Insert least significant 12 bits timestamp value by computation. 651292739Smav * Highest significant 4 bits is insert at just before packet sending. 652292725Smav */ 653292739Smav fp = (struct fw_pkt *)(it->stproc->buf); 654292739Smav/* XXX: Parameter relies on NTSC type DV video */ 655292739Smav tmpsync = (u_int64_t)3072 * 8000 * 100 / 2997; 656292739Smav tmpsync *= it->dvsync; 657196008Smjacob dvsync = tmpsync; 658196008Smjacob dvsync %= 0xc00; 659196008Smjacob fp->mode.ld[2] = htonl(0x80000000 | (dvsync % 0xc00)); 660196008Smjacob it->dvsync ++; 661196008Smjacob it->dvsync %= 2997; 662196008Smjacob 663196008Smjacob for( i = 0, j = 0 ; i < it->dvpacket ; i++){ 664196008Smjacob bcopy(it->dvdma->buf + it->queued * it->psize, 665196008Smjacob it->stproc->buf + j * it->psize, it->psize); 666196008Smjacob fp = (struct fw_pkt *)(it->stproc->buf + j * it->psize); 667196008Smjacob fp->mode.stream.len = htons(488); 668196008Smjacob fp->mode.stream.chtag = chtag; 669196008Smjacob fp->mode.stream.tcode = FWTCODE_STREAM; 670196008Smjacob fp->mode.ld[1] = htonl((fc->nodeid << 24) | 0x00780000 | it->dvdbc); 671196008Smjacob it->dvdbc++; 672196008Smjacob it->dvdbc %= 256; 673196008Smjacob it->queued ++; 674196008Smjacob j++; 675196008Smjacob/* XXX: Parameter relies on NTSC type DV video */ 676196008Smjacob#if 1 677155228Smjacob#define DVDIFF 203 678155228Smjacob#define DVFRAC 2997 679155228Smjacob#else 680155228Smjacob#define DVDIFF 127 681155228Smjacob#define DVFRAC 1875 682155228Smjacob#endif 683155228Smjacob it->dvdiff += DVDIFF; 684155228Smjacob if(it->dvdiff >= DVFRAC){ 685155228Smjacob it->dvdiff %= DVFRAC; 686155228Smjacob fp = (struct fw_pkt *)(it->stproc->buf + j * it->psize); 687155228Smjacob 688196008Smjacob fp->mode.stream.len = htons(0x8); 689155228Smjacob fp->mode.stream.chtag = chtag; 690163899Smjacob fp->mode.stream.tcode = FWTCODE_STREAM; 691155228Smjacob fp->mode.ld[1] = htonl((fc->nodeid << 24) | 692155228Smjacob 0x00780000 | it->dvdbc); 693155228Smjacob j++; 694155228Smjacob } 695163899Smjacob } 696155228Smjacob it->stproc->npacket = j; 697155228Smjacob s = splfw(); 698196008Smjacob STAILQ_INSERT_TAIL(&it->stvalid, it->stproc, link); 699196008Smjacob splx(s); 700196008Smjacob if(it->queued >= it->dvpacket){ 701196008Smjacob s = splfw(); 702155228Smjacob STAILQ_INSERT_TAIL(&it->dvfree, it->dvdma, link); 703196008Smjacob it->dvdma = NULL; 704196008Smjacob splx(s); 705196008Smjacob wakeup(it); 706196008Smjacob goto dvloop; 707155228Smjacob } 708155228Smjacob } 709155228Smjacob return err; 710155228Smjacob} 711163899Smjacob/* 712155228Smjacob * receving buffer update. 713155228Smjacob */ 714196008Smjacobint 715196008Smjacobfw_rbuf_update(struct firewire_comm *fc, int sub, int flag){ 716196008Smjacob struct fw_bulkxfer *bulkxfer, *bulkxfer2 = NULL; 717196008Smjacob struct fw_xferq *ir; 718155228Smjacob int s, err = 0; 719196008Smjacob 720196008Smjacob ir = fc->ir[sub]; 721196008Smjacob s = splfw(); 722196008Smjacob if(ir->stdma != NULL){ 723155228Smjacob if(flag != 0){ 724155228Smjacob STAILQ_INSERT_TAIL(&ir->stvalid, ir->stdma, link); 725155228Smjacob }else{ 726155228Smjacob ir->stdma->flag = 0; 727155704Smjacob STAILQ_INSERT_TAIL(&ir->stfree, ir->stdma, link); 728155228Smjacob } 729155704Smjacob } 730155228Smjacob if(ir->stdma2 != NULL){ 731155228Smjacob bulkxfer = ir->stdma2; 732155228Smjacob bulkxfer2 = STAILQ_FIRST(&ir->stfree); 733155228Smjacob if(bulkxfer2 != NULL){ 734155228Smjacob STAILQ_REMOVE_HEAD(&ir->stfree, link); 735155228Smjacob } 736155228Smjacob }else{ 737155228Smjacob bulkxfer = STAILQ_FIRST(&ir->stfree); 738155228Smjacob if(bulkxfer != NULL){ 739155704Smjacob STAILQ_REMOVE_HEAD(&ir->stfree, link); 740155228Smjacob bulkxfer2 = STAILQ_FIRST(&ir->stfree); 741155228Smjacob if(bulkxfer2 != NULL){ 742163899Smjacob STAILQ_REMOVE_HEAD(&ir->stfree, link); 743155228Smjacob } 744155228Smjacob }else{ 745155228Smjacob bulkxfer = STAILQ_FIRST(&ir->stvalid); 746155228Smjacob STAILQ_REMOVE_HEAD(&ir->stvalid, link); 747155228Smjacob } 748155228Smjacob } 749155228Smjacob splx(s); 750155228Smjacob ir->stdma = bulkxfer; 751155228Smjacob ir->stdma2 = bulkxfer2; 752155228Smjacob return err; 753155228Smjacob} 754155228Smjacob/* 755163899Smjacob * ioctl support. 756155228Smjacob */ 757155228Smjacobint 758155228Smjacobfw_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td) 759196008Smjacob{ 760196008Smjacob struct firewire_softc *sc; 761155228Smjacob int unit = DEV2UNIT(dev); 762155228Smjacob int sub = DEV2DMACH(dev); 763155228Smjacob int i, len, err = 0; 764155228Smjacob struct fw_device *fwdev; 765163899Smjacob struct fw_bind *fwb; 766155228Smjacob struct fw_xferq *ir, *it; 767155228Smjacob struct fw_xfer *xfer; 768163899Smjacob struct fw_pkt *fp; 769163899Smjacob 770163899Smjacob struct fw_devlstreq *fwdevlst = (struct fw_devlstreq *)data; 771163899Smjacob struct fw_asyreq *asyreq = (struct fw_asyreq *)data; 772163899Smjacob struct fw_isochreq *ichreq = (struct fw_isochreq *)data; 773163899Smjacob struct fw_isobufreq *ibufreq = (struct fw_isobufreq *)data; 774163899Smjacob struct fw_asybindreq *bindreq = (struct fw_asybindreq *)data; 775163899Smjacob#if 0 776155228Smjacob struct fw_map_buf *map_buf = (struct fw_map_buf *)data; 777163899Smjacob#endif 778163899Smjacob struct fw_crom_buf *crom_buf = (struct fw_crom_buf *)data; 779163899Smjacob 780163899Smjacob if (DEV_FWMEM(dev)) 781196008Smjacob return fwmem_ioctl(dev, cmd, data, flag, td); 782163899Smjacob 783163899Smjacob sc = devclass_get_softc(firewire_devclass, unit); 784163899Smjacob if (!data) 785163899Smjacob return(EINVAL); 786196008Smjacob 787163899Smjacob switch (cmd) { 788163899Smjacob case FW_STSTREAM: 789163899Smjacob sc->fc->it[sub]->flag &= ~0xff; 790163899Smjacob sc->fc->it[sub]->flag |= (0x3f & ichreq->ch); 791163899Smjacob sc->fc->it[sub]->flag |= ((0x3 & ichreq->tag) << 6); 792163899Smjacob err = 0; 793163899Smjacob break; 794163899Smjacob case FW_GTSTREAM: 795163899Smjacob ichreq->ch = sc->fc->it[sub]->flag & 0x3f; 796163899Smjacob ichreq->tag =(sc->fc->it[sub]->flag) >> 2 & 0x3; 797163899Smjacob err = 0; 798163899Smjacob break; 799163899Smjacob case FW_SRSTREAM: 800163899Smjacob sc->fc->ir[sub]->flag &= ~0xff; 801196008Smjacob sc->fc->ir[sub]->flag |= (0x3f & ichreq->ch); 802163899Smjacob sc->fc->ir[sub]->flag |= ((0x3 & ichreq->tag) << 6); 803163899Smjacob err = sc->fc->irx_enable(sc->fc, sub); 804163899Smjacob break; 805163899Smjacob case FW_GRSTREAM: 806163899Smjacob ichreq->ch = sc->fc->ir[sub]->flag & 0x3f; 807163899Smjacob ichreq->tag =(sc->fc->ir[sub]->flag) >> 2 & 0x3; 808163899Smjacob err = 0; 809163899Smjacob break; 810163899Smjacob case FW_SSTDV: 811163899Smjacob ibufreq = (struct fw_isobufreq *) 812163899Smjacob malloc(sizeof(struct fw_isobufreq), M_DEVBUF, M_NOWAIT); 813163899Smjacob if(ibufreq == NULL){ 814163899Smjacob err = ENOMEM; 815291209Smav break; 816291209Smav } 817163899Smjacob#define FWDVPACKET 250 818163899Smjacob#define FWDVPMAX 512 819163899Smjacob ibufreq->rx.nchunk = 8; 820163899Smjacob ibufreq->rx.npacket = 50; 821163899Smjacob ibufreq->rx.psize = FWDVPMAX; 822163899Smjacob 823155228Smjacob ibufreq->tx.nchunk = 5; 824196008Smjacob ibufreq->tx.npacket = 300; 825196008Smjacob ibufreq->tx.psize = FWDVPMAX; 826155228Smjacob 827155228Smjacob err = fw_ioctl(dev, FW_SSTBUF, (caddr_t)ibufreq, flag, td); 828155228Smjacob sc->fc->it[sub]->dvpacket = FWDVPACKET; 829155228Smjacob free(ibufreq, M_DEVBUF); 830163899Smjacob/* reserve a buffer space */ 831155228Smjacob#define NDVCHUNK 8 832155228Smjacob sc->fc->it[sub]->dvproc = NULL; 833163899Smjacob sc->fc->it[sub]->dvdma = NULL; 834163899Smjacob sc->fc->it[sub]->flag |= FWXFERQ_DV; 835163899Smjacob sc->fc->it[sub]->dvbuf 836163899Smjacob = (struct fw_dvbuf *)malloc(sizeof(struct fw_dvbuf) * NDVCHUNK, M_DEVBUF, M_DONTWAIT); 837163899Smjacob STAILQ_INIT(&sc->fc->it[sub]->dvvalid); 838291209Smav STAILQ_INIT(&sc->fc->it[sub]->dvfree); 839291209Smav for( i = 0 ; i < NDVCHUNK ; i++){ 840163899Smjacob sc->fc->it[sub]->dvbuf[i].buf 841163899Smjacob = malloc(FWDVPMAX * sc->fc->it[sub]->dvpacket, M_DEVBUF, M_DONTWAIT); 842163899Smjacob STAILQ_INSERT_TAIL(&sc->fc->it[sub]->dvfree, 843163899Smjacob &sc->fc->it[sub]->dvbuf[i], link); 844155228Smjacob } 845163899Smjacob break; 846155228Smjacob case FW_SSTBUF: 847196008Smjacob ir = sc->fc->ir[sub]; 848196008Smjacob it = sc->fc->it[sub]; 849155228Smjacob 850155228Smjacob if(ir->flag & FWXFERQ_RUNNING || it->flag & FWXFERQ_RUNNING){ 851155228Smjacob return(EBUSY); 852155228Smjacob } 853163899Smjacob if((ir->flag & FWXFERQ_EXTBUF) || (it->flag & FWXFERQ_EXTBUF)){ 854155228Smjacob return(EBUSY); 855155228Smjacob } 856163899Smjacob if((ibufreq->rx.nchunk * 857163899Smjacob ibufreq->rx.psize * ibufreq->rx.npacket) + 858163899Smjacob (ibufreq->tx.nchunk * 859163899Smjacob ibufreq->tx.psize * ibufreq->tx.npacket) <= 0){ 860163899Smjacob return(EINVAL); 861163899Smjacob } 862238869Smjacob if(ibufreq->rx.nchunk > FWSTMAXCHUNK || 863238869Smjacob ibufreq->tx.nchunk > FWSTMAXCHUNK){ 864163899Smjacob return(EINVAL); 865163899Smjacob } 866163899Smjacob ir->bulkxfer 867163899Smjacob = (struct fw_bulkxfer *)malloc(sizeof(struct fw_bulkxfer) * ibufreq->rx.nchunk, M_DEVBUF, M_DONTWAIT); 868155228Smjacob if(ir->bulkxfer == NULL){ 869163899Smjacob return(ENOMEM); 870155228Smjacob } 871196008Smjacob it->bulkxfer 872196008Smjacob = (struct fw_bulkxfer *)malloc(sizeof(struct fw_bulkxfer) * ibufreq->tx.nchunk, M_DEVBUF, M_DONTWAIT); 873196008Smjacob if(it->bulkxfer == NULL){ 874155228Smjacob return(ENOMEM); 875155228Smjacob } 876155228Smjacob ir->buf = malloc( 877155228Smjacob ibufreq->rx.nchunk * ibufreq->rx.npacket 878163899Smjacob * ((ibufreq->rx.psize + 3) &~3), 879155228Smjacob M_DEVBUF, M_DONTWAIT); 880155228Smjacob if(ir->buf == NULL){ 881163899Smjacob free(ir->bulkxfer, M_DEVBUF); 882163899Smjacob free(it->bulkxfer, M_DEVBUF); 883163899Smjacob ir->bulkxfer = NULL; 884163899Smjacob it->bulkxfer = NULL; 885163899Smjacob it->buf = NULL; 886238869Smjacob return(ENOMEM); 887238869Smjacob } 888163899Smjacob it->buf = malloc( 889163899Smjacob ibufreq->tx.nchunk * ibufreq->tx.npacket 890163899Smjacob * ((ibufreq->tx.psize + 3) &~3), 891163899Smjacob M_DEVBUF, M_DONTWAIT); 892155228Smjacob if(it->buf == NULL){ 893163899Smjacob free(ir->bulkxfer, M_DEVBUF); 894155228Smjacob free(it->bulkxfer, M_DEVBUF); 895196008Smjacob free(ir->buf, M_DEVBUF); 896196008Smjacob ir->bulkxfer = NULL; 897196008Smjacob it->bulkxfer = NULL; 898155228Smjacob it->buf = NULL; 899155228Smjacob return(ENOMEM); 900155228Smjacob } 901155228Smjacob 902163899Smjacob ir->bnchunk = ibufreq->rx.nchunk; 903155228Smjacob ir->bnpacket = ibufreq->rx.npacket; 904155228Smjacob ir->btpacket = ibufreq->rx.npacket; 905163899Smjacob ir->psize = (ibufreq->rx.psize + 3) & ~3; 906163899Smjacob ir->queued = 0; 907155228Smjacob 908163899Smjacob it->bnchunk = ibufreq->tx.nchunk; 909163899Smjacob it->bnpacket = ibufreq->tx.npacket; 910155228Smjacob it->btpacket = ibufreq->tx.npacket; 911163899Smjacob it->psize = (ibufreq->tx.psize + 3) & ~3; 912163899Smjacob ir->queued = 0; 913155228Smjacob it->dvdbc = 0; 914163899Smjacob it->dvdiff = 0; 915163899Smjacob it->dvsync = 0; 916163899Smjacob 917163899Smjacob STAILQ_INIT(&ir->stvalid); 918163899Smjacob STAILQ_INIT(&ir->stfree); 919163899Smjacob ir->stdma = NULL; 920155228Smjacob ir->stdma2 = NULL; 921155228Smjacob ir->stproc = NULL; 922155228Smjacob 923155228Smjacob STAILQ_INIT(&it->stvalid); 924163899Smjacob STAILQ_INIT(&it->stfree); 925155228Smjacob it->stdma = NULL; 926155228Smjacob it->stdma2 = NULL; 927163899Smjacob it->stproc = NULL; 928163899Smjacob 929163899Smjacob for(i = 0 ; i < sc->fc->ir[sub]->bnchunk; i++){ 930163899Smjacob ir->bulkxfer[i].buf = 931163899Smjacob ir->buf + 932163899Smjacob i * sc->fc->ir[sub]->bnpacket * 933163899Smjacob sc->fc->ir[sub]->psize; 934163899Smjacob ir->bulkxfer[i].flag = 0; 935163899Smjacob STAILQ_INSERT_TAIL(&ir->stfree, 936163899Smjacob &ir->bulkxfer[i], link); 937163899Smjacob ir->bulkxfer[i].npacket = ir->bnpacket; 938171159Smjacob } 939163899Smjacob for(i = 0 ; i < sc->fc->it[sub]->bnchunk; i++){ 940163899Smjacob it->bulkxfer[i].buf = 941163899Smjacob it->buf + 942163899Smjacob i * sc->fc->it[sub]->bnpacket * 943163899Smjacob sc->fc->it[sub]->psize; 944163899Smjacob it->bulkxfer[i].flag = 0; 945163899Smjacob STAILQ_INSERT_TAIL(&it->stfree, 946171159Smjacob &it->bulkxfer[i], link); 947171159Smjacob it->bulkxfer[i].npacket = it->bnpacket; 948163899Smjacob } 949163899Smjacob ir->flag &= ~FWXFERQ_MODEMASK; 950163899Smjacob ir->flag |= FWXFERQ_STREAM; 951163899Smjacob ir->flag |= FWXFERQ_EXTBUF; 952163899Smjacob 953196008Smjacob it->flag &= ~FWXFERQ_MODEMASK; 954196008Smjacob it->flag |= FWXFERQ_STREAM; 955196008Smjacob it->flag |= FWXFERQ_EXTBUF; 956163899Smjacob err = 0; 957163899Smjacob break; 958163899Smjacob case FW_GSTBUF: 959196008Smjacob ibufreq->rx.nchunk = sc->fc->ir[sub]->bnchunk; 960196008Smjacob ibufreq->rx.npacket = sc->fc->ir[sub]->bnpacket; 961196008Smjacob ibufreq->rx.psize = sc->fc->ir[sub]->psize; 962196008Smjacob 963196008Smjacob ibufreq->tx.nchunk = sc->fc->it[sub]->bnchunk; 964196008Smjacob ibufreq->tx.npacket = sc->fc->it[sub]->bnpacket; 965196008Smjacob ibufreq->tx.psize = sc->fc->it[sub]->psize; 966196008Smjacob break; 967196008Smjacob case FW_ASYREQ: 968196008Smjacob xfer = fw_xfer_alloc(); 969196008Smjacob if(xfer == NULL){ 970196008Smjacob err = ENOMEM; 971196008Smjacob return err; 972196008Smjacob } 973196008Smjacob fp = &asyreq->pkt; 974196008Smjacob switch (asyreq->req.type) { 975196008Smjacob case FWASREQNODE: 976196008Smjacob xfer->dst = ntohs(fp->mode.hdr.dst); 977196008Smjacob break; 978196008Smjacob case FWASREQEUI: 979196008Smjacob fwdev = fw_noderesolve(sc->fc, asyreq->req.dst.eui); 980196008Smjacob if (fwdev == NULL) { 981196008Smjacob printf("%s:cannot found node\n", 982196008Smjacob device_get_nameunit(sc->fc->dev)); 983196008Smjacob err = EINVAL; 984196008Smjacob goto error; 985196008Smjacob } 986196008Smjacob xfer->dst = fwdev->dst; 987196008Smjacob fp->mode.hdr.dst = htons(FWLOCALBUS | xfer->dst); 988196008Smjacob break; 989196008Smjacob case FWASRESTL: 990163899Smjacob /* XXX what's this? */ 991163899Smjacob break; 992163899Smjacob case FWASREQSTREAM: 993163899Smjacob /* nothing to do */ 994163899Smjacob break; 995163899Smjacob } 996163899Smjacob xfer->spd = asyreq->req.sped; 997163899Smjacob xfer->send.len = asyreq->req.len; 998289886Smav xfer->send.buf = malloc(xfer->send.len, M_DEVBUF, M_NOWAIT); 999163899Smjacob if(xfer->send.buf == NULL){ 1000196008Smjacob return ENOMEM; 1001163899Smjacob } 1002163899Smjacob xfer->send.off = 0; 1003163899Smjacob bcopy(fp, xfer->send.buf, xfer->send.len); 1004163899Smjacob xfer->act.hand = fw_asy_callback; 1005163899Smjacob err = fw_asyreq(sc->fc, sub, xfer); 1006196008Smjacob if(err){ 1007163899Smjacob fw_xfer_free( xfer); 1008163899Smjacob return err; 1009163899Smjacob } 1010163899Smjacob err = tsleep((caddr_t)xfer, FWPRI, "asyreq", hz); 1011163899Smjacob if(err == 0){ 1012163899Smjacob if(asyreq->req.len >= xfer->recv.len){ 1013163899Smjacob asyreq->req.len = xfer->recv.len; 1014163899Smjacob }else{ 1015155228Smjacob err = EINVAL; 1016196008Smjacob } 1017196008Smjacob bcopy(xfer->recv.buf + xfer->recv.off, fp, asyreq->req.len); 1018155228Smjacob } 1019155228Smjacoberror: 1020155228Smjacob fw_xfer_free( xfer); 1021155228Smjacob break; 1022163899Smjacob case FW_IBUSRST: 1023155228Smjacob sc->fc->ibr(sc->fc); 1024155228Smjacob break; 1025163899Smjacob case FW_CBINDADDR: 1026155228Smjacob fwb = fw_bindlookup(sc->fc, 1027196008Smjacob bindreq->start.hi, bindreq->start.lo); 1028196008Smjacob if(fwb == NULL){ 1029196008Smjacob err = EINVAL; 1030155228Smjacob break; 1031155228Smjacob } 1032155228Smjacob STAILQ_REMOVE(&sc->fc->binds, fwb, fw_bind, fclist); 1033155228Smjacob STAILQ_REMOVE(&sc->fc->ir[sub]->binds, fwb, fw_bind, chlist); 1034163899Smjacob free(fwb, M_DEVBUF); 1035155228Smjacob break; 1036155228Smjacob case FW_SBINDADDR: 1037163899Smjacob if(bindreq->len <= 0 ){ 1038163899Smjacob err = EINVAL; 1039163899Smjacob break; 1040196008Smjacob } 1041163899Smjacob if(bindreq->start.hi > 0xffff ){ 1042163899Smjacob err = EINVAL; 1043163899Smjacob break; 1044163899Smjacob } 1045163899Smjacob fwb = (struct fw_bind *)malloc(sizeof (struct fw_bind), M_DEVBUF, M_DONTWAIT); 1046238869Smjacob if(fwb == NULL){ 1047196008Smjacob err = ENOMEM; 1048155228Smjacob break; 1049238869Smjacob } 1050196008Smjacob fwb->start_hi = bindreq->start.hi; 1051155228Smjacob fwb->start_lo = bindreq->start.lo; 1052155228Smjacob fwb->addrlen = bindreq->len; 1053155228Smjacob 1054155228Smjacob xfer = fw_xfer_alloc(); 1055238869Smjacob if(xfer == NULL){ 1056238869Smjacob err = ENOMEM; 1057238869Smjacob return err; 1058238869Smjacob } 1059238869Smjacob xfer->act_type = FWACT_CH; 1060238869Smjacob xfer->sub = sub; 1061238869Smjacob xfer->fc = sc->fc; 1062238869Smjacob 1063238869Smjacob fwb->xfer = xfer; 1064238869Smjacob err = fw_bindadd(sc->fc, fwb); 1065238869Smjacob break; 1066238869Smjacob case FW_GDEVLST: 1067238869Smjacob i = 0; 1068238869Smjacob for(fwdev = TAILQ_FIRST(&sc->fc->devices); fwdev != NULL; 1069238869Smjacob fwdev = TAILQ_NEXT(fwdev, link)){ 1070238869Smjacob if(i < fwdevlst->n){ 1071238869Smjacob fwdevlst->dst[i] = fwdev->dst; 1072238869Smjacob fwdevlst->status[i] = 1073238869Smjacob (fwdev->status == FWDEVATTACHED)?1:0; 1074196008Smjacob fwdevlst->eui[i].hi = fwdev->eui.hi; 1075155228Smjacob fwdevlst->eui[i].lo = fwdev->eui.lo; 1076155228Smjacob } 1077171159Smjacob i++; 1078171159Smjacob } 1079163899Smjacob fwdevlst->n = i; 1080163899Smjacob break; 1081196008Smjacob case FW_GTPMAP: 1082163899Smjacob bcopy(sc->fc->topology_map, data, 1083163899Smjacob (sc->fc->topology_map->crc_len + 1) * 4); 1084163899Smjacob break; 1085163899Smjacob case FW_GSPMAP: 1086289855Smav /* speed_map is larger than a page */ 1087163899Smjacob err = copyout(sc->fc->speed_map, *(void **)data, 1088163899Smjacob (sc->fc->speed_map->crc_len + 1) * 4); 1089163899Smjacob break; 1090163899Smjacob case FW_GCROM: 1091171159Smjacob for (fwdev = TAILQ_FIRST(&sc->fc->devices); fwdev != NULL; 1092171159Smjacob fwdev = TAILQ_NEXT(fwdev, link)) { 1093171159Smjacob if (fwdev->eui.hi == crom_buf->eui.hi && 1094171159Smjacob fwdev->eui.lo == crom_buf->eui.lo) 1095155228Smjacob break; 1096155228Smjacob } 1097155228Smjacob if (fwdev == NULL) { 1098155228Smjacob err = FWNODE_INVAL; 1099163899Smjacob break; 1100163899Smjacob } 1101163899Smjacob#if 0 1102163899Smjacob if (fwdev->csrrom[0] >> 24 == 1) 1103163899Smjacob len = 4; 1104163899Smjacob else 1105163899Smjacob len = (1 + ((fwdev->csrrom[0] >> 16) & 0xff)) * 4; 1106163899Smjacob#else 1107289886Smav if (fwdev->rommax < CSRROMOFF) 1108171159Smjacob len = 0; 1109196008Smjacob else 1110163899Smjacob len = fwdev->rommax - CSRROMOFF + 4; 1111163899Smjacob#endif 1112163899Smjacob if (crom_buf->len < len) 1113163899Smjacob len = crom_buf->len; 1114171159Smjacob else 1115196008Smjacob crom_buf->len = len; 1116163899Smjacob err = copyout(&fwdev->csrrom[0], crom_buf->ptr, len); 1117163899Smjacob break; 1118163899Smjacob default: 1119163899Smjacob sc->fc->ioctl (dev, cmd, data, flag, td); 1120163899Smjacob break; 1121204397Smjacob } 1122204397Smjacob return err; 1123204397Smjacob} 1124204397Smjacobint 1125204397Smjacobfw_poll(dev_t dev, int events, fw_proc *td) 1126204397Smjacob{ 1127204397Smjacob int revents; 1128204397Smjacob int tmp; 1129204397Smjacob int unit = DEV2UNIT(dev); 1130204397Smjacob int sub = DEV2DMACH(dev); 1131204397Smjacob struct firewire_softc *sc; 1132204397Smjacob 1133204397Smjacob if (DEV_FWMEM(dev)) 1134204397Smjacob return fwmem_poll(dev, events, td); 1135204397Smjacob 1136204397Smjacob sc = devclass_get_softc(firewire_devclass, unit); 1137204397Smjacob revents = 0; 1138155704Smjacob tmp = POLLIN | POLLRDNORM; 1139155228Smjacob if (events & tmp) { 1140204397Smjacob if (STAILQ_FIRST(&sc->fc->ir[sub]->q) != NULL) 1141155228Smjacob revents |= tmp; 1142204397Smjacob else 1143163899Smjacob selrecord(td, &sc->fc->ir[sub]->rsel); 1144204397Smjacob } 1145204397Smjacob tmp = POLLOUT | POLLWRNORM; 1146163899Smjacob if (events & tmp) { 1147155228Smjacob /* XXX should be fixed */ 1148196008Smjacob revents |= tmp; 1149155228Smjacob } 1150204397Smjacob 1151155228Smjacob return revents; 1152155228Smjacob} 1153155228Smjacob 1154155228Smjacob/* 1155155228Smjacob * To lookup node id. from EUI64. 1156163899Smjacob */ 1157155228Smjacobstruct fw_device * 1158155228Smjacobfw_noderesolve(struct firewire_comm *fc, struct fw_eui64 eui) 1159155228Smjacob{ 1160163899Smjacob struct fw_device *fwdev; 1161163899Smjacob for(fwdev = TAILQ_FIRST(&fc->devices); fwdev != NULL; 1162155228Smjacob fwdev = TAILQ_NEXT(fwdev, link)){ 1163163899Smjacob if(fwdev->eui.hi == eui.hi && fwdev->eui.lo == eui.lo){ 1164163899Smjacob break; 1165155228Smjacob } 1166163899Smjacob } 1167163899Smjacob if(fwdev == NULL) return NULL; 1168163899Smjacob if(fwdev->status == FWDEVINVAL) return NULL; 1169163899Smjacob return fwdev; 1170155228Smjacob} 1171163899Smjacob/* 1172163899Smjacob * Async. request procedure for userland application. 1173155228Smjacob */ 1174163899Smjacobint 1175163899Smjacobfw_asyreq(struct firewire_comm *fc, int sub, struct fw_xfer *xfer) 1176155228Smjacob{ 1177155228Smjacob int err = 0; 1178163899Smjacob struct fw_xferq *xferq; 1179155228Smjacob int tl = 0, len; 1180163899Smjacob struct fw_pkt *fp; 1181155228Smjacob int tcode; 1182163899Smjacob struct tcode_info *info; 1183163899Smjacob 1184155228Smjacob if(xfer == NULL) return EINVAL; 1185163899Smjacob if(xfer->send.len > fc->maxrec){ 1186163899Smjacob printf("send.len > maxrec\n"); 1187155228Smjacob return EINVAL; 1188155228Smjacob } 1189163899Smjacob if(xfer->act.hand == NULL){ 1190155228Smjacob printf("act.hand == NULL\n"); 1191163899Smjacob return EINVAL; 1192163899Smjacob } 1193163899Smjacob fp = (struct fw_pkt *)xfer->send.buf; 1194163899Smjacob 1195155228Smjacob tcode = fp->mode.common.tcode & 0xf; 1196163899Smjacob info = &fc->tcode[tcode]; 1197155228Smjacob if (info->flag == 0) { 1198155228Smjacob printf("invalid tcode=%d\n", tcode); 1199163899Smjacob return EINVAL; 1200155228Smjacob } 1201163899Smjacob if (info->flag & FWTI_REQ) 1202155228Smjacob xferq = fc->atq; 1203163899Smjacob else 1204163899Smjacob xferq = fc->ats; 1205155228Smjacob len = info->hdr_len; 1206163899Smjacob if (info->flag & FWTI_BLOCK_STR) 1207163899Smjacob len += ntohs(fp->mode.stream.len); 1208155228Smjacob else if (info->flag & FWTI_BLOCK_ASY) 1209163899Smjacob len += ntohs(fp->mode.rresb.len); 1210163899Smjacob if( len > xfer->send.len ){ 1211163899Smjacob printf("len(%d) > send.len(%d) (tcode=%d)\n", 1212155228Smjacob len, xfer->send.len, tcode); 1213163899Smjacob return EINVAL; 1214163899Smjacob } 1215155228Smjacob xfer->send.len = len; 1216163899Smjacob 1217163899Smjacob if(xferq->start == NULL){ 1218155228Smjacob printf("xferq->start == NULL\n"); 1219163899Smjacob return EINVAL; 1220155228Smjacob } 1221155228Smjacob if(!(xferq->queued < xferq->maxq)){ 1222155228Smjacob printf("%s:Discard a packet (queued=%d)\n", 1223163899Smjacob device_get_nameunit(fc->dev), xferq->queued); 1224155228Smjacob return EINVAL; 1225155228Smjacob } 1226163899Smjacob 1227163899Smjacob 1228163899Smjacob if (info->flag & FWTI_TLABEL) { 1229163899Smjacob if((tl = fw_get_tlabel(fc, xfer)) == -1 ) 1230163899Smjacob return EIO; 1231163899Smjacob fp->mode.hdr.tlrt = tl << 2; 1232163899Smjacob } 1233163899Smjacob 1234163899Smjacob xfer->tl = tl; 1235163899Smjacob xfer->tcode = tcode; 1236163899Smjacob xfer->resp = 0; 1237163899Smjacob xfer->fc = fc; 1238163899Smjacob xfer->q = xferq; 1239163899Smjacob xfer->act_type = FWACT_XFER; 1240163899Smjacob xfer->retry_req = fw_asybusy; 1241163899Smjacob 1242163899Smjacob fw_asystart(xfer); 1243163899Smjacob return err; 1244163899Smjacob} 1245163899Smjacob/* 1246163899Smjacob * Wakeup blocked process. 1247163899Smjacob */ 1248163899Smjacobvoid 1249163899Smjacobfw_asy_callback(struct fw_xfer *xfer){ 1250163899Smjacob wakeup(xfer); 1251163899Smjacob return; 1252163899Smjacob} 1253163899Smjacob/* 1254163899Smjacob * Postpone to later retry. 1255291730Smav */ 1256291730Smavvoid fw_asybusy(struct fw_xfer *xfer){ 1257291730Smav#if 0 1258196008Smjacob printf("fw_asybusy\n"); 1259163899Smjacob#endif 1260163899Smjacob#if XFER_TIMEOUT 1261163899Smjacob untimeout(fw_xfer_timeout, (void *)xfer, xfer->ch); 1262163899Smjacob#endif 1263196008Smjacob/* 1264163899Smjacob xfer->ch = timeout((timeout_t *)fw_asystart, (void *)xfer, 20000); 1265163899Smjacob*/ 1266163899Smjacob DELAY(20000); 1267163899Smjacob fw_asystart(xfer); 1268163899Smjacob return; 1269163899Smjacob} 1270291730Smav#if XFER_TIMEOUT 1271291730Smav/* 1272196008Smjacob * Post timeout for async. request. 1273291730Smav */ 1274291730Smavvoid 1275291730Smavfw_xfer_timeout(void *arg) 1276291730Smav{ 1277291730Smav int s; 1278163899Smjacob struct fw_xfer *xfer; 1279163899Smjacob 1280163899Smjacob xfer = (struct fw_xfer *)arg; 1281196008Smjacob printf("fw_xfer_timeout status=%d resp=%d\n", xfer->state, xfer->resp); 1282196008Smjacob /* XXX set error code */ 1283196008Smjacob s = splfw(); 1284196008Smjacob xfer->act.hand(xfer); 1285196008Smjacob splx(s); 1286196008Smjacob} 1287196008Smjacob#endif 1288196008Smjacob/* 1289196008Smjacob * Async. request with given xfer structure. 1290196008Smjacob */ 1291196008Smjacobstatic void 1292196008Smjacobfw_asystart(struct fw_xfer *xfer) 1293196008Smjacob{ 1294196008Smjacob struct firewire_comm *fc = xfer->fc; 1295196008Smjacob int s; 1296196008Smjacob if(xfer->retry++ >= fc->max_asyretry){ 1297196008Smjacob xfer->resp = EBUSY; 1298196008Smjacob xfer->state = FWXF_BUSY; 1299196008Smjacob xfer->act.hand(xfer); 1300196008Smjacob return; 1301196008Smjacob } 1302196008Smjacob#if 0 /* XXX allow bus explore packets only after bus rest */ 1303196008Smjacob if (fc->status < FWBUSEXPLORE) { 1304196008Smjacob xfer->resp = EAGAIN; 1305196008Smjacob xfer->state = FWXF_BUSY; 1306196008Smjacob if (xfer->act.hand != NULL) 1307196008Smjacob xfer->act.hand(xfer); 1308196008Smjacob return; 1309196008Smjacob } 1310196008Smjacob#endif 1311196008Smjacob s = splfw(); 1312196008Smjacob xfer->state = FWXF_INQ; 1313196008Smjacob STAILQ_INSERT_TAIL(&xfer->q->q, xfer, link); 1314196008Smjacob xfer->q->queued ++; 1315196008Smjacob splx(s); 1316196008Smjacob /* XXX just queue for mbuf */ 1317196008Smjacob if (xfer->mbuf == NULL) 1318196008Smjacob xfer->q->start(fc); 1319196008Smjacob#if XFER_TIMEOUT 1320196008Smjacob if (xfer->act.hand != NULL) 1321196008Smjacob xfer->ch = timeout(fw_xfer_timeout, (void *)xfer, hz); 1322196008Smjacob#endif 1323196008Smjacob return; 1324196008Smjacob} 1325196008Smjacob 1326196008Smjacobstatic int 1327196008Smjacobfw_mmap (dev_t dev, vm_offset_t offset, int nproto) 1328196008Smjacob{ 1329196008Smjacob struct firewire_softc *fc; 1330196008Smjacob int unit = DEV2UNIT(dev); 1331196008Smjacob 1332196008Smjacob if (DEV_FWMEM(dev)) 1333196008Smjacob return fwmem_mmap(dev, offset, nproto); 1334290018Smav 1335196008Smjacob fc = devclass_get_softc(firewire_devclass, unit); 1336290018Smav 1337196008Smjacob return EINVAL; 1338196008Smjacob} 1339196008Smjacob 1340196008Smjacobstatic int 1341196008Smjacobfirewire_match( device_t dev ) 1342196008Smjacob{ 1343196008Smjacob device_set_desc(dev, "IEEE1394(Firewire) bus"); 1344196008Smjacob return -140; 1345196008Smjacob} 1346196008Smjacob 1347196008Smjacob/* 1348196008Smjacob * The attach routine. 1349196008Smjacob */ 1350196008Smjacobstatic int 1351196008Smjacobfirewire_attach( device_t dev ) 1352196008Smjacob{ 1353290018Smav int i, unitmask, mn; 1354196008Smjacob struct firewire_softc *sc = device_get_softc(dev); 1355290018Smav device_t pa = device_get_parent(dev); 1356196008Smjacob struct firewire_comm *fc; 1357196008Smjacob dev_t d; 1358196008Smjacob 1359196008Smjacob fc = (struct firewire_comm *)device_get_softc(pa); 1360196008Smjacob sc->fc = fc; 1361196008Smjacob sc->fc->dev = dev; 1362196008Smjacob 1363196008Smjacob unitmask = UNIT2MIN(device_get_unit(dev)); 1364196008Smjacob 1365196008Smjacob if( fc->nisodma > FWMAXNDMA) fc->nisodma = FWMAXNDMA; 1366196008Smjacob for ( i = 0 ; i < fc->nisodma ; i++ ){ 1367196008Smjacob mn = unitmask | i; 1368196008Smjacob /* XXX device name should be improved */ 1369196008Smjacob d = make_dev(&firewire_cdevsw, unit2minor(mn), 1370196008Smjacob UID_ROOT, GID_OPERATOR, 0770, 1371196008Smjacob "fw%x", mn); 1372196008Smjacob#if __FreeBSD_version >= 500000 1373196008Smjacob if (i == 0) 1374196008Smjacob sc->dev = d; 1375196008Smjacob else 1376196008Smjacob dev_depends(sc->dev, d); 1377196008Smjacob#else 1378196008Smjacob sc->dev[i] = d; 1379196008Smjacob#endif 1380196008Smjacob } 1381196008Smjacob d = make_dev(&firewire_cdevsw, unit2minor(unitmask | FWMEM_FLAG), 1382196008Smjacob UID_ROOT, GID_OPERATOR, 0770, 1383196008Smjacob "fwmem%d", device_get_unit(dev)); 1384196008Smjacob#if __FreeBSD_version >= 500000 1385196008Smjacob dev_depends(sc->dev, d); 1386196008Smjacob#else 1387196008Smjacob sc->dev[i] = d; 1388196008Smjacob#endif 1389196008Smjacob printf("%s: firewire bus attach\n", device_get_nameunit(sc->fc->dev)); 1390196008Smjacob sc->fc->timeouthandle = timeout((timeout_t *)sc->fc->timeout, (void *)sc->fc, hz * 10); 1391196008Smjacob 1392196008Smjacob /* Locate our children */ 1393196008Smjacob bus_generic_probe(dev); 1394196008Smjacob 1395196008Smjacob /* launch attachement of the added children */ 1396196008Smjacob bus_generic_attach(dev); 1397196008Smjacob 1398196008Smjacob /* bus_reset */ 1399196008Smjacob fc->ibr(fc); 1400196008Smjacob 1401196008Smjacob return 0; 1402196008Smjacob} 1403196008Smjacob 1404196008Smjacob/* 1405196008Smjacob * Attach it as child. 1406196008Smjacob */ 1407196008Smjacobstatic device_t 1408196008Smjacobfirewire_add_child(device_t dev, int order, const char *name, int unit) 1409196008Smjacob{ 1410196008Smjacob device_t child; 1411196008Smjacob struct firewire_softc *sc; 1412196008Smjacob 1413196008Smjacob sc = (struct firewire_softc *)device_get_softc(dev); 1414196008Smjacob child = device_add_child(dev, name, unit); 1415163899Smjacob if (child) { 1416163899Smjacob device_set_ivars(child, sc->fc); 1417163899Smjacob device_probe_and_attach(child); 1418155228Smjacob } 1419155228Smjacob 1420155228Smjacob return child; 1421155228Smjacob} 1422196008Smjacob 1423155228Smjacob/* 1424155228Smjacob * Dettach it. 1425196008Smjacob */ 1426155228Smjacobstatic int 1427155228Smjacobfirewire_detach( device_t dev ) 1428155228Smjacob{ 1429155228Smjacob struct firewire_softc *sc; 1430155228Smjacob 1431155228Smjacob sc = (struct firewire_softc *)device_get_softc(dev); 1432155228Smjacob 1433155228Smjacob#if __FreeBSD_version >= 500000 1434155228Smjacob destroy_dev(sc->dev); 1435155228Smjacob#else 1436155228Smjacob { 1437155228Smjacob int j; 1438155228Smjacob for (j = 0 ; j < sc->fc->nisodma + 1; j++) 1439155228Smjacob destroy_dev(sc->dev[j]); 1440155228Smjacob } 1441155228Smjacob#endif 1442155228Smjacob /* XXX xfree_free and untimeout on all xfers */ 1443155228Smjacob untimeout((timeout_t *)sc->fc->timeout, sc->fc, sc->fc->timeouthandle); 1444155228Smjacob free(sc->fc->topology_map, M_DEVBUF); 1445155228Smjacob free(sc->fc->speed_map, M_DEVBUF); 1446155228Smjacob bus_generic_detach(dev); 1447155228Smjacob return(0); 1448155228Smjacob} 1449155228Smjacob#if 0 1450155228Smjacobstatic int 1451155228Smjacobfirewire_shutdown( device_t dev ) 1452155228Smjacob{ 1453155228Smjacob return 0; 1454155228Smjacob} 1455155228Smjacob#endif 1456155228Smjacob 1457155228Smjacob/* 1458155228Smjacob * Called after bus reset. 1459155228Smjacob */ 1460155228Smjacobvoid 1461155228Smjacobfw_busreset(struct firewire_comm *fc) 1462155228Smjacob{ 1463155228Smjacob int i; 1464155228Smjacob struct fw_xfer *xfer; 1465155228Smjacob 1466163899Smjacob switch(fc->status){ 1467163899Smjacob case FWBUSMGRELECT: 1468163899Smjacob untimeout((timeout_t *)fw_try_bmr, (void *)fc, fc->bmrhandle); 1469163899Smjacob break; 1470163899Smjacob default: 1471163899Smjacob break; 1472163899Smjacob } 1473163899Smjacob fc->status = FWBUSRESET; 1474196008Smjacob/* XXX: discard all queued packet */ 1475163899Smjacob while((xfer = STAILQ_FIRST(&fc->atq->q)) != NULL){ 1476163899Smjacob STAILQ_REMOVE_HEAD(&fc->atq->q, link); 1477196008Smjacob xfer->resp = EAGAIN; 1478163899Smjacob switch(xfer->act_type){ 1479163899Smjacob case FWACT_XFER: 1480163899Smjacob fw_xfer_done(xfer); 1481163899Smjacob break; 1482163899Smjacob default: 1483163899Smjacob break; 1484163899Smjacob } 1485163899Smjacob fw_xfer_free( xfer); 1486163899Smjacob } 1487163899Smjacob while((xfer = STAILQ_FIRST(&fc->ats->q)) != NULL){ 1488163899Smjacob STAILQ_REMOVE_HEAD(&fc->ats->q, link); 1489163899Smjacob xfer->resp = EAGAIN; 1490163899Smjacob switch(xfer->act_type){ 1491163899Smjacob case FWACT_XFER: 1492196008Smjacob fw_xfer_done(xfer); 1493163899Smjacob default: 1494163899Smjacob break; 1495155228Smjacob } 1496290104Smav fw_xfer_free( xfer); 1497290104Smav } 1498290104Smav for(i = 0; i < fc->nisodma; i++) 1499290104Smav while((xfer = STAILQ_FIRST(&fc->it[i]->q)) != NULL){ 1500290104Smav STAILQ_REMOVE_HEAD(&fc->it[i]->q, link); 1501290104Smav xfer->resp = 0; 1502290104Smav switch(xfer->act_type){ 1503290104Smav case FWACT_XFER: 1504290104Smav fw_xfer_done(xfer); 1505290104Smav break; 1506290104Smav default: 1507290104Smav break; 1508290104Smav } 1509290104Smav fw_xfer_free( xfer); 1510290104Smav } 1511290104Smav 1512290104Smav CSRARC(fc, STATE_CLEAR) 1513290104Smav = 1 << 23 | 0 << 17 | 1 << 16 | 1 << 15 | 1 << 14 ; 1514290104Smav CSRARC(fc, STATE_SET) = CSRARC(fc, STATE_CLEAR); 1515290104Smav CSRARC(fc, NODE_IDS) = 0x3f; 1516290104Smav 1517290104Smav CSRARC(fc, TOPO_MAP + 8) = 0; 1518290104Smav fc->irm = -1; 1519290104Smav 1520290104Smav fc->max_node = -1; 1521290104Smav 1522290104Smav for(i = 2; i < 0x100/4 - 2 ; i++){ 1523290104Smav CSRARC(fc, SPED_MAP + i * 4) = 0; 1524290104Smav } 1525290104Smav CSRARC(fc, STATE_CLEAR) = 1 << 23 | 0 << 17 | 1 << 16 | 1 << 15 | 1 << 14 ; 1526290104Smav CSRARC(fc, STATE_SET) = CSRARC(fc, STATE_CLEAR); 1527290104Smav CSRARC(fc, RESET_START) = 0; 1528290104Smav CSRARC(fc, SPLIT_TIMEOUT_HI) = 0; 1529290104Smav CSRARC(fc, SPLIT_TIMEOUT_LO) = 800 << 19; 1530290104Smav CSRARC(fc, CYCLE_TIME) = 0x0; 1531290104Smav CSRARC(fc, BUS_TIME) = 0x0; 1532290104Smav CSRARC(fc, BUS_MGR_ID) = 0x3f; 1533290104Smav CSRARC(fc, BANDWIDTH_AV) = 4915; 1534155228Smjacob CSRARC(fc, CHANNELS_AV_HI) = 0xffffffff; 1535163899Smjacob CSRARC(fc, CHANNELS_AV_LO) = 0xffffffff; 1536155228Smjacob CSRARC(fc, IP_CHANNELS) = (1 << 31); 1537163899Smjacob 1538155228Smjacob CSRARC(fc, CONF_ROM) = 0x04 << 24; 1539163899Smjacob CSRARC(fc, CONF_ROM + 4) = 0x31333934; /* means strings 1394 */ 1540155228Smjacob CSRARC(fc, CONF_ROM + 8) = 1 << 31 | 1 << 30 | 1 << 29 | 1541163899Smjacob 1 << 28 | 0xff << 16 | 0x09 << 8; 1542163899Smjacob CSRARC(fc, CONF_ROM + 0xc) = 0; 1543163899Smjacob 1544163899Smjacob/* DV depend CSRs see blue book */ 1545163899Smjacob CSRARC(fc, oPCR) &= ~DV_BROADCAST_ON; 1546163899Smjacob CSRARC(fc, iPCR) &= ~DV_BROADCAST_ON; 1547163899Smjacob 1548163899Smjacob CSRARC(fc, STATE_CLEAR) &= ~(1 << 23 | 1 << 15 | 1 << 14 ); 1549163899Smjacob CSRARC(fc, STATE_SET) = CSRARC(fc, STATE_CLEAR); 1550163899Smjacob} 1551196008Smjacob 1552196008Smjacob/* Call once after reboot */ 1553163899Smjacobvoid fw_init(struct firewire_comm *fc) 1554155228Smjacob{ 1555155228Smjacob int i; 1556163899Smjacob struct csrdir *csrd; 1557163899Smjacob#ifdef FW_VMACCESS 1558163899Smjacob struct fw_xfer *xfer; 1559163899Smjacob struct fw_bind *fwb; 1560163899Smjacob#endif 1561163899Smjacob 1562163899Smjacob fc->max_asyretry = FW_MAXASYRTY; 1563163899Smjacob 1564163899Smjacob fc->arq->queued = 0; 1565163899Smjacob fc->ars->queued = 0; 1566163899Smjacob fc->atq->queued = 0; 1567163899Smjacob fc->ats->queued = 0; 1568163899Smjacob 1569196008Smjacob fc->arq->psize = FWPMAX_S400; 1570196008Smjacob fc->ars->psize = FWPMAX_S400; 1571163899Smjacob fc->atq->psize = FWPMAX_S400; 1572163899Smjacob fc->ats->psize = FWPMAX_S400; 1573163899Smjacob 1574155228Smjacob 1575196008Smjacob fc->arq->buf = NULL; 1576196008Smjacob fc->ars->buf = NULL; 1577196008Smjacob fc->atq->buf = NULL; 1578196008Smjacob fc->ats->buf = NULL; 1579196008Smjacob 1580196008Smjacob fc->arq->flag = FWXFERQ_PACKET; 1581196008Smjacob fc->ars->flag = FWXFERQ_PACKET; 1582196008Smjacob fc->atq->flag = FWXFERQ_PACKET; 1583290978Smav fc->ats->flag = FWXFERQ_PACKET; 1584290978Smav 1585290978Smav STAILQ_INIT(&fc->atq->q); 1586290978Smav STAILQ_INIT(&fc->ats->q); 1587196008Smjacob 1588196008Smjacob for( i = 0 ; i < fc->nisodma ; i ++ ){ 1589196008Smjacob fc->it[i]->queued = 0; 1590196008Smjacob fc->ir[i]->queued = 0; 1591196008Smjacob 1592196008Smjacob fc->it[i]->start = NULL; 1593196008Smjacob fc->ir[i]->start = NULL; 1594196008Smjacob 1595196008Smjacob fc->it[i]->buf = NULL; 1596196008Smjacob fc->ir[i]->buf = NULL; 1597196008Smjacob 1598196008Smjacob fc->it[i]->flag = FWXFERQ_STREAM; 1599196008Smjacob fc->ir[i]->flag = FWXFERQ_STREAM; 1600163899Smjacob 1601163899Smjacob STAILQ_INIT(&fc->it[i]->q); 1602163899Smjacob STAILQ_INIT(&fc->ir[i]->q); 1603163899Smjacob 1604163899Smjacob STAILQ_INIT(&fc->it[i]->binds); 1605163899Smjacob STAILQ_INIT(&fc->ir[i]->binds); 1606163899Smjacob } 1607163899Smjacob 1608163899Smjacob fc->arq->maxq = FWMAXQUEUE; 1609163899Smjacob fc->ars->maxq = FWMAXQUEUE; 1610163899Smjacob fc->atq->maxq = FWMAXQUEUE; 1611163899Smjacob fc->ats->maxq = FWMAXQUEUE; 1612196008Smjacob 1613196008Smjacob for( i = 0 ; i < fc->nisodma ; i++){ 1614163899Smjacob fc->ir[i]->maxq = FWMAXQUEUE; 1615196008Smjacob fc->it[i]->maxq = FWMAXQUEUE; 1616163899Smjacob } 1617163899Smjacob/* Initialize csr registers */ 1618196008Smjacob fc->topology_map = (struct fw_topology_map *)malloc( 1619163899Smjacob sizeof(struct fw_topology_map), 1620163899Smjacob M_DEVBUF, M_DONTWAIT | M_ZERO); 1621163899Smjacob fc->speed_map = (struct fw_speed_map *)malloc( 1622163899Smjacob sizeof(struct fw_speed_map), 1623196008Smjacob M_DEVBUF, M_DONTWAIT | M_ZERO); 1624196008Smjacob CSRARC(fc, TOPO_MAP) = 0x3f1 << 16; 1625196008Smjacob CSRARC(fc, TOPO_MAP + 4) = 1; 1626163899Smjacob CSRARC(fc, SPED_MAP) = 0x3f1 << 16; 1627163899Smjacob CSRARC(fc, SPED_MAP + 4) = 1; 1628163899Smjacob 1629163899Smjacob TAILQ_INIT(&fc->devices); 1630164370Smjacob STAILQ_INIT(&fc->pending); 1631164370Smjacob 1632164370Smjacob/* Initialize csr ROM work space */ 1633164370Smjacob SLIST_INIT(&fc->ongocsr); 1634164370Smjacob SLIST_INIT(&fc->csrfree); 1635164370Smjacob for( i = 0 ; i < FWMAXCSRDIR ; i++){ 1636164370Smjacob csrd = (struct csrdir *) malloc(sizeof(struct csrdir), M_DEVBUF,M_DONTWAIT); 1637164370Smjacob if(csrd == NULL) break; 1638164370Smjacob SLIST_INSERT_HEAD(&fc->csrfree, csrd, link); 1639164370Smjacob } 1640164370Smjacob 1641164370Smjacob/* Initialize Async handlers */ 1642164370Smjacob STAILQ_INIT(&fc->binds); 1643164370Smjacob for( i = 0 ; i < 0x40 ; i++){ 1644164370Smjacob STAILQ_INIT(&fc->tlabels[i]); 1645164370Smjacob } 1646164370Smjacob 1647164370Smjacob/* DV depend CSRs see blue book */ 1648164370Smjacob#if 0 1649164370Smjacob CSRARC(fc, oMPR) = 0x3fff0001; /* # output channel = 1 */ 1650196008Smjacob CSRARC(fc, oPCR) = 0x8000007a; 1651196008Smjacob for(i = 4 ; i < 0x7c/4 ; i+=4){ 1652196008Smjacob CSRARC(fc, i + oPCR) = 0x8000007a; 1653164370Smjacob } 1654164370Smjacob 1655164370Smjacob CSRARC(fc, iMPR) = 0x00ff0001; /* # input channel = 1 */ 1656164370Smjacob CSRARC(fc, iPCR) = 0x803f0000; 1657163899Smjacob for(i = 4 ; i < 0x7c/4 ; i+=4){ 1658163899Smjacob CSRARC(fc, i + iPCR) = 0x0; 1659163899Smjacob } 1660163899Smjacob#endif 1661163899Smjacob 1662163899Smjacob 1663163899Smjacob#ifdef FW_VMACCESS 1664163899Smjacob xfer = fw_xfer_alloc(); 1665163899Smjacob if(xfer == NULL) return; 1666196008Smjacob 1667196008Smjacob fwb = (struct fw_bind *)malloc(sizeof (struct fw_bind), M_DEVBUF, M_DONTWAIT); 1668163899Smjacob if(fwb == NULL){ 1669196008Smjacob fw_xfer_free(xfer); 1670163899Smjacob } 1671163899Smjacob xfer->act.hand = fw_vmaccess; 1672196008Smjacob xfer->act_type = FWACT_XFER; 1673163899Smjacob xfer->fc = fc; 1674163899Smjacob xfer->sc = NULL; 1675163899Smjacob 1676163899Smjacob fwb->start_hi = 0x2; 1677196008Smjacob fwb->start_lo = 0; 1678196008Smjacob fwb->addrlen = 0xffffffff; 1679196008Smjacob fwb->xfer = xfer; 1680163899Smjacob fw_bindadd(fc, fwb); 1681163899Smjacob#endif 1682163899Smjacob} 1683164370Smjacob 1684164370Smjacob/* 1685164370Smjacob * To lookup binded process from IEEE1394 address. 1686164370Smjacob */ 1687164370Smjacobstatic struct fw_bind * 1688164370Smjacobfw_bindlookup(struct firewire_comm *fc, u_int32_t dest_hi, u_int32_t dest_lo) 1689164370Smjacob{ 1690164370Smjacob struct fw_bind *tfw; 1691164370Smjacob for(tfw = STAILQ_FIRST(&fc->binds) ; tfw != NULL ; 1692164370Smjacob tfw = STAILQ_NEXT(tfw, fclist)){ 1693164370Smjacob if(tfw->xfer->act_type != FWACT_NULL && 1694164370Smjacob tfw->start_hi == dest_hi && 1695164370Smjacob tfw->start_lo <= dest_lo && 1696164370Smjacob (tfw->start_lo + tfw->addrlen) > dest_lo){ 1697164370Smjacob return(tfw); 1698164370Smjacob } 1699164370Smjacob } 1700164370Smjacob return(NULL); 1701164370Smjacob} 1702164370Smjacob 1703164370Smjacob/* 1704196008Smjacob * To bind IEEE1394 address block to process. 1705196008Smjacob */ 1706196008Smjacobint 1707164370Smjacobfw_bindadd(struct firewire_comm *fc, struct fw_bind *fwb) 1708164370Smjacob{ 1709164370Smjacob struct fw_bind *tfw, *tfw2 = NULL; 1710163899Smjacob int err = 0; 1711155228Smjacob tfw = STAILQ_FIRST(&fc->binds); 1712155228Smjacob if(tfw == NULL){ 1713155228Smjacob STAILQ_INSERT_HEAD(&fc->binds, fwb, fclist); 1714155228Smjacob goto out; 1715155704Smjacob } 1716155228Smjacob if((tfw->start_hi > fwb->start_hi) || 1717155228Smjacob (tfw->start_hi == fwb->start_hi && 1718155228Smjacob (tfw->start_lo > (fwb->start_lo + fwb->addrlen)))){ 1719155228Smjacob STAILQ_INSERT_HEAD(&fc->binds, fwb, fclist); 1720155228Smjacob goto out; 1721155228Smjacob } 1722155228Smjacob for(; tfw != NULL; tfw = STAILQ_NEXT(tfw, fclist)){ 1723155228Smjacob if((tfw->start_hi < fwb->start_hi) || 1724155228Smjacob (tfw->start_hi == fwb->start_hi && 1725155228Smjacob (tfw->start_lo + tfw->addrlen) < fwb->start_lo)){ 1726155228Smjacob tfw2 = STAILQ_NEXT(tfw, fclist); 1727155228Smjacob if(tfw2 == NULL) 1728155228Smjacob break; 1729196008Smjacob if((tfw2->start_hi > fwb->start_hi) || 1730155228Smjacob (tfw2->start_hi == fwb->start_hi && 1731155228Smjacob tfw2->start_lo > (fwb->start_lo + fwb->addrlen))){ 1732163899Smjacob break; 1733155228Smjacob }else{ 1734155228Smjacob err = EBUSY; 1735155228Smjacob goto out; 1736155228Smjacob } 1737155228Smjacob } 1738163899Smjacob } 1739155228Smjacob if(tfw != NULL){ 1740155228Smjacob STAILQ_INSERT_AFTER(&fc->binds, tfw, fwb, fclist); 1741163899Smjacob }else{ 1742155228Smjacob STAILQ_INSERT_TAIL(&fc->binds, fwb, fclist); 1743155228Smjacob } 1744155228Smjacobout: 1745155228Smjacob if(!err && fwb->xfer->act_type == FWACT_CH){ 1746321870Smav STAILQ_INSERT_HEAD(&fc->ir[fwb->xfer->sub]->binds, fwb, chlist); 1747155228Smjacob } 1748155228Smjacob return err; 1749163899Smjacob} 1750155228Smjacob 1751155228Smjacob/* 1752155228Smjacob * To free IEEE1394 address block. 1753155228Smjacob */ 1754155228Smjacobint 1755163899Smjacobfw_bindremove(struct firewire_comm *fc, struct fw_bind *fwb) 1756155228Smjacob{ 1757321870Smav int s; 1758163899Smjacob 1759321870Smav s = splfw(); 1760321870Smav /* shall we check the existance? */ 1761321870Smav STAILQ_REMOVE(&fc->binds, fwb, fw_bind, fclist); 1762321870Smav splx(s); 1763155228Smjacob if (fwb->xfer) 1764155228Smjacob fw_xfer_free(fwb->xfer); 1765155228Smjacob 1766321870Smav return 0; 1767155228Smjacob} 1768321870Smav 1769321870Smav/* 1770321870Smav * To free transaction label. 1771321870Smav */ 1772321870Smavstatic void 1773321870Smavfw_tl_free(struct firewire_comm *fc, struct fw_xfer *xfer) 1774321870Smav{ 1775321870Smav struct tlabel *tl; 1776321870Smav int s = splfw(); 1777321870Smav 1778321870Smav for( tl = STAILQ_FIRST(&fc->tlabels[xfer->tl]); tl != NULL; 1779321870Smav tl = STAILQ_NEXT(tl, link)){ 1780155228Smjacob if(tl->xfer == xfer){ 1781155228Smjacob STAILQ_REMOVE(&fc->tlabels[xfer->tl], tl, tlabel, link); 1782155228Smjacob free(tl, M_DEVBUF); 1783321870Smav splx(s); 1784155228Smjacob return; 1785321870Smav } 1786321870Smav } 1787155228Smjacob splx(s); 1788155228Smjacob return; 1789321870Smav} 1790321870Smav 1791155228Smjacob/* 1792321870Smav * To obtain XFER structure by transaction label. 1793321870Smav */ 1794155228Smjacobstatic struct fw_xfer * 1795321870Smavfw_tl2xfer(struct firewire_comm *fc, int node, int tlabel) 1796155228Smjacob{ 1797155228Smjacob struct fw_xfer *xfer; 1798155228Smjacob struct tlabel *tl; 1799155228Smjacob int s = splfw(); 1800155228Smjacob 1801196008Smjacob for( tl = STAILQ_FIRST(&fc->tlabels[tlabel]); tl != NULL; 1802155228Smjacob tl = STAILQ_NEXT(tl, link)){ 1803155228Smjacob if(tl->xfer->dst == node){ 1804321870Smav xfer = tl->xfer; 1805155228Smjacob splx(s); 1806321870Smav return(xfer); 1807321870Smav } 1808321870Smav } 1809321870Smav splx(s); 1810321870Smav return(NULL); 1811321870Smav} 1812321870Smav 1813321870Smav/* 1814321870Smav * To allocate IEEE1394 XFER structure. 1815321870Smav */ 1816196008Smjacobstruct fw_xfer * 1817321870Smavfw_xfer_alloc() 1818321870Smav{ 1819196008Smjacob struct fw_xfer *xfer; 1820155228Smjacob 1821155228Smjacob xfer = malloc(sizeof(struct fw_xfer), M_DEVBUF, M_DONTWAIT | M_ZERO); 1822155228Smjacob if (xfer == NULL) 1823196008Smjacob return xfer; 1824155228Smjacob 1825155228Smjacob xfer->time = time_second; 1826321870Smav xfer->sub = -1; 1827155228Smjacob 1828155228Smjacob return xfer; 1829321870Smav} 1830321870Smav 1831155228Smjacob/* 1832155228Smjacob * IEEE1394 XFER post process. 1833155228Smjacob */ 1834155228Smjacobvoid 1835196008Smjacobfw_xfer_done(struct fw_xfer *xfer) 1836155228Smjacob{ 1837155228Smjacob if (xfer->act.hand == NULL) 1838155228Smjacob return; 1839321870Smav 1840155228Smjacob#if XFER_TIMEOUT 1841321870Smav untimeout(fw_xfer_timeout, (void *)xfer, xfer->ch); 1842155228Smjacob#endif 1843155228Smjacob 1844321870Smav if (xfer->fc->status != FWBUSRESET) 1845155228Smjacob xfer->act.hand(xfer); 1846321870Smav else { 1847155228Smjacob printf("fw_xfer_done: pending\n"); 1848321870Smav if (xfer->fc != NULL) 1849155228Smjacob STAILQ_INSERT_TAIL(&xfer->fc->pending, xfer, link); 1850155228Smjacob else 1851321870Smav panic("fw_xfer_done: why xfer->fc is NULL?"); 1852155228Smjacob } 1853321870Smav} 1854155228Smjacob 1855321870Smav/* 1856155228Smjacob * To free IEEE1394 XFER structure. 1857155228Smjacob */ 1858321870Smavvoid 1859155228Smjacobfw_xfer_free( struct fw_xfer* xfer) 1860155228Smjacob{ 1861321870Smav int s; 1862155228Smjacob if(xfer == NULL ) return; 1863155228Smjacob if(xfer->state == FWXF_INQ){ 1864321870Smav printf("fw_xfer_free FWXF_INQ\n"); 1865155228Smjacob s = splfw(); 1866155228Smjacob STAILQ_REMOVE(&xfer->q->q, xfer, fw_xfer, link); 1867321870Smav xfer->q->queued --; 1868155228Smjacob splx(s); 1869155228Smjacob } 1870321870Smav if(xfer->fc != NULL){ 1871155228Smjacob if(xfer->state == FWXF_START){ 1872321870Smav#if 0 /* this could happen if we call fwohci_arcv() before fwohci_txd() */ 1873155228Smjacob printf("fw_xfer_free FWXF_START\n"); 1874321870Smav#endif 1875155228Smjacob s = splfw(); 1876155228Smjacob xfer->q->drain(xfer->fc, xfer); 1877155228Smjacob splx(s); 1878163899Smjacob } 1879163899Smjacob } 1880163899Smjacob if(xfer->send.buf != NULL){ 1881163899Smjacob free(xfer->send.buf, M_DEVBUF); 1882163899Smjacob } 1883163899Smjacob if(xfer->recv.buf != NULL){ 1884163899Smjacob free(xfer->recv.buf, M_DEVBUF); 1885163899Smjacob } 1886163899Smjacob if(xfer->fc != NULL){ 1887163899Smjacob fw_tl_free(xfer->fc, xfer); 1888163899Smjacob } 1889163899Smjacob free(xfer, M_DEVBUF); 1890163899Smjacob} 1891163899Smjacob 1892163899Smjacob/* 1893163899Smjacob * Callback for PHY configuration. 1894163899Smjacob */ 1895163899Smjacobstatic void 1896163899Smjacobfw_phy_config_callback(struct fw_xfer *xfer) 1897163899Smjacob{ 1898163899Smjacob#if 0 1899163899Smjacob printf("phy_config done state=%d resp=%d\n", 1900163899Smjacob xfer->state, xfer->resp); 1901163899Smjacob#endif 1902163899Smjacob fw_xfer_free(xfer); 1903163899Smjacob /* XXX need bus reset ?? */ 1904196008Smjacob /* sc->fc->ibr(xfer->fc); LOOP */ 1905163899Smjacob} 1906163899Smjacob 1907163899Smjacob/* 1908163899Smjacob * To configure PHY. 1909163899Smjacob */ 1910163899Smjacobstatic void 1911163899Smjacobfw_phy_config(struct firewire_comm *fc, int root_node, int gap_count) 1912163899Smjacob{ 1913163899Smjacob struct fw_xfer *xfer; 1914163899Smjacob struct fw_pkt *fp; 1915163899Smjacob 1916163899Smjacob fc->status = FWBUSPHYCONF; 1917163899Smjacob 1918163899Smjacob DELAY(100000); 1919163899Smjacob xfer = fw_xfer_alloc(); 1920163899Smjacob xfer->send.len = 12; 1921163899Smjacob xfer->send.off = 0; 1922163899Smjacob xfer->fc = fc; 1923163899Smjacob xfer->retry_req = fw_asybusy; 1924163899Smjacob xfer->act.hand = fw_phy_config_callback; 1925163899Smjacob 1926163899Smjacob xfer->send.buf = malloc(sizeof(u_int32_t), 1927163899Smjacob M_DEVBUF, M_DONTWAIT | M_ZERO); 1928163899Smjacob fp = (struct fw_pkt *)xfer->send.buf; 1929163899Smjacob fp->mode.ld[1] = 0; 1930163899Smjacob if (root_node >= 0) 1931163899Smjacob fp->mode.ld[1] |= htonl((root_node & 0x3f) << 24 | 1 << 23); 1932163899Smjacob if (gap_count >= 0) 1933163899Smjacob fp->mode.ld[1] |= htonl(1 << 22 | (gap_count & 0x3f) << 16); 1934163899Smjacob fp->mode.ld[2] = ~fp->mode.ld[1]; 1935163899Smjacob/* XXX Dangerous, how to pass PHY packet to device driver */ 1936163899Smjacob fp->mode.common.tcode |= FWTCODE_PHY; 1937163899Smjacob 1938163899Smjacob printf("send phy_config root_node=%d gap_count=%d\n", 1939163899Smjacob root_node, gap_count); 1940163899Smjacob fw_asyreq(fc, -1, xfer); 1941163899Smjacob} 1942163899Smjacob 1943163899Smjacob#if 0 1944163899Smjacob/* 1945163899Smjacob * Dump self ID. 1946163899Smjacob */ 1947163899Smjacobstatic void 1948163899Smjacobfw_print_sid(u_int32_t sid) 1949163899Smjacob{ 1950163899Smjacob union fw_self_id *s; 1951163899Smjacob s = (union fw_self_id *) &sid; 1952163899Smjacob printf("node:%d link:%d gap:%d spd:%d del:%d con:%d pwr:%d" 1953163899Smjacob " p0:%d p1:%d p2:%d i:%d m:%d\n", 1954163899Smjacob s->p0.phy_id, s->p0.link_active, s->p0.gap_count, 1955163899Smjacob s->p0.phy_speed, s->p0.phy_delay, s->p0.contender, 1956163899Smjacob s->p0.power_class, s->p0.port0, s->p0.port1, 1957163899Smjacob s->p0.port2, s->p0.initiated_reset, s->p0.more_packets); 1958196008Smjacob} 1959196008Smjacob#endif 1960196008Smjacob 1961163899Smjacob/* 1962163899Smjacob * To receive self ID. 1963163899Smjacob */ 1964163899Smjacobvoid fw_sidrcv(struct firewire_comm* fc, caddr_t buf, u_int len, u_int off) 1965163899Smjacob{ 1966163899Smjacob u_int32_t *p, *sid = (u_int32_t *)(buf + off); 1967163899Smjacob union fw_self_id *self_id; 1968163899Smjacob u_int i, j, node, c_port = 0, i_branch = 0; 1969163899Smjacob 1970238869Smjacob fc->sid_cnt = len /(sizeof(u_int32_t) * 2); 1971238869Smjacob fc->status = FWBUSINIT; 1972238869Smjacob fc->max_node = fc->nodeid & 0x3f; 1973238869Smjacob CSRARC(fc, NODE_IDS) = ((u_int32_t)fc->nodeid) << 16; 1974238869Smjacob fc->status = FWBUSCYMELECT; 1975238869Smjacob fc->topology_map->crc_len = 2; 1976238869Smjacob fc->topology_map->generation ++; 1977238869Smjacob fc->topology_map->self_id_count = 0; 1978238869Smjacob fc->topology_map->node_count = 0; 1979238869Smjacob fc->speed_map->generation ++; 1980238869Smjacob fc->speed_map->crc_len = 1 + (64*64 + 3) / 4; 1981238869Smjacob self_id = &fc->topology_map->self_id[0]; 1982238869Smjacob for(i = 0; i < fc->sid_cnt; i ++){ 1983238869Smjacob if (sid[1] != ~sid[0]) { 1984238869Smjacob printf("fw_sidrcv: invalid self-id packet\n"); 1985238869Smjacob sid += 2; 1986238869Smjacob continue; 1987238869Smjacob } 1988238869Smjacob *self_id = *((union fw_self_id *)sid); 1989238869Smjacob fc->topology_map->crc_len++; 1990238869Smjacob if(self_id->p0.sequel == 0){ 1991238869Smjacob fc->topology_map->node_count ++; 1992238869Smjacob c_port = 0; 1993163899Smjacob#if 0 1994163899Smjacob fw_print_sid(sid[0]); 1995163899Smjacob#endif 1996163899Smjacob node = self_id->p0.phy_id; 1997163899Smjacob if(fc->max_node < node){ 1998163899Smjacob fc->max_node = self_id->p0.phy_id; 1999163899Smjacob } 2000163899Smjacob /* XXX I'm not sure this is the right speed_map */ 2001196008Smjacob fc->speed_map->speed[node][node] 2002196008Smjacob = self_id->p0.phy_speed; 2003196008Smjacob for (j = 0; j < node; j ++) { 2004163899Smjacob fc->speed_map->speed[j][node] 2005196008Smjacob = fc->speed_map->speed[node][j] 2006163899Smjacob = min(fc->speed_map->speed[j][j], 2007196008Smjacob self_id->p0.phy_speed); 2008163899Smjacob } 2009163899Smjacob if ((fc->irm == -1 || self_id->p0.phy_id > fc->irm) && 2010163899Smjacob (self_id->p0.link_active && self_id->p0.contender)) { 2011163899Smjacob fc->irm = self_id->p0.phy_id; 2012163899Smjacob } 2013163899Smjacob if(self_id->p0.port0 >= 0x2){ 2014163899Smjacob c_port++; 2015163899Smjacob } 2016163899Smjacob if(self_id->p0.port1 >= 0x2){ 2017163899Smjacob c_port++; 2018163899Smjacob } 2019163899Smjacob if(self_id->p0.port2 >= 0x2){ 2020196008Smjacob c_port++; 2021163899Smjacob } 2022163899Smjacob } 2023163899Smjacob if(c_port > 2){ 2024163899Smjacob i_branch += (c_port - 2); 2025297751Smav } 2026297751Smav sid += 2; 2027297751Smav self_id++; 2028297751Smav fc->topology_map->self_id_count ++; 2029297751Smav } 2030297751Smav printf("%s: %d nodes", device_get_nameunit(fc->dev), fc->max_node + 1); 2031297751Smav /* CRC */ 2032297751Smav fc->topology_map->crc = fw_crc16( 2033297751Smav (u_int32_t *)&fc->topology_map->generation, 2034297751Smav fc->topology_map->crc_len * 4); 2035297751Smav fc->speed_map->crc = fw_crc16( 2036291000Smav (u_int32_t *)&fc->speed_map->generation, 2037291000Smav fc->speed_map->crc_len * 4); 2038291000Smav /* byteswap and copy to CSR */ 2039291000Smav p = (u_int32_t *)fc->topology_map; 2040291000Smav for (i = 0; i <= fc->topology_map->crc_len; i++) 2041291000Smav CSRARC(fc, TOPO_MAP + i * 4) = htonl(*p++); 2042291000Smav p = (u_int32_t *)fc->speed_map; 2043291000Smav CSRARC(fc, SPED_MAP) = htonl(*p++); 2044291000Smav CSRARC(fc, SPED_MAP + 4) = htonl(*p++); 2045291000Smav /* don't byte-swap u_int8_t array */ 2046291000Smav bcopy(p, &CSRARC(fc, SPED_MAP + 8), (fc->speed_map->crc_len - 1)*4); 2047291000Smav 2048291000Smav fc->max_hop = fc->max_node - i_branch; 2049291000Smav#if 1 2050297751Smav printf(", maxhop <= %d", fc->max_hop); 2051297751Smav#endif 2052297751Smav 2053297751Smav if(fc->irm == -1 ){ 2054297751Smav printf(", Not found IRM capable node"); 2055297751Smav }else{ 2056297751Smav printf(", cable IRM = %d", fc->irm); 2057297751Smav if (fc->irm == fc->nodeid) 2058297751Smav printf(" (me)\n"); 2059297751Smav else 2060297751Smav printf("\n"); 2061297751Smav } 2062163899Smjacob 2063163899Smjacob if((fc->irm != -1) && (CSRARC(fc, BUS_MGR_ID) == 0x3f) ){ 2064163899Smjacob if(fc->irm == ((CSRARC(fc, NODE_IDS) >> 16 ) & 0x3f)){ 2065163899Smjacob fc->status = FWBUSMGRDONE; 2066163899Smjacob CSRARC(fc, BUS_MGR_ID) = fc->set_bmr(fc, fc->irm); 2067163899Smjacob }else{ 2068163899Smjacob fc->status = FWBUSMGRELECT; 2069163899Smjacob fc->bmrhandle = timeout((timeout_t *)fw_try_bmr,(void *)fc, hz / 8); 2070163899Smjacob } 2071163899Smjacob }else{ 2072163899Smjacob fc->status = FWBUSMGRDONE; 2073163899Smjacob printf("%s: BMR = %x\n", device_get_nameunit(fc->dev), CSRARC(fc, BUS_MGR_ID)); 2074163899Smjacob } 2075163899Smjacob free(buf, M_DEVBUF); 2076163899Smjacob#if 1 2077163899Smjacob /* XXX optimize gap_count, if I am BMGR */ 2078163899Smjacob if(fc->irm == ((CSRARC(fc, NODE_IDS) >> 16 ) & 0x3f)){ 2079163899Smjacob fw_phy_config(fc, -1, gap_cnt[fc->max_hop]); 2080163899Smjacob } 2081163899Smjacob#endif 2082163899Smjacob#if 1 2083163899Smjacob timeout((timeout_t *)fw_bus_probe, (void *)fc, hz/4); 2084163899Smjacob#else 2085163899Smjacob fw_bus_probe(fc); 2086163899Smjacob#endif 2087163899Smjacob} 2088163899Smjacob 2089163899Smjacob/* 2090163899Smjacob * To probe devices on the IEEE1394 bus. 2091163899Smjacob */ 2092163899Smjacobstatic void 2093163899Smjacobfw_bus_probe(struct firewire_comm *fc) 2094163899Smjacob{ 2095163899Smjacob int s; 2096163899Smjacob struct fw_device *fwdev, *next; 2097163899Smjacob 2098163899Smjacob s = splfw(); 2099238869Smjacob fc->status = FWBUSEXPLORE; 2100238869Smjacob fc->retry_count = 0; 2101238869Smjacob 2102238869Smjacob/* 2103238869Smjacob * Invalidate all devices, just after bus reset. Devices 2104238869Smjacob * to be removed has not been seen longer time. 2105238869Smjacob */ 2106238869Smjacob for(fwdev = TAILQ_FIRST(&fc->devices); fwdev != NULL; fwdev = next) { 2107238869Smjacob next = TAILQ_NEXT(fwdev, link); 2108238869Smjacob if(fwdev->status != FWDEVINVAL){ 2109238869Smjacob fwdev->status = FWDEVINVAL; 2110238869Smjacob fwdev->rcnt = 0; 2111238869Smjacob }else if(fwdev->rcnt < FW_MAXDEVRCNT){ 2112238869Smjacob fwdev->rcnt ++; 2113238869Smjacob }else{ 2114196008Smjacob TAILQ_REMOVE(&fc->devices, fwdev, link); 2115285459Smav free(fwdev, M_DEVBUF); 2116196008Smjacob } 2117196008Smjacob } 2118291080Smav fc->ongonode = 0; 2119196008Smjacob fc->ongoaddr = CSRROMOFF; 2120291080Smav fc->ongodev = NULL; 2121196008Smjacob fc->ongoeui.hi = 0xffffffff; fc->ongoeui.lo = 0xffffffff; 2122196008Smjacob fw_bus_explore(fc); 2123285459Smav splx(s); 2124284681Smav} 2125196008Smjacob 2126291080Smav/* 2127291080Smav * To collect device informations on the IEEE1394 bus. 2128291080Smav */ 2129291080Smavstatic void 2130291080Smavfw_bus_explore(struct firewire_comm *fc ) 2131291080Smav{ 2132291080Smav int err = 0; 2133291080Smav struct fw_device *fwdev, *tfwdev; 2134291080Smav u_int32_t addr; 2135291080Smav struct fw_xfer *xfer; 2136291080Smav struct fw_pkt *fp; 2137291080Smav 2138291080Smav if(fc->status != FWBUSEXPLORE) 2139291080Smav return; 2140291080Smav 2141291080Smavloop: 2142291080Smav if(fc->ongonode == fc->nodeid) fc->ongonode++; 2143285459Smav 2144284681Smav if(fc->ongonode > fc->max_node) goto done; 2145291080Smav if(fc->ongonode >= 0x3f) goto done; 2146284681Smav 2147284681Smav /* check link */ 2148196008Smjacob /* XXX we need to check phy_id first */ 2149196008Smjacob if (!fc->topology_map->self_id[fc->ongonode].p0.link_active) { 2150196008Smjacob printf("fw_bus_explore: node %d link down\n", fc->ongonode); 2151196008Smjacob fc->ongonode++; 2152196008Smjacob goto loop; 2153196008Smjacob } 2154291080Smav 2155291080Smav if(fc->ongoaddr <= CSRROMOFF && 2156196008Smjacob fc->ongoeui.hi == 0xffffffff && 2157291080Smav fc->ongoeui.lo == 0xffffffff ){ 2158196008Smjacob fc->ongoaddr = CSRROMOFF; 2159196008Smjacob addr = 0xf0000000 | fc->ongoaddr; 2160285459Smav }else if(fc->ongoeui.hi == 0xffffffff ){ 2161285459Smav fc->ongoaddr = CSRROMOFF + 0xc; 2162285459Smav addr = 0xf0000000 | fc->ongoaddr; 2163285459Smav }else if(fc->ongoeui.lo == 0xffffffff ){ 2164285459Smav fc->ongoaddr = CSRROMOFF + 0x10; 2165285459Smav addr = 0xf0000000 | fc->ongoaddr; 2166285459Smav }else if(fc->ongodev == NULL){ 2167285459Smav for(fwdev = TAILQ_FIRST(&fc->devices); fwdev != NULL; 2168285459Smav fwdev = TAILQ_NEXT(fwdev, link)){ 2169196008Smjacob if(fwdev->eui.hi == fc->ongoeui.hi && fwdev->eui.lo == fc->ongoeui.lo){ 2170196008Smjacob break; 2171196008Smjacob } 2172196008Smjacob } 2173196008Smjacob if(fwdev != NULL){ 2174291080Smav fwdev->dst = fc->ongonode; 2175291080Smav fwdev->status = FWDEVATTACHED; 2176196008Smjacob fc->ongonode++; 2177291080Smav fc->ongoaddr = CSRROMOFF; 2178196008Smjacob fc->ongodev = NULL; 2179196008Smjacob fc->ongoeui.hi = 0xffffffff; fc->ongoeui.lo = 0xffffffff; 2180285459Smav goto loop; 2181196008Smjacob } 2182196008Smjacob fwdev = malloc(sizeof(struct fw_device), M_DEVBUF, M_DONTWAIT); 2183285459Smav if(fwdev == NULL) 2184196008Smjacob return; 2185291080Smav fwdev->fc = fc; 2186196008Smjacob fwdev->rommax = 0; 2187196008Smjacob fwdev->dst = fc->ongonode; 2188196008Smjacob fwdev->eui.hi = fc->ongoeui.hi; fwdev->eui.lo = fc->ongoeui.lo; 2189196008Smjacob fwdev->status = FWDEVINIT; 2190196008Smjacob#if 0 2191196008Smjacob fwdev->speed = CSRARC(fc, SPED_MAP + 8 + fc->ongonode / 4) 2192196008Smjacob >> ((3 - (fc->ongonode % 4)) * 8); 2193291080Smav#else 2194155228Smjacob fwdev->speed = fc->speed_map->speed[fc->nodeid][fc->ongonode]; 2195196008Smjacob#endif 2196196008Smjacob 2197196008Smjacob tfwdev = TAILQ_FIRST(&fc->devices); 2198196008Smjacob while( tfwdev != NULL && 2199196008Smjacob (tfwdev->eui.hi > fwdev->eui.hi) && 2200196008Smjacob ((tfwdev->eui.hi == fwdev->eui.hi) && 2201196008Smjacob tfwdev->eui.lo > fwdev->eui.lo)){ 2202290993Smav tfwdev = TAILQ_NEXT( tfwdev, link); 2203297991Smav } 2204196008Smjacob if(tfwdev == NULL){ 2205196008Smjacob TAILQ_INSERT_TAIL(&fc->devices, fwdev, link); 2206196008Smjacob }else{ 2207196008Smjacob TAILQ_INSERT_BEFORE(tfwdev, fwdev, link); 2208196008Smjacob } 2209196008Smjacob 2210196008Smjacob printf("%s:Discover new %s device ID:%08x%08x\n", device_get_nameunit(fc->dev), linkspeed[fwdev->speed], fc->ongoeui.hi, fc->ongoeui.lo); 2211196008Smjacob 2212196008Smjacob fc->ongodev = fwdev; 2213196008Smjacob fc->ongoaddr = CSRROMOFF; 2214196008Smjacob addr = 0xf0000000 | fc->ongoaddr; 2215196008Smjacob }else{ 2216196008Smjacob addr = 0xf0000000 | fc->ongoaddr; 2217289838Smav } 2218289838Smav#if 0 2219196008Smjacob xfer = asyreqq(fc, FWSPD_S100, 0, 0, 2220238869Smjacob ((FWLOCALBUS | fc->ongonode) << 16) | 0xffff , addr, 2221196008Smjacob fw_bus_explore_callback); 2222196008Smjacob if(xfer == NULL) goto done; 2223285459Smav#else 2224196008Smjacob xfer = fw_xfer_alloc(); 2225196008Smjacob if(xfer == NULL){ 2226196008Smjacob goto done; 2227285459Smav } 2228285459Smav xfer->send.len = 16; 2229289838Smav xfer->spd = 0; 2230196008Smjacob xfer->send.buf = malloc(16, M_DEVBUF, M_DONTWAIT); 2231196008Smjacob if(xfer->send.buf == NULL){ 2232196008Smjacob fw_xfer_free( xfer); 2233284681Smav return; 2234284681Smav } 2235284681Smav 2236284681Smav xfer->send.off = 0; 2237284681Smav fp = (struct fw_pkt *)xfer->send.buf; 2238291080Smav fp->mode.rreqq.dest_hi = htons(0xffff); 2239291144Smav fp->mode.rreqq.tlrt = 0; 2240285459Smav fp->mode.rreqq.tcode = FWTCODE_RREQQ; 2241285459Smav fp->mode.rreqq.pri = 0; 2242285459Smav fp->mode.rreqq.src = 0; 2243291144Smav xfer->dst = FWLOCALBUS | fc->ongonode; 2244291144Smav fp->mode.rreqq.dst = htons(xfer->dst); 2245284681Smav fp->mode.rreqq.dest_lo = htonl(addr); 2246285459Smav xfer->act.hand = fw_bus_explore_callback; 2247285459Smav 2248284681Smav err = fw_asyreq(fc, -1, xfer); 2249284681Smav if(err){ 2250284681Smav fw_xfer_free( xfer); 2251284681Smav return; 2252285459Smav } 2253285459Smav#endif 2254284681Smav return; 2255284681Smavdone: 2256284681Smav /* fw_attach_devs */ 2257284681Smav fc->status = FWBUSEXPDONE; 2258196008Smjacob printf("bus_explore done\n"); 2259285459Smav fw_attach_dev(fc); 2260285459Smav return; 2261196008Smjacob 2262289838Smav} 2263196008Smjacob 2264284681Smav/* Portable Async. request read quad */ 2265285459Smavstruct fw_xfer * 2266289838Smavasyreqq(struct firewire_comm *fc, u_int8_t spd, u_int8_t tl, u_int8_t rt, 2267285459Smav u_int32_t addr_hi, u_int32_t addr_lo, 2268289838Smav void (*hand) __P((struct fw_xfer*))) 2269289838Smav{ 2270284681Smav struct fw_xfer *xfer; 2271285459Smav struct fw_pkt *fp; 2272289838Smav int err; 2273285459Smav 2274284681Smav xfer = fw_xfer_alloc(); 2275289838Smav if(xfer == NULL){ 2276284681Smav return NULL; 2277284681Smav } 2278196008Smjacob xfer->send.len = 16; 2279289838Smav xfer->spd = spd; /* XXX:min(spd, fc->spd) */ 2280285459Smav xfer->send.buf = malloc(16, M_DEVBUF, M_DONTWAIT); 2281196008Smjacob if(xfer->send.buf == NULL){ 2282289838Smav fw_xfer_free( xfer); 2283289838Smav return NULL; 2284289838Smav } 2285289838Smav 2286289838Smav xfer->send.off = 0; 2287289838Smav fp = (struct fw_pkt *)xfer->send.buf; 2288289838Smav fp->mode.rreqq.dest_hi = htons(addr_hi & 0xffff); 2289289838Smav if(tl & FWP_TL_VALID){ 2290289838Smav fp->mode.rreqq.tlrt = (tl & 0x3f) << 2; 2291289838Smav }else{ 2292289838Smav fp->mode.rreqq.tlrt = 0; 2293289838Smav } 2294289838Smav fp->mode.rreqq.tlrt |= rt & 0x3; 2295289838Smav fp->mode.rreqq.tcode = FWTCODE_RREQQ; 2296289838Smav fp->mode.rreqq.pri = 0; 2297289838Smav fp->mode.rreqq.src = 0; 2298289838Smav xfer->dst = addr_hi >> 16; 2299289838Smav fp->mode.rreqq.dst = htons(xfer->dst); 2300285459Smav fp->mode.rreqq.dest_lo = htonl(addr_lo); 2301285459Smav xfer->act.hand = hand; 2302284681Smav 2303285459Smav err = fw_asyreq(fc, -1, xfer); 2304285459Smav if(err){ 2305284681Smav fw_xfer_free( xfer); 2306285459Smav return NULL; 2307285459Smav } 2308285459Smav return xfer; 2309238869Smjacob} 2310285459Smav 2311285459Smav/* 2312285459Smav * Callback for the IEEE1394 bus information collection. 2313285459Smav */ 2314284681Smavstatic void 2315285459Smavfw_bus_explore_callback(struct fw_xfer *xfer) 2316285459Smav{ 2317285459Smav struct firewire_comm *fc; 2318196008Smjacob struct fw_pkt *sfp,*rfp; 2319285459Smav struct csrhdr *chdr; 2320285459Smav struct csrdir *csrd; 2321285459Smav struct csrreg *csrreg; 2322285459Smav u_int32_t offset; 2323285459Smav 2324285459Smav 2325285459Smav if(xfer == NULL) return; 2326285459Smav fc = xfer->fc; 2327285459Smav if(xfer->resp != 0){ 2328284681Smav printf("resp != 0: node=%d addr=0x%x\n", 2329285459Smav fc->ongonode, fc->ongoaddr); 2330285459Smav fc->retry_count++; 2331196008Smjacob goto nextnode; 2332285459Smav } 2333284681Smav 2334284681Smav if(xfer->send.buf == NULL){ 2335284681Smav printf("send.buf == NULL: node=%d addr=0x%x\n", 2336285459Smav fc->ongonode, fc->ongoaddr); 2337285459Smav printf("send.buf == NULL\n"); 2338285459Smav fc->retry_count++; 2339196008Smjacob goto nextnode; 2340285459Smav } 2341284681Smav sfp = (struct fw_pkt *)xfer->send.buf; 2342285459Smav 2343284681Smav if(xfer->recv.buf == NULL){ 2344289838Smav printf("recv.buf == NULL: node=%d addr=0x%x\n", 2345284681Smav fc->ongonode, fc->ongoaddr); 2346284681Smav fc->retry_count++; 2347196008Smjacob goto nextnode; 2348196008Smjacob } 2349196008Smjacob rfp = (struct fw_pkt *)xfer->recv.buf; 2350284681Smav#if 0 2351285459Smav { 2352196008Smjacob u_int32_t *qld; 2353196008Smjacob int i; 2354196008Smjacob qld = (u_int32_t *)xfer->recv.buf; 2355289838Smav printf("len:%d\n", xfer->recv.len); 2356289838Smav for( i = 0 ; i <= xfer->recv.len && i < 32; i+= 4){ 2357285459Smav printf("0x%08x ", ntohl(rfp->mode.ld[i/4])); 2358284681Smav if((i % 16) == 15) printf("\n"); 2359284681Smav } 2360238869Smjacob if((i % 16) != 15) printf("\n"); 2361285459Smav } 2362285459Smav#endif 2363289838Smav if(fc->ongodev == NULL){ 2364196008Smjacob if(sfp->mode.rreqq.dest_lo == htonl((0xf0000000 | CSRROMOFF))){ 2365285459Smav rfp->mode.rresq.data = ntohl(rfp->mode.rresq.data); 2366285459Smav chdr = (struct csrhdr *)(&rfp->mode.rresq.data); 2367196008Smjacob/* If CSR is minimul confinguration, more investgation is not needed. */ 2368196008Smjacob if(chdr->info_len == 1){ 2369196008Smjacob goto nextnode; 2370196008Smjacob }else{ 2371196008Smjacob fc->ongoaddr = CSRROMOFF + 0xc; 2372196008Smjacob } 2373289838Smav }else if(sfp->mode.rreqq.dest_lo == htonl((0xf0000000 |(CSRROMOFF + 0xc)))){ 2374196008Smjacob fc->ongoeui.hi = ntohl(rfp->mode.rresq.data); 2375196008Smjacob fc->ongoaddr = CSRROMOFF + 0x10; 2376196008Smjacob }else if(sfp->mode.rreqq.dest_lo == htonl((0xf0000000 |(CSRROMOFF + 0x10)))){ 2377196008Smjacob fc->ongoeui.lo = ntohl(rfp->mode.rresq.data); 2378196008Smjacob if (fc->ongoeui.hi == 0 && fc->ongoeui.lo == 0) 2379285459Smav goto nextnode; 2380289838Smav fc->ongoaddr = CSRROMOFF; 2381196008Smjacob } 2382196008Smjacob }else{ 2383196008Smjacob fc->ongodev->csrrom[(fc->ongoaddr - CSRROMOFF)/4] = ntohl(rfp->mode.rresq.data); 2384196008Smjacob if(fc->ongoaddr > fc->ongodev->rommax){ 2385285459Smav fc->ongodev->rommax = fc->ongoaddr; 2386285459Smav } 2387289838Smav csrd = SLIST_FIRST(&fc->ongocsr); 2388196008Smjacob if((csrd = SLIST_FIRST(&fc->ongocsr)) == NULL){ 2389196008Smjacob chdr = (struct csrhdr *)(fc->ongodev->csrrom); 2390196008Smjacob offset = CSRROMOFF; 2391285459Smav }else{ 2392285459Smav chdr = (struct csrhdr *)&fc->ongodev->csrrom[(csrd->off - CSRROMOFF)/4]; 2393285459Smav offset = csrd->off; 2394196008Smjacob } 2395285459Smav if(fc->ongoaddr > (CSRROMOFF + 0x14) && fc->ongoaddr != offset){ 2396285459Smav csrreg = (struct csrreg *)&fc->ongodev->csrrom[(fc->ongoaddr - CSRROMOFF)/4]; 2397196008Smjacob if( csrreg->key == 0x81 || csrreg->key == 0xd1){ 2398196008Smjacob csrd = SLIST_FIRST(&fc->csrfree); 2399196008Smjacob if(csrd == NULL){ 2400196008Smjacob goto nextnode; 2401196008Smjacob }else{ 2402196008Smjacob csrd->ongoaddr = fc->ongoaddr; 2403196008Smjacob fc->ongoaddr += csrreg->val * 4; 2404196008Smjacob csrd->off = fc->ongoaddr; 2405196008Smjacob SLIST_REMOVE_HEAD(&fc->csrfree, link); 2406196008Smjacob SLIST_INSERT_HEAD(&fc->ongocsr, csrd, link); 2407196008Smjacob goto nextaddr; 2408196008Smjacob } 2409196008Smjacob } 2410196008Smjacob } 2411196008Smjacob fc->ongoaddr += 4; 2412196008Smjacob if(((fc->ongoaddr - offset)/4 > chdr->crc_len) && 2413196008Smjacob (fc->ongodev->rommax < 0x414)){ 2414196008Smjacob if(fc->ongodev->rommax <= 0x414){ 2415196008Smjacob csrd = SLIST_FIRST(&fc->csrfree); 2416196008Smjacob if(csrd == NULL) goto nextnode; 2417196008Smjacob csrd->off = fc->ongoaddr; 2418196008Smjacob csrd->ongoaddr = fc->ongoaddr; 2419196008Smjacob SLIST_REMOVE_HEAD(&fc->csrfree, link); 2420196008Smjacob SLIST_INSERT_HEAD(&fc->ongocsr, csrd, link); 2421196008Smjacob } 2422196008Smjacob goto nextaddr; 2423196008Smjacob } 2424196008Smjacob 2425196008Smjacob while(((fc->ongoaddr - offset)/4 > chdr->crc_len)){ 2426196008Smjacob if(csrd == NULL){ 2427285459Smav goto nextnode; 2428285459Smav }; 2429285459Smav fc->ongoaddr = csrd->ongoaddr + 4; 2430285459Smav SLIST_REMOVE_HEAD(&fc->ongocsr, link); 2431196008Smjacob SLIST_INSERT_HEAD(&fc->csrfree, csrd, link); 2432196008Smjacob csrd = SLIST_FIRST(&fc->ongocsr); 2433196008Smjacob if((csrd = SLIST_FIRST(&fc->ongocsr)) == NULL){ 2434196008Smjacob chdr = (struct csrhdr *)(fc->ongodev->csrrom); 2435196008Smjacob offset = CSRROMOFF; 2436196008Smjacob }else{ 2437196008Smjacob chdr = (struct csrhdr *)&(fc->ongodev->csrrom[(csrd->off - CSRROMOFF)/4]); 2438196008Smjacob offset = csrd->off; 2439196008Smjacob } 2440196008Smjacob } 2441196008Smjacob if((fc->ongoaddr - CSRROMOFF) > CSRROMSIZE){ 2442196008Smjacob goto nextnode; 2443196008Smjacob } 2444196008Smjacob } 2445196008Smjacobnextaddr: 2446196008Smjacob fw_xfer_free( xfer); 2447196008Smjacob fw_bus_explore(fc); 2448196008Smjacob return; 2449196008Smjacobnextnode: 2450196008Smjacob fw_xfer_free( xfer); 2451196008Smjacob fc->ongonode++; 2452196008Smjacob/* housekeeping work space */ 2453196008Smjacob fc->ongoaddr = CSRROMOFF; 2454196008Smjacob fc->ongodev = NULL; 2455196008Smjacob fc->ongoeui.hi = 0xffffffff; fc->ongoeui.lo = 0xffffffff; 2456196008Smjacob while((csrd = SLIST_FIRST(&fc->ongocsr)) != NULL){ 2457196008Smjacob SLIST_REMOVE_HEAD(&fc->ongocsr, link); 2458285459Smav SLIST_INSERT_HEAD(&fc->csrfree, csrd, link); 2459196008Smjacob } 2460196008Smjacob fw_bus_explore(fc); 2461196008Smjacob return; 2462196008Smjacob} 2463291144Smav#if 0 2464291080Smav/* 2465196008Smjacob * Async. write responce support for kernel internal use. 2466196008Smjacob */ 2467196008Smjacobint 2468196008Smjacobfw_writeres(struct firewire_comm *fc, u_int32_t dst, u_int32_t tlrt) 2469291144Smav{ 2470291080Smav int err = 0; 2471196008Smjacob struct fw_xfer *xfer; 2472196008Smjacob struct fw_pkt *fp; 2473196008Smjacob 2474196008Smjacob xfer = fw_xfer_alloc(); 2475285459Smav if(xfer == NULL){ 2476285459Smav err = ENOMEM; 2477196008Smjacob return err; 2478196008Smjacob } 2479196008Smjacob xfer->send.len = 12; 2480163899Smjacob xfer->spd = 0; 2481155228Smjacob xfer->send.buf = malloc(xfer->send.len, M_DEVBUF, M_NOWAIT); 2482155228Smjacob if(xfer->send.buf == NULL){ 2483163899Smjacob return ENOMEM; 2484163899Smjacob } 2485163899Smjacob xfer->send.off = 0; 2486163899Smjacob fp = (struct fw_pkt *)xfer->send.buf; 2487163899Smjacob 2488163899Smjacob fp->mode.wres.tlrt = tlrt; 2489163899Smjacob fp->mode.wres.tcode = FWTCODE_WRES; 2490163899Smjacob fp->mode.wres.pri = 0; 2491163899Smjacob fp->mode.wres.dst = htons(dst); 2492163899Smjacob 2493163899Smjacob xfer->act.hand = fw_asy_callback; 2494155228Smjacob err = fw_asyreq(fc, -1, xfer); 2495163899Smjacob if(err){ 2496155228Smjacob fw_xfer_free( xfer); 2497163899Smjacob return err; 2498163899Smjacob } 2499155228Smjacob err = tsleep((caddr_t)xfer, FWPRI, "asyreq", 0); 2500163899Smjacob fw_xfer_free( xfer); 2501155228Smjacob 2502155228Smjacob return err; 2503196008Smjacob} 2504155228Smjacob 2505163899Smjacob/* 2506155228Smjacob * Async. read responce block support for kernel internal use. 2507155228Smjacob */ 2508155228Smjacobint 2509163899Smjacobfw_readresb(struct firewire_comm *fc, u_int32_t dst, u_int32_t tlrt, 2510155228Smjacob u_int32_t len, u_int32_t *buf) 2511155228Smjacob{ 2512163899Smjacob int err = 0; 2513163899Smjacob struct fw_xfer *xfer ; 2514163899Smjacob struct fw_pkt *fp; 2515163899Smjacob 2516163899Smjacob xfer = fw_xfer_alloc(); 2517163899Smjacob if(xfer == NULL){ 2518163899Smjacob err = ENOMEM; 2519163899Smjacob return err; 2520163899Smjacob } 2521163899Smjacob xfer->send.len = sizeof(struct fw_pkt) + len; 2522155228Smjacob xfer->spd = 0; 2523163899Smjacob xfer->send.buf = malloc(sizeof(struct fw_pkt) + 1024, M_DEVBUF, M_DONTWAIT); 2524155228Smjacob if(xfer->send.buf == NULL){ 2525163899Smjacob return ENOMEM; 2526163899Smjacob } 2527155228Smjacob xfer->send.off = 0; 2528163899Smjacob fp = (struct fw_pkt *)xfer->send.buf; 2529155228Smjacob fp->mode.rresb.tlrt = tlrt; 2530155228Smjacob fp->mode.rresb.tcode = FWTCODE_RRESB; 2531196008Smjacob fp->mode.rresb.pri = 0; 2532155228Smjacob fp->mode.rresb.dst = htons(dst); 2533163899Smjacob fp->mode.rresb.rtcode = 0; 2534155228Smjacob fp->mode.rresb.extcode = 0; 2535155228Smjacob fp->mode.rresb.len = htons(len); 2536155228Smjacob bcopy(buf, fp->mode.rresb.payload, len); 2537163899Smjacob xfer->act.hand = fw_asy_callback; 2538155228Smjacob err = fw_asyreq(fc, -1, xfer); 2539155228Smjacob if(err){ 2540163899Smjacob fw_xfer_free( xfer); 2541163899Smjacob return err; 2542163899Smjacob } 2543163899Smjacob err = tsleep((caddr_t)xfer, FWPRI, "asyreq", 0); 2544163899Smjacob 2545163899Smjacob fw_xfer_free( xfer); 2546163899Smjacob return err; 2547163899Smjacob} 2548163899Smjacob 2549163899Smjacob/* 2550163899Smjacob * Async. write request block support for kernel internal use. 2551155228Smjacob */ 2552163899Smjacobint 2553155228Smjacobfw_writereqb(struct firewire_comm *fc, u_int32_t addr_hi, u_int32_t addr_lo, 2554163899Smjacob u_int len, u_int32_t *buf) 2555163899Smjacob{ 2556155228Smjacob int err = 0; 2557163899Smjacob struct fw_xfer *xfer ; 2558155228Smjacob struct fw_pkt *fp; 2559155228Smjacob 2560196008Smjacob xfer = fw_xfer_alloc(); 2561155228Smjacob if(xfer == NULL){ 2562163899Smjacob err = ENOMEM; 2563155228Smjacob return err; 2564155228Smjacob } 2565155228Smjacob xfer->send.len = sizeof(struct fw_pkt) + len; 2566163899Smjacob xfer->spd = 0; 2567155228Smjacob xfer->send.buf = malloc(sizeof(struct fw_pkt) + 1024, M_DEVBUF, M_DONTWAIT); 2568155228Smjacob if(xfer->send.buf == NULL){ 2569163899Smjacob return ENOMEM; 2570163899Smjacob } 2571163899Smjacob xfer->send.off = 0; 2572163899Smjacob fp = (struct fw_pkt *)xfer->send.buf; 2573163899Smjacob fp->mode.wreqb.dest_hi = htonl(addr_hi & 0xffff); 2574163899Smjacob fp->mode.wreqb.tlrt = 0; 2575163899Smjacob fp->mode.wreqb.tcode = FWTCODE_WREQB; 2576163899Smjacob fp->mode.wreqb.pri = 0; 2577163899Smjacob fp->mode.wreqb.dst = htons(addr_hi >> 16); 2578163899Smjacob fp->mode.wreqb.dest_lo = htonl(addr_lo); 2579155228Smjacob fp->mode.wreqb.len = htons(len); 2580163899Smjacob fp->mode.wreqb.extcode = 0; 2581155228Smjacob bcopy(buf, fp->mode.wreqb.payload, len); 2582163899Smjacob xfer->act.hand = fw_asy_callback; 2583163899Smjacob err = fw_asyreq(fc, -1, xfer); 2584155228Smjacob if(err){ 2585163899Smjacob fw_xfer_free( xfer); 2586155228Smjacob return err; 2587155228Smjacob } 2588196008Smjacob err = tsleep((caddr_t)xfer, FWPRI, "asyreq", 0); 2589155228Smjacob 2590163899Smjacob fw_xfer_free( xfer); 2591155228Smjacob return err; 2592155228Smjacob} 2593155228Smjacob 2594163899Smjacob/* 2595155228Smjacob * Async. read request support for kernel internal use. 2596163899Smjacob */ 2597163899Smjacobint 2598163899Smjacobfw_readreqq(struct firewire_comm *fc, u_int32_t addr_hi, u_int32_t addr_lo, u_int32_t *ret){ 2599163899Smjacob int err = 0; 2600163899Smjacob struct fw_xfer *xfer ; 2601163899Smjacob struct fw_pkt *fp, *rfp; 2602163899Smjacob 2603163899Smjacob xfer = fw_xfer_alloc(); 2604163899Smjacob if(xfer == NULL){ 2605163899Smjacob err = ENOMEM; 2606155228Smjacob return err; 2607155228Smjacob } 2608163899Smjacob xfer->send.len = 16; 2609163899Smjacob xfer->spd = 0; 2610163899Smjacob xfer->send.buf = malloc(16, M_DEVBUF, M_DONTWAIT); 2611163899Smjacob if(xfer->send.buf == NULL){ 2612163899Smjacob return ENOMEM; 2613163899Smjacob } 2614163899Smjacob xfer->send.off = 0; 2615163899Smjacob fp = (struct fw_pkt *)xfer->send.buf; 2616163899Smjacob fp->mode.rreqq.dest_hi = htonl(addr_hi & 0xffff); 2617163899Smjacob fp->mode.rreqq.tlrt = 0; 2618163899Smjacob fp->mode.rreqq.tcode = FWTCODE_RREQQ; 2619196008Smjacob fp->mode.rreqq.pri = 0; 2620196008Smjacob xfer->dst = addr_hi >> 16; 2621196008Smjacob fp->mode.rreqq.dst = htons(xfer->dst); 2622196008Smjacob fp->mode.rreqq.dest_lo = htonl(addr_lo); 2623163899Smjacob xfer->act.hand = fw_asy_callback; 2624155228Smjacob err = fw_asyreq(fc, -1, xfer); 2625196008Smjacob if(err){ 2626196008Smjacob fw_xfer_free( xfer); 2627155228Smjacob return err; 2628163899Smjacob } 2629155228Smjacob err = tsleep((caddr_t)xfer, FWPRI, "asyreq", 0); 2630196008Smjacob 2631196008Smjacob if(err == 0 && xfer->recv.buf != NULL){ 2632196008Smjacob rfp = (struct fw_pkt *)xfer->recv.buf; 2633155228Smjacob *ret = ntohl(rfp->mode.rresq.data); 2634163899Smjacob } 2635196008Smjacob fw_xfer_free( xfer); 2636163899Smjacob return err; 2637196008Smjacob} 2638155228Smjacob#endif 2639163899Smjacob/* 2640196008Smjacob * To obtain CSR register values. 2641196008Smjacob */ 2642196008Smjacobu_int32_t getcsrdata(struct fw_device *fwdev, u_int8_t key) 2643196008Smjacob{ 2644196008Smjacob int i; 2645155228Smjacob struct csrhdr *chdr; 2646196008Smjacob struct csrreg *creg; 2647155228Smjacob chdr = (struct csrhdr *)&fwdev->csrrom[0]; 2648155228Smjacob for( i = chdr->info_len + 4; i <= fwdev->rommax - CSRROMOFF; i+=4){ 2649196008Smjacob creg = (struct csrreg *)&fwdev->csrrom[i/4]; 2650196008Smjacob if(creg->key == key){ 2651196008Smjacob return (u_int32_t)creg->val; 2652196008Smjacob } 2653238869Smjacob } 2654238869Smjacob return 0; 2655238869Smjacob} 2656238869Smjacob/* 2657238869Smjacob * To attach sub-devices layer onto IEEE1394 bus. 2658238869Smjacob */ 2659238869Smjacobstatic void fw_attach_dev(struct firewire_comm *fc) 2660238869Smjacob{ 2661155228Smjacob struct fw_device *fwdev; 2662155228Smjacob struct fw_xfer *xfer; 2663155228Smjacob int i, err; 2664155228Smjacob device_t *devlistp; 2665163899Smjacob int devcnt; 2666155228Smjacob struct firewire_dev_comm *fdc; 2667155228Smjacob 2668163899Smjacob for(fwdev = TAILQ_FIRST(&fc->devices); fwdev != NULL; 2669163899Smjacob fwdev = TAILQ_NEXT(fwdev, link)){ 2670163899Smjacob if(fwdev->status == FWDEVINIT){ 2671163899Smjacob fwdev->spec = getcsrdata(fwdev, CSRKEY_SPEC); 2672163899Smjacob if(fwdev->spec == 0) 2673163899Smjacob continue; 2674163899Smjacob fwdev->ver = getcsrdata(fwdev, CSRKEY_VER); 2675163899Smjacob if(fwdev->ver == 0) 2676163899Smjacob continue; 2677163899Smjacob fwdev->maxrec = (fwdev->csrrom[2] >> 12) & 0xf; 2678196008Smjacob 2679196008Smjacob switch(fwdev->spec){ 2680196008Smjacob case CSRVAL_ANSIT10: 2681196008Smjacob switch(fwdev->ver){ 2682163899Smjacob case CSRVAL_T10SBP2: 2683155228Smjacob printf("Device SBP-II"); 2684196008Smjacob break; 2685196008Smjacob default: 2686155228Smjacob break; 2687163899Smjacob } 2688155228Smjacob break; 2689196008Smjacob case CSRVAL_1394TA: 2690196008Smjacob switch(fwdev->ver){ 2691196008Smjacob case CSR_PROTAVC: 2692155228Smjacob printf("Device AV/C"); 2693163899Smjacob break; 2694196008Smjacob case CSR_PROTCAL: 2695196008Smjacob printf("Device CAL"); 2696196008Smjacob break; 2697155228Smjacob case CSR_PROTEHS: 2698163899Smjacob printf("Device EHS"); 2699196008Smjacob break; 2700196008Smjacob case CSR_PROTHAVI: 2701196008Smjacob printf("Device HAVi"); 2702196008Smjacob break; 2703196008Smjacob case CSR_PROTCAM104: 2704155228Smjacob printf("Device 1394 Cam 1.04"); 2705196008Smjacob break; 2706155228Smjacob case CSR_PROTCAM120: 2707155228Smjacob printf("Device 1394 Cam 1.20"); 2708196008Smjacob break; 2709196008Smjacob case CSR_PROTCAM130: 2710196008Smjacob printf("Device 1394 Cam 1.30"); 2711196008Smjacob break; 2712238869Smjacob case CSR_PROTDPP: 2713238869Smjacob printf("Device 1394 Direct print"); 2714238869Smjacob break; 2715238869Smjacob case CSR_PROTIICP: 2716238869Smjacob printf("Device Industrial & Instrument"); 2717238869Smjacob break; 2718238869Smjacob default: 2719238869Smjacob printf("Device unkwon 1394TA"); 2720155228Smjacob break; 2721155228Smjacob } 2722155228Smjacob break; 2723155228Smjacob default: 2724163899Smjacob break; 2725155228Smjacob } 2726163899Smjacob fwdev->status = FWDEVATTACHED; 2727163899Smjacob printf("\n"); 2728163899Smjacob } 2729163899Smjacob } 2730163899Smjacob err = device_get_children(fc->dev, &devlistp, &devcnt); 2731163899Smjacob if( err != 0 ) 2732163899Smjacob return; 2733196008Smjacob for( i = 0 ; i < devcnt ; i++){ 2734163899Smjacob if (device_get_state(devlistp[i]) >= DS_ATTACHED) { 2735163899Smjacob fdc = device_get_softc(devlistp[i]); 2736163899Smjacob if (fdc->post_explore != NULL) 2737163899Smjacob fdc->post_explore(fdc); 2738163899Smjacob } 2739163899Smjacob } 2740163899Smjacob free(devlistp, M_TEMP); 2741163899Smjacob 2742163899Smjacob /* call pending handlers */ 2743163899Smjacob i = 0; 2744163899Smjacob while ((xfer = STAILQ_FIRST(&fc->pending))) { 2745163899Smjacob STAILQ_REMOVE_HEAD(&fc->pending, link); 2746196008Smjacob i++; 2747196008Smjacob if (xfer->act.hand) 2748196008Smjacob xfer->act.hand(xfer); 2749196008Smjacob } 2750196008Smjacob if (i > 0) 2751196008Smjacob printf("fw_attach_dev: %d pending handlers called\n", i); 2752163899Smjacob if (fc->retry_count > 0) { 2753196008Smjacob printf("retry_count = %d\n", fc->retry_count); 2754196008Smjacob fc->retry_probe_handle = timeout((timeout_t *)fc->ibr, 2755196008Smjacob (void *)fc, hz*2); 2756163899Smjacob } 2757196008Smjacob return; 2758196008Smjacob} 2759196008Smjacob/* 2760196008Smjacob * To allocate uniq transaction label. 2761163899Smjacob */ 2762163899Smjacobstatic int fw_get_tlabel(struct firewire_comm *fc, struct fw_xfer *xfer) 2763196008Smjacob{ 2764238869Smjacob u_int i; 2765196008Smjacob struct tlabel *tl, *tmptl; 2766238869Smjacob int s; 2767196008Smjacob static u_int32_t label = 0; 2768196008Smjacob 2769196008Smjacob s = splfw(); 2770163899Smjacob for( i = 0 ; i < 0x40 ; i ++){ 2771155228Smjacob label = (label + 1) & 0x3f; 2772155228Smjacob for(tmptl = STAILQ_FIRST(&fc->tlabels[label]); 2773163899Smjacob tmptl != NULL; tmptl = STAILQ_NEXT(tmptl, link)){ 2774155228Smjacob if(tmptl->xfer->dst == xfer->dst) break; 2775163899Smjacob } 2776155228Smjacob if(tmptl == NULL) { 2777163899Smjacob tl = malloc(sizeof(struct tlabel),M_DEVBUF,M_DONTWAIT); 2778163899Smjacob if (tl == NULL) { 2779163899Smjacob splx(s); 2780163899Smjacob return (-1); 2781163899Smjacob } 2782163899Smjacob tl->xfer = xfer; 2783163899Smjacob STAILQ_INSERT_TAIL(&fc->tlabels[label], tl, link); 2784163899Smjacob splx(s); 2785163899Smjacob return(label); 2786163899Smjacob } 2787163899Smjacob } 2788163899Smjacob splx(s); 2789163899Smjacob 2790163899Smjacob printf("fw_get_tlabel: no free tlabel\n"); 2791196008Smjacob return(-1); 2792196008Smjacob} 2793196008Smjacob/* 2794196008Smjacob * Generic packet receving process. 2795163899Smjacob */ 2796163899Smjacobvoid fw_rcv(struct firewire_comm* fc, caddr_t buf, u_int len, u_int sub, u_int off, u_int spd) 2797196008Smjacob{ 2798196008Smjacob struct fw_pkt *fp, *resfp; 2799163899Smjacob struct fw_xfer *xfer; 2800163899Smjacob struct fw_bind *bind; 2801163899Smjacob struct firewire_softc *sc; 2802196008Smjacob int s; 2803196008Smjacob#if 0 2804196008Smjacob { 2805163899Smjacob u_int32_t *qld; 2806163899Smjacob int i; 2807196008Smjacob qld = (u_int32_t *)buf; 2808196008Smjacob printf("spd %d len:%d\n", spd, len); 2809196008Smjacob for( i = 0 ; i <= len && i < 32; i+= 4){ 2810163899Smjacob printf("0x%08x ", ntohl(qld[i/4])); 2811163899Smjacob if((i % 16) == 15) printf("\n"); 2812196008Smjacob } 2813196008Smjacob if((i % 16) != 15) printf("\n"); 2814196008Smjacob } 2815196008Smjacob#endif 2816196008Smjacob fp = (struct fw_pkt *)(buf + off); 2817163899Smjacob switch(fp->mode.common.tcode){ 2818196008Smjacob case FWTCODE_WRES: 2819163899Smjacob case FWTCODE_RRESQ: 2820163899Smjacob case FWTCODE_RRESB: 2821196008Smjacob case FWTCODE_LRES: 2822196008Smjacob xfer = fw_tl2xfer(fc, ntohs(fp->mode.hdr.src), 2823196008Smjacob fp->mode.hdr.tlrt >> 2); 2824196008Smjacob if(xfer == NULL) { 2825238869Smjacob printf("fw_rcv: unknown response " 2826238869Smjacob "tcode=%d src=0x%x tl=%x rt=%d data=0x%x\n", 2827238869Smjacob fp->mode.common.tcode, 2828238869Smjacob ntohs(fp->mode.hdr.src), 2829238869Smjacob fp->mode.hdr.tlrt >> 2, 2830238869Smjacob fp->mode.hdr.tlrt & 3, 2831238869Smjacob fp->mode.rresq.data); 2832238869Smjacob#if 1 2833163899Smjacob printf("try ad-hoc work around!!\n"); 2834155228Smjacob xfer = fw_tl2xfer(fc, ntohs(fp->mode.hdr.src), 2835155228Smjacob (fp->mode.hdr.tlrt >> 2)^3); 2836155228Smjacob if (xfer == NULL) { 2837163899Smjacob printf("no use...\n"); 2838163899Smjacob goto err; 2839163899Smjacob } 2840163899Smjacob#else 2841163899Smjacob goto err; 2842163899Smjacob#endif 2843163899Smjacob } 2844163899Smjacob switch(xfer->act_type){ 2845163899Smjacob case FWACT_XFER: 2846163899Smjacob if((xfer->sub >= 0) && 2847163899Smjacob ((fc->ir[xfer->sub]->flag & FWXFERQ_MODEMASK ) == 0)){ 2848163899Smjacob xfer->resp = EINVAL; 2849163899Smjacob fw_xfer_done(xfer); 2850163899Smjacob goto err; 2851163899Smjacob } 2852196008Smjacob xfer->recv.len = len; 2853196008Smjacob xfer->recv.off = off; 2854196008Smjacob xfer->recv.buf = buf; 2855196008Smjacob xfer->resp = 0; 2856163899Smjacob fw_xfer_done(xfer); 2857163899Smjacob return; 2858196008Smjacob break; 2859196008Smjacob case FWACT_CH: 2860163899Smjacob default: 2861163899Smjacob goto err; 2862163899Smjacob break; 2863196008Smjacob } 2864196008Smjacob break; 2865196008Smjacob case FWTCODE_WREQQ: 2866163899Smjacob case FWTCODE_WREQB: 2867163899Smjacob case FWTCODE_RREQQ: 2868196008Smjacob case FWTCODE_RREQB: 2869196008Smjacob case FWTCODE_LREQ: 2870196008Smjacob bind = fw_bindlookup(fc, ntohs(fp->mode.rreqq.dest_hi), 2871163899Smjacob ntohl(fp->mode.rreqq.dest_lo)); 2872163899Smjacob if(bind == NULL){ 2873196008Smjacob printf("Unknown service addr 0x%08x:0x%08x tcode=%x\n", 2874196008Smjacob ntohs(fp->mode.rreqq.dest_hi), 2875196008Smjacob ntohl(fp->mode.rreqq.dest_lo), 2876196008Smjacob fp->mode.common.tcode); 2877196008Smjacob if (fc->status == FWBUSRESET) { 2878163899Smjacob printf("fw_rcv: cannot response(bus reset)!\n"); 2879196008Smjacob goto err; 2880163899Smjacob } 2881163899Smjacob xfer = fw_xfer_alloc(); 2882196008Smjacob if(xfer == NULL){ 2883196008Smjacob return; 2884196008Smjacob } 2885196008Smjacob xfer->spd = spd; 2886238869Smjacob xfer->send.buf = malloc(16, M_DEVBUF, M_DONTWAIT); 2887238869Smjacob resfp = (struct fw_pkt *)xfer->send.buf; 2888238869Smjacob switch(fp->mode.common.tcode){ 2889238869Smjacob case FWTCODE_WREQQ: 2890238869Smjacob case FWTCODE_WREQB: 2891238869Smjacob resfp->mode.hdr.tcode = FWTCODE_WRES; 2892238869Smjacob xfer->send.len = 12; 2893238869Smjacob break; 2894163899Smjacob case FWTCODE_RREQQ: 2895163899Smjacob resfp->mode.hdr.tcode = FWTCODE_RRESQ; 2896163899Smjacob xfer->send.len = 16; 2897163899Smjacob break; 2898163899Smjacob case FWTCODE_RREQB: 2899163899Smjacob resfp->mode.hdr.tcode = FWTCODE_RRESB; 2900163899Smjacob xfer->send.len = 16; 2901163899Smjacob break; 2902163899Smjacob case FWTCODE_LREQ: 2903163899Smjacob resfp->mode.hdr.tcode = FWTCODE_LRES; 2904163899Smjacob xfer->send.len = 16; 2905163899Smjacob break; 2906163899Smjacob } 2907196008Smjacob resfp->mode.hdr.dst = fp->mode.hdr.src; 2908163899Smjacob resfp->mode.hdr.tlrt = fp->mode.hdr.tlrt; 2909163899Smjacob resfp->mode.hdr.pri = fp->mode.hdr.pri; 2910163899Smjacob resfp->mode.rresb.rtcode = 7; 2911163899Smjacob resfp->mode.rresb.extcode = 0; 2912163899Smjacob resfp->mode.rresb.len = 0; 2913163899Smjacob/* 2914163899Smjacob xfer->act.hand = fw_asy_callback; 2915163899Smjacob*/ 2916163899Smjacob xfer->act.hand = fw_xfer_free; 2917163899Smjacob if(fw_asyreq(fc, -1, xfer)){ 2918163899Smjacob fw_xfer_free( xfer); 2919163899Smjacob return; 2920196008Smjacob } 2921196008Smjacob goto err; 2922196008Smjacob } 2923196008Smjacob switch(bind->xfer->act_type){ 2924196008Smjacob case FWACT_XFER: 2925196008Smjacob xfer = fw_xfer_alloc(); 2926163899Smjacob if(xfer == NULL) goto err; 2927196008Smjacob xfer->fc = bind->xfer->fc; 2928196008Smjacob xfer->sc = bind->xfer->sc; 2929196008Smjacob xfer->recv.buf = buf; 2930163899Smjacob xfer->recv.len = len; 2931196008Smjacob xfer->recv.off = off; 2932196008Smjacob xfer->spd = spd; 2933163899Smjacob xfer->act.hand = bind->xfer->act.hand; 2934196008Smjacob if (fc->status != FWBUSRESET) 2935163899Smjacob xfer->act.hand(xfer); 2936196008Smjacob else 2937196008Smjacob STAILQ_INSERT_TAIL(&fc->pending, xfer, link); 2938196008Smjacob return; 2939163899Smjacob break; 2940196008Smjacob case FWACT_CH: 2941196008Smjacob if(fc->ir[bind->xfer->sub]->queued >= 2942196008Smjacob fc->ir[bind->xfer->sub]->maxq){ 2943196008Smjacob printf("%s:Discard a packet %x %d\n", 2944196008Smjacob device_get_nameunit(fc->dev), 2945196008Smjacob bind->xfer->sub, 2946163899Smjacob fc->ir[bind->xfer->sub]->queued); 2947163899Smjacob goto err; 2948163899Smjacob } 2949163899Smjacob xfer = fw_xfer_alloc(); 2950196008Smjacob if(xfer == NULL) goto err; 2951155228Smjacob xfer->recv.buf = buf; 2952163899Smjacob xfer->recv.len = len; 2953163899Smjacob xfer->recv.off = off; 2954163899Smjacob xfer->spd = spd; 2955163899Smjacob s = splfw(); 2956163899Smjacob fc->ir[bind->xfer->sub]->queued++; 2957163899Smjacob STAILQ_INSERT_TAIL(&fc->ir[bind->xfer->sub]->q, xfer, link); 2958163899Smjacob splx(s); 2959163899Smjacob 2960163899Smjacob wakeup((caddr_t)fc->ir[bind->xfer->sub]); 2961155228Smjacob 2962155228Smjacob return; 2963155228Smjacob break; 2964196008Smjacob default: 2965155228Smjacob goto err; 2966163899Smjacob break; 2967163899Smjacob } 2968163899Smjacob break; 2969163899Smjacob case FWTCODE_STREAM: 2970163899Smjacob { 2971163899Smjacob struct fw_xferq *xferq; 2972163899Smjacob 2973163899Smjacob xferq = fc->ir[sub]; 2974155228Smjacob#if 0 2975155228Smjacob printf("stream rcv dma %d len %d off %d spd %d\n", 2976155228Smjacob sub, len, off, spd); 2977196008Smjacob#endif 2978155228Smjacob if(xferq->queued >= xferq->maxq) { 2979163899Smjacob printf("receive queue is full\n"); 2980163899Smjacob goto err; 2981163899Smjacob } 2982163899Smjacob xfer = fw_xfer_alloc(); 2983163899Smjacob if(xfer == NULL) goto err; 2984163899Smjacob xfer->recv.buf = buf; 2985163899Smjacob xfer->recv.len = len; 2986163899Smjacob xfer->recv.off = off; 2987163899Smjacob xfer->spd = spd; 2988163899Smjacob s = splfw(); 2989289838Smav xferq->queued++; 2990163899Smjacob STAILQ_INSERT_TAIL(&xferq->q, xfer, link); 2991163899Smjacob splx(s); 2992163899Smjacob sc = device_get_softc(fc->bdev); 2993163899Smjacob#if __FreeBSD_version >= 500000 2994163899Smjacob if (SEL_WAITING(&xferq->rsel)) 2995196008Smjacob#else 2996196008Smjacob if (&xferq->rsel.si_pid != 0) 2997196008Smjacob#endif 2998196008Smjacob selwakeup(&xferq->rsel); 2999196008Smjacob if (xferq->flag & FWXFERQ_WAKEUP) { 3000196008Smjacob xferq->flag &= ~FWXFERQ_WAKEUP; 3001163899Smjacob wakeup((caddr_t)xferq); 3002196008Smjacob } 3003196008Smjacob if (xferq->flag & FWXFERQ_HANDLER) { 3004196008Smjacob xferq->hand(xferq); 3005163899Smjacob } 3006163899Smjacob return; 3007196008Smjacob break; 3008196008Smjacob } 3009163899Smjacob default: 3010155228Smjacob printf("fw_rcv: unknow tcode\n"); 3011155228Smjacob break; 3012155228Smjacob } 3013196008Smjacoberr: 3014155228Smjacob free(buf, M_DEVBUF); 3015163899Smjacob} 3016163899Smjacob/* 3017163899Smjacob * Post process for Bus Manager election process. 3018163899Smjacob */ 3019163899Smjacobstatic void 3020163899Smjacobfw_try_bmr_callback(struct fw_xfer *xfer) 3021163899Smjacob{ 3022163899Smjacob struct fw_pkt *sfp,*rfp; 3023163899Smjacob struct firewire_comm *fc; 3024155228Smjacob 3025155228Smjacob if(xfer == NULL) return; 3026155228Smjacob fc = xfer->fc; 3027196008Smjacob if(xfer->resp != 0){ 3028155228Smjacob goto error; 3029163899Smjacob } 3030163899Smjacob 3031163899Smjacob if(xfer->send.buf == NULL){ 3032163899Smjacob goto error; 3033163899Smjacob } 3034163899Smjacob sfp = (struct fw_pkt *)xfer->send.buf; 3035163899Smjacob 3036163899Smjacob if(xfer->recv.buf == NULL){ 3037163899Smjacob goto error; 3038163899Smjacob } 3039163899Smjacob rfp = (struct fw_pkt *)xfer->recv.buf; 3040196008Smjacob CSRARC(fc, BUS_MGR_ID) 3041163899Smjacob = fc->set_bmr(fc, ntohl(rfp->mode.lres.payload[0]) & 0x3f); 3042155228Smjacob printf("%s: new bus manager %d ", 3043163899Smjacob device_get_nameunit(fc->dev), CSRARC(fc, BUS_MGR_ID)); 3044163899Smjacob if((htonl(rfp->mode.lres.payload[0]) & 0x3f) == fc->nodeid){ 3045163899Smjacob printf("(me)\n"); 3046163899Smjacob/* If I am bus manager, optimize gapcount */ 3047163899Smjacob if(fc->max_hop <= MAX_GAPHOP ){ 3048163899Smjacob fw_phy_config(fc, -1, gap_cnt[fc->max_hop]); 3049163899Smjacob } 3050163899Smjacob }else{ 3051163899Smjacob printf("\n"); 3052289838Smav } 3053163899Smjacoberror: 3054163899Smjacob fw_xfer_free(xfer); 3055163899Smjacob} 3056163899Smjacob/* 3057163899Smjacob * To candidate Bus Manager election process. 3058196008Smjacob */ 3059196008Smjacobvoid fw_try_bmr(void *arg) 3060196008Smjacob{ 3061196008Smjacob struct fw_xfer *xfer; 3062196008Smjacob struct firewire_comm *fc = (struct firewire_comm *)arg; 3063196008Smjacob struct fw_pkt *fp; 3064163899Smjacob int err = 0; 3065196008Smjacob 3066196008Smjacob xfer = fw_xfer_alloc(); 3067196008Smjacob if(xfer == NULL){ 3068163899Smjacob return; 3069163899Smjacob } 3070196008Smjacob xfer->send.len = 24; 3071196008Smjacob xfer->spd = 0; 3072163899Smjacob xfer->send.buf = malloc(24, M_DEVBUF, M_DONTWAIT); 3073163899Smjacob if(xfer->send.buf == NULL){ 3074163899Smjacob fw_xfer_free( xfer); 3075163899Smjacob return; 3076196008Smjacob } 3077155228Smjacob 3078155228Smjacob fc->status = FWBUSMGRELECT; 3079163899Smjacob 3080163899Smjacob xfer->send.off = 0; 3081163899Smjacob fp = (struct fw_pkt *)xfer->send.buf; 3082163899Smjacob fp->mode.lreq.dest_hi = htons(0xffff); 3083163899Smjacob fp->mode.lreq.tlrt = 0; 3084163899Smjacob fp->mode.lreq.tcode = FWTCODE_LREQ; 3085163899Smjacob fp->mode.lreq.pri = 0; 3086163899Smjacob fp->mode.lreq.src = 0; 3087163899Smjacob fp->mode.lreq.len = htons(8); 3088163899Smjacob fp->mode.lreq.extcode = htons(FW_LREQ_CMPSWAP); 3089155228Smjacob xfer->dst = FWLOCALBUS | fc->irm; 3090196008Smjacob fp->mode.lreq.dst = htons(xfer->dst); 3091155228Smjacob fp->mode.lreq.dest_lo = htonl(0xf0000000 | BUS_MGR_ID); 3092155228Smjacob fp->mode.lreq.payload[0] = 0x3f; 3093155228Smjacob fp->mode.lreq.payload[1] = fc->nodeid; 3094155228Smjacob xfer->act_type = FWACT_XFER; 3095196008Smjacob xfer->act.hand = fw_try_bmr_callback; 3096155228Smjacob 3097155228Smjacob err = fw_asyreq(fc, -1, xfer); 3098163899Smjacob if(err){ 3099163899Smjacob fw_xfer_free( xfer); 3100163899Smjacob return; 3101163899Smjacob } 3102163899Smjacob return; 3103163899Smjacob} 3104163899Smjacob 3105163899Smjacob#ifdef FW_VMACCESS 3106163899Smjacob/* 3107155228Smjacob * Software implementation for physical memory block access. 3108196008Smjacob * XXX:Too slow, usef for debug purpose only. 3109155228Smjacob */ 3110155228Smjacobstatic void fw_vmaccess(struct fw_xfer *xfer){ 3111155228Smjacob struct fw_pkt *rfp, *sfp = NULL; 3112155228Smjacob u_int32_t *ld = (u_int32_t *)(xfer->recv.buf + xfer->recv.off); 3113196008Smjacob 3114155228Smjacob printf("vmaccess spd:%2x len:%03x %d data:%08x %08x %08x %08x\n", 3115155228Smjacob xfer->spd, xfer->recv.len, xfer->recv.off, ntohl(ld[0]), ntohl(ld[1]), ntohl(ld[2]), ntohl(ld[3])); 3116163899Smjacob printf("vmaccess data:%08x %08x %08x %08x\n", ntohl(ld[4]), ntohl(ld[5]), ntohl(ld[6]), ntohl(ld[7])); 3117163899Smjacob if(xfer->resp != 0){ 3118163899Smjacob fw_xfer_free( xfer); 3119163899Smjacob return; 3120163899Smjacob } 3121163899Smjacob if(xfer->recv.buf == NULL){ 3122163899Smjacob fw_xfer_free( xfer); 3123163899Smjacob return; 3124163899Smjacob } 3125289838Smav rfp = (struct fw_pkt *)xfer->recv.buf; 3126163899Smjacob switch(rfp->mode.hdr.tcode){ 3127163899Smjacob /* XXX need fix for 64bit arch */ 3128163899Smjacob case FWTCODE_WREQB: 3129163899Smjacob xfer->send.buf = malloc(12, M_DEVBUF, M_NOWAIT); 3130163899Smjacob xfer->send.len = 12; 3131163899Smjacob sfp = (struct fw_pkt *)xfer->send.buf; 3132163899Smjacob bcopy(rfp->mode.wreqb.payload, 3133163899Smjacob (caddr_t)ntohl(rfp->mode.wreqb.dest_lo), ntohs(rfp->mode.wreqb.len)); 3134163899Smjacob sfp->mode.wres.tcode = FWTCODE_WRES; 3135196008Smjacob sfp->mode.wres.rtcode = 0; 3136196008Smjacob break; 3137196008Smjacob case FWTCODE_WREQQ: 3138163899Smjacob xfer->send.buf = malloc(12, M_DEVBUF, M_NOWAIT); 3139163899Smjacob xfer->send.len = 12; 3140163899Smjacob sfp->mode.wres.tcode = FWTCODE_WRES; 3141163899Smjacob *((u_int32_t *)(ntohl(rfp->mode.wreqb.dest_lo))) = rfp->mode.wreqq.data; 3142163899Smjacob sfp->mode.wres.rtcode = 0; 3143163899Smjacob break; 3144163899Smjacob case FWTCODE_RREQB: 3145163899Smjacob xfer->send.buf = malloc(16 + rfp->mode.rreqb.len, M_DEVBUF, M_NOWAIT); 3146163899Smjacob xfer->send.len = 16 + ntohs(rfp->mode.rreqb.len); 3147196008Smjacob sfp = (struct fw_pkt *)xfer->send.buf; 3148163899Smjacob bcopy((caddr_t)ntohl(rfp->mode.rreqb.dest_lo), 3149163899Smjacob sfp->mode.rresb.payload, (u_int16_t)ntohs(rfp->mode.rreqb.len)); 3150163899Smjacob sfp->mode.rresb.tcode = FWTCODE_RRESB; 3151163899Smjacob sfp->mode.rresb.len = rfp->mode.rreqb.len; 3152163899Smjacob sfp->mode.rresb.rtcode = 0; 3153163899Smjacob sfp->mode.rresb.extcode = 0; 3154163899Smjacob break; 3155163899Smjacob case FWTCODE_RREQQ: 3156163899Smjacob xfer->send.buf = malloc(16, M_DEVBUF, M_NOWAIT); 3157163899Smjacob xfer->send.len = 16; 3158163899Smjacob sfp = (struct fw_pkt *)xfer->send.buf; 3159163899Smjacob sfp->mode.rresq.data = *(u_int32_t *)(ntohl(rfp->mode.rreqq.dest_lo)); 3160155228Smjacob sfp->mode.wres.tcode = FWTCODE_RRESQ; 3161196008Smjacob sfp->mode.rresb.rtcode = 0; 3162155228Smjacob break; 3163155228Smjacob default: 3164155228Smjacob fw_xfer_free( xfer); 3165155228Smjacob return; 3166196008Smjacob } 3167155228Smjacob xfer->send.off = 0; 3168155228Smjacob sfp->mode.hdr.dst = rfp->mode.hdr.src; 3169163899Smjacob xfer->dst = ntohs(rfp->mode.hdr.src); 3170163899Smjacob xfer->act.hand = fw_xfer_free; 3171163899Smjacob xfer->retry_req = fw_asybusy; 3172163899Smjacob 3173163899Smjacob sfp->mode.hdr.tlrt = rfp->mode.hdr.tlrt; 3174163899Smjacob sfp->mode.hdr.pri = 0; 3175163899Smjacob 3176163899Smjacob fw_asyreq(xfer->fc, -1, xfer); 3177163899Smjacob/**/ 3178155228Smjacob return; 3179196008Smjacob} 3180155228Smjacob#endif 3181155228Smjacob 3182163899Smjacob/* 3183163899Smjacob * CRC16 check-sum for IEEE1394 register blocks. 3184196008Smjacob */ 3185163899Smjacobu_int16_t fw_crc16(u_int32_t *ptr, u_int32_t len){ 3186163899Smjacob u_int32_t i, sum, crc = 0; 3187163899Smjacob int shift; 3188163899Smjacob len = (len + 3) & ~3; 3189163899Smjacob for(i = 0 ; i < len ; i+= 4){ 3190163899Smjacob for( shift = 28 ; shift >= 0 ; shift -= 4){ 3191163899Smjacob sum = ((crc >> 12) ^ (ptr[i/4] >> shift)) & 0xf; 3192163899Smjacob crc = (crc << 4) ^ ( sum << 12 ) ^ ( sum << 5) ^ sum; 3193163899Smjacob } 3194163899Smjacob crc &= 0xffff; 3195163899Smjacob } 3196289838Smav return((u_int16_t) crc); 3197163899Smjacob} 3198163899SmjacobDRIVER_MODULE(firewire,fwohci,firewire_driver,firewire_devclass,0,0); 3199163899SmjacobMODULE_VERSION(firewire, 1); 3200163899Smjacob