Home | History | Annotate | Line # | Download | only in ieee1394
fwmem.c revision 1.7
      1  1.7  kiyohara /*	$NetBSD: fwmem.c,v 1.7 2007/11/05 19:08:56 kiyohara Exp $	*/
      2  1.1  kiyohara /*-
      3  1.1  kiyohara  * Copyright (c) 2002-2003
      4  1.1  kiyohara  * 	Hidetoshi Shimokawa. All rights reserved.
      5  1.1  kiyohara  *
      6  1.1  kiyohara  * Redistribution and use in source and binary forms, with or without
      7  1.1  kiyohara  * modification, are permitted provided that the following conditions
      8  1.1  kiyohara  * are met:
      9  1.1  kiyohara  * 1. Redistributions of source code must retain the above copyright
     10  1.1  kiyohara  *    notice, this list of conditions and the following disclaimer.
     11  1.1  kiyohara  * 2. Redistributions in binary form must reproduce the above copyright
     12  1.1  kiyohara  *    notice, this list of conditions and the following disclaimer in the
     13  1.1  kiyohara  *    documentation and/or other materials provided with the distribution.
     14  1.1  kiyohara  * 3. All advertising materials mentioning features or use of this software
     15  1.1  kiyohara  *    must display the following acknowledgement:
     16  1.1  kiyohara  *
     17  1.1  kiyohara  *	This product includes software developed by Hidetoshi Shimokawa.
     18  1.1  kiyohara  *
     19  1.1  kiyohara  * 4. Neither the name of the author nor the names of its contributors
     20  1.1  kiyohara  *    may be used to endorse or promote products derived from this software
     21  1.1  kiyohara  *    without specific prior written permission.
     22  1.1  kiyohara  *
     23  1.1  kiyohara  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     24  1.1  kiyohara  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  1.1  kiyohara  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26  1.1  kiyohara  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     27  1.1  kiyohara  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28  1.1  kiyohara  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29  1.1  kiyohara  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  1.1  kiyohara  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  1.1  kiyohara  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  1.1  kiyohara  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  1.1  kiyohara  * SUCH DAMAGE.
     34  1.1  kiyohara  *
     35  1.1  kiyohara  */
     36  1.1  kiyohara 
     37  1.1  kiyohara #include <sys/cdefs.h>
     38  1.1  kiyohara #ifdef __FBSDID
     39  1.7  kiyohara __FBSDID("$FreeBSD: src/sys/dev/firewire/fwmem.c,v 1.34 2007/06/06 14:31:36 simokawa Exp $");
     40  1.1  kiyohara #endif
     41  1.1  kiyohara 
     42  1.1  kiyohara #if defined(__FreeBSD__)
     43  1.1  kiyohara #include <sys/param.h>
     44  1.1  kiyohara #include <sys/systm.h>
     45  1.1  kiyohara #include <sys/types.h>
     46  1.1  kiyohara 
     47  1.1  kiyohara #include <sys/kernel.h>
     48  1.1  kiyohara #include <sys/malloc.h>
     49  1.1  kiyohara #include <sys/conf.h>
     50  1.1  kiyohara #include <sys/sysctl.h>
     51  1.1  kiyohara #if defined(__DragonFly__) || __FreeBSD_version < 500000
     52  1.1  kiyohara #include <sys/buf.h>
     53  1.1  kiyohara #else
     54  1.1  kiyohara #include <sys/bio.h>
     55  1.1  kiyohara #endif
     56  1.1  kiyohara 
     57  1.1  kiyohara #include <sys/bus.h>
     58  1.6        ad #include <sys/bus.h>
     59  1.1  kiyohara 
     60  1.1  kiyohara #include <sys/signal.h>
     61  1.1  kiyohara #include <sys/mman.h>
     62  1.1  kiyohara #include <sys/ioccom.h>
     63  1.1  kiyohara #include <sys/fcntl.h>
     64  1.1  kiyohara #include <sys/ktr.h>
     65  1.1  kiyohara 
     66  1.1  kiyohara #ifdef __DragonFly__
     67  1.1  kiyohara #include "fw_port.h"
     68  1.1  kiyohara #include "firewire.h"
     69  1.1  kiyohara #include "firewirereg.h"
     70  1.1  kiyohara #include "fwmem.h"
     71  1.1  kiyohara #else
     72  1.1  kiyohara #include <dev/firewire/fw_port.h>
     73  1.1  kiyohara #include <dev/firewire/firewire.h>
     74  1.1  kiyohara #include <dev/firewire/firewirereg.h>
     75  1.1  kiyohara #include <dev/firewire/fwmem.h>
     76  1.1  kiyohara #endif
     77  1.1  kiyohara #elif defined(__NetBSD__)
     78  1.1  kiyohara #include <sys/param.h>
     79  1.1  kiyohara #include <sys/device.h>
     80  1.1  kiyohara #include <sys/errno.h>
     81  1.1  kiyohara #include <sys/buf.h>
     82  1.1  kiyohara #include <sys/conf.h>
     83  1.1  kiyohara #include <sys/fcntl.h>
     84  1.1  kiyohara #include <sys/malloc.h>
     85  1.1  kiyohara #include <sys/sysctl.h>
     86  1.1  kiyohara 
     87  1.6        ad #include <sys/bus.h>
     88  1.1  kiyohara 
     89  1.1  kiyohara #include <dev/ieee1394/fw_port.h>
     90  1.1  kiyohara #include <dev/ieee1394/firewire.h>
     91  1.1  kiyohara #include <dev/ieee1394/firewirereg.h>
     92  1.1  kiyohara #include <dev/ieee1394/fwmem.h>
     93  1.1  kiyohara #endif
     94  1.1  kiyohara 
     95  1.1  kiyohara static int fwmem_speed=2, fwmem_debug=0;
     96  1.1  kiyohara static struct fw_eui64 fwmem_eui64;
     97  1.1  kiyohara #if defined(__FreeBSD__)
     98  1.1  kiyohara SYSCTL_DECL(_hw_firewire);
     99  1.1  kiyohara SYSCTL_NODE(_hw_firewire, OID_AUTO, fwmem, CTLFLAG_RD, 0,
    100  1.1  kiyohara 	"FireWire Memory Access");
    101  1.1  kiyohara SYSCTL_UINT(_hw_firewire_fwmem, OID_AUTO, eui64_hi, CTLFLAG_RW,
    102  1.1  kiyohara 	&fwmem_eui64.hi, 0, "Fwmem target EUI64 high");
    103  1.1  kiyohara SYSCTL_UINT(_hw_firewire_fwmem, OID_AUTO, eui64_lo, CTLFLAG_RW,
    104  1.1  kiyohara 	&fwmem_eui64.lo, 0, "Fwmem target EUI64 low");
    105  1.1  kiyohara SYSCTL_INT(_hw_firewire_fwmem, OID_AUTO, speed, CTLFLAG_RW, &fwmem_speed, 0,
    106  1.1  kiyohara 	"Fwmem link speed");
    107  1.1  kiyohara SYSCTL_INT(_debug, OID_AUTO, fwmem_debug, CTLFLAG_RW, &fwmem_debug, 0,
    108  1.1  kiyohara 	"Fwmem driver debug flag");
    109  1.1  kiyohara MALLOC_DEFINE(M_FWMEM, "fwmem", "fwmem/FireWire");
    110  1.1  kiyohara #elif defined(__NetBSD__)
    111  1.1  kiyohara static int sysctl_fwmem_verify(SYSCTLFN_PROTO, int, int);
    112  1.1  kiyohara static int sysctl_fwmem_verify_speed(SYSCTLFN_PROTO);
    113  1.1  kiyohara 
    114  1.1  kiyohara /*
    115  1.1  kiyohara  * Setup sysctl(3) MIB, hw.fwmem.*
    116  1.1  kiyohara  *
    117  1.1  kiyohara  * TBD condition CTLFLAG_PERMANENT on being an LKM or not
    118  1.1  kiyohara  */
    119  1.1  kiyohara SYSCTL_SETUP(sysctl_fwmem, "sysctl fwmem subtree setup")
    120  1.1  kiyohara {
    121  1.1  kiyohara 	int rc, fwmem_node_num;
    122  1.1  kiyohara 	const struct sysctlnode *node;
    123  1.1  kiyohara 
    124  1.1  kiyohara 	if ((rc = sysctl_createv(clog, 0, NULL, NULL,
    125  1.1  kiyohara 	    CTLFLAG_PERMANENT, CTLTYPE_NODE, "hw", NULL,
    126  1.1  kiyohara 	    NULL, 0, NULL, 0, CTL_HW, CTL_EOL)) != 0) {
    127  1.1  kiyohara 		goto err;
    128  1.1  kiyohara 	}
    129  1.1  kiyohara 
    130  1.1  kiyohara 	if ((rc = sysctl_createv(clog, 0, NULL, &node,
    131  1.1  kiyohara 	    CTLFLAG_PERMANENT, CTLTYPE_NODE, "fwmem",
    132  1.1  kiyohara 	    SYSCTL_DESCR("IEEE1394 Memory Access"),
    133  1.1  kiyohara 	    NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL)) != 0) {
    134  1.1  kiyohara 		goto err;
    135  1.1  kiyohara 	}
    136  1.1  kiyohara 	fwmem_node_num = node->sysctl_num;
    137  1.1  kiyohara 
    138  1.1  kiyohara 	/* fwmem target EUI64 high/low */
    139  1.1  kiyohara 	if ((rc = sysctl_createv(clog, 0, NULL, &node,
    140  1.1  kiyohara 	    CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT,
    141  1.1  kiyohara 	    "eui64_hi", SYSCTL_DESCR("Fwmem target EUI64 high"),
    142  1.1  kiyohara 	    NULL, 0, &fwmem_eui64.hi,
    143  1.1  kiyohara 	    0, CTL_HW, fwmem_node_num, CTL_CREATE, CTL_EOL)) != 0) {
    144  1.1  kiyohara 		goto err;
    145  1.1  kiyohara 	}
    146  1.1  kiyohara 	if ((rc = sysctl_createv(clog, 0, NULL, &node,
    147  1.1  kiyohara 	    CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT,
    148  1.1  kiyohara 	    "eui64_lo", SYSCTL_DESCR("Fwmem target EUI64 low"),
    149  1.1  kiyohara 	    NULL, 0, &fwmem_eui64.lo,
    150  1.1  kiyohara 	    0, CTL_HW, fwmem_node_num, CTL_CREATE, CTL_EOL)) != 0) {
    151  1.1  kiyohara 		goto err;
    152  1.1  kiyohara 	}
    153  1.1  kiyohara 
    154  1.1  kiyohara 	/* fwmem link speed */
    155  1.1  kiyohara 	if ((rc = sysctl_createv(clog, 0, NULL, &node,
    156  1.1  kiyohara 	    CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT,
    157  1.1  kiyohara 	    "speed", SYSCTL_DESCR("Fwmem link speed"),
    158  1.1  kiyohara 	    sysctl_fwmem_verify_speed, 0, &fwmem_speed,
    159  1.1  kiyohara 	    0, CTL_HW, fwmem_node_num, CTL_CREATE, CTL_EOL)) != 0) {
    160  1.1  kiyohara 		goto err;
    161  1.1  kiyohara 	}
    162  1.1  kiyohara 
    163  1.1  kiyohara 	/* fwmem driver debug flag */
    164  1.1  kiyohara 	if ((rc = sysctl_createv(clog, 0, NULL, &node,
    165  1.1  kiyohara 	    CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT,
    166  1.1  kiyohara 	    "fwmem_debug", SYSCTL_DESCR("Fwmem driver debug flag"),
    167  1.1  kiyohara 	    NULL, 0, &fwmem_debug,
    168  1.1  kiyohara 	    0, CTL_HW, fwmem_node_num, CTL_CREATE, CTL_EOL)) != 0) {
    169  1.1  kiyohara 		goto err;
    170  1.1  kiyohara 	}
    171  1.1  kiyohara 
    172  1.1  kiyohara 	return;
    173  1.1  kiyohara 
    174  1.1  kiyohara err:
    175  1.1  kiyohara 	printf("%s: sysctl_createv failed (rc = %d)\n", __func__, rc);
    176  1.1  kiyohara }
    177  1.1  kiyohara 
    178  1.1  kiyohara static int
    179  1.1  kiyohara sysctl_fwmem_verify(SYSCTLFN_ARGS, int lower, int upper)
    180  1.1  kiyohara {
    181  1.1  kiyohara 	int error, t;
    182  1.1  kiyohara 	struct sysctlnode node;
    183  1.1  kiyohara 
    184  1.1  kiyohara 	node = *rnode;
    185  1.1  kiyohara 	t = *(int*)rnode->sysctl_data;
    186  1.1  kiyohara 	node.sysctl_data = &t;
    187  1.1  kiyohara 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
    188  1.1  kiyohara 	if (error || newp == NULL)
    189  1.1  kiyohara 		return (error);
    190  1.1  kiyohara 
    191  1.1  kiyohara 	if (t < lower || t > upper)
    192  1.1  kiyohara 		return (EINVAL);
    193  1.1  kiyohara 
    194  1.1  kiyohara 	*(int*)rnode->sysctl_data = t;
    195  1.1  kiyohara 
    196  1.1  kiyohara 	return (0);
    197  1.1  kiyohara }
    198  1.1  kiyohara 
    199  1.1  kiyohara static int
    200  1.1  kiyohara sysctl_fwmem_verify_speed(SYSCTLFN_ARGS)
    201  1.1  kiyohara {
    202  1.1  kiyohara 	return (sysctl_fwmem_verify(SYSCTLFN_CALL(rnode), 0, FWSPD_S400));
    203  1.1  kiyohara }
    204  1.1  kiyohara 
    205  1.1  kiyohara MALLOC_DEFINE(M_FWMEM, "fwmem", "fwmem/IEEE1394");
    206  1.1  kiyohara #endif
    207  1.1  kiyohara 
    208  1.1  kiyohara #define MAXLEN (512 << fwmem_speed)
    209  1.1  kiyohara 
    210  1.1  kiyohara struct fwmem_softc {
    211  1.1  kiyohara 	struct fw_eui64 eui;
    212  1.7  kiyohara 	struct firewire_softc *sc;
    213  1.1  kiyohara 	int refcount;
    214  1.1  kiyohara 	STAILQ_HEAD(, fw_xfer) xferlist;
    215  1.1  kiyohara };
    216  1.1  kiyohara 
    217  1.1  kiyohara static struct fw_xfer *
    218  1.1  kiyohara fwmem_xfer_req(
    219  1.1  kiyohara 	struct fw_device *fwdev,
    220  1.3  christos 	void *sc,
    221  1.1  kiyohara 	int spd,
    222  1.1  kiyohara 	int slen,
    223  1.1  kiyohara 	int rlen,
    224  1.1  kiyohara 	void *hand)
    225  1.1  kiyohara {
    226  1.1  kiyohara 	struct fw_xfer *xfer;
    227  1.1  kiyohara 
    228  1.1  kiyohara 	xfer = fw_xfer_alloc(M_FWMEM);
    229  1.1  kiyohara 	if (xfer == NULL)
    230  1.1  kiyohara 		return NULL;
    231  1.1  kiyohara 
    232  1.1  kiyohara 	xfer->fc = fwdev->fc;
    233  1.1  kiyohara 	xfer->send.hdr.mode.hdr.dst = FWLOCALBUS | fwdev->dst;
    234  1.1  kiyohara 	if (spd < 0)
    235  1.1  kiyohara 		xfer->send.spd = fwdev->speed;
    236  1.1  kiyohara 	else
    237  1.1  kiyohara 		xfer->send.spd = min(spd, fwdev->speed);
    238  1.1  kiyohara 	xfer->hand = hand;
    239  1.1  kiyohara 	xfer->sc = sc;
    240  1.1  kiyohara 	xfer->send.pay_len = slen;
    241  1.1  kiyohara 	xfer->recv.pay_len = rlen;
    242  1.1  kiyohara 
    243  1.1  kiyohara 	return xfer;
    244  1.1  kiyohara }
    245  1.1  kiyohara 
    246  1.1  kiyohara struct fw_xfer *
    247  1.1  kiyohara fwmem_read_quad(
    248  1.1  kiyohara 	struct fw_device *fwdev,
    249  1.3  christos 	void *	sc,
    250  1.1  kiyohara 	uint8_t spd,
    251  1.1  kiyohara 	uint16_t dst_hi,
    252  1.1  kiyohara 	uint32_t dst_lo,
    253  1.1  kiyohara 	void *data,
    254  1.1  kiyohara 	void (*hand)(struct fw_xfer *))
    255  1.1  kiyohara {
    256  1.1  kiyohara 	struct fw_xfer *xfer;
    257  1.1  kiyohara 	struct fw_pkt *fp;
    258  1.1  kiyohara 
    259  1.1  kiyohara 	xfer = fwmem_xfer_req(fwdev, (void *)sc, spd, 0, 4, hand);
    260  1.1  kiyohara 	if (xfer == NULL) {
    261  1.1  kiyohara 		return NULL;
    262  1.1  kiyohara 	}
    263  1.1  kiyohara 
    264  1.1  kiyohara 	fp = &xfer->send.hdr;
    265  1.1  kiyohara 	fp->mode.rreqq.tcode = FWTCODE_RREQQ;
    266  1.1  kiyohara 	fp->mode.rreqq.dest_hi = dst_hi;
    267  1.1  kiyohara 	fp->mode.rreqq.dest_lo = dst_lo;
    268  1.1  kiyohara 
    269  1.1  kiyohara 	xfer->send.payload = NULL;
    270  1.1  kiyohara 	xfer->recv.payload = (uint32_t *)data;
    271  1.1  kiyohara 
    272  1.1  kiyohara 	if (fwmem_debug)
    273  1.1  kiyohara 		printf("fwmem_read_quad: %d %04x:%08x\n", fwdev->dst,
    274  1.1  kiyohara 				dst_hi, dst_lo);
    275  1.1  kiyohara 
    276  1.1  kiyohara 	if (fw_asyreq(xfer->fc, -1, xfer) == 0)
    277  1.1  kiyohara 		return xfer;
    278  1.1  kiyohara 
    279  1.1  kiyohara 	fw_xfer_free(xfer);
    280  1.1  kiyohara 	return NULL;
    281  1.1  kiyohara }
    282  1.1  kiyohara 
    283  1.1  kiyohara struct fw_xfer *
    284  1.1  kiyohara fwmem_write_quad(
    285  1.1  kiyohara 	struct fw_device *fwdev,
    286  1.3  christos 	void *	sc,
    287  1.1  kiyohara 	uint8_t spd,
    288  1.1  kiyohara 	uint16_t dst_hi,
    289  1.1  kiyohara 	uint32_t dst_lo,
    290  1.1  kiyohara 	void *data,
    291  1.1  kiyohara 	void (*hand)(struct fw_xfer *))
    292  1.1  kiyohara {
    293  1.1  kiyohara 	struct fw_xfer *xfer;
    294  1.1  kiyohara 	struct fw_pkt *fp;
    295  1.1  kiyohara 
    296  1.1  kiyohara 	xfer = fwmem_xfer_req(fwdev, sc, spd, 0, 0, hand);
    297  1.1  kiyohara 	if (xfer == NULL)
    298  1.1  kiyohara 		return NULL;
    299  1.1  kiyohara 
    300  1.1  kiyohara 	fp = &xfer->send.hdr;
    301  1.1  kiyohara 	fp->mode.wreqq.tcode = FWTCODE_WREQQ;
    302  1.1  kiyohara 	fp->mode.wreqq.dest_hi = dst_hi;
    303  1.1  kiyohara 	fp->mode.wreqq.dest_lo = dst_lo;
    304  1.1  kiyohara 	fp->mode.wreqq.data = *(uint32_t *)data;
    305  1.1  kiyohara 
    306  1.1  kiyohara 	xfer->send.payload = xfer->recv.payload = NULL;
    307  1.1  kiyohara 
    308  1.1  kiyohara 	if (fwmem_debug)
    309  1.1  kiyohara 		printf("fwmem_write_quad: %d %04x:%08x %08x\n", fwdev->dst,
    310  1.1  kiyohara 			dst_hi, dst_lo, *(uint32_t *)data);
    311  1.1  kiyohara 
    312  1.1  kiyohara 	if (fw_asyreq(xfer->fc, -1, xfer) == 0)
    313  1.1  kiyohara 		return xfer;
    314  1.1  kiyohara 
    315  1.1  kiyohara 	fw_xfer_free(xfer);
    316  1.1  kiyohara 	return NULL;
    317  1.1  kiyohara }
    318  1.1  kiyohara 
    319  1.1  kiyohara struct fw_xfer *
    320  1.1  kiyohara fwmem_read_block(
    321  1.1  kiyohara 	struct fw_device *fwdev,
    322  1.3  christos 	void *	sc,
    323  1.1  kiyohara 	uint8_t spd,
    324  1.1  kiyohara 	uint16_t dst_hi,
    325  1.1  kiyohara 	uint32_t dst_lo,
    326  1.1  kiyohara 	int len,
    327  1.1  kiyohara 	void *data,
    328  1.1  kiyohara 	void (*hand)(struct fw_xfer *))
    329  1.1  kiyohara {
    330  1.1  kiyohara 	struct fw_xfer *xfer;
    331  1.1  kiyohara 	struct fw_pkt *fp;
    332  1.1  kiyohara 
    333  1.1  kiyohara 	xfer = fwmem_xfer_req(fwdev, sc, spd, 0, roundup2(len, 4), hand);
    334  1.1  kiyohara 	if (xfer == NULL)
    335  1.1  kiyohara 		return NULL;
    336  1.1  kiyohara 
    337  1.1  kiyohara 	fp = &xfer->send.hdr;
    338  1.1  kiyohara 	fp->mode.rreqb.tcode = FWTCODE_RREQB;
    339  1.1  kiyohara 	fp->mode.rreqb.dest_hi = dst_hi;
    340  1.1  kiyohara 	fp->mode.rreqb.dest_lo = dst_lo;
    341  1.1  kiyohara 	fp->mode.rreqb.len = len;
    342  1.1  kiyohara 	fp->mode.rreqb.extcode = 0;
    343  1.1  kiyohara 
    344  1.1  kiyohara 	xfer->send.payload = NULL;
    345  1.1  kiyohara 	xfer->recv.payload = data;
    346  1.1  kiyohara 
    347  1.1  kiyohara 	if (fwmem_debug)
    348  1.1  kiyohara 		printf("fwmem_read_block: %d %04x:%08x %d\n", fwdev->dst,
    349  1.1  kiyohara 				dst_hi, dst_lo, len);
    350  1.1  kiyohara 	if (fw_asyreq(xfer->fc, -1, xfer) == 0)
    351  1.1  kiyohara 		return xfer;
    352  1.1  kiyohara 
    353  1.1  kiyohara 	fw_xfer_free(xfer);
    354  1.1  kiyohara 	return NULL;
    355  1.1  kiyohara }
    356  1.1  kiyohara 
    357  1.1  kiyohara struct fw_xfer *
    358  1.1  kiyohara fwmem_write_block(
    359  1.1  kiyohara 	struct fw_device *fwdev,
    360  1.3  christos 	void *	sc,
    361  1.1  kiyohara 	uint8_t spd,
    362  1.1  kiyohara 	uint16_t dst_hi,
    363  1.1  kiyohara 	uint32_t dst_lo,
    364  1.1  kiyohara 	int len,
    365  1.1  kiyohara 	void *data,
    366  1.1  kiyohara 	void (*hand)(struct fw_xfer *))
    367  1.1  kiyohara {
    368  1.1  kiyohara 	struct fw_xfer *xfer;
    369  1.1  kiyohara 	struct fw_pkt *fp;
    370  1.1  kiyohara 
    371  1.1  kiyohara 	xfer = fwmem_xfer_req(fwdev, sc, spd, len, 0, hand);
    372  1.1  kiyohara 	if (xfer == NULL)
    373  1.1  kiyohara 		return NULL;
    374  1.1  kiyohara 
    375  1.1  kiyohara 	fp = &xfer->send.hdr;
    376  1.1  kiyohara 	fp->mode.wreqb.tcode = FWTCODE_WREQB;
    377  1.1  kiyohara 	fp->mode.wreqb.dest_hi = dst_hi;
    378  1.1  kiyohara 	fp->mode.wreqb.dest_lo = dst_lo;
    379  1.1  kiyohara 	fp->mode.wreqb.len = len;
    380  1.1  kiyohara 	fp->mode.wreqb.extcode = 0;
    381  1.1  kiyohara 
    382  1.1  kiyohara 	xfer->send.payload = data;
    383  1.1  kiyohara 	xfer->recv.payload = NULL;
    384  1.1  kiyohara 
    385  1.1  kiyohara 	if (fwmem_debug)
    386  1.1  kiyohara 		printf("fwmem_write_block: %d %04x:%08x %d\n", fwdev->dst,
    387  1.1  kiyohara 				dst_hi, dst_lo, len);
    388  1.1  kiyohara 	if (fw_asyreq(xfer->fc, -1, xfer) == 0)
    389  1.1  kiyohara 		return xfer;
    390  1.1  kiyohara 
    391  1.1  kiyohara 	fw_xfer_free(xfer);
    392  1.1  kiyohara 	return NULL;
    393  1.1  kiyohara }
    394  1.1  kiyohara 
    395  1.1  kiyohara 
    396  1.1  kiyohara FW_OPEN(fwmem)
    397  1.1  kiyohara {
    398  1.1  kiyohara 	struct fwmem_softc *fms;
    399  1.1  kiyohara 	struct fw_xfer *xfer;
    400  1.1  kiyohara 	FW_OPEN_START;
    401  1.1  kiyohara 
    402  1.1  kiyohara 	if (dev->si_drv1 != NULL) {
    403  1.7  kiyohara 		if ((flags & FWRITE) != 0) {
    404  1.7  kiyohara 			FW_GUNLOCK(sc->fc);
    405  1.1  kiyohara 			return (EBUSY);
    406  1.7  kiyohara 		}
    407  1.7  kiyohara 		FW_GUNLOCK(sc->fc);
    408  1.1  kiyohara 		fms = (struct fwmem_softc *)dev->si_drv1;
    409  1.1  kiyohara 		fms->refcount ++;
    410  1.1  kiyohara 	} else {
    411  1.7  kiyohara 		dev->si_drv1 = (void *)-1;
    412  1.7  kiyohara 		FW_GUNLOCK(sc->fc);
    413  1.7  kiyohara 		dev->si_drv1 = malloc(sizeof(struct fwmem_softc),
    414  1.7  kiyohara 		    M_FWMEM, M_WAITOK);
    415  1.7  kiyohara 		if (dev->si_drv1 == NULL)
    416  1.1  kiyohara 			return ENOMEM;
    417  1.7  kiyohara 		dev->si_iosize_max = DFLTPHYS;
    418  1.7  kiyohara 		fms = (struct fwmem_softc *)dev->si_drv1;
    419  1.1  kiyohara 		bcopy(&fwmem_eui64, &fms->eui, sizeof(struct fw_eui64));
    420  1.7  kiyohara 		fms->sc = sc;
    421  1.1  kiyohara 		fms->refcount = 1;
    422  1.1  kiyohara 		STAILQ_INIT(&fms->xferlist);
    423  1.1  kiyohara 		xfer = fw_xfer_alloc(M_FWMEM);
    424  1.1  kiyohara 		STAILQ_INSERT_TAIL(&fms->xferlist, xfer, link);
    425  1.1  kiyohara 	}
    426  1.1  kiyohara 	if (fwmem_debug)
    427  1.1  kiyohara 		printf("%s: refcount=%d\n", __func__, fms->refcount);
    428  1.1  kiyohara 
    429  1.1  kiyohara 	return (0);
    430  1.1  kiyohara }
    431  1.1  kiyohara 
    432  1.1  kiyohara FW_CLOSE(fwmem)
    433  1.1  kiyohara {
    434  1.1  kiyohara 	struct fwmem_softc *fms;
    435  1.1  kiyohara 	struct fw_xfer *xfer;
    436  1.1  kiyohara 	FW_CLOSE_START;
    437  1.1  kiyohara 
    438  1.1  kiyohara 	fms = (struct fwmem_softc *)dev->si_drv1;
    439  1.7  kiyohara 
    440  1.7  kiyohara 	FW_GLOCK(fms->sc->fc);
    441  1.1  kiyohara 	fms->refcount --;
    442  1.7  kiyohara 	FW_GUNLOCK(fms->sc->fc);
    443  1.1  kiyohara 	if (fwmem_debug)
    444  1.1  kiyohara 		printf("%s: refcount=%d\n", __func__, fms->refcount);
    445  1.1  kiyohara 	if (fms->refcount < 1) {
    446  1.1  kiyohara 		while ((xfer = STAILQ_FIRST(&fms->xferlist)) != NULL) {
    447  1.1  kiyohara 			STAILQ_REMOVE_HEAD(&fms->xferlist, link);
    448  1.1  kiyohara 			fw_xfer_free(xfer);
    449  1.1  kiyohara 		}
    450  1.1  kiyohara 		free(dev->si_drv1, M_FW);
    451  1.1  kiyohara 		dev->si_drv1 = NULL;
    452  1.1  kiyohara 	}
    453  1.1  kiyohara 
    454  1.1  kiyohara 	return (0);
    455  1.1  kiyohara }
    456  1.1  kiyohara 
    457  1.1  kiyohara 
    458  1.1  kiyohara static void
    459  1.1  kiyohara fwmem_biodone(struct fw_xfer *xfer)
    460  1.1  kiyohara {
    461  1.1  kiyohara 	struct bio *bp;
    462  1.1  kiyohara 
    463  1.1  kiyohara 	bp = (struct bio *)xfer->sc;
    464  1.1  kiyohara 	bp->bio_error = xfer->resp;
    465  1.1  kiyohara 
    466  1.1  kiyohara 	if (bp->bio_error != 0) {
    467  1.1  kiyohara 		if (fwmem_debug)
    468  1.1  kiyohara 			printf("%s: err=%d\n", __func__, bp->bio_error);
    469  1.1  kiyohara 		bp->bio_resid = bp->bio_bcount;
    470  1.1  kiyohara 	}
    471  1.1  kiyohara 
    472  1.1  kiyohara 	CTR0(KTR_DEV, "biodone0");
    473  1.1  kiyohara 	fw_xfer_free(xfer);
    474  1.1  kiyohara 	CTR0(KTR_DEV, "biodone1");
    475  1.1  kiyohara 	biodone(bp);
    476  1.1  kiyohara 	CTR0(KTR_DEV, "biodone2");
    477  1.1  kiyohara }
    478  1.1  kiyohara 
    479  1.1  kiyohara void
    480  1.1  kiyohara fwmem_strategy(struct bio *bp)
    481  1.1  kiyohara {
    482  1.1  kiyohara 	FW_STRATEGY_START;
    483  1.1  kiyohara 	struct fwmem_softc *fms;
    484  1.1  kiyohara 	struct fw_device *fwdev;
    485  1.1  kiyohara 	struct fw_xfer *xfer;
    486  1.7  kiyohara 	int err = 0, s, iolen;
    487  1.1  kiyohara 
    488  1.1  kiyohara 	CTR0(KTR_DEV, "strategy");
    489  1.1  kiyohara 
    490  1.1  kiyohara 	/* XXX check request length */
    491  1.1  kiyohara 
    492  1.1  kiyohara 	s = splfw();
    493  1.1  kiyohara 	fms = (struct fwmem_softc *)dev->si_drv1;
    494  1.7  kiyohara 	fwdev = fw_noderesolve_eui64(fms->sc->fc, &fms->eui);
    495  1.1  kiyohara 	if (fwdev == NULL) {
    496  1.1  kiyohara 		if (fwmem_debug)
    497  1.1  kiyohara 			printf("fwmem: no such device ID:%08x%08x\n",
    498  1.1  kiyohara 					fms->eui.hi, fms->eui.lo);
    499  1.1  kiyohara 		err = EINVAL;
    500  1.1  kiyohara 		goto error;
    501  1.1  kiyohara 	}
    502  1.1  kiyohara 
    503  1.1  kiyohara 	iolen = MIN(bp->bio_bcount, MAXLEN);
    504  1.1  kiyohara 	if ((bp->bio_cmd & BIO_READ) == BIO_READ) {
    505  1.1  kiyohara 		if (iolen == 4 && (bp->bio_offset & 3) == 0)
    506  1.1  kiyohara 			xfer = fwmem_read_quad(fwdev,
    507  1.1  kiyohara 			    (void *) bp, fwmem_speed,
    508  1.1  kiyohara 			    bp->bio_offset >> 32, bp->bio_offset & 0xffffffff,
    509  1.1  kiyohara 			    bp->bio_data, fwmem_biodone);
    510  1.1  kiyohara 		else
    511  1.1  kiyohara 			xfer = fwmem_read_block(fwdev,
    512  1.1  kiyohara 			    (void *) bp, fwmem_speed,
    513  1.1  kiyohara 			    bp->bio_offset >> 32, bp->bio_offset & 0xffffffff,
    514  1.1  kiyohara 			    iolen, bp->bio_data, fwmem_biodone);
    515  1.1  kiyohara 	} else {
    516  1.1  kiyohara 		if (iolen == 4 && (bp->bio_offset & 3) == 0)
    517  1.1  kiyohara 			xfer = fwmem_write_quad(fwdev,
    518  1.1  kiyohara 			    (void *)bp, fwmem_speed,
    519  1.1  kiyohara 			    bp->bio_offset >> 32, bp->bio_offset & 0xffffffff,
    520  1.1  kiyohara 			    bp->bio_data, fwmem_biodone);
    521  1.1  kiyohara 		else
    522  1.1  kiyohara 			xfer = fwmem_write_block(fwdev,
    523  1.1  kiyohara 			    (void *)bp, fwmem_speed,
    524  1.1  kiyohara 			    bp->bio_offset >> 32, bp->bio_offset & 0xffffffff,
    525  1.1  kiyohara 			    iolen, bp->bio_data, fwmem_biodone);
    526  1.1  kiyohara 	}
    527  1.1  kiyohara 	if (xfer == NULL) {
    528  1.1  kiyohara 		err = EIO;
    529  1.1  kiyohara 		goto error;
    530  1.1  kiyohara 	}
    531  1.1  kiyohara 	/* XXX */
    532  1.1  kiyohara 	bp->bio_resid = bp->bio_bcount - iolen;
    533  1.1  kiyohara error:
    534  1.1  kiyohara 	splx(s);
    535  1.1  kiyohara 	if (err != 0) {
    536  1.1  kiyohara 		if (fwmem_debug)
    537  1.1  kiyohara 			printf("%s: err=%d\n", __func__, err);
    538  1.1  kiyohara 		bp->bio_error = err;
    539  1.1  kiyohara 		bp->bio_resid = bp->bio_bcount;
    540  1.1  kiyohara 		biodone(bp);
    541  1.1  kiyohara 	}
    542  1.1  kiyohara }
    543  1.1  kiyohara 
    544  1.1  kiyohara FW_IOCTL(fwmem)
    545  1.1  kiyohara {
    546  1.1  kiyohara 	FW_IOCTL_START;
    547  1.1  kiyohara 	struct fwmem_softc *fms;
    548  1.1  kiyohara 	int err = 0;
    549  1.1  kiyohara 
    550  1.1  kiyohara 	fms = (struct fwmem_softc *)dev->si_drv1;
    551  1.1  kiyohara 	switch (cmd) {
    552  1.1  kiyohara 	case FW_SDEUI64:
    553  1.1  kiyohara 		bcopy(data, &fms->eui, sizeof(struct fw_eui64));
    554  1.1  kiyohara 		break;
    555  1.1  kiyohara 	case FW_GDEUI64:
    556  1.1  kiyohara 		bcopy(&fms->eui, data, sizeof(struct fw_eui64));
    557  1.1  kiyohara 		break;
    558  1.1  kiyohara 	default:
    559  1.1  kiyohara 		err = EINVAL;
    560  1.1  kiyohara 	}
    561  1.1  kiyohara 	return(err);
    562  1.1  kiyohara }
    563  1.1  kiyohara 
    564  1.1  kiyohara FW_POLL(fwmem)
    565  1.1  kiyohara {
    566  1.1  kiyohara 	return EINVAL;
    567  1.1  kiyohara }
    568  1.1  kiyohara 
    569  1.1  kiyohara FW_MMAP(fwmem)
    570  1.1  kiyohara {
    571  1.1  kiyohara 	return EINVAL;
    572  1.1  kiyohara }
    573