fwmem.c revision 103285
1130407Sdfr/* 2130407Sdfr * Copyright (C) 2002 3130407Sdfr * Hidetoshi Shimokawa. All rights reserved. 4130407Sdfr * 5130407Sdfr * Redistribution and use in source and binary forms, with or without 6130407Sdfr * modification, are permitted provided that the following conditions 7130407Sdfr * are met: 8130407Sdfr * 1. Redistributions of source code must retain the above copyright 9130407Sdfr * notice, this list of conditions and the following disclaimer. 10130407Sdfr * 2. Redistributions in binary form must reproduce the above copyright 11130407Sdfr * notice, this list of conditions and the following disclaimer in the 12130407Sdfr * documentation and/or other materials provided with the distribution. 13130407Sdfr * 3. All advertising materials mentioning features or use of this software 14130407Sdfr * must display the following acknowledgement: 15130407Sdfr * 16130407Sdfr * This product includes software developed by Hidetoshi Shimokawa. 17130407Sdfr * 18130407Sdfr * 4. Neither the name of the author nor the names of its contributors 19130407Sdfr * may be used to endorse or promote products derived from this software 20130407Sdfr * without specific prior written permission. 21130407Sdfr * 22130407Sdfr * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23130407Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24130407Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25130407Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26130407Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27130407Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28130407Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29130407Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30130407Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31130407Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32130407Sdfr * SUCH DAMAGE. 33130407Sdfr * 34130407Sdfr * $FreeBSD: head/sys/dev/firewire/fwmem.c 103285 2002-09-13 12:31:56Z ikob $ 35130407Sdfr */ 36130407Sdfr 37130407Sdfr#include <sys/param.h> 38130407Sdfr#include <sys/systm.h> 39130407Sdfr#include <sys/types.h> 40130407Sdfr 41130407Sdfr#include <sys/kernel.h> 42130407Sdfr#include <sys/malloc.h> 43130407Sdfr#include <sys/conf.h> 44130407Sdfr#include <sys/uio.h> 45130407Sdfr#include <sys/sysctl.h> 46130407Sdfr 47130407Sdfr#include <sys/bus.h> 48130407Sdfr 49130407Sdfr#include <sys/signal.h> 50130407Sdfr#include <sys/mman.h> 51130407Sdfr#include <sys/ioccom.h> 52130407Sdfr 53130407Sdfr#include <dev/firewire/firewire.h> 54130407Sdfr#include <dev/firewire/firewirereg.h> 55130407Sdfr#include <dev/firewire/fwmem.h> 56130407Sdfr 57130407Sdfrstatic int fwmem_node=0, fwmem_speed=2, fwmem_debug=0; 58130407SdfrSYSCTL_DECL(_hw_firewire); 59130407SdfrSYSCTL_NODE(_hw_firewire, OID_AUTO, fwmem, CTLFLAG_RD, 0, 60130407Sdfr "Firewire Memory Access"); 61130407SdfrSYSCTL_INT(_hw_firewire_fwmem, OID_AUTO, node, CTLFLAG_RW, &fwmem_node, 0, 62130407Sdfr "Fwmem target node"); 63130407SdfrSYSCTL_INT(_hw_firewire_fwmem, OID_AUTO, speed, CTLFLAG_RW, &fwmem_speed, 0, 64130407Sdfr "Fwmem link speed"); 65130407SdfrSYSCTL_INT(_debug, OID_AUTO, fwmem_debug, CTLFLAG_RW, &fwmem_debug, 0, 66130407Sdfr "Fwmem driver debug flag"); 67130407Sdfr 68130407Sdfrstruct fw_xfer * 69130407Sdfrfwmem_read_quad( 70130407Sdfr struct firewire_comm *fc, 71130407Sdfr int dst, 72130407Sdfr u_int16_t dst_hi, 73130407Sdfr u_int32_t dst_lo 74130407Sdfr ) 75130407Sdfr{ 76130407Sdfr struct fw_xfer *xfer; 77130407Sdfr struct fw_pkt *fp; 78130407Sdfr int err = 0; 79130407Sdfr 80130407Sdfr xfer = fw_xfer_alloc(); 81130407Sdfr if (xfer == NULL) { 82130407Sdfr err = ENOMEM; 83130407Sdfr return NULL; 84130407Sdfr } 85130407Sdfr xfer->fc = fc; 86130407Sdfr xfer->dst = FWLOCALBUS | dst; 87130407Sdfr xfer->spd = fwmem_speed; /* XXX */ 88130407Sdfr xfer->send.len = 12; 89130407Sdfr xfer->send.buf = malloc(xfer->send.len, M_DEVBUF, M_NOWAIT | M_ZERO); 90130407Sdfr if (xfer->send.buf == NULL) { 91130407Sdfr err = ENOMEM; 92130407Sdfr goto error; 93130407Sdfr } 94130407Sdfr xfer->send.off = 0; 95130407Sdfr xfer->act.hand = fw_asy_callback; 96130407Sdfr xfer->retry_req = fw_asybusy; 97130407Sdfr xfer->sc = NULL; 98130407Sdfr 99130407Sdfr fp = (struct fw_pkt *)xfer->send.buf; 100130407Sdfr fp->mode.rreqq.tcode = FWTCODE_RREQQ; 101130407Sdfr fp->mode.rreqq.dst = htons(xfer->dst); 102130407Sdfr fp->mode.rreqq.dest_hi = htons(dst_hi); 103130407Sdfr fp->mode.rreqq.dest_lo = htonl(dst_lo); 104130407Sdfr 105130407Sdfr if (fwmem_debug) 106130407Sdfr printf("fwmem: %d %04x:%08x\n", dst, dst_hi, dst_lo); 107130407Sdfr err = fw_asyreq(fc, -1, xfer); 108130407Sdfr if (err) 109130407Sdfr goto error; 110130407Sdfr err = tsleep((caddr_t)xfer, FWPRI, "fwmem", hz); 111130407Sdfr if (err == 0) { 112130407Sdfr return xfer; 113130407Sdfr } 114130407Sdfrerror: 115130407Sdfr fw_xfer_free(xfer); 116130407Sdfr return NULL; 117130407Sdfr} 118130407Sdfr 119130407Sdfrstruct fw_xfer * 120130407Sdfrfwmem_read_block( 121130407Sdfr struct firewire_comm *fc, 122130407Sdfr int dst, 123130407Sdfr u_int16_t dst_hi, 124130407Sdfr u_int32_t dst_lo, 125130407Sdfr int len 126130407Sdfr ) 127130407Sdfr{ 128130407Sdfr struct fw_xfer *xfer; 129130407Sdfr struct fw_pkt *fp; 130130407Sdfr int err = 0; 131130407Sdfr 132130407Sdfr xfer = fw_xfer_alloc(); 133130407Sdfr if (xfer == NULL) { 134130407Sdfr err = ENOMEM; 135130407Sdfr return NULL; 136130407Sdfr } 137130407Sdfr xfer->fc = fc; 138130407Sdfr xfer->dst = FWLOCALBUS | dst; 139130407Sdfr xfer->spd = fwmem_speed; /* XXX */ 140130407Sdfr xfer->send.len = 16; 141130407Sdfr xfer->send.buf = malloc(xfer->send.len, M_DEVBUF, M_NOWAIT | M_ZERO); 142130407Sdfr if (xfer->send.buf == NULL) { 143130407Sdfr err = ENOMEM; 144130407Sdfr goto error; 145130407Sdfr } 146130407Sdfr xfer->send.off = 0; 147130407Sdfr xfer->act.hand = fw_asy_callback; 148130407Sdfr xfer->retry_req = fw_asybusy; 149130407Sdfr xfer->sc = NULL; 150130407Sdfr 151130407Sdfr fp = (struct fw_pkt *)xfer->send.buf; 152130407Sdfr fp->mode.rreqb.tcode = FWTCODE_RREQB; 153130407Sdfr fp->mode.rreqb.dst = htons(xfer->dst); 154130407Sdfr fp->mode.rreqb.dest_hi = htons(dst_hi); 155130407Sdfr fp->mode.rreqb.dest_lo = htonl(dst_lo); 156130407Sdfr fp->mode.rreqb.len = htons(len); 157130407Sdfr 158130407Sdfr if (fwmem_debug) 159130407Sdfr printf("fwmem: %d %04x:%08x %d\n", dst, dst_hi, dst_lo, len); 160130407Sdfr err = fw_asyreq(fc, -1, xfer); 161130407Sdfr if (err) 162130407Sdfr goto error; 163130407Sdfr err = tsleep((caddr_t)xfer, FWPRI, "fwmem", hz); 164130407Sdfr if (err == 0) { 165130407Sdfr return xfer; 166130407Sdfr } 167130407Sdfrerror: 168130407Sdfr fw_xfer_free(xfer); 169130407Sdfr return NULL; 170130407Sdfr} 171130407Sdfr 172130407Sdfrint 173130407Sdfrfwmem_open (dev_t dev, int flags, int fmt, fw_proc *td) 174130407Sdfr{ 175130407Sdfr int err = 0; 176130407Sdfr return err; 177130407Sdfr} 178130407Sdfr 179130407Sdfrint 180130407Sdfrfwmem_close (dev_t dev, int flags, int fmt, fw_proc *td) 181130407Sdfr{ 182130407Sdfr int err = 0; 183130407Sdfr return err; 184130407Sdfr} 185130407Sdfr 186130407Sdfr#define MAXLEN 2048 187130407Sdfr#define USE_QUAD 0 188130407Sdfrint 189130407Sdfrfwmem_read (dev_t dev, struct uio *uio, int ioflag) 190130407Sdfr{ 191130407Sdfr struct firewire_softc *sc; 192130407Sdfr struct firewire_comm *fc; 193130407Sdfr struct fw_xfer *xfer; 194130407Sdfr int err = 0, pad; 195130407Sdfr int unit = DEV2UNIT(dev); 196130407Sdfr u_int16_t dst_hi; 197130407Sdfr u_int32_t dst_lo; 198130407Sdfr off_t offset; 199130407Sdfr int len; 200130407Sdfr 201130407Sdfr sc = devclass_get_softc(firewire_devclass, unit); 202130407Sdfr fc = sc->fc; 203130407Sdfr 204130407Sdfr pad = uio->uio_offset % 4; 205130407Sdfr if (fwmem_debug && pad != 0) 206130407Sdfr printf("unaligned\n"); 207130407Sdfr while(uio->uio_resid > 0) { 208130407Sdfr offset = uio->uio_offset; 209130407Sdfr offset -= pad; 210130407Sdfr dst_hi = (offset >> 32) & 0xffff; 211130407Sdfr dst_lo = offset & 0xffffffff; 212130407Sdfr#if USE_QUAD 213130407Sdfr xfer = fwmem_read_quad(fc, fwmem_node, dst_hi, dst_lo); 214130407Sdfr if (xfer == NULL || xfer->resp != 0 || xfer->recv.buf == NULL) 215130407Sdfr return EINVAL; /* XXX */ 216130407Sdfr err = uiomove(xfer->recv.buf + xfer->recv.off + 4*3 + pad, 217130407Sdfr 4 - pad, uio); 218130407Sdfr#else 219130407Sdfr len = uio->uio_resid; 220130407Sdfr if (len > MAXLEN) 221130407Sdfr len = MAXLEN; 222130407Sdfr xfer = fwmem_read_block(fc, fwmem_node, dst_hi, dst_lo, len); 223130407Sdfr if (xfer == NULL || xfer->resp != 0 || xfer->recv.buf == NULL) 224130407Sdfr return EINVAL; /* XXX */ 225130407Sdfr err = uiomove(xfer->recv.buf + xfer->recv.off + 4*4 + pad, 226130407Sdfr len - pad, uio); 227130407Sdfr#endif 228130407Sdfr if (err) 229130407Sdfr return err; 230130407Sdfr fw_xfer_free(xfer); 231130407Sdfr pad = 0; 232130407Sdfr } 233130407Sdfr return err; 234130407Sdfr} 235130407Sdfrint 236130407Sdfrfwmem_write (dev_t dev, struct uio *uio, int ioflag) 237130407Sdfr{ 238130407Sdfr return EINVAL; 239130407Sdfr} 240130407Sdfrint 241130407Sdfrfwmem_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td) 242130407Sdfr{ 243130407Sdfr return EINVAL; 244130407Sdfr} 245130407Sdfrint 246130407Sdfrfwmem_poll (dev_t dev, int events, fw_proc *td) 247130407Sdfr{ 248130407Sdfr return EINVAL; 249130407Sdfr} 250130407Sdfrint 251130407Sdfrfwmem_mmap (dev_t dev, vm_offset_t offset, int nproto) 252130407Sdfr{ 253130407Sdfr return EINVAL; 254130407Sdfr} 255130407Sdfr