1*2f345d8eSLuigi Rizzo /*- 2*2f345d8eSLuigi Rizzo * Copyright (C) 2012 Emulex 3*2f345d8eSLuigi Rizzo * All rights reserved. 4*2f345d8eSLuigi Rizzo * 5*2f345d8eSLuigi Rizzo * Redistribution and use in source and binary forms, with or without 6*2f345d8eSLuigi Rizzo * modification, are permitted provided that the following conditions are met: 7*2f345d8eSLuigi Rizzo * 8*2f345d8eSLuigi Rizzo * 1. Redistributions of source code must retain the above copyright notice, 9*2f345d8eSLuigi Rizzo * this list of conditions and the following disclaimer. 10*2f345d8eSLuigi Rizzo * 11*2f345d8eSLuigi Rizzo * 2. Redistributions in binary form must reproduce the above copyright 12*2f345d8eSLuigi Rizzo * notice, this list of conditions and the following disclaimer in the 13*2f345d8eSLuigi Rizzo * documentation and/or other materials provided with the distribution. 14*2f345d8eSLuigi Rizzo * 15*2f345d8eSLuigi Rizzo * 3. Neither the name of the Emulex Corporation nor the names of its 16*2f345d8eSLuigi Rizzo * contributors may be used to endorse or promote products derived from 17*2f345d8eSLuigi Rizzo * this software without specific prior written permission. 18*2f345d8eSLuigi Rizzo * 19*2f345d8eSLuigi Rizzo * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20*2f345d8eSLuigi Rizzo * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21*2f345d8eSLuigi Rizzo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22*2f345d8eSLuigi Rizzo * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23*2f345d8eSLuigi Rizzo * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24*2f345d8eSLuigi Rizzo * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25*2f345d8eSLuigi Rizzo * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26*2f345d8eSLuigi Rizzo * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27*2f345d8eSLuigi Rizzo * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28*2f345d8eSLuigi Rizzo * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29*2f345d8eSLuigi Rizzo * POSSIBILITY OF SUCH DAMAGE. 30*2f345d8eSLuigi Rizzo * 31*2f345d8eSLuigi Rizzo * Contact Information: 32*2f345d8eSLuigi Rizzo * freebsd-drivers@emulex.com 33*2f345d8eSLuigi Rizzo * 34*2f345d8eSLuigi Rizzo * Emulex 35*2f345d8eSLuigi Rizzo * 3333 Susan Street 36*2f345d8eSLuigi Rizzo * Costa Mesa, CA 92626 37*2f345d8eSLuigi Rizzo */ 38*2f345d8eSLuigi Rizzo 39*2f345d8eSLuigi Rizzo 40*2f345d8eSLuigi Rizzo /* $FreeBSD$ */ 41*2f345d8eSLuigi Rizzo 42*2f345d8eSLuigi Rizzo 43*2f345d8eSLuigi Rizzo #include "oce_if.h" 44*2f345d8eSLuigi Rizzo 45*2f345d8eSLuigi Rizzo static void oce_dma_map_ring(void *arg, 46*2f345d8eSLuigi Rizzo bus_dma_segment_t *segs, 47*2f345d8eSLuigi Rizzo int nseg, 48*2f345d8eSLuigi Rizzo int error); 49*2f345d8eSLuigi Rizzo 50*2f345d8eSLuigi Rizzo /** 51*2f345d8eSLuigi Rizzo * @brief Allocate DMA memory 52*2f345d8eSLuigi Rizzo * @param sc software handle to the device 53*2f345d8eSLuigi Rizzo * @param size bus size 54*2f345d8eSLuigi Rizzo * @param dma dma memory area 55*2f345d8eSLuigi Rizzo * @param flags creation flags 56*2f345d8eSLuigi Rizzo * @returns 0 on success, error otherwize 57*2f345d8eSLuigi Rizzo */ 58*2f345d8eSLuigi Rizzo int 59*2f345d8eSLuigi Rizzo oce_dma_alloc(POCE_SOFTC sc, bus_size_t size, POCE_DMA_MEM dma, int flags) 60*2f345d8eSLuigi Rizzo { 61*2f345d8eSLuigi Rizzo int rc; 62*2f345d8eSLuigi Rizzo 63*2f345d8eSLuigi Rizzo 64*2f345d8eSLuigi Rizzo memset(dma, 0, sizeof(OCE_DMA_MEM)); 65*2f345d8eSLuigi Rizzo 66*2f345d8eSLuigi Rizzo rc = bus_dma_tag_create(bus_get_dma_tag(sc->dev), 67*2f345d8eSLuigi Rizzo 8, 0, 68*2f345d8eSLuigi Rizzo BUS_SPACE_MAXADDR, 69*2f345d8eSLuigi Rizzo BUS_SPACE_MAXADDR, 70*2f345d8eSLuigi Rizzo NULL, NULL, 71*2f345d8eSLuigi Rizzo size, 1, size, 0, NULL, NULL, &dma->tag); 72*2f345d8eSLuigi Rizzo 73*2f345d8eSLuigi Rizzo if (rc == 0) { 74*2f345d8eSLuigi Rizzo rc = bus_dmamem_alloc(dma->tag, 75*2f345d8eSLuigi Rizzo &dma->ptr, 76*2f345d8eSLuigi Rizzo BUS_DMA_NOWAIT | BUS_DMA_COHERENT, 77*2f345d8eSLuigi Rizzo &dma->map); 78*2f345d8eSLuigi Rizzo } 79*2f345d8eSLuigi Rizzo 80*2f345d8eSLuigi Rizzo dma->paddr = 0; 81*2f345d8eSLuigi Rizzo if (rc == 0) { 82*2f345d8eSLuigi Rizzo rc = bus_dmamap_load(dma->tag, 83*2f345d8eSLuigi Rizzo dma->map, 84*2f345d8eSLuigi Rizzo dma->ptr, 85*2f345d8eSLuigi Rizzo size, 86*2f345d8eSLuigi Rizzo oce_dma_map_addr, 87*2f345d8eSLuigi Rizzo &dma->paddr, flags | BUS_DMA_NOWAIT); 88*2f345d8eSLuigi Rizzo if (dma->paddr == 0) 89*2f345d8eSLuigi Rizzo rc = ENXIO; 90*2f345d8eSLuigi Rizzo } 91*2f345d8eSLuigi Rizzo 92*2f345d8eSLuigi Rizzo if (rc != 0) 93*2f345d8eSLuigi Rizzo oce_dma_free(sc, dma); 94*2f345d8eSLuigi Rizzo 95*2f345d8eSLuigi Rizzo return rc; 96*2f345d8eSLuigi Rizzo } 97*2f345d8eSLuigi Rizzo 98*2f345d8eSLuigi Rizzo /** 99*2f345d8eSLuigi Rizzo * @brief Free DMA memory 100*2f345d8eSLuigi Rizzo * @param sc software handle to the device 101*2f345d8eSLuigi Rizzo * @param dma dma area to free 102*2f345d8eSLuigi Rizzo */ 103*2f345d8eSLuigi Rizzo void 104*2f345d8eSLuigi Rizzo oce_dma_free(POCE_SOFTC sc, POCE_DMA_MEM dma) 105*2f345d8eSLuigi Rizzo { 106*2f345d8eSLuigi Rizzo if (dma->tag == NULL) 107*2f345d8eSLuigi Rizzo return; 108*2f345d8eSLuigi Rizzo 109*2f345d8eSLuigi Rizzo if (dma->map != NULL) { 110*2f345d8eSLuigi Rizzo bus_dmamap_sync(dma->tag, dma->map, 111*2f345d8eSLuigi Rizzo BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 112*2f345d8eSLuigi Rizzo bus_dmamap_unload(dma->tag, dma->map); 113*2f345d8eSLuigi Rizzo } 114*2f345d8eSLuigi Rizzo 115*2f345d8eSLuigi Rizzo if (dma->ptr != NULL) { 116*2f345d8eSLuigi Rizzo bus_dmamem_free(dma->tag, dma->ptr, dma->map); 117*2f345d8eSLuigi Rizzo dma->map = NULL; 118*2f345d8eSLuigi Rizzo dma->ptr = NULL; 119*2f345d8eSLuigi Rizzo } 120*2f345d8eSLuigi Rizzo 121*2f345d8eSLuigi Rizzo bus_dma_tag_destroy(dma->tag); 122*2f345d8eSLuigi Rizzo dma->tag = NULL; 123*2f345d8eSLuigi Rizzo 124*2f345d8eSLuigi Rizzo return; 125*2f345d8eSLuigi Rizzo } 126*2f345d8eSLuigi Rizzo 127*2f345d8eSLuigi Rizzo 128*2f345d8eSLuigi Rizzo 129*2f345d8eSLuigi Rizzo /** 130*2f345d8eSLuigi Rizzo * @brief Map DMA memory segment addresses 131*2f345d8eSLuigi Rizzo * @param arg physical address pointer 132*2f345d8eSLuigi Rizzo * @param segs dma memory segments 133*2f345d8eSLuigi Rizzo * @param nseg number of dma memory segments 134*2f345d8eSLuigi Rizzo * @param error if error, zeroes the physical address 135*2f345d8eSLuigi Rizzo */ 136*2f345d8eSLuigi Rizzo void 137*2f345d8eSLuigi Rizzo oce_dma_map_addr(void *arg, bus_dma_segment_t * segs, int nseg, int error) 138*2f345d8eSLuigi Rizzo { 139*2f345d8eSLuigi Rizzo bus_addr_t *paddr = arg; 140*2f345d8eSLuigi Rizzo 141*2f345d8eSLuigi Rizzo if (error) 142*2f345d8eSLuigi Rizzo *paddr = 0; 143*2f345d8eSLuigi Rizzo else 144*2f345d8eSLuigi Rizzo *paddr = segs->ds_addr; 145*2f345d8eSLuigi Rizzo } 146*2f345d8eSLuigi Rizzo 147*2f345d8eSLuigi Rizzo 148*2f345d8eSLuigi Rizzo 149*2f345d8eSLuigi Rizzo /** 150*2f345d8eSLuigi Rizzo * @brief Destroy a ring buffer 151*2f345d8eSLuigi Rizzo * @param sc software handle to the device 152*2f345d8eSLuigi Rizzo * @param ring ring buffer 153*2f345d8eSLuigi Rizzo */ 154*2f345d8eSLuigi Rizzo 155*2f345d8eSLuigi Rizzo void 156*2f345d8eSLuigi Rizzo oce_destroy_ring_buffer(POCE_SOFTC sc, oce_ring_buffer_t *ring) 157*2f345d8eSLuigi Rizzo { 158*2f345d8eSLuigi Rizzo oce_dma_free(sc, &ring->dma); 159*2f345d8eSLuigi Rizzo free(ring, M_DEVBUF); 160*2f345d8eSLuigi Rizzo } 161*2f345d8eSLuigi Rizzo 162*2f345d8eSLuigi Rizzo 163*2f345d8eSLuigi Rizzo 164*2f345d8eSLuigi Rizzo oce_ring_buffer_t * 165*2f345d8eSLuigi Rizzo oce_create_ring_buffer(POCE_SOFTC sc, 166*2f345d8eSLuigi Rizzo uint32_t q_len, uint32_t item_size) 167*2f345d8eSLuigi Rizzo { 168*2f345d8eSLuigi Rizzo uint32_t size = q_len * item_size; 169*2f345d8eSLuigi Rizzo int rc; 170*2f345d8eSLuigi Rizzo oce_ring_buffer_t *ring; 171*2f345d8eSLuigi Rizzo 172*2f345d8eSLuigi Rizzo 173*2f345d8eSLuigi Rizzo ring = malloc(sizeof(oce_ring_buffer_t), M_DEVBUF, M_NOWAIT | M_ZERO); 174*2f345d8eSLuigi Rizzo if (ring == NULL) 175*2f345d8eSLuigi Rizzo return NULL; 176*2f345d8eSLuigi Rizzo 177*2f345d8eSLuigi Rizzo ring->item_size = item_size; 178*2f345d8eSLuigi Rizzo ring->num_items = q_len; 179*2f345d8eSLuigi Rizzo 180*2f345d8eSLuigi Rizzo rc = bus_dma_tag_create(bus_get_dma_tag(sc->dev), 181*2f345d8eSLuigi Rizzo 4096, 0, 182*2f345d8eSLuigi Rizzo BUS_SPACE_MAXADDR, 183*2f345d8eSLuigi Rizzo BUS_SPACE_MAXADDR, 184*2f345d8eSLuigi Rizzo NULL, NULL, 185*2f345d8eSLuigi Rizzo size, 8, 4096, 0, NULL, NULL, &ring->dma.tag); 186*2f345d8eSLuigi Rizzo if (rc) 187*2f345d8eSLuigi Rizzo goto fail; 188*2f345d8eSLuigi Rizzo 189*2f345d8eSLuigi Rizzo 190*2f345d8eSLuigi Rizzo rc = bus_dmamem_alloc(ring->dma.tag, 191*2f345d8eSLuigi Rizzo &ring->dma.ptr, 192*2f345d8eSLuigi Rizzo BUS_DMA_NOWAIT | BUS_DMA_COHERENT, 193*2f345d8eSLuigi Rizzo &ring->dma.map); 194*2f345d8eSLuigi Rizzo if (rc) 195*2f345d8eSLuigi Rizzo goto fail; 196*2f345d8eSLuigi Rizzo 197*2f345d8eSLuigi Rizzo bzero(ring->dma.ptr, size); 198*2f345d8eSLuigi Rizzo bus_dmamap_sync(ring->dma.tag, ring->dma.map, 199*2f345d8eSLuigi Rizzo BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 200*2f345d8eSLuigi Rizzo ring->dma.paddr = 0; 201*2f345d8eSLuigi Rizzo 202*2f345d8eSLuigi Rizzo return ring; 203*2f345d8eSLuigi Rizzo 204*2f345d8eSLuigi Rizzo fail: 205*2f345d8eSLuigi Rizzo oce_dma_free(sc, &ring->dma); 206*2f345d8eSLuigi Rizzo free(ring, M_DEVBUF); 207*2f345d8eSLuigi Rizzo ring = NULL; 208*2f345d8eSLuigi Rizzo return NULL; 209*2f345d8eSLuigi Rizzo } 210*2f345d8eSLuigi Rizzo 211*2f345d8eSLuigi Rizzo 212*2f345d8eSLuigi Rizzo 213*2f345d8eSLuigi Rizzo struct _oce_dmamap_paddr_table { 214*2f345d8eSLuigi Rizzo uint32_t max_entries; 215*2f345d8eSLuigi Rizzo uint32_t num_entries; 216*2f345d8eSLuigi Rizzo struct phys_addr *paddrs; 217*2f345d8eSLuigi Rizzo }; 218*2f345d8eSLuigi Rizzo 219*2f345d8eSLuigi Rizzo 220*2f345d8eSLuigi Rizzo 221*2f345d8eSLuigi Rizzo /** 222*2f345d8eSLuigi Rizzo * @brief Map ring buffer 223*2f345d8eSLuigi Rizzo * @param arg dma map phyical address table pointer 224*2f345d8eSLuigi Rizzo * @param segs dma memory segments 225*2f345d8eSLuigi Rizzo * @param nseg number of dma memory segments 226*2f345d8eSLuigi Rizzo * @param error maps only if error is 0 227*2f345d8eSLuigi Rizzo */ 228*2f345d8eSLuigi Rizzo static void 229*2f345d8eSLuigi Rizzo oce_dma_map_ring(void *arg, bus_dma_segment_t * segs, int nseg, int error) 230*2f345d8eSLuigi Rizzo { 231*2f345d8eSLuigi Rizzo int i; 232*2f345d8eSLuigi Rizzo struct _oce_dmamap_paddr_table *dpt = 233*2f345d8eSLuigi Rizzo (struct _oce_dmamap_paddr_table *)arg; 234*2f345d8eSLuigi Rizzo 235*2f345d8eSLuigi Rizzo if (error == 0) { 236*2f345d8eSLuigi Rizzo if (nseg <= dpt->max_entries) { 237*2f345d8eSLuigi Rizzo for (i = 0; i < nseg; i++) { 238*2f345d8eSLuigi Rizzo dpt->paddrs[i].lo = ADDR_LO(segs[i].ds_addr); 239*2f345d8eSLuigi Rizzo dpt->paddrs[i].hi = ADDR_HI(segs[i].ds_addr); 240*2f345d8eSLuigi Rizzo } 241*2f345d8eSLuigi Rizzo dpt->num_entries = nseg; 242*2f345d8eSLuigi Rizzo } 243*2f345d8eSLuigi Rizzo } 244*2f345d8eSLuigi Rizzo } 245*2f345d8eSLuigi Rizzo 246*2f345d8eSLuigi Rizzo 247*2f345d8eSLuigi Rizzo 248*2f345d8eSLuigi Rizzo /** 249*2f345d8eSLuigi Rizzo * @brief Load bus dma map for a ring buffer 250*2f345d8eSLuigi Rizzo * @param ring ring buffer pointer 251*2f345d8eSLuigi Rizzo * @param pa_list physical address list 252*2f345d8eSLuigi Rizzo * @returns number entries 253*2f345d8eSLuigi Rizzo */ 254*2f345d8eSLuigi Rizzo uint32_t 255*2f345d8eSLuigi Rizzo oce_page_list(oce_ring_buffer_t *ring, struct phys_addr *pa_list) 256*2f345d8eSLuigi Rizzo { 257*2f345d8eSLuigi Rizzo struct _oce_dmamap_paddr_table dpt; 258*2f345d8eSLuigi Rizzo 259*2f345d8eSLuigi Rizzo dpt.max_entries = 8; 260*2f345d8eSLuigi Rizzo dpt.num_entries = 0; 261*2f345d8eSLuigi Rizzo dpt.paddrs = pa_list; 262*2f345d8eSLuigi Rizzo 263*2f345d8eSLuigi Rizzo bus_dmamap_load(ring->dma.tag, 264*2f345d8eSLuigi Rizzo ring->dma.map, 265*2f345d8eSLuigi Rizzo ring->dma.ptr, 266*2f345d8eSLuigi Rizzo ring->item_size * ring->num_items, 267*2f345d8eSLuigi Rizzo oce_dma_map_ring, &dpt, BUS_DMA_NOWAIT); 268*2f345d8eSLuigi Rizzo 269*2f345d8eSLuigi Rizzo return dpt.num_entries; 270*2f345d8eSLuigi Rizzo } 271