1 /*- 2 * Copyright (c) 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 <OS.h> 37 #include <malloc.h> 38 39 #include "queue.h" 40 #include "fwglue.h" 41 #include "firewire.h" 42 #include "iec13213.h" 43 #include "firewirereg.h" 44 #include "fwdma.h" 45 #include "util.h" 46 47 #if 0 48 static void 49 fwdma_map_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) 50 { 51 bus_addr_t *baddr; 52 53 if (error) 54 printf("fwdma_map_cb: error=%d\n", error); 55 baddr = (bus_addr_t *)arg; 56 *baddr = segs->ds_addr; 57 } 58 59 void * 60 fwdma_malloc(struct firewire_comm *fc, int alignment, bus_size_t size, 61 struct fwdma_alloc *dma, int flag) 62 { 63 int err; 64 65 dma->v_addr = NULL; 66 err = bus_dma_tag_create( 67 /*parent*/ fc->dmat, 68 /*alignment*/ alignment, 69 /*boundary*/ 0, 70 /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT, 71 /*highaddr*/ BUS_SPACE_MAXADDR, 72 /*filter*/NULL, /*filterarg*/NULL, 73 /*maxsize*/ size, 74 /*nsegments*/ 1, 75 /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 76 /*flags*/ BUS_DMA_ALLOCNOW, 77 #if defined(__FreeBSD__) && __FreeBSD_version >= 501102 78 /*lockfunc*/busdma_lock_mutex, 79 /*lockarg*/FW_GMTX(fc), 80 #endif 81 &dma->dma_tag); 82 if (err) { 83 printf("fwdma_malloc: failed(1)\n"); 84 return(NULL); 85 } 86 87 err = bus_dmamem_alloc(dma->dma_tag, &dma->v_addr, 88 flag, &dma->dma_map); 89 if (err) { 90 printf("fwdma_malloc: failed(2)\n"); 91 /* XXX destroy tag */ 92 return(NULL); 93 } 94 95 bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->v_addr, 96 size, fwdma_map_cb, &dma->bus_addr, /*flags*/0); 97 98 return(dma->v_addr); 99 } 100 //=>alloc_mem(void **v_addr, bus_addr, uint32 protection, const char*name) 101 102 void 103 fwdma_free(struct firewire_comm *fc, struct fwdma_alloc *dma) 104 { 105 bus_dmamap_unload(dma->dma_tag, dma->dma_map); 106 bus_dmamem_free(dma->dma_tag, dma->v_addr, dma->dma_map); 107 bus_dma_tag_destroy(dma->dma_tag); 108 } 109 //=>delete_area(area_id area) 110 111 void * 112 fwdma_malloc_size(bus_dma_tag_t dmat, bus_dmamap_t *dmamap, 113 bus_size_t size, bus_addr_t *bus_addr, int flag) 114 { 115 void *v_addr; 116 117 if (bus_dmamem_alloc(dmat, &v_addr, flag, dmamap)) { 118 printf("fwdma_malloc_size: failed(1)\n"); 119 return(NULL); 120 } 121 bus_dmamap_load(dmat, *dmamap, v_addr, size, 122 fwdma_map_cb, bus_addr, /*flags*/0); 123 return(v_addr); 124 } 125 //=>alloc_mem(void **v_addr, bus_addr, uint32 protection, const char*name) 126 127 128 void 129 fwdma_free_size(bus_dma_tag_t dmat, bus_dmamap_t dmamap, 130 void *vaddr, bus_size_t size) 131 { 132 bus_dmamap_unload(dmat, dmamap); 133 bus_dmamem_free(dmat, vaddr, dmamap); 134 } 135 //=>delete_area(area_id area) 136 #endif 137 138 /* 139 * Allocate multisegment dma buffers 140 * each segment size is eqaul to ssize except last segment. 141 */ 142 struct fwdma_alloc_multi * 143 fwdma_malloc_multiseg(int alignment, 144 int esize, int n) 145 { 146 struct fwdma_alloc_multi *am; 147 struct fwdma_seg *seg; 148 int ssize; 149 int nseg, i; 150 void *buf_virt, *buf_phy; 151 152 if (esize > B_PAGE_SIZE) { 153 /* round up to PAGE_SIZE */ 154 esize = ssize = roundup2(esize, B_PAGE_SIZE); 155 nseg = n; 156 } else { 157 /* allocate PAGE_SIZE segment for small elements */ 158 /*ssize = rounddown(PAGE_SIZE, esize); 159 nseg = howmany(n, ssize / esize);*/ 160 esize = roundup2(esize, alignment); 161 ssize = rounddown(B_PAGE_SIZE, esize); 162 nseg = howmany(n, ssize / esize); 163 164 } 165 am = (struct fwdma_alloc_multi *)malloc(sizeof(struct fwdma_alloc_multi) 166 + sizeof(struct fwdma_seg)*nseg); 167 if (am == NULL) { 168 dprintf("fwdma_malloc_multiseg: malloc failed\n"); 169 return(NULL); 170 } 171 am->ssize = ssize; 172 am->esize = esize; 173 // am->nseg = 0; 174 am->nseg = nseg; 175 176 #if 0 177 if (bus_dma_tag_create( 178 /*parent*/ fc->dmat, 179 /*alignment*/ alignment, 180 /*boundary*/ 0, 181 /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT, 182 /*highaddr*/ BUS_SPACE_MAXADDR, 183 /*filter*/NULL, /*filterarg*/NULL, 184 /*maxsize*/ ssize, 185 /*nsegments*/ 1, 186 /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 187 /*flags*/ BUS_DMA_ALLOCNOW, 188 #if defined(__FreeBSD__) && __FreeBSD_version >= 501102 189 /*lockfunc*/busdma_lock_mutex, 190 /*lockarg*/FW_GMTX(fc), 191 #endif 192 &am->dma_tag)) { 193 printf("fwdma_malloc_multiseg: tag_create failed\n"); 194 free(am, M_FW); 195 return(NULL); 196 } 197 #endif 198 am->Area = alloc_mem(&buf_virt, &buf_phy, nseg*ssize, 0, "fw multi dma buf"); 199 200 201 /* for (seg = &am->seg[0]; nseg --; seg ++) { 202 seg->v_addr = fwdma_malloc_size(am->dma_tag, &seg->dma_map, 203 ssize, &seg->bus_addr, flag); 204 if (seg->v_addr == NULL) { 205 printf("fwdma_malloc_multi: malloc_size failed %d\n", 206 am->nseg); 207 fwdma_free_multiseg(am); 208 return(NULL); 209 } 210 am->nseg++; 211 }*/ 212 for(i = 0, seg=&am->seg[0]; i < nseg; i++){ 213 seg->v_addr =(char *)buf_virt + (i * ssize); 214 seg->bus_addr = (bus_addr_t)((char *)buf_phy + (i * ssize)); 215 seg++; 216 } 217 return(am); 218 } 219 220 void 221 fwdma_free_multiseg(struct fwdma_alloc_multi *am) 222 { 223 /* struct fwdma_seg *seg; 224 225 for (seg = &am->seg[0]; am->nseg --; seg ++) { 226 fwdma_free_size(am->dma_tag, seg->dma_map, 227 seg->v_addr, am->ssize); 228 } 229 bus_dma_tag_destroy(am->dma_tag);*/ 230 delete_area(am->Area); 231 232 free(am); 233 } 234