1 /*- 2 * Copyright 2016-2021 Microchip Technology, Inc. and/or its subsidiaries. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26 27 #include "smartpqi_includes.h" 28 29 MALLOC_DEFINE(M_SMARTPQI, "smartpqi", "Buffers for the smartpqi driver"); 30 31 /* 32 * DMA map load callback function 33 */ 34 static void 35 os_dma_map(void *arg, bus_dma_segment_t *segs, int nseg, int error) 36 { 37 bus_addr_t *paddr = (bus_addr_t *)arg; 38 *paddr = segs[0].ds_addr; 39 } 40 41 int 42 os_dma_setup(pqisrc_softstate_t *softs) 43 { 44 DBG_FUNC("IN\n"); 45 DBG_FUNC("OUT\n"); 46 return PQI_STATUS_SUCCESS; 47 } 48 49 int 50 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 void 58 os_update_dma_attributes(pqisrc_softstate_t *softs) 59 { 60 DBG_FUNC("IN\n"); 61 DBG_FUNC("OUT\n"); 62 } 63 64 /* 65 * DMA mem resource allocation wrapper function 66 */ 67 int 68 os_dma_mem_alloc(pqisrc_softstate_t *softs, struct dma_mem *dma_mem) 69 { 70 int ret = BSD_SUCCESS; 71 72 /* DBG_FUNC("IN\n"); */ 73 74 /* Make sure the alignment is at least 4 bytes */ 75 ASSERT(dma_mem->align >= 4); 76 77 /* DMA memory needed - allocate it */ 78 if ((ret = bus_dma_tag_create( 79 softs->os_specific.pqi_parent_dmat, /* parent */ 80 dma_mem->align, 0, /* algnmnt, boundary */ 81 BUS_SPACE_MAXADDR, /* lowaddr */ 82 BUS_SPACE_MAXADDR, /* highaddr */ 83 NULL, NULL, /* filter, filterarg */ 84 dma_mem->size, /* maxsize */ 85 1, /* nsegments */ 86 dma_mem->size, /* maxsegsize */ 87 0, /* flags */ 88 NULL, NULL, /* No locking needed */ 89 &dma_mem->dma_tag)) != 0 ) { 90 DBG_ERR("can't allocate DMA tag with error = 0x%x\n", ret); 91 goto err_out; 92 } 93 94 if (!dma_mem->dma_tag) { 95 DBG_ERR("dma tag is NULL\n"); 96 ret = ENOMEM; 97 goto err_out; 98 } 99 100 if ((ret = bus_dmamem_alloc(dma_mem->dma_tag, (void **)&dma_mem->virt_addr, 101 BUS_DMA_NOWAIT, &dma_mem->dma_map)) != 0) { 102 DBG_ERR("can't allocate DMA memory for required object \ 103 with error = 0x%x\n", ret); 104 goto err_mem; 105 } 106 107 if((ret = bus_dmamap_load(dma_mem->dma_tag, dma_mem->dma_map, 108 dma_mem->virt_addr, dma_mem->size, 109 os_dma_map, &dma_mem->dma_addr, 0)) != 0) { 110 DBG_ERR("can't load DMA memory for required \ 111 object with error = 0x%x\n", ret); 112 goto err_load; 113 } 114 115 memset(dma_mem->virt_addr, 0, dma_mem->size); 116 117 ret = bsd_status_to_pqi_status(ret); 118 119 /* DBG_FUNC("OUT\n"); */ 120 return ret; 121 122 err_load: 123 if(dma_mem->virt_addr) 124 bus_dmamem_free(dma_mem->dma_tag, dma_mem->virt_addr, 125 dma_mem->dma_map); 126 err_mem: 127 if(dma_mem->dma_tag) 128 bus_dma_tag_destroy(dma_mem->dma_tag); 129 err_out: 130 DBG_FUNC("failed OUT\n"); 131 132 ret = bsd_status_to_pqi_status(ret); 133 134 return ret; 135 } 136 137 /* 138 * DMA mem resource deallocation wrapper function 139 */ 140 void 141 os_dma_mem_free(pqisrc_softstate_t *softs, struct dma_mem *dma_mem) 142 { 143 /* DBG_FUNC("IN\n"); */ 144 145 if(dma_mem->dma_addr) { 146 bus_dmamap_unload(dma_mem->dma_tag, dma_mem->dma_map); 147 dma_mem->dma_addr = 0; 148 } 149 150 if(dma_mem->virt_addr) { 151 bus_dmamem_free(dma_mem->dma_tag, dma_mem->virt_addr, 152 dma_mem->dma_map); 153 dma_mem->virt_addr = NULL; 154 } 155 156 if(dma_mem->dma_tag) { 157 bus_dma_tag_destroy(dma_mem->dma_tag); 158 dma_mem->dma_tag = NULL; 159 } 160 161 /* DBG_FUNC("OUT\n"); */ 162 } 163 164 165 /* 166 * Mem resource allocation wrapper function 167 */ 168 void 169 *os_mem_alloc(pqisrc_softstate_t *softs, size_t size) 170 { 171 void *addr = NULL; 172 173 /* DBG_FUNC("IN\n"); */ 174 175 addr = malloc((unsigned long)size, M_SMARTPQI, 176 M_NOWAIT | M_ZERO); 177 178 /* DBG_FUNC("OUT\n"); */ 179 180 return addr; 181 } 182 183 /* 184 * Mem resource deallocation wrapper function 185 */ 186 void 187 os_mem_free(pqisrc_softstate_t *softs, char *addr, size_t size) 188 { 189 /* DBG_FUNC("IN\n"); */ 190 191 free((void*)addr, M_SMARTPQI); 192 193 /* DBG_FUNC("OUT\n"); */ 194 } 195 196 /* 197 * dma/bus resource deallocation wrapper function 198 */ 199 void 200 os_resource_free(pqisrc_softstate_t *softs) 201 { 202 if(softs->os_specific.pqi_parent_dmat) 203 bus_dma_tag_destroy(softs->os_specific.pqi_parent_dmat); 204 205 if (softs->os_specific.pqi_regs_res0 != NULL) 206 bus_release_resource(softs->os_specific.pqi_dev, 207 SYS_RES_MEMORY, 208 softs->os_specific.pqi_regs_rid0, 209 softs->os_specific.pqi_regs_res0); 210 } 211