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 /* $FreeBSD$ */ 27 28 #include "smartpqi_includes.h" 29 30 MALLOC_DEFINE(M_SMARTPQI, "smartpqi", "Buffers for the smartpqi driver"); 31 32 /* 33 * DMA map load callback function 34 */ 35 static void 36 os_dma_map(void *arg, bus_dma_segment_t *segs, int nseg, int error) 37 { 38 bus_addr_t *paddr = (bus_addr_t *)arg; 39 *paddr = segs[0].ds_addr; 40 } 41 42 int 43 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 51 os_dma_destroy(pqisrc_softstate_t *softs) 52 { 53 DBG_FUNC("IN\n"); 54 DBG_FUNC("OUT\n"); 55 return PQI_STATUS_SUCCESS; 56 } 57 58 void 59 os_update_dma_attributes(pqisrc_softstate_t *softs) 60 { 61 DBG_FUNC("IN\n"); 62 DBG_FUNC("OUT\n"); 63 } 64 65 /* 66 * DMA mem resource allocation wrapper function 67 */ 68 int 69 os_dma_mem_alloc(pqisrc_softstate_t *softs, struct dma_mem *dma_mem) 70 { 71 int ret = BSD_SUCCESS; 72 73 /* DBG_FUNC("IN\n"); */ 74 75 /* Make sure the alignment is at least 4 bytes */ 76 ASSERT(dma_mem->align >= 4); 77 78 /* DMA memory needed - allocate it */ 79 if ((ret = bus_dma_tag_create( 80 softs->os_specific.pqi_parent_dmat, /* parent */ 81 dma_mem->align, 0, /* algnmnt, boundary */ 82 BUS_SPACE_MAXADDR, /* lowaddr */ 83 BUS_SPACE_MAXADDR, /* highaddr */ 84 NULL, NULL, /* filter, filterarg */ 85 dma_mem->size, /* maxsize */ 86 1, /* nsegments */ 87 dma_mem->size, /* maxsegsize */ 88 0, /* flags */ 89 NULL, NULL, /* No locking needed */ 90 &dma_mem->dma_tag)) != 0 ) { 91 DBG_ERR("can't allocate DMA tag with error = 0x%x\n", ret); 92 goto err_out; 93 } 94 95 if (!dma_mem->dma_tag) { 96 DBG_ERR("dma tag is NULL\n"); 97 ret = ENOMEM; 98 goto err_out; 99 } 100 101 if ((ret = bus_dmamem_alloc(dma_mem->dma_tag, (void **)&dma_mem->virt_addr, 102 BUS_DMA_WAITOK, &dma_mem->dma_map)) != 0) { 103 DBG_ERR("can't allocate DMA memory for required object \ 104 with error = 0x%x\n", ret); 105 goto err_mem; 106 } 107 108 if((ret = bus_dmamap_load(dma_mem->dma_tag, dma_mem->dma_map, 109 dma_mem->virt_addr, dma_mem->size, 110 os_dma_map, &dma_mem->dma_addr, 0)) != 0) { 111 DBG_ERR("can't load DMA memory for required \ 112 object with error = 0x%x\n", ret); 113 goto err_load; 114 } 115 116 memset(dma_mem->virt_addr, 0, dma_mem->size); 117 118 ret = bsd_status_to_pqi_status(ret); 119 120 /* DBG_FUNC("OUT\n"); */ 121 return ret; 122 123 err_load: 124 if(dma_mem->virt_addr) 125 bus_dmamem_free(dma_mem->dma_tag, dma_mem->virt_addr, 126 dma_mem->dma_map); 127 err_mem: 128 if(dma_mem->dma_tag) 129 bus_dma_tag_destroy(dma_mem->dma_tag); 130 err_out: 131 DBG_FUNC("failed OUT\n"); 132 133 ret = bsd_status_to_pqi_status(ret); 134 135 return ret; 136 } 137 138 /* 139 * DMA mem resource deallocation wrapper function 140 */ 141 void 142 os_dma_mem_free(pqisrc_softstate_t *softs, struct dma_mem *dma_mem) 143 { 144 /* DBG_FUNC("IN\n"); */ 145 146 if(dma_mem->dma_addr) { 147 bus_dmamap_unload(dma_mem->dma_tag, dma_mem->dma_map); 148 dma_mem->dma_addr = 0; 149 } 150 151 if(dma_mem->virt_addr) { 152 bus_dmamem_free(dma_mem->dma_tag, dma_mem->virt_addr, 153 dma_mem->dma_map); 154 dma_mem->virt_addr = NULL; 155 } 156 157 if(dma_mem->dma_tag) { 158 bus_dma_tag_destroy(dma_mem->dma_tag); 159 dma_mem->dma_tag = NULL; 160 } 161 162 /* DBG_FUNC("OUT\n"); */ 163 } 164 165 166 /* 167 * Mem resource allocation wrapper function 168 */ 169 void 170 *os_mem_alloc(pqisrc_softstate_t *softs, size_t size) 171 { 172 void *addr = NULL; 173 174 /* DBG_FUNC("IN\n"); */ 175 176 addr = malloc((unsigned long)size, M_SMARTPQI, 177 M_NOWAIT | M_ZERO); 178 179 /* DBG_FUNC("OUT\n"); */ 180 181 return addr; 182 } 183 184 /* 185 * Mem resource deallocation wrapper function 186 */ 187 void 188 os_mem_free(pqisrc_softstate_t *softs, char *addr, size_t size) 189 { 190 /* DBG_FUNC("IN\n"); */ 191 192 free((void*)addr, M_SMARTPQI); 193 194 /* DBG_FUNC("OUT\n"); */ 195 } 196 197 /* 198 * dma/bus resource deallocation wrapper function 199 */ 200 void 201 os_resource_free(pqisrc_softstate_t *softs) 202 { 203 if(softs->os_specific.pqi_parent_dmat) 204 bus_dma_tag_destroy(softs->os_specific.pqi_parent_dmat); 205 206 if (softs->os_specific.pqi_regs_res0 != NULL) 207 bus_release_resource(softs->os_specific.pqi_dev, 208 SYS_RES_MEMORY, 209 softs->os_specific.pqi_regs_rid0, 210 softs->os_specific.pqi_regs_res0); 211 } 212