xref: /haiku/src/add-ons/kernel/bus_managers/firewire/fwmem.cpp (revision 4535495d80c86e19e2610e7444a4fcefe3e0f8e6)
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