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 * 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 * 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 * 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 * 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 * 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