fwmem.c revision 106810
165806Sdwmalone/* 265806Sdwmalone * Copyright (C) 2002 365806Sdwmalone * Hidetoshi Shimokawa. All rights reserved. 465806Sdwmalone * 565806Sdwmalone * Redistribution and use in source and binary forms, with or without 665806Sdwmalone * modification, are permitted provided that the following conditions 765806Sdwmalone * are met: 865806Sdwmalone * 1. Redistributions of source code must retain the above copyright 965806Sdwmalone * notice, this list of conditions and the following disclaimer. 1065806Sdwmalone * 2. Redistributions in binary form must reproduce the above copyright 1165806Sdwmalone * notice, this list of conditions and the following disclaimer in the 1265806Sdwmalone * documentation and/or other materials provided with the distribution. 1365806Sdwmalone * 3. All advertising materials mentioning features or use of this software 1465806Sdwmalone * must display the following acknowledgement: 1565806Sdwmalone * 1665806Sdwmalone * This product includes software developed by Hidetoshi Shimokawa. 1765806Sdwmalone * 1865806Sdwmalone * 4. Neither the name of the author nor the names of its contributors 1965806Sdwmalone * may be used to endorse or promote products derived from this software 2065806Sdwmalone * without specific prior written permission. 2165806Sdwmalone * 2265806Sdwmalone * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2365806Sdwmalone * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2465806Sdwmalone * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2565806Sdwmalone * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2665806Sdwmalone * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27175799Strhodes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2865806Sdwmalone * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2965806Sdwmalone * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3065806Sdwmalone * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3165806Sdwmalone * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3265806Sdwmalone * SUCH DAMAGE. 3365806Sdwmalone * 3465806Sdwmalone * $FreeBSD: head/sys/dev/firewire/fwmem.c 106810 2002-11-12 13:49:17Z simokawa $ 3565806Sdwmalone */ 3665806Sdwmalone 3765806Sdwmalone#include <sys/param.h> 3865806Sdwmalone#include <sys/systm.h> 3965806Sdwmalone#include <sys/types.h> 4065806Sdwmalone 4165806Sdwmalone#include <sys/kernel.h> 4265806Sdwmalone#include <sys/malloc.h> 4365806Sdwmalone#include <sys/conf.h> 4465806Sdwmalone#include <sys/uio.h> 4565806Sdwmalone#include <sys/sysctl.h> 4665806Sdwmalone 4765806Sdwmalone#include <sys/bus.h> 4865806Sdwmalone 4965806Sdwmalone#include <sys/signal.h> 5065806Sdwmalone#include <sys/mman.h> 5165806Sdwmalone#include <sys/ioccom.h> 5265806Sdwmalone 5365806Sdwmalone#include <dev/firewire/firewire.h> 5465806Sdwmalone#include <dev/firewire/firewirereg.h> 5565806Sdwmalone#include <dev/firewire/fwmem.h> 5665806Sdwmalone 5765806Sdwmalonestatic int fwmem_speed=2, fwmem_debug=0; 5865806Sdwmalonestatic struct fw_eui64 fwmem_eui64; 5965806SdwmaloneSYSCTL_DECL(_hw_firewire); 6065806SdwmaloneSYSCTL_NODE(_hw_firewire, OID_AUTO, fwmem, CTLFLAG_RD, 0, 6165806Sdwmalone "Firewire Memory Access"); 6265806SdwmaloneSYSCTL_UINT(_hw_firewire_fwmem, OID_AUTO, eui64_hi, CTLFLAG_RW, 6365806Sdwmalone &fwmem_eui64.hi, 0, "Fwmem target EUI64 high"); 6465806SdwmaloneSYSCTL_UINT(_hw_firewire_fwmem, OID_AUTO, eui64_low, CTLFLAG_RW, 6565806Sdwmalone &fwmem_eui64.lo, 0, "Fwmem target EUI64 low"); 6665806SdwmaloneSYSCTL_INT(_hw_firewire_fwmem, OID_AUTO, speed, CTLFLAG_RW, &fwmem_speed, 0, 6765806Sdwmalone "Fwmem link speed"); 6865806SdwmaloneSYSCTL_INT(_debug, OID_AUTO, fwmem_debug, CTLFLAG_RW, &fwmem_debug, 0, 6965806Sdwmalone "Fwmem driver debug flag"); 7065806Sdwmalone 7165806Sdwmalonestruct fw_xfer * 7265806Sdwmalonefwmem_read_quad( 7365806Sdwmalone struct fw_device *fwdev, 7465806Sdwmalone caddr_t sc, 7565806Sdwmalone u_int8_t spd, 7665806Sdwmalone u_int16_t dst_hi, 7765806Sdwmalone u_int32_t dst_lo, 7865806Sdwmalone void (*hand)(struct fw_xfer *)) 7965806Sdwmalone{ 8065806Sdwmalone struct fw_xfer *xfer; 8165806Sdwmalone struct fw_pkt *fp; 8265806Sdwmalone 8365806Sdwmalone xfer = fw_xfer_alloc(); 8465806Sdwmalone if (xfer == NULL) 8565806Sdwmalone return NULL; 8679755Sdd 87197330Sed xfer->fc = fwdev->fc; 8865806Sdwmalone xfer->dst = FWLOCALBUS | fwdev->dst; 8965806Sdwmalone xfer->spd = spd; 9065806Sdwmalone xfer->send.len = 12; 9165806Sdwmalone xfer->send.buf = malloc(xfer->send.len, M_DEVBUF, M_NOWAIT | M_ZERO); 9265806Sdwmalone 9365806Sdwmalone if (xfer->send.buf == NULL) 9465806Sdwmalone goto error; 95197330Sed 9665806Sdwmalone xfer->send.off = 0; 9765806Sdwmalone xfer->act.hand = hand; 9865806Sdwmalone xfer->retry_req = fw_asybusy; 9965806Sdwmalone xfer->sc = NULL; 10065806Sdwmalone 10165806Sdwmalone fp = (struct fw_pkt *)xfer->send.buf; 10265806Sdwmalone fp->mode.rreqq.tcode = FWTCODE_RREQQ; 10365806Sdwmalone fp->mode.rreqq.dst = htons(xfer->dst); 10465806Sdwmalone fp->mode.rreqq.dest_hi = htons(dst_hi); 10565806Sdwmalone fp->mode.rreqq.dest_lo = htonl(dst_lo); 10665806Sdwmalone 10765806Sdwmalone if (fwmem_debug) 10865806Sdwmalone printf("fwmem: %d %04x:%08x\n", fwdev->dst, dst_hi, dst_lo); 10965806Sdwmalone 11065806Sdwmalone if (fw_asyreq(xfer->fc, -1, xfer) == 0) 11165806Sdwmalone return xfer; 11265806Sdwmalone 11365806Sdwmaloneerror: 11465806Sdwmalone fw_xfer_free(xfer); 11565806Sdwmalone return NULL; 11665806Sdwmalone} 11765806Sdwmalone 11865806Sdwmalonestruct fw_xfer * 11965806Sdwmalonefwmem_write_quad( 12065806Sdwmalone struct fw_device *fwdev, 12165806Sdwmalone caddr_t sc, 12265806Sdwmalone u_int8_t spd, 12365806Sdwmalone u_int16_t dst_hi, 12465806Sdwmalone u_int32_t dst_lo, 12565806Sdwmalone u_int32_t data, 12665806Sdwmalone void (*hand)(struct fw_xfer *)) 12765806Sdwmalone{ 12865806Sdwmalone struct fw_xfer *xfer; 12965806Sdwmalone struct fw_pkt *fp; 13065806Sdwmalone 13165806Sdwmalone xfer = fw_xfer_alloc(); 13265806Sdwmalone if (xfer == NULL) 13365806Sdwmalone return NULL; 13465806Sdwmalone 13565806Sdwmalone xfer->fc = fwdev->fc; 13665806Sdwmalone xfer->dst = FWLOCALBUS | fwdev->dst; 13765806Sdwmalone xfer->spd = spd; 13865806Sdwmalone xfer->send.len = 16; 13965806Sdwmalone xfer->send.buf = malloc(xfer->send.len, M_DEVBUF, M_NOWAIT | M_ZERO); 14065806Sdwmalone 14165806Sdwmalone if (xfer->send.buf == NULL) 14265806Sdwmalone goto error; 14365806Sdwmalone 14465806Sdwmalone xfer->send.off = 0; 14565806Sdwmalone xfer->act.hand = hand; 14665806Sdwmalone xfer->retry_req = fw_asybusy; 14765806Sdwmalone xfer->sc = sc; 14865806Sdwmalone 14965806Sdwmalone fp = (struct fw_pkt *)xfer->send.buf; 15065806Sdwmalone fp->mode.wreqq.tcode = FWTCODE_RREQQ; 15165806Sdwmalone fp->mode.wreqq.dst = htons(xfer->dst); 15265806Sdwmalone fp->mode.wreqq.dest_hi = htons(dst_hi); 15365806Sdwmalone fp->mode.wreqq.dest_lo = htonl(dst_lo); 15465806Sdwmalone 15565806Sdwmalone fp->mode.wreqq.data = htonl(data); 15665806Sdwmalone 15765806Sdwmalone if (fwmem_debug) 15865806Sdwmalone printf("fwmem: %d %04x:%08x\n", fwdev->dst, dst_hi, dst_lo); 15965806Sdwmalone 16065806Sdwmalone if (fw_asyreq(xfer->fc, -1, xfer) == 0) 16165806Sdwmalone return xfer; 16265806Sdwmalone 16365806Sdwmaloneerror: 16465806Sdwmalone fw_xfer_free(xfer); 16565806Sdwmalone return NULL; 16665806Sdwmalone} 16765806Sdwmalone 168175799Strhodesstruct fw_xfer * 169175799Strhodesfwmem_read_block( 170175799Strhodes struct fw_device *fwdev, 171175799Strhodes caddr_t sc, 172175799Strhodes u_int8_t spd, 173175799Strhodes u_int16_t dst_hi, 174175799Strhodes u_int32_t dst_lo, 175175799Strhodes int len, 176175799Strhodes void (*hand)(struct fw_xfer *)) 17779755Sdd{ 17865806Sdwmalone struct fw_xfer *xfer; 17979755Sdd struct fw_pkt *fp; 18065806Sdwmalone 18179755Sdd xfer = fw_xfer_alloc(); 18265806Sdwmalone if (xfer == NULL) 18379755Sdd return NULL; 18465806Sdwmalone 18579755Sdd xfer->fc = fwdev->fc; 18665806Sdwmalone xfer->dst = FWLOCALBUS | fwdev->dst; 18779755Sdd xfer->spd = spd; 18865806Sdwmalone xfer->send.len = 16; 18979755Sdd xfer->send.buf = malloc(xfer->send.len, M_DEVBUF, M_NOWAIT | M_ZERO); 19065806Sdwmalone 19179755Sdd if (xfer->send.buf == NULL) 19265806Sdwmalone goto error; 19379755Sdd 19465806Sdwmalone xfer->send.off = 0; 19579755Sdd xfer->act.hand = fw_asy_callback; 19665806Sdwmalone xfer->retry_req = fw_asybusy; 19779755Sdd xfer->sc = NULL; 19865806Sdwmalone 19979755Sdd fp = (struct fw_pkt *)xfer->send.buf; 20065806Sdwmalone fp->mode.rreqb.tcode = FWTCODE_RREQB; 20179755Sdd fp->mode.rreqb.dst = htons(xfer->dst); 20265806Sdwmalone fp->mode.rreqb.dest_hi = htons(dst_hi); 20379755Sdd fp->mode.rreqb.dest_lo = htonl(dst_lo); 20465806Sdwmalone fp->mode.rreqb.len = htons(len); 20579755Sdd 20665806Sdwmalone if (fwmem_debug) 20779755Sdd printf("fwmem: %d %04x:%08x %d\n", fwdev->dst, 20865806Sdwmalone dst_hi, dst_lo, len); 20979755Sdd if (fw_asyreq(xfer->fc, -1, xfer) == 0) 21065806Sdwmalone return xfer; 21179755Sdd 21265806Sdwmaloneerror: 21379755Sdd fw_xfer_free(xfer); 21465806Sdwmalone return NULL; 21579755Sdd} 21665806Sdwmalone 21779755Sddint 21865806Sdwmalonefwmem_open (dev_t dev, int flags, int fmt, fw_proc *td) 21965806Sdwmalone{ 22065806Sdwmalone int err = 0; 22165806Sdwmalone return err; 22265806Sdwmalone} 22365806Sdwmalone 22465806Sdwmaloneint 22579755Sddfwmem_close (dev_t dev, int flags, int fmt, fw_proc *td) 22665806Sdwmalone{ 22779755Sdd int err = 0; 22865806Sdwmalone return err; 22979755Sdd} 23065806Sdwmalone 23165806Sdwmalone#define MAXLEN 2048 23279755Sdd#define USE_QUAD 0 23365806Sdwmaloneint 23479755Sddfwmem_read (dev_t dev, struct uio *uio, int ioflag) 23565806Sdwmalone{ 23679755Sdd struct firewire_softc *sc; 23765806Sdwmalone struct fw_device *fwdev; 23865806Sdwmalone struct fw_xfer *xfer; 23979755Sdd int err = 0, pad; 240134117Ssimon int unit = DEV2UNIT(dev); 241134117Ssimon u_int16_t dst_hi; 242132993Sscottl u_int32_t dst_lo; 243132993Sscottl off_t offset; 244132993Sscottl int len; 245132993Sscottl 24674145Sache sc = devclass_get_softc(firewire_devclass, unit); 24774145Sache fwdev = fw_noderesolve(sc->fc, fwmem_eui64); 24865806Sdwmalone if (fwdev == NULL) { 24965806Sdwmalone printf("fwmem: no such device ID:%08x%08x\n", 25065806Sdwmalone fwmem_eui64.hi, fwmem_eui64.lo); 25165806Sdwmalone return EINVAL; 25265806Sdwmalone } 25365806Sdwmalone 25465806Sdwmalone pad = uio->uio_offset % 4; 25565806Sdwmalone if (fwmem_debug && pad != 0) 25665806Sdwmalone printf("unaligned\n"); 25765806Sdwmalone while(uio->uio_resid > 0) { 25865806Sdwmalone offset = uio->uio_offset; 25965806Sdwmalone offset -= pad; 26065806Sdwmalone dst_hi = (offset >> 32) & 0xffff; 26165806Sdwmalone dst_lo = offset & 0xffffffff; 26265806Sdwmalone#if USE_QUAD 26365806Sdwmalone xfer = fwmem_read_quad(fwdev, NULL, fwmem_speed, 26465806Sdwmalone dst_hi, dst_lo, fw_asy_callback); 26565806Sdwmalone if (xfer == NULL) 26665806Sdwmalone return EINVAL; 26765806Sdwmalone err = tsleep((caddr_t)xfer, FWPRI, "fwmem", hz); 26865806Sdwmalone if (err !=0 || xfer->resp != 0 || xfer->recv.buf == NULL) 26965806Sdwmalone return EINVAL; /* XXX */ 27065806Sdwmalone err = uiomove(xfer->recv.buf + xfer->recv.off + 4*3 + pad, 27165806Sdwmalone 4 - pad, uio); 27265806Sdwmalone#else 27365806Sdwmalone len = uio->uio_resid; 27465806Sdwmalone if (len > MAXLEN) 27565806Sdwmalone len = MAXLEN; 27665806Sdwmalone xfer = fwmem_read_block(fwdev, NULL, fwmem_speed, 277197330Sed dst_hi, dst_lo, len, fw_asy_callback); 27865806Sdwmalone if (xfer == NULL) 27965806Sdwmalone return EINVAL; 28065806Sdwmalone err = tsleep((caddr_t)xfer, FWPRI, "fwmem", hz); 28165806Sdwmalone if (err != 0 || xfer->resp != 0 || xfer->recv.buf == NULL) 28265806Sdwmalone return EINVAL; /* XXX */ 28365806Sdwmalone err = uiomove(xfer->recv.buf + xfer->recv.off + 4*4 + pad, 28465806Sdwmalone len - pad, uio); 28565806Sdwmalone#endif 28665806Sdwmalone if (err) 28765806Sdwmalone return err; 28865806Sdwmalone fw_xfer_free(xfer); 28965806Sdwmalone pad = 0; 29065806Sdwmalone } 29165806Sdwmalone return err; 29265806Sdwmalone} 293197330Sedint 29465806Sdwmalonefwmem_write (dev_t dev, struct uio *uio, int ioflag) 29565806Sdwmalone{ 29665806Sdwmalone return EINVAL; 29765806Sdwmalone} 29868965Sruint 29965806Sdwmalonefwmem_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td) 30065806Sdwmalone{ 30165806Sdwmalone return EINVAL; 30265806Sdwmalone} 30365806Sdwmaloneint 30465806Sdwmalonefwmem_poll (dev_t dev, int events, fw_proc *td) 30565806Sdwmalone{ 30665806Sdwmalone return EINVAL; 30765806Sdwmalone} 30865806Sdwmaloneint 30965806Sdwmalonefwmem_mmap (dev_t dev, vm_offset_t offset, int nproto) 31065806Sdwmalone{ 31165806Sdwmalone return EINVAL; 31265806Sdwmalone} 31365806Sdwmalone