4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
26 * SD card common framework. This module provides most of the common
27 * functionality so that SecureDigital host adapters and client devices
28 * (such as the sdcard driver) can share common code.
31 #include <sys/types.h>
33 #include <sys/sysmacros.h>
35 #include <sys/sunddi.h>
36 #include <sys/sunndi.h>
37 #include <sys/sdcard/sda_impl.h>
40 * Types and Structures.
43 typedef struct sda_cmd_impl
{
44 struct sda_cmd c_public
;
47 * Implementation private stuff.
55 sda_index_t c_acmd
; /* saved acmd */
56 sda_rtype_t c_artype
; /* saved rtype */
57 uint32_t c_aarg
; /* saved argument */
59 void (*c_done
)(struct sda_cmd
*);
63 #define c_index c_public.sc_index
64 #define c_argument c_public.sc_argument
65 #define c_rtype c_public.sc_rtype
66 #define c_response c_public.sc_response
67 #define c_blksz c_public.sc_blksz
68 #define c_nblks c_public.sc_nblks
69 #define c_resid c_public.sc_resid
70 #define c_flags c_public.sc_flags
71 #define c_ndmac c_public.sc_ndmac
72 #define c_dmah c_public.sc_dmah
73 #define c_dmac c_public.sc_dmac
74 #define c_kvaddr c_public.sc_kvaddr
80 static void sda_cmd_wait(sda_cmd_t
*);
81 static int sda_cmd_ctor(void *, void *, int);
82 static void sda_cmd_dtor(void *, void *);
88 static kmem_cache_t
*sda_cmd_cache
;
94 #define CIP(cmdp) ((sda_cmd_impl_t *)(void *)cmdp)
103 sda_cmd_cache
= kmem_cache_create("sda_cmd_cache",
104 sizeof (struct sda_cmd_impl
), 0, sda_cmd_ctor
, sda_cmd_dtor
,
105 NULL
, NULL
, NULL
, 0);
111 kmem_cache_destroy(sda_cmd_cache
);
115 sda_cmd_list_init(list_t
*list
)
117 list_create(list
, sizeof (struct sda_cmd_impl
),
118 offsetof(struct sda_cmd_impl
, c_list
));
122 sda_cmd_list_fini(list_t
*list
)
129 sda_cmd_ctor(void *cbuf
, void *arg
, int kmflags
)
131 sda_cmd_impl_t
*c
= cbuf
;
133 mutex_init(&c
->c_lock
, NULL
, MUTEX_DRIVER
, NULL
);
134 cv_init(&c
->c_cv
, NULL
, CV_DRIVER
, NULL
);
140 sda_cmd_dtor(void *cbuf
, void *arg
)
142 sda_cmd_impl_t
*c
= cbuf
;
144 cv_destroy(&c
->c_cv
);
145 mutex_destroy(&c
->c_lock
);
149 sda_cmd_data(sda_cmd_t
*cmdp
)
151 return (CIP(cmdp
)->c_private
);
155 sda_cmd_errno(sda_cmd_t
*cmdp
)
157 return (CIP(cmdp
)->c_errno
);
161 sda_cmd_notify(sda_cmd_t
*cmdp
, uint16_t flags
, sda_err_t errno
)
163 sda_cmd_impl_t
*c
= CIP(cmdp
);
166 * Now we need to make sure that we wake anyone waiting on this
167 * command to complete, if it is complete.
169 mutex_enter(&c
->c_lock
);
170 c
->c_flags
&= ~(flags
);
172 * Don't overwrite an earlier error.
174 if (c
->c_errno
== SDA_EOK
) {
177 if ((c
->c_flags
& (SDA_CMDF_BUSY
| SDA_CMDF_DAT
)) == 0) {
179 if (c
->c_done
!= NULL
) {
180 mutex_exit(&c
->c_lock
);
183 cv_broadcast(&c
->c_cv
);
184 mutex_exit(&c
->c_lock
);
187 mutex_exit(&c
->c_lock
);
192 sda_cmd_wait(sda_cmd_t
*cmdp
)
194 sda_cmd_impl_t
*c
= CIP(cmdp
);
196 mutex_enter(&c
->c_lock
);
197 while ((c
->c_flags
& (SDA_CMDF_BUSY
| SDA_CMDF_DAT
)) != 0)
198 cv_wait(&c
->c_cv
, &c
->c_lock
);
199 mutex_exit(&c
->c_lock
);
203 sda_cmd_submit(sda_slot_t
*slot
, sda_cmd_t
*cmdp
, void (*done
)(sda_cmd_t
*))
205 sda_cmd_impl_t
*c
= CIP(cmdp
);
208 mutex_enter(&c
->c_lock
);
210 c
->c_flags
|= SDA_CMDF_BUSY
;
211 mutex_exit(&c
->c_lock
);
213 sda_slot_enter(slot
);
215 /* checks for cases where the slot can't accept the command */
216 if (slot
->s_failed
) {
219 if (!slot
->s_inserted
) {
222 if (errno
!= SDA_EOK
) {
224 * We have to return failure conditions asynchronously.
225 * What we do in this case is mark the command failed,
226 * and move it to the abortlist so that the slot thread
227 * will execute the failure notification asynchronously.
229 * NB: using 0 for flags ensures that we don't execute
230 * the notification callback yet, we're just stashing
233 sda_cmd_notify(cmdp
, 0, errno
);
234 list_insert_tail(&slot
->s_abortlist
, cmdp
);
236 } else if (c
->c_flags
& SDA_CMDF_INIT
) {
237 /* Initialization commands go to the head of the class */
238 list_insert_head(&slot
->s_cmdlist
, c
);
240 list_insert_tail(&slot
->s_cmdlist
, c
);
244 sda_slot_wakeup(slot
);
248 sda_cmd_resubmit_acmd(sda_slot_t
*slot
, sda_cmd_t
*cmdp
)
250 sda_cmd_impl_t
*c
= CIP(cmdp
);
252 ASSERT(sda_slot_owned(slot
));
254 c
->c_index
= c
->c_acmd
;
255 c
->c_argument
= c
->c_aarg
;
256 c
->c_rtype
= c
->c_artype
;
259 list_insert_head(&slot
->s_cmdlist
, c
);
263 sda_cmd_alloc(sda_slot_t
*slot
, sda_index_t index
, uint32_t argument
,
264 sda_rtype_t rtype
, void *data
, int kmflag
)
268 c
= kmem_cache_alloc(sda_cmd_cache
, kmflag
);
274 c
->c_argument
= argument
;
283 bzero(&c
->c_dmac
, sizeof (c
->c_dmac
));
287 c
->c_errno
= SDA_EOK
;
292 return (&(c
->c_public
));
296 sda_cmd_alloc_acmd(sda_slot_t
*slot
, sda_index_t index
, uint32_t argument
,
297 sda_rtype_t rtype
, void *data
, int kmflag
)
301 c
= kmem_cache_alloc(sda_cmd_cache
, kmflag
);
305 c
->c_index
= CMD_APP_CMD
;
306 c
->c_argument
= index
== ACMD_SD_SEND_OCR
? 0 : slot
->s_rca
<< 16;
310 c
->c_aarg
= argument
;
318 bzero(&c
->c_dmac
, sizeof (c
->c_dmac
));
322 c
->c_errno
= SDA_EOK
;
326 return (&(c
->c_public
));
330 sda_cmd_free(sda_cmd_t
*cmdp
)
332 kmem_cache_free(sda_cmd_cache
, cmdp
);
336 sda_cmd_exec(sda_slot_t
*slot
, sda_cmd_t
*cmdp
, uint32_t *resp
)
340 if ((cmdp
->sc_rtype
& Rb
) || (cmdp
->sc_nblks
!= 0)) {
341 cmdp
->sc_flags
|= SDA_CMDF_DAT
;
343 sda_cmd_submit(slot
, cmdp
, NULL
);
348 switch (cmdp
->sc_rtype
) {
352 resp
[0] = cmdp
->sc_response
[0];
353 resp
[1] = cmdp
->sc_response
[1];
354 resp
[2] = cmdp
->sc_response
[2];
355 resp
[3] = cmdp
->sc_response
[3];
358 resp
[0] = cmdp
->sc_response
[0];
363 errno
= CIP(cmdp
)->c_errno
;