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