1*62dadd65SYuri Pankov /* 2*62dadd65SYuri Pankov * Copyright (C) 2007 VMware, Inc. All rights reserved. 3*62dadd65SYuri Pankov * 4*62dadd65SYuri Pankov * The contents of this file are subject to the terms of the Common 5*62dadd65SYuri Pankov * Development and Distribution License (the "License") version 1.0 6*62dadd65SYuri Pankov * and no later version. You may not use this file except in 7*62dadd65SYuri Pankov * compliance with the License. 8*62dadd65SYuri Pankov * 9*62dadd65SYuri Pankov * You can obtain a copy of the License at 10*62dadd65SYuri Pankov * http://www.opensource.org/licenses/cddl1.php 11*62dadd65SYuri Pankov * 12*62dadd65SYuri Pankov * See the License for the specific language governing permissions 13*62dadd65SYuri Pankov * and limitations under the License. 14*62dadd65SYuri Pankov */ 15*62dadd65SYuri Pankov 16*62dadd65SYuri Pankov #include <vmxnet3.h> 17*62dadd65SYuri Pankov 18*62dadd65SYuri Pankov /* Used by ddi_regs_map_setup() and ddi_dma_mem_alloc() */ 19*62dadd65SYuri Pankov ddi_device_acc_attr_t vmxnet3_dev_attr = { 20*62dadd65SYuri Pankov DDI_DEVICE_ATTR_V0, 21*62dadd65SYuri Pankov DDI_STRUCTURE_LE_ACC, 22*62dadd65SYuri Pankov DDI_STRICTORDER_ACC 23*62dadd65SYuri Pankov }; 24*62dadd65SYuri Pankov 25*62dadd65SYuri Pankov /* Buffers with no alignment constraint DMA description */ 26*62dadd65SYuri Pankov static ddi_dma_attr_t vmxnet3_dma_attrs_1 = { 27*62dadd65SYuri Pankov .dma_attr_version = DMA_ATTR_V0, 28*62dadd65SYuri Pankov .dma_attr_addr_lo = 0x0000000000000000ull, 29*62dadd65SYuri Pankov .dma_attr_addr_hi = 0xFFFFFFFFFFFFFFFFull, 30*62dadd65SYuri Pankov .dma_attr_count_max = 0xFFFFFFFFFFFFFFFFull, 31*62dadd65SYuri Pankov .dma_attr_align = 0x0000000000000001ull, 32*62dadd65SYuri Pankov .dma_attr_burstsizes = 0x0000000000000001ull, 33*62dadd65SYuri Pankov .dma_attr_minxfer = 0x00000001, 34*62dadd65SYuri Pankov .dma_attr_maxxfer = 0xFFFFFFFFFFFFFFFFull, 35*62dadd65SYuri Pankov .dma_attr_seg = 0xFFFFFFFFFFFFFFFFull, 36*62dadd65SYuri Pankov .dma_attr_sgllen = 1, 37*62dadd65SYuri Pankov .dma_attr_granular = 0x00000001, 38*62dadd65SYuri Pankov .dma_attr_flags = 0 39*62dadd65SYuri Pankov }; 40*62dadd65SYuri Pankov 41*62dadd65SYuri Pankov /* Buffers with a 128-bytes alignment constraint DMA description */ 42*62dadd65SYuri Pankov static ddi_dma_attr_t vmxnet3_dma_attrs_128 = { 43*62dadd65SYuri Pankov .dma_attr_version = DMA_ATTR_V0, 44*62dadd65SYuri Pankov .dma_attr_addr_lo = 0x0000000000000000ull, 45*62dadd65SYuri Pankov .dma_attr_addr_hi = 0xFFFFFFFFFFFFFFFFull, 46*62dadd65SYuri Pankov .dma_attr_count_max = 0xFFFFFFFFFFFFFFFFull, 47*62dadd65SYuri Pankov .dma_attr_align = 0x0000000000000080ull, 48*62dadd65SYuri Pankov .dma_attr_burstsizes = 0x0000000000000001ull, 49*62dadd65SYuri Pankov .dma_attr_minxfer = 0x00000001, 50*62dadd65SYuri Pankov .dma_attr_maxxfer = 0xFFFFFFFFFFFFFFFFull, 51*62dadd65SYuri Pankov .dma_attr_seg = 0xFFFFFFFFFFFFFFFFull, 52*62dadd65SYuri Pankov .dma_attr_sgllen = 1, 53*62dadd65SYuri Pankov .dma_attr_granular = 0x00000001, 54*62dadd65SYuri Pankov .dma_attr_flags = 0 55*62dadd65SYuri Pankov }; 56*62dadd65SYuri Pankov 57*62dadd65SYuri Pankov /* Buffers with a 512-bytes alignment constraint DMA description */ 58*62dadd65SYuri Pankov static ddi_dma_attr_t vmxnet3_dma_attrs_512 = { 59*62dadd65SYuri Pankov .dma_attr_version = DMA_ATTR_V0, 60*62dadd65SYuri Pankov .dma_attr_addr_lo = 0x0000000000000000ull, 61*62dadd65SYuri Pankov .dma_attr_addr_hi = 0xFFFFFFFFFFFFFFFFull, 62*62dadd65SYuri Pankov .dma_attr_count_max = 0xFFFFFFFFFFFFFFFFull, 63*62dadd65SYuri Pankov .dma_attr_align = 0x0000000000000200ull, 64*62dadd65SYuri Pankov .dma_attr_burstsizes = 0x0000000000000001ull, 65*62dadd65SYuri Pankov .dma_attr_minxfer = 0x00000001, 66*62dadd65SYuri Pankov .dma_attr_maxxfer = 0xFFFFFFFFFFFFFFFFull, 67*62dadd65SYuri Pankov .dma_attr_seg = 0xFFFFFFFFFFFFFFFFull, 68*62dadd65SYuri Pankov .dma_attr_sgllen = 1, 69*62dadd65SYuri Pankov .dma_attr_granular = 0x00000001, 70*62dadd65SYuri Pankov .dma_attr_flags = 0 71*62dadd65SYuri Pankov }; 72*62dadd65SYuri Pankov 73*62dadd65SYuri Pankov /* 74*62dadd65SYuri Pankov * vmxnet3_alloc_dma_mem -- 75*62dadd65SYuri Pankov * 76*62dadd65SYuri Pankov * Allocate /size/ bytes of contiguous DMA-ble memory. 77*62dadd65SYuri Pankov * 78*62dadd65SYuri Pankov * Results: 79*62dadd65SYuri Pankov * DDI_SUCCESS or DDI_FAILURE. 80*62dadd65SYuri Pankov * 81*62dadd65SYuri Pankov * Side effects: 82*62dadd65SYuri Pankov * None. 83*62dadd65SYuri Pankov */ 84*62dadd65SYuri Pankov static int 85*62dadd65SYuri Pankov vmxnet3_alloc_dma_mem(vmxnet3_softc_t *dp, vmxnet3_dmabuf_t *dma, size_t size, 86*62dadd65SYuri Pankov boolean_t canSleep, ddi_dma_attr_t *dma_attrs) 87*62dadd65SYuri Pankov { 88*62dadd65SYuri Pankov ddi_dma_cookie_t cookie; 89*62dadd65SYuri Pankov uint_t cookieCount; 90*62dadd65SYuri Pankov int (*cb) (caddr_t) = canSleep ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT; 91*62dadd65SYuri Pankov 92*62dadd65SYuri Pankov ASSERT(size != 0); 93*62dadd65SYuri Pankov 94*62dadd65SYuri Pankov /* 95*62dadd65SYuri Pankov * Allocate a DMA handle 96*62dadd65SYuri Pankov */ 97*62dadd65SYuri Pankov if (ddi_dma_alloc_handle(dp->dip, dma_attrs, cb, NULL, 98*62dadd65SYuri Pankov &dma->dmaHandle) != DDI_SUCCESS) { 99*62dadd65SYuri Pankov VMXNET3_WARN(dp, "ddi_dma_alloc_handle() failed\n"); 100*62dadd65SYuri Pankov goto error; 101*62dadd65SYuri Pankov } 102*62dadd65SYuri Pankov 103*62dadd65SYuri Pankov /* 104*62dadd65SYuri Pankov * Allocate memory 105*62dadd65SYuri Pankov */ 106*62dadd65SYuri Pankov if (ddi_dma_mem_alloc(dma->dmaHandle, size, &vmxnet3_dev_attr, 107*62dadd65SYuri Pankov DDI_DMA_CONSISTENT, cb, NULL, &dma->buf, &dma->bufLen, 108*62dadd65SYuri Pankov &dma->dataHandle) != DDI_SUCCESS) { 109*62dadd65SYuri Pankov VMXNET3_WARN(dp, "ddi_dma_mem_alloc() failed\n"); 110*62dadd65SYuri Pankov goto error_dma_handle; 111*62dadd65SYuri Pankov } 112*62dadd65SYuri Pankov 113*62dadd65SYuri Pankov /* 114*62dadd65SYuri Pankov * Map the memory 115*62dadd65SYuri Pankov */ 116*62dadd65SYuri Pankov if (ddi_dma_addr_bind_handle(dma->dmaHandle, NULL, dma->buf, 117*62dadd65SYuri Pankov dma->bufLen, DDI_DMA_RDWR | DDI_DMA_STREAMING, cb, NULL, &cookie, 118*62dadd65SYuri Pankov &cookieCount) != DDI_DMA_MAPPED) { 119*62dadd65SYuri Pankov VMXNET3_WARN(dp, "ddi_dma_addr_bind_handle() failed\n"); 120*62dadd65SYuri Pankov goto error_dma_mem; 121*62dadd65SYuri Pankov } 122*62dadd65SYuri Pankov 123*62dadd65SYuri Pankov ASSERT(cookieCount == 1); 124*62dadd65SYuri Pankov dma->bufPA = cookie.dmac_laddress; 125*62dadd65SYuri Pankov 126*62dadd65SYuri Pankov return (DDI_SUCCESS); 127*62dadd65SYuri Pankov 128*62dadd65SYuri Pankov error_dma_mem: 129*62dadd65SYuri Pankov ddi_dma_mem_free(&dma->dataHandle); 130*62dadd65SYuri Pankov error_dma_handle: 131*62dadd65SYuri Pankov ddi_dma_free_handle(&dma->dmaHandle); 132*62dadd65SYuri Pankov error: 133*62dadd65SYuri Pankov dma->buf = NULL; 134*62dadd65SYuri Pankov dma->bufPA = NULL; 135*62dadd65SYuri Pankov dma->bufLen = 0; 136*62dadd65SYuri Pankov return (DDI_FAILURE); 137*62dadd65SYuri Pankov } 138*62dadd65SYuri Pankov 139*62dadd65SYuri Pankov int 140*62dadd65SYuri Pankov vmxnet3_alloc_dma_mem_1(vmxnet3_softc_t *dp, vmxnet3_dmabuf_t *dma, size_t size, 141*62dadd65SYuri Pankov boolean_t canSleep) 142*62dadd65SYuri Pankov { 143*62dadd65SYuri Pankov return (vmxnet3_alloc_dma_mem(dp, dma, size, canSleep, 144*62dadd65SYuri Pankov &vmxnet3_dma_attrs_1)); 145*62dadd65SYuri Pankov } 146*62dadd65SYuri Pankov 147*62dadd65SYuri Pankov int 148*62dadd65SYuri Pankov vmxnet3_alloc_dma_mem_512(vmxnet3_softc_t *dp, vmxnet3_dmabuf_t *dma, 149*62dadd65SYuri Pankov size_t size, boolean_t canSleep) 150*62dadd65SYuri Pankov { 151*62dadd65SYuri Pankov return (vmxnet3_alloc_dma_mem(dp, dma, size, canSleep, 152*62dadd65SYuri Pankov &vmxnet3_dma_attrs_512)); 153*62dadd65SYuri Pankov } 154*62dadd65SYuri Pankov 155*62dadd65SYuri Pankov int 156*62dadd65SYuri Pankov vmxnet3_alloc_dma_mem_128(vmxnet3_softc_t *dp, vmxnet3_dmabuf_t *dma, 157*62dadd65SYuri Pankov size_t size, boolean_t canSleep) 158*62dadd65SYuri Pankov { 159*62dadd65SYuri Pankov return (vmxnet3_alloc_dma_mem(dp, dma, size, canSleep, 160*62dadd65SYuri Pankov &vmxnet3_dma_attrs_128)); 161*62dadd65SYuri Pankov } 162*62dadd65SYuri Pankov 163*62dadd65SYuri Pankov /* 164*62dadd65SYuri Pankov * vmxnet3_free_dma_mem -- 165*62dadd65SYuri Pankov * 166*62dadd65SYuri Pankov * Free DMA-ble memory. 167*62dadd65SYuri Pankov * 168*62dadd65SYuri Pankov * Results: 169*62dadd65SYuri Pankov * None. 170*62dadd65SYuri Pankov * 171*62dadd65SYuri Pankov * Side effects: 172*62dadd65SYuri Pankov * None. 173*62dadd65SYuri Pankov */ 174*62dadd65SYuri Pankov void 175*62dadd65SYuri Pankov vmxnet3_free_dma_mem(vmxnet3_dmabuf_t *dma) 176*62dadd65SYuri Pankov { 177*62dadd65SYuri Pankov (void) ddi_dma_unbind_handle(dma->dmaHandle); 178*62dadd65SYuri Pankov ddi_dma_mem_free(&dma->dataHandle); 179*62dadd65SYuri Pankov ddi_dma_free_handle(&dma->dmaHandle); 180*62dadd65SYuri Pankov 181*62dadd65SYuri Pankov dma->buf = NULL; 182*62dadd65SYuri Pankov dma->bufPA = NULL; 183*62dadd65SYuri Pankov dma->bufLen = 0; 184*62dadd65SYuri Pankov } 185*62dadd65SYuri Pankov 186*62dadd65SYuri Pankov /* 187*62dadd65SYuri Pankov * vmxnet3_getprop -- 188*62dadd65SYuri Pankov * 189*62dadd65SYuri Pankov * Get the numeric value of the property "name" in vmxnet3s.conf for 190*62dadd65SYuri Pankov * the corresponding device instance. 191*62dadd65SYuri Pankov * If the property isn't found or if it doesn't satisfy the conditions, 192*62dadd65SYuri Pankov * "def" is returned. 193*62dadd65SYuri Pankov * 194*62dadd65SYuri Pankov * Results: 195*62dadd65SYuri Pankov * The value of the property or "def". 196*62dadd65SYuri Pankov * 197*62dadd65SYuri Pankov * Side effects: 198*62dadd65SYuri Pankov * None. 199*62dadd65SYuri Pankov */ 200*62dadd65SYuri Pankov int 201*62dadd65SYuri Pankov vmxnet3_getprop(vmxnet3_softc_t *dp, char *name, int min, int max, int def) 202*62dadd65SYuri Pankov { 203*62dadd65SYuri Pankov int ret = def; 204*62dadd65SYuri Pankov int *props; 205*62dadd65SYuri Pankov uint_t nprops; 206*62dadd65SYuri Pankov 207*62dadd65SYuri Pankov if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dp->dip, DDI_PROP_DONTPASS, 208*62dadd65SYuri Pankov name, &props, &nprops) == DDI_PROP_SUCCESS) { 209*62dadd65SYuri Pankov if (dp->instance < nprops) { 210*62dadd65SYuri Pankov ret = props[dp->instance]; 211*62dadd65SYuri Pankov } else { 212*62dadd65SYuri Pankov VMXNET3_WARN(dp, "property %s not available for this " 213*62dadd65SYuri Pankov "device\n", name); 214*62dadd65SYuri Pankov } 215*62dadd65SYuri Pankov ddi_prop_free(props); 216*62dadd65SYuri Pankov } 217*62dadd65SYuri Pankov 218*62dadd65SYuri Pankov if (ret < min || ret > max) { 219*62dadd65SYuri Pankov ASSERT(def >= min && def <= max); 220*62dadd65SYuri Pankov VMXNET3_WARN(dp, "property %s invalid (%d <= %d <= %d)\n", 221*62dadd65SYuri Pankov name, min, ret, max); 222*62dadd65SYuri Pankov ret = def; 223*62dadd65SYuri Pankov } 224*62dadd65SYuri Pankov 225*62dadd65SYuri Pankov VMXNET3_DEBUG(dp, 2, "getprop(%s) -> %d\n", name, ret); 226*62dadd65SYuri Pankov 227*62dadd65SYuri Pankov return (ret); 228*62dadd65SYuri Pankov } 229