fwmem.c revision 106804
1103285Sikob/* 2103285Sikob * Copyright (C) 2002 3103285Sikob * Hidetoshi Shimokawa. All rights reserved. 4103285Sikob * 5103285Sikob * Redistribution and use in source and binary forms, with or without 6103285Sikob * modification, are permitted provided that the following conditions 7103285Sikob * are met: 8103285Sikob * 1. Redistributions of source code must retain the above copyright 9103285Sikob * notice, this list of conditions and the following disclaimer. 10103285Sikob * 2. Redistributions in binary form must reproduce the above copyright 11103285Sikob * notice, this list of conditions and the following disclaimer in the 12103285Sikob * documentation and/or other materials provided with the distribution. 13103285Sikob * 3. All advertising materials mentioning features or use of this software 14103285Sikob * must display the following acknowledgement: 15103285Sikob * 16103285Sikob * This product includes software developed by Hidetoshi Shimokawa. 17103285Sikob * 18103285Sikob * 4. Neither the name of the author nor the names of its contributors 19103285Sikob * may be used to endorse or promote products derived from this software 20103285Sikob * without specific prior written permission. 21103285Sikob * 22103285Sikob * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23103285Sikob * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24103285Sikob * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25103285Sikob * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26103285Sikob * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27103285Sikob * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28103285Sikob * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29103285Sikob * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30103285Sikob * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31103285Sikob * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32103285Sikob * SUCH DAMAGE. 33103285Sikob * 34103285Sikob * $FreeBSD: head/sys/dev/firewire/fwmem.c 106804 2002-11-12 11:08:50Z simokawa $ 35103285Sikob */ 36103285Sikob 37103285Sikob#include <sys/param.h> 38103285Sikob#include <sys/systm.h> 39103285Sikob#include <sys/types.h> 40103285Sikob 41103285Sikob#include <sys/kernel.h> 42103285Sikob#include <sys/malloc.h> 43103285Sikob#include <sys/conf.h> 44103285Sikob#include <sys/uio.h> 45103285Sikob#include <sys/sysctl.h> 46103285Sikob 47103285Sikob#include <sys/bus.h> 48103285Sikob 49103285Sikob#include <sys/signal.h> 50103285Sikob#include <sys/mman.h> 51103285Sikob#include <sys/ioccom.h> 52103285Sikob 53103285Sikob#include <dev/firewire/firewire.h> 54103285Sikob#include <dev/firewire/firewirereg.h> 55103285Sikob#include <dev/firewire/fwmem.h> 56103285Sikob 57103285Sikobstatic int fwmem_node=0, fwmem_speed=2, fwmem_debug=0; 58103285SikobSYSCTL_DECL(_hw_firewire); 59103285SikobSYSCTL_NODE(_hw_firewire, OID_AUTO, fwmem, CTLFLAG_RD, 0, 60103285Sikob "Firewire Memory Access"); 61103285SikobSYSCTL_INT(_hw_firewire_fwmem, OID_AUTO, node, CTLFLAG_RW, &fwmem_node, 0, 62103285Sikob "Fwmem target node"); 63103285SikobSYSCTL_INT(_hw_firewire_fwmem, OID_AUTO, speed, CTLFLAG_RW, &fwmem_speed, 0, 64103285Sikob "Fwmem link speed"); 65103285SikobSYSCTL_INT(_debug, OID_AUTO, fwmem_debug, CTLFLAG_RW, &fwmem_debug, 0, 66103285Sikob "Fwmem driver debug flag"); 67103285Sikob 68103285Sikobstruct fw_xfer * 69103285Sikobfwmem_read_quad( 70103285Sikob struct firewire_comm *fc, 71106804Ssimokawa u_int8_t spd, 72103285Sikob int dst, 73103285Sikob u_int16_t dst_hi, 74106804Ssimokawa u_int32_t dst_lo, 75106804Ssimokawa void (*hand)(struct fw_xfer *)) 76103285Sikob{ 77103285Sikob struct fw_xfer *xfer; 78103285Sikob struct fw_pkt *fp; 79103285Sikob 80103285Sikob xfer = fw_xfer_alloc(); 81106804Ssimokawa if (xfer == NULL) 82103285Sikob return NULL; 83106804Ssimokawa 84103285Sikob xfer->fc = fc; 85103285Sikob xfer->dst = FWLOCALBUS | dst; 86106804Ssimokawa xfer->spd = spd; 87103285Sikob xfer->send.len = 12; 88103285Sikob xfer->send.buf = malloc(xfer->send.len, M_DEVBUF, M_NOWAIT | M_ZERO); 89106804Ssimokawa 90106804Ssimokawa if (xfer->send.buf == NULL) 91103285Sikob goto error; 92106804Ssimokawa 93103285Sikob xfer->send.off = 0; 94106804Ssimokawa xfer->act.hand = hand; 95103285Sikob xfer->retry_req = fw_asybusy; 96103285Sikob xfer->sc = NULL; 97103285Sikob 98103285Sikob fp = (struct fw_pkt *)xfer->send.buf; 99103285Sikob fp->mode.rreqq.tcode = FWTCODE_RREQQ; 100103285Sikob fp->mode.rreqq.dst = htons(xfer->dst); 101103285Sikob fp->mode.rreqq.dest_hi = htons(dst_hi); 102103285Sikob fp->mode.rreqq.dest_lo = htonl(dst_lo); 103103285Sikob 104103285Sikob if (fwmem_debug) 105103285Sikob printf("fwmem: %d %04x:%08x\n", dst, dst_hi, dst_lo); 106106804Ssimokawa 107106804Ssimokawa if (fw_asyreq(fc, -1, xfer) == 0) 108103285Sikob return xfer; 109106804Ssimokawa 110103285Sikoberror: 111103285Sikob fw_xfer_free(xfer); 112103285Sikob return NULL; 113103285Sikob} 114103285Sikob 115103285Sikobstruct fw_xfer * 116103285Sikobfwmem_read_block( 117103285Sikob struct firewire_comm *fc, 118106804Ssimokawa u_int8_t spd, 119103285Sikob int dst, 120103285Sikob u_int16_t dst_hi, 121103285Sikob u_int32_t dst_lo, 122106804Ssimokawa int len, 123106804Ssimokawa void (*hand)(struct fw_xfer *)) 124103285Sikob{ 125103285Sikob struct fw_xfer *xfer; 126103285Sikob struct fw_pkt *fp; 127103285Sikob 128103285Sikob xfer = fw_xfer_alloc(); 129106804Ssimokawa if (xfer == NULL) 130103285Sikob return NULL; 131106804Ssimokawa 132103285Sikob xfer->fc = fc; 133103285Sikob xfer->dst = FWLOCALBUS | dst; 134106804Ssimokawa xfer->spd = spd; 135103285Sikob xfer->send.len = 16; 136103285Sikob xfer->send.buf = malloc(xfer->send.len, M_DEVBUF, M_NOWAIT | M_ZERO); 137106804Ssimokawa 138106804Ssimokawa if (xfer->send.buf == NULL) 139103285Sikob goto error; 140106804Ssimokawa 141103285Sikob xfer->send.off = 0; 142103285Sikob xfer->act.hand = fw_asy_callback; 143103285Sikob xfer->retry_req = fw_asybusy; 144103285Sikob xfer->sc = NULL; 145103285Sikob 146103285Sikob fp = (struct fw_pkt *)xfer->send.buf; 147103285Sikob fp->mode.rreqb.tcode = FWTCODE_RREQB; 148103285Sikob fp->mode.rreqb.dst = htons(xfer->dst); 149103285Sikob fp->mode.rreqb.dest_hi = htons(dst_hi); 150103285Sikob fp->mode.rreqb.dest_lo = htonl(dst_lo); 151103285Sikob fp->mode.rreqb.len = htons(len); 152103285Sikob 153103285Sikob if (fwmem_debug) 154103285Sikob printf("fwmem: %d %04x:%08x %d\n", dst, dst_hi, dst_lo, len); 155106804Ssimokawa if (fw_asyreq(fc, -1, xfer) == 0) 156103285Sikob return xfer; 157106804Ssimokawa 158103285Sikoberror: 159103285Sikob fw_xfer_free(xfer); 160103285Sikob return NULL; 161103285Sikob} 162103285Sikob 163103285Sikobint 164103285Sikobfwmem_open (dev_t dev, int flags, int fmt, fw_proc *td) 165103285Sikob{ 166103285Sikob int err = 0; 167103285Sikob return err; 168103285Sikob} 169103285Sikob 170103285Sikobint 171103285Sikobfwmem_close (dev_t dev, int flags, int fmt, fw_proc *td) 172103285Sikob{ 173103285Sikob int err = 0; 174103285Sikob return err; 175103285Sikob} 176103285Sikob 177103285Sikob#define MAXLEN 2048 178103285Sikob#define USE_QUAD 0 179103285Sikobint 180103285Sikobfwmem_read (dev_t dev, struct uio *uio, int ioflag) 181103285Sikob{ 182103285Sikob struct firewire_softc *sc; 183103285Sikob struct firewire_comm *fc; 184103285Sikob struct fw_xfer *xfer; 185103285Sikob int err = 0, pad; 186103285Sikob int unit = DEV2UNIT(dev); 187103285Sikob u_int16_t dst_hi; 188103285Sikob u_int32_t dst_lo; 189103285Sikob off_t offset; 190103285Sikob int len; 191103285Sikob 192103285Sikob sc = devclass_get_softc(firewire_devclass, unit); 193103285Sikob fc = sc->fc; 194103285Sikob 195103285Sikob pad = uio->uio_offset % 4; 196103285Sikob if (fwmem_debug && pad != 0) 197103285Sikob printf("unaligned\n"); 198103285Sikob while(uio->uio_resid > 0) { 199103285Sikob offset = uio->uio_offset; 200103285Sikob offset -= pad; 201103285Sikob dst_hi = (offset >> 32) & 0xffff; 202103285Sikob dst_lo = offset & 0xffffffff; 203103285Sikob#if USE_QUAD 204106804Ssimokawa xfer = fwmem_read_quad(fc, fwmem_speed, fwmem_node, 205106804Ssimokawa dst_hi, dst_lo, fw_asy_callback); 206106804Ssimokawa if (xfer == NULL) 207106804Ssimokawa return EINVAL; 208106804Ssimokawa err = tsleep((caddr_t)xfer, FWPRI, "fwmem", hz); 209106804Ssimokawa if (err !=0 || xfer->resp != 0 || xfer->recv.buf == NULL) 210103285Sikob return EINVAL; /* XXX */ 211103285Sikob err = uiomove(xfer->recv.buf + xfer->recv.off + 4*3 + pad, 212103285Sikob 4 - pad, uio); 213103285Sikob#else 214103285Sikob len = uio->uio_resid; 215103285Sikob if (len > MAXLEN) 216103285Sikob len = MAXLEN; 217106804Ssimokawa xfer = fwmem_read_block(fc, fwmem_speed, fwmem_node, 218106804Ssimokawa dst_hi, dst_lo, len, fw_asy_callback); 219106804Ssimokawa if (xfer == NULL) 220106804Ssimokawa return EINVAL; 221106804Ssimokawa err = tsleep((caddr_t)xfer, FWPRI, "fwmem", hz); 222106804Ssimokawa if (err != 0 || xfer->resp != 0 || xfer->recv.buf == NULL) 223103285Sikob return EINVAL; /* XXX */ 224103285Sikob err = uiomove(xfer->recv.buf + xfer->recv.off + 4*4 + pad, 225103285Sikob len - pad, uio); 226103285Sikob#endif 227103285Sikob if (err) 228103285Sikob return err; 229103285Sikob fw_xfer_free(xfer); 230103285Sikob pad = 0; 231103285Sikob } 232103285Sikob return err; 233103285Sikob} 234103285Sikobint 235103285Sikobfwmem_write (dev_t dev, struct uio *uio, int ioflag) 236103285Sikob{ 237103285Sikob return EINVAL; 238103285Sikob} 239103285Sikobint 240103285Sikobfwmem_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td) 241103285Sikob{ 242103285Sikob return EINVAL; 243103285Sikob} 244103285Sikobint 245103285Sikobfwmem_poll (dev_t dev, int events, fw_proc *td) 246103285Sikob{ 247103285Sikob return EINVAL; 248103285Sikob} 249103285Sikobint 250103285Sikobfwmem_mmap (dev_t dev, vm_offset_t offset, int nproto) 251103285Sikob{ 252103285Sikob return EINVAL; 253103285Sikob} 254