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