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