xref: /onnv-gate/usr/src/uts/common/io/1394/adapters/hci1394_buf.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate /*
30*0Sstevel@tonic-gate  * hci1394_buf.c
31*0Sstevel@tonic-gate  *   These routines handle IO mapped memory.  They include routines to alloc and
32*0Sstevel@tonic-gate  *   free  IO mapped memory and a routine to get the adapters default dma
33*0Sstevel@tonic-gate  *   attributes. These routines are meant to be called from the base context.
34*0Sstevel@tonic-gate  *   They should not be called from an interrupt handler.
35*0Sstevel@tonic-gate  */
36*0Sstevel@tonic-gate 
37*0Sstevel@tonic-gate #include <sys/conf.h>
38*0Sstevel@tonic-gate #include <sys/ddi.h>
39*0Sstevel@tonic-gate #include <sys/modctl.h>
40*0Sstevel@tonic-gate #include <sys/stat.h>
41*0Sstevel@tonic-gate #include <sys/sunddi.h>
42*0Sstevel@tonic-gate #include <sys/kmem.h>
43*0Sstevel@tonic-gate 
44*0Sstevel@tonic-gate #include <sys/1394/h1394.h>
45*0Sstevel@tonic-gate #include <sys/1394/adapters/hci1394.h>
46*0Sstevel@tonic-gate 
47*0Sstevel@tonic-gate 
48*0Sstevel@tonic-gate /*
49*0Sstevel@tonic-gate  * hci1394_buffer_attr_get()
50*0Sstevel@tonic-gate  *    returns (in dma_attr) the default DMA attributes for this adapter.
51*0Sstevel@tonic-gate  */
52*0Sstevel@tonic-gate void
hci1394_buf_attr_get(ddi_dma_attr_t * dma_attr)53*0Sstevel@tonic-gate hci1394_buf_attr_get(ddi_dma_attr_t *dma_attr)
54*0Sstevel@tonic-gate {
55*0Sstevel@tonic-gate 	dma_attr->dma_attr_version = DMA_ATTR_V0;
56*0Sstevel@tonic-gate 	dma_attr->dma_attr_addr_lo = (uint64_t)0x00000000;
57*0Sstevel@tonic-gate 	dma_attr->dma_attr_addr_hi = (uint64_t)0xFFFFFFFF;
58*0Sstevel@tonic-gate 	dma_attr->dma_attr_count_max = (uint64_t)0xFFFFFFFF;
59*0Sstevel@tonic-gate 	dma_attr->dma_attr_align = 64;
60*0Sstevel@tonic-gate 	dma_attr->dma_attr_burstsizes = 0x3FF;
61*0Sstevel@tonic-gate 	dma_attr->dma_attr_minxfer = 1;
62*0Sstevel@tonic-gate 	dma_attr->dma_attr_maxxfer = (uint64_t)0xFFFFFFFF;
63*0Sstevel@tonic-gate 	dma_attr->dma_attr_seg = (uint64_t)0xFFFFFFFF;
64*0Sstevel@tonic-gate 	dma_attr->dma_attr_sgllen = 0x7FFFFFFF;
65*0Sstevel@tonic-gate 	dma_attr->dma_attr_granular = 4;
66*0Sstevel@tonic-gate 	dma_attr->dma_attr_flags = 0;
67*0Sstevel@tonic-gate 
68*0Sstevel@tonic-gate #if defined(__i386) || defined(__amd64)
69*0Sstevel@tonic-gate 	/* XXX - Not sure why x86 wants the dma_attr_seg to be 0x7FFF?? */
70*0Sstevel@tonic-gate 	dma_attr->dma_attr_seg = (uint64_t)0x7FFF;
71*0Sstevel@tonic-gate #endif
72*0Sstevel@tonic-gate }
73*0Sstevel@tonic-gate 
74*0Sstevel@tonic-gate 
75*0Sstevel@tonic-gate /*
76*0Sstevel@tonic-gate  * hci1394_buf_alloc()
77*0Sstevel@tonic-gate  *    Allocate an IO mapped buffer. drvinfo is passed in and contains generic
78*0Sstevel@tonic-gate  *    driver info, like dip, instance, buf_attr, etc.  Parms is passed in and
79*0Sstevel@tonic-gate  *    contains the input parameters for alloc, ow much memory to alloc, how many
80*0Sstevel@tonic-gate  *    cookies can we handle, and alignment requirements. info is returned with
81*0Sstevel@tonic-gate  *    all the info about the mapped buffer.  handle is returned. It should be
82*0Sstevel@tonic-gate  *    used when calling hci1394_buf_free().
83*0Sstevel@tonic-gate  */
84*0Sstevel@tonic-gate int
hci1394_buf_alloc(hci1394_drvinfo_t * drvinfo,hci1394_buf_parms_t * parms,hci1394_buf_info_t * info,hci1394_buf_handle_t * handle)85*0Sstevel@tonic-gate hci1394_buf_alloc(hci1394_drvinfo_t *drvinfo, hci1394_buf_parms_t *parms,
86*0Sstevel@tonic-gate     hci1394_buf_info_t *info, hci1394_buf_handle_t *handle)
87*0Sstevel@tonic-gate {
88*0Sstevel@tonic-gate 	ddi_dma_attr_t dma_attr;
89*0Sstevel@tonic-gate 	hci1394_buf_t *buf;
90*0Sstevel@tonic-gate 	int status;
91*0Sstevel@tonic-gate 
92*0Sstevel@tonic-gate 
93*0Sstevel@tonic-gate 	ASSERT(drvinfo != NULL);
94*0Sstevel@tonic-gate 	ASSERT(parms != NULL);
95*0Sstevel@tonic-gate 	ASSERT(info != NULL);
96*0Sstevel@tonic-gate 	ASSERT(handle != NULL);
97*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_buf_alloc_enter, HCI1394_TNF_HAL_STACK, "");
98*0Sstevel@tonic-gate 
99*0Sstevel@tonic-gate 	/* alloc the space to keep track of the buffer */
100*0Sstevel@tonic-gate 	buf = kmem_alloc(sizeof (hci1394_buf_t), KM_SLEEP);
101*0Sstevel@tonic-gate 
102*0Sstevel@tonic-gate 	/* setup the return parameter */
103*0Sstevel@tonic-gate 	*handle = buf;
104*0Sstevel@tonic-gate 
105*0Sstevel@tonic-gate 	/* save away pointer to general info */
106*0Sstevel@tonic-gate 	buf->bu_drvinfo = drvinfo;
107*0Sstevel@tonic-gate 
108*0Sstevel@tonic-gate 	/* Get the default DMA attributes and override sgllen and alignment */
109*0Sstevel@tonic-gate 
110*0Sstevel@tonic-gate 	_NOTE(SCHEME_PROTECTS_DATA("unique (on stack)", ddi_dma_attr_t))
111*0Sstevel@tonic-gate 	hci1394_buf_attr_get(&dma_attr);
112*0Sstevel@tonic-gate 	dma_attr.dma_attr_sgllen = parms->bp_max_cookies;
113*0Sstevel@tonic-gate 	dma_attr.dma_attr_align = parms->bp_alignment;
114*0Sstevel@tonic-gate 
115*0Sstevel@tonic-gate 	status = ddi_dma_alloc_handle(drvinfo->di_dip, &dma_attr,
116*0Sstevel@tonic-gate 	    DDI_DMA_SLEEP, NULL, &buf->bu_dma_handle);
117*0Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
118*0Sstevel@tonic-gate 		kmem_free(buf, sizeof (hci1394_buf_t));
119*0Sstevel@tonic-gate 		TNF_PROBE_0(hci1394_buf_alloc_dah_fail, HCI1394_TNF_HAL_ERROR,
120*0Sstevel@tonic-gate 		    "");
121*0Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(hci1394_buf_alloc_exit, HCI1394_TNF_HAL_STACK,
122*0Sstevel@tonic-gate 		    "");
123*0Sstevel@tonic-gate 		return (DDI_FAILURE);
124*0Sstevel@tonic-gate 	}
125*0Sstevel@tonic-gate 
126*0Sstevel@tonic-gate 	status = ddi_dma_mem_alloc(buf->bu_dma_handle, parms->bp_length,
127*0Sstevel@tonic-gate 	    &drvinfo->di_buf_attr, DDI_DMA_STREAMING, DDI_DMA_SLEEP,
128*0Sstevel@tonic-gate 	    NULL, &info->bi_kaddr, &info->bi_real_length, &buf->bu_handle);
129*0Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
130*0Sstevel@tonic-gate 		ddi_dma_free_handle(&buf->bu_dma_handle);
131*0Sstevel@tonic-gate 		kmem_free(buf, sizeof (hci1394_buf_t));
132*0Sstevel@tonic-gate 		TNF_PROBE_0(hci1394_buf_alloc_dam_fail, HCI1394_TNF_HAL_ERROR,
133*0Sstevel@tonic-gate 		    "");
134*0Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(hci1394_buf_alloc_exit, HCI1394_TNF_HAL_STACK,
135*0Sstevel@tonic-gate 		    "");
136*0Sstevel@tonic-gate 		return (DDI_FAILURE);
137*0Sstevel@tonic-gate 	}
138*0Sstevel@tonic-gate 
139*0Sstevel@tonic-gate 	status = ddi_dma_addr_bind_handle(buf->bu_dma_handle, NULL,
140*0Sstevel@tonic-gate 	    info->bi_kaddr, info->bi_real_length, DDI_DMA_RDWR |
141*0Sstevel@tonic-gate 	    DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL, &info->bi_cookie,
142*0Sstevel@tonic-gate 	    &info->bi_cookie_count);
143*0Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
144*0Sstevel@tonic-gate 		ddi_dma_mem_free(&buf->bu_handle);
145*0Sstevel@tonic-gate 		ddi_dma_free_handle(&buf->bu_dma_handle);
146*0Sstevel@tonic-gate 		kmem_free(buf, sizeof (hci1394_buf_t));
147*0Sstevel@tonic-gate 		TNF_PROBE_0(hci1394_buf_alloc_dbh_fail, HCI1394_TNF_HAL_ERROR,
148*0Sstevel@tonic-gate 		    "");
149*0Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(hci1394_buf_alloc_exit, HCI1394_TNF_HAL_STACK,
150*0Sstevel@tonic-gate 		    "");
151*0Sstevel@tonic-gate 		return (DDI_FAILURE);
152*0Sstevel@tonic-gate 	}
153*0Sstevel@tonic-gate 
154*0Sstevel@tonic-gate 	/* setup rest of buffer info returned to caller */
155*0Sstevel@tonic-gate 	info->bi_handle = buf->bu_handle;
156*0Sstevel@tonic-gate 	info->bi_dma_handle = buf->bu_dma_handle;
157*0Sstevel@tonic-gate 	info->bi_length = parms->bp_length;
158*0Sstevel@tonic-gate 
159*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_buf_alloc_exit, HCI1394_TNF_HAL_STACK, "");
160*0Sstevel@tonic-gate 
161*0Sstevel@tonic-gate 	return (DDI_SUCCESS);
162*0Sstevel@tonic-gate }
163*0Sstevel@tonic-gate 
164*0Sstevel@tonic-gate 
165*0Sstevel@tonic-gate /*
166*0Sstevel@tonic-gate  * hci1394_buf_free()
167*0Sstevel@tonic-gate  *    Free IO mapped buffer. Notice that a pointer to the handle is used for
168*0Sstevel@tonic-gate  *    the parameter.  free() will set your handle to NULL before returning.
169*0Sstevel@tonic-gate  */
170*0Sstevel@tonic-gate void
hci1394_buf_free(hci1394_buf_handle_t * handle)171*0Sstevel@tonic-gate hci1394_buf_free(hci1394_buf_handle_t *handle)
172*0Sstevel@tonic-gate {
173*0Sstevel@tonic-gate 	hci1394_buf_t *buf;
174*0Sstevel@tonic-gate 
175*0Sstevel@tonic-gate 	ASSERT(handle != NULL);
176*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_buf_free_enter, HCI1394_TNF_HAL_STACK, "");
177*0Sstevel@tonic-gate 
178*0Sstevel@tonic-gate 	buf = *handle;
179*0Sstevel@tonic-gate 	(void) ddi_dma_unbind_handle(buf->bu_dma_handle);
180*0Sstevel@tonic-gate 	ddi_dma_mem_free(&buf->bu_handle);
181*0Sstevel@tonic-gate 	ddi_dma_free_handle(&buf->bu_dma_handle);
182*0Sstevel@tonic-gate 
183*0Sstevel@tonic-gate 	/* free the space to keep track of the buffer */
184*0Sstevel@tonic-gate 	kmem_free(buf, sizeof (hci1394_buf_t));
185*0Sstevel@tonic-gate 
186*0Sstevel@tonic-gate 	/* set the handle to NULL to help catch bugs */
187*0Sstevel@tonic-gate 	*handle = NULL;
188*0Sstevel@tonic-gate 
189*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_buf_free_exit, HCI1394_TNF_HAL_STACK, "");
190*0Sstevel@tonic-gate }
191