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