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