1 /*- 2 * Copyright (c) 2018 Microsemi Corporation. 3 * 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 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 /* $FreeBSD$ */ 28 29 #include "smartpqi_includes.h" 30 31 MALLOC_DEFINE(M_SMARTRAID, "smartraidbuf", "Buffers for the smartraid driver"); 32 33 /* 34 * DMA map load callback function 35 */ 36 static void 37 os_dma_map(void *arg, bus_dma_segment_t *segs, int nseg, int error) 38 { 39 bus_addr_t *paddr = (bus_addr_t *)arg; 40 *paddr = segs[0].ds_addr; 41 } 42 43 int os_dma_setup(pqisrc_softstate_t *softs) 44 { 45 DBG_FUNC("IN\n"); 46 DBG_FUNC("OUT\n"); 47 return PQI_STATUS_SUCCESS; 48 } 49 50 int os_dma_destroy(pqisrc_softstate_t *softs) 51 { 52 DBG_FUNC("IN\n"); 53 DBG_FUNC("OUT\n"); 54 return PQI_STATUS_SUCCESS; 55 } 56 57 /* 58 * DMA mem resource allocation wrapper function 59 */ 60 int os_dma_mem_alloc(pqisrc_softstate_t *softs, struct dma_mem *dma_mem) 61 { 62 int ret = 0; 63 64 /* DBG_FUNC("IN\n"); */ 65 66 /* DMA memory needed - allocate it */ 67 if ((ret = bus_dma_tag_create( 68 softs->os_specific.pqi_parent_dmat, /* parent */ 69 dma_mem->align, 0, /* algnmnt, boundary */ 70 BUS_SPACE_MAXADDR, /* lowaddr */ 71 BUS_SPACE_MAXADDR, /* highaddr */ 72 NULL, NULL, /* filter, filterarg */ 73 dma_mem->size, /* maxsize */ 74 1, /* nsegments */ 75 dma_mem->size, /* maxsegsize */ 76 0, /* flags */ 77 NULL, NULL, /* No locking needed */ 78 &dma_mem->dma_tag)) != 0 ) { 79 DBG_ERR("can't allocate DMA tag with error = 0x%x\n", ret); 80 goto err_out; 81 } 82 if ((ret = bus_dmamem_alloc(dma_mem->dma_tag, (void **)&dma_mem->virt_addr, 83 BUS_DMA_NOWAIT, &dma_mem->dma_map)) != 0) { 84 DBG_ERR("can't allocate DMA memory for required object \ 85 with error = 0x%x\n", ret); 86 goto err_mem; 87 } 88 89 if((ret = bus_dmamap_load(dma_mem->dma_tag, dma_mem->dma_map, 90 dma_mem->virt_addr, dma_mem->size, 91 os_dma_map, &dma_mem->dma_addr, 0)) != 0) { 92 DBG_ERR("can't load DMA memory for required \ 93 object with error = 0x%x\n", ret); 94 goto err_load; 95 } 96 97 memset(dma_mem->virt_addr, 0, dma_mem->size); 98 99 /* DBG_FUNC("OUT\n"); */ 100 return ret; 101 102 err_load: 103 if(dma_mem->virt_addr) 104 bus_dmamem_free(dma_mem->dma_tag, dma_mem->virt_addr, 105 dma_mem->dma_map); 106 err_mem: 107 if(dma_mem->dma_tag) 108 bus_dma_tag_destroy(dma_mem->dma_tag); 109 err_out: 110 DBG_FUNC("failed OUT\n"); 111 return ret; 112 } 113 114 /* 115 * DMA mem resource deallocation wrapper function 116 */ 117 void os_dma_mem_free(pqisrc_softstate_t *softs, struct dma_mem *dma_mem) 118 { 119 /* DBG_FUNC("IN\n"); */ 120 121 if(dma_mem->dma_addr) { 122 bus_dmamap_unload(dma_mem->dma_tag, dma_mem->dma_map); 123 dma_mem->dma_addr = 0; 124 } 125 126 if(dma_mem->virt_addr) { 127 bus_dmamem_free(dma_mem->dma_tag, dma_mem->virt_addr, 128 dma_mem->dma_map); 129 dma_mem->virt_addr = NULL; 130 } 131 132 if(dma_mem->dma_tag) { 133 bus_dma_tag_destroy(dma_mem->dma_tag); 134 dma_mem->dma_tag = NULL; 135 } 136 137 /* DBG_FUNC("OUT\n"); */ 138 } 139 140 141 /* 142 * Mem resource allocation wrapper function 143 */ 144 void *os_mem_alloc(pqisrc_softstate_t *softs, size_t size) 145 { 146 void *addr = NULL; 147 148 /* DBG_FUNC("IN\n"); */ 149 150 addr = malloc((unsigned long)size, M_SMARTRAID, 151 M_NOWAIT | M_ZERO); 152 153 /* DBG_FUNC("OUT\n"); */ 154 155 return addr; 156 } 157 158 /* 159 * Mem resource deallocation wrapper function 160 */ 161 void os_mem_free(pqisrc_softstate_t *softs, 162 char *addr, size_t size) 163 { 164 /* DBG_FUNC("IN\n"); */ 165 166 free((void*)addr, M_SMARTRAID); 167 168 /* DBG_FUNC("OUT\n"); */ 169 } 170 171 /* 172 * dma/bus resource deallocation wrapper function 173 */ 174 void os_resource_free(pqisrc_softstate_t *softs) 175 { 176 if(softs->os_specific.pqi_parent_dmat) 177 bus_dma_tag_destroy(softs->os_specific.pqi_parent_dmat); 178 179 if (softs->os_specific.pqi_regs_res0 != NULL) 180 bus_release_resource(softs->os_specific.pqi_dev, 181 SYS_RES_MEMORY, 182 softs->os_specific.pqi_regs_rid0, 183 softs->os_specific.pqi_regs_res0); 184 } 185