1*4535495dSIngo Weinhold /*-
2*4535495dSIngo Weinhold * Copyright (c) 2002-2003
3*4535495dSIngo Weinhold * Hidetoshi Shimokawa. All rights reserved.
4*4535495dSIngo Weinhold *
5*4535495dSIngo Weinhold * Redistribution and use in source and binary forms, with or without
6*4535495dSIngo Weinhold * modification, are permitted provided that the following conditions
7*4535495dSIngo Weinhold * are met:
8*4535495dSIngo Weinhold * 1. Redistributions of source code must retain the above copyright
9*4535495dSIngo Weinhold * notice, this list of conditions and the following disclaimer.
10*4535495dSIngo Weinhold * 2. Redistributions in binary form must reproduce the above copyright
11*4535495dSIngo Weinhold * notice, this list of conditions and the following disclaimer in the
12*4535495dSIngo Weinhold * documentation and/or other materials provided with the distribution.
13*4535495dSIngo Weinhold * 3. All advertising materials mentioning features or use of this software
14*4535495dSIngo Weinhold * must display the following acknowledgement:
15*4535495dSIngo Weinhold *
16*4535495dSIngo Weinhold * This product includes software developed by Hidetoshi Shimokawa.
17*4535495dSIngo Weinhold *
18*4535495dSIngo Weinhold * 4. Neither the name of the author nor the names of its contributors
19*4535495dSIngo Weinhold * may be used to endorse or promote products derived from this software
20*4535495dSIngo Weinhold * without specific prior written permission.
21*4535495dSIngo Weinhold *
22*4535495dSIngo Weinhold * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23*4535495dSIngo Weinhold * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24*4535495dSIngo Weinhold * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25*4535495dSIngo Weinhold * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26*4535495dSIngo Weinhold * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27*4535495dSIngo Weinhold * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28*4535495dSIngo Weinhold * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29*4535495dSIngo Weinhold * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30*4535495dSIngo Weinhold * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31*4535495dSIngo Weinhold * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32*4535495dSIngo Weinhold * SUCH DAMAGE.
33*4535495dSIngo Weinhold *
34*4535495dSIngo Weinhold */
35*4535495dSIngo Weinhold
36*4535495dSIngo Weinhold #include <sys/param.h>
37*4535495dSIngo Weinhold #include <sys/types.h>
38*4535495dSIngo Weinhold #include <endian.h>
39*4535495dSIngo Weinhold
40*4535495dSIngo Weinhold #include <sys/ioccom.h>
41*4535495dSIngo Weinhold #include "queue.h"
42*4535495dSIngo Weinhold #include "fwglue.h"
43*4535495dSIngo Weinhold #include "firewire.h"
44*4535495dSIngo Weinhold #include "iec13213.h"
45*4535495dSIngo Weinhold #include "firewirereg.h"
46*4535495dSIngo Weinhold #include "fwmem.h"
47*4535495dSIngo Weinhold
48*4535495dSIngo Weinhold
49*4535495dSIngo Weinhold static int fwmem_debug=0;
50*4535495dSIngo Weinhold
51*4535495dSIngo Weinhold static struct fw_xfer *
fwmem_xfer_req(struct fw_device * fwdev,caddr_t sc,int spd,int slen,int rlen,void * hand)52*4535495dSIngo Weinhold fwmem_xfer_req(
53*4535495dSIngo Weinhold struct fw_device *fwdev,
54*4535495dSIngo Weinhold caddr_t sc,
55*4535495dSIngo Weinhold int spd,
56*4535495dSIngo Weinhold int slen,
57*4535495dSIngo Weinhold int rlen,
58*4535495dSIngo Weinhold void *hand)
59*4535495dSIngo Weinhold {
60*4535495dSIngo Weinhold struct fw_xfer *xfer;
61*4535495dSIngo Weinhold
62*4535495dSIngo Weinhold xfer = fw_xfer_alloc();
63*4535495dSIngo Weinhold if (xfer == NULL)
64*4535495dSIngo Weinhold return NULL;
65*4535495dSIngo Weinhold
66*4535495dSIngo Weinhold xfer->fc = fwdev->fc;
67*4535495dSIngo Weinhold xfer->send.hdr.mode.hdr.dst = FWLOCALBUS | fwdev->dst;
68*4535495dSIngo Weinhold if (spd < 0)
69*4535495dSIngo Weinhold xfer->send.spd = fwdev->speed;
70*4535495dSIngo Weinhold else
71*4535495dSIngo Weinhold xfer->send.spd = min_c(spd, fwdev->speed);
72*4535495dSIngo Weinhold xfer->hand = (void (*)(fw_xfer*))hand;
73*4535495dSIngo Weinhold xfer->sc = sc;
74*4535495dSIngo Weinhold xfer->send.pay_len = slen;
75*4535495dSIngo Weinhold xfer->recv.pay_len = rlen;
76*4535495dSIngo Weinhold
77*4535495dSIngo Weinhold return xfer;
78*4535495dSIngo Weinhold }
79*4535495dSIngo Weinhold
80*4535495dSIngo Weinhold struct fw_xfer *
fwmem_read_quad(struct fw_device * fwdev,caddr_t sc,uint8_t spd,uint16_t dst_hi,uint32_t dst_lo,void * data,void (* hand)(struct fw_xfer *))81*4535495dSIngo Weinhold fwmem_read_quad(
82*4535495dSIngo Weinhold struct fw_device *fwdev,
83*4535495dSIngo Weinhold caddr_t sc,
84*4535495dSIngo Weinhold uint8_t spd,
85*4535495dSIngo Weinhold uint16_t dst_hi,
86*4535495dSIngo Weinhold uint32_t dst_lo,
87*4535495dSIngo Weinhold void *data,
88*4535495dSIngo Weinhold void (*hand)(struct fw_xfer *))
89*4535495dSIngo Weinhold {
90*4535495dSIngo Weinhold struct fw_xfer *xfer;
91*4535495dSIngo Weinhold struct fw_pkt *fp;
92*4535495dSIngo Weinhold
93*4535495dSIngo Weinhold xfer = fwmem_xfer_req(fwdev, (char *)sc, spd, 0, 4, (void*)hand);
94*4535495dSIngo Weinhold if (xfer == NULL) {
95*4535495dSIngo Weinhold return NULL;
96*4535495dSIngo Weinhold }
97*4535495dSIngo Weinhold
98*4535495dSIngo Weinhold fp = &xfer->send.hdr;
99*4535495dSIngo Weinhold fp->mode.rreqq.tcode = FWTCODE_RREQQ;
100*4535495dSIngo Weinhold fp->mode.rreqq.dest_hi = dst_hi;
101*4535495dSIngo Weinhold fp->mode.rreqq.dest_lo = dst_lo;
102*4535495dSIngo Weinhold
103*4535495dSIngo Weinhold xfer->send.payload = NULL;
104*4535495dSIngo Weinhold xfer->recv.payload = (uint32_t *)data;
105*4535495dSIngo Weinhold
106*4535495dSIngo Weinhold if (fwmem_debug)
107*4535495dSIngo Weinhold printf("fwmem_read_quad: %d %04x:%08x\n", fwdev->dst,
108*4535495dSIngo Weinhold dst_hi, dst_lo);
109*4535495dSIngo Weinhold
110*4535495dSIngo Weinhold if (fw_asyreq(xfer->fc, -1, xfer) == 0)
111*4535495dSIngo Weinhold return xfer;
112*4535495dSIngo Weinhold
113*4535495dSIngo Weinhold fw_xfer_free(xfer);
114*4535495dSIngo Weinhold return NULL;
115*4535495dSIngo Weinhold }
116*4535495dSIngo Weinhold
117*4535495dSIngo Weinhold struct fw_xfer *
fwmem_write_quad(struct fw_device * fwdev,caddr_t sc,uint8_t spd,uint16_t dst_hi,uint32_t dst_lo,void * data,void (* hand)(struct fw_xfer *))118*4535495dSIngo Weinhold fwmem_write_quad(
119*4535495dSIngo Weinhold struct fw_device *fwdev,
120*4535495dSIngo Weinhold caddr_t sc,
121*4535495dSIngo Weinhold uint8_t spd,
122*4535495dSIngo Weinhold uint16_t dst_hi,
123*4535495dSIngo Weinhold uint32_t dst_lo,
124*4535495dSIngo Weinhold void *data,
125*4535495dSIngo Weinhold void (*hand)(struct fw_xfer *))
126*4535495dSIngo Weinhold {
127*4535495dSIngo Weinhold struct fw_xfer *xfer;
128*4535495dSIngo Weinhold struct fw_pkt *fp;
129*4535495dSIngo Weinhold
130*4535495dSIngo Weinhold xfer = fwmem_xfer_req(fwdev, sc, spd, 0, 0, (void*)hand);
131*4535495dSIngo Weinhold if (xfer == NULL)
132*4535495dSIngo Weinhold return NULL;
133*4535495dSIngo Weinhold
134*4535495dSIngo Weinhold fp = &xfer->send.hdr;
135*4535495dSIngo Weinhold fp->mode.wreqq.tcode = FWTCODE_WREQQ;
136*4535495dSIngo Weinhold fp->mode.wreqq.dest_hi = dst_hi;
137*4535495dSIngo Weinhold fp->mode.wreqq.dest_lo = dst_lo;
138*4535495dSIngo Weinhold fp->mode.wreqq.data = *(uint32_t *)data;
139*4535495dSIngo Weinhold
140*4535495dSIngo Weinhold xfer->send.payload = xfer->recv.payload = NULL;
141*4535495dSIngo Weinhold
142*4535495dSIngo Weinhold if (fwmem_debug)
143*4535495dSIngo Weinhold printf("fwmem_write_quad: %d %04x:%08x %08x\n", fwdev->dst,
144*4535495dSIngo Weinhold dst_hi, dst_lo, *(uint32_t *)data);
145*4535495dSIngo Weinhold
146*4535495dSIngo Weinhold if (fw_asyreq(xfer->fc, -1, xfer) == 0)
147*4535495dSIngo Weinhold return xfer;
148*4535495dSIngo Weinhold
149*4535495dSIngo Weinhold fw_xfer_free(xfer);
150*4535495dSIngo Weinhold return NULL;
151*4535495dSIngo Weinhold }
152*4535495dSIngo Weinhold
153*4535495dSIngo Weinhold struct fw_xfer *
fwmem_read_block(struct fw_device * fwdev,caddr_t sc,uint8_t spd,uint16_t dst_hi,uint32_t dst_lo,int len,void * data,void (* hand)(struct fw_xfer *))154*4535495dSIngo Weinhold fwmem_read_block(
155*4535495dSIngo Weinhold struct fw_device *fwdev,
156*4535495dSIngo Weinhold caddr_t sc,
157*4535495dSIngo Weinhold uint8_t spd,
158*4535495dSIngo Weinhold uint16_t dst_hi,
159*4535495dSIngo Weinhold uint32_t dst_lo,
160*4535495dSIngo Weinhold int len,
161*4535495dSIngo Weinhold void *data,
162*4535495dSIngo Weinhold void (*hand)(struct fw_xfer *))
163*4535495dSIngo Weinhold {
164*4535495dSIngo Weinhold struct fw_xfer *xfer;
165*4535495dSIngo Weinhold struct fw_pkt *fp;
166*4535495dSIngo Weinhold
167*4535495dSIngo Weinhold xfer = fwmem_xfer_req(fwdev, sc, spd, 0, roundup2(len, 4), (void*)hand);
168*4535495dSIngo Weinhold if (xfer == NULL)
169*4535495dSIngo Weinhold return NULL;
170*4535495dSIngo Weinhold
171*4535495dSIngo Weinhold fp = &xfer->send.hdr;
172*4535495dSIngo Weinhold fp->mode.rreqb.tcode = FWTCODE_RREQB;
173*4535495dSIngo Weinhold fp->mode.rreqb.dest_hi = dst_hi;
174*4535495dSIngo Weinhold fp->mode.rreqb.dest_lo = dst_lo;
175*4535495dSIngo Weinhold fp->mode.rreqb.len = len;
176*4535495dSIngo Weinhold fp->mode.rreqb.extcode = 0;
177*4535495dSIngo Weinhold
178*4535495dSIngo Weinhold xfer->send.payload = NULL;
179*4535495dSIngo Weinhold xfer->recv.payload = (uint32_t*)data;
180*4535495dSIngo Weinhold
181*4535495dSIngo Weinhold if (fwmem_debug)
182*4535495dSIngo Weinhold printf("fwmem_read_block: %d %04x:%08x %d\n", fwdev->dst,
183*4535495dSIngo Weinhold dst_hi, dst_lo, len);
184*4535495dSIngo Weinhold if (fw_asyreq(xfer->fc, -1, xfer) == 0)
185*4535495dSIngo Weinhold return xfer;
186*4535495dSIngo Weinhold
187*4535495dSIngo Weinhold fw_xfer_free(xfer);
188*4535495dSIngo Weinhold return NULL;
189*4535495dSIngo Weinhold }
190*4535495dSIngo Weinhold
191*4535495dSIngo Weinhold struct fw_xfer *
fwmem_write_block(struct fw_device * fwdev,caddr_t sc,uint8_t spd,uint16_t dst_hi,uint32_t dst_lo,int len,void * data,void (* hand)(struct fw_xfer *))192*4535495dSIngo Weinhold fwmem_write_block(
193*4535495dSIngo Weinhold struct fw_device *fwdev,
194*4535495dSIngo Weinhold caddr_t sc,
195*4535495dSIngo Weinhold uint8_t spd,
196*4535495dSIngo Weinhold uint16_t dst_hi,
197*4535495dSIngo Weinhold uint32_t dst_lo,
198*4535495dSIngo Weinhold int len,
199*4535495dSIngo Weinhold void *data,
200*4535495dSIngo Weinhold void (*hand)(struct fw_xfer *))
201*4535495dSIngo Weinhold {
202*4535495dSIngo Weinhold struct fw_xfer *xfer;
203*4535495dSIngo Weinhold struct fw_pkt *fp;
204*4535495dSIngo Weinhold
205*4535495dSIngo Weinhold xfer = fwmem_xfer_req(fwdev, sc, spd, len, 0, (void*)hand);
206*4535495dSIngo Weinhold if (xfer == NULL)
207*4535495dSIngo Weinhold return NULL;
208*4535495dSIngo Weinhold
209*4535495dSIngo Weinhold fp = &xfer->send.hdr;
210*4535495dSIngo Weinhold fp->mode.wreqb.tcode = FWTCODE_WREQB;
211*4535495dSIngo Weinhold fp->mode.wreqb.dest_hi = dst_hi;
212*4535495dSIngo Weinhold fp->mode.wreqb.dest_lo = dst_lo;
213*4535495dSIngo Weinhold fp->mode.wreqb.len = len;
214*4535495dSIngo Weinhold fp->mode.wreqb.extcode = 0;
215*4535495dSIngo Weinhold
216*4535495dSIngo Weinhold xfer->send.payload = (uint32_t*)data;
217*4535495dSIngo Weinhold xfer->recv.payload = NULL;
218*4535495dSIngo Weinhold
219*4535495dSIngo Weinhold if (fwmem_debug)
220*4535495dSIngo Weinhold printf("fwmem_write_block: %d %04x:%08x %d\n", fwdev->dst,
221*4535495dSIngo Weinhold dst_hi, dst_lo, len);
222*4535495dSIngo Weinhold if (fw_asyreq(xfer->fc, -1, xfer) == 0)
223*4535495dSIngo Weinhold return xfer;
224*4535495dSIngo Weinhold
225*4535495dSIngo Weinhold fw_xfer_free(xfer);
226*4535495dSIngo Weinhold return NULL;
227*4535495dSIngo Weinhold }
228