1 /* 2 * CDDL HEADER START 3 * 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. 7 * 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. 12 * 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] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 /* 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. 29 */ 30 31 #include <sys/types.h> 32 #include <sys/kmem.h> 33 #include <sys/sysmacros.h> 34 #include <sys/ddi.h> 35 #include <sys/sunddi.h> 36 #include <sys/sunndi.h> 37 #include <sys/sdcard/sda_impl.h> 38 39 /* 40 * Types and Structures. 41 */ 42 43 typedef struct sda_cmd_impl { 44 struct sda_cmd c_public; 45 46 /* 47 * Implementation private stuff. 48 */ 49 sda_slot_t *c_slot; 50 kmutex_t c_lock; 51 kcondvar_t c_cv; 52 list_node_t c_list; 53 sda_err_t c_errno; 54 55 sda_index_t c_acmd; /* saved acmd */ 56 sda_rtype_t c_artype; /* saved rtype */ 57 uint32_t c_aarg; /* saved argument */ 58 59 void (*c_done)(struct sda_cmd *); 60 void *c_private; 61 } sda_cmd_impl_t; 62 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 75 76 /* 77 * Local Prototypes. 78 */ 79 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 *); 83 84 /* 85 * Static Variables. 86 */ 87 88 static kmem_cache_t *sda_cmd_cache; 89 90 /* 91 * Macros. 92 */ 93 94 #define CIP(cmdp) ((sda_cmd_impl_t *)(void *)cmdp) 95 96 /* 97 * Implementation. 98 */ 99 100 void 101 sda_cmd_init(void) 102 { 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); 106 } 107 108 void 109 sda_cmd_fini(void) 110 { 111 kmem_cache_destroy(sda_cmd_cache); 112 } 113 114 void 115 sda_cmd_list_init(list_t *list) 116 { 117 list_create(list, sizeof (struct sda_cmd_impl), 118 offsetof(struct sda_cmd_impl, c_list)); 119 } 120 121 void 122 sda_cmd_list_fini(list_t *list) 123 { 124 list_destroy(list); 125 } 126 127 /*ARGSUSED1*/ 128 int 129 sda_cmd_ctor(void *cbuf, void *arg, int kmflags) 130 { 131 sda_cmd_impl_t *c = cbuf; 132 133 mutex_init(&c->c_lock, NULL, MUTEX_DRIVER, NULL); 134 cv_init(&c->c_cv, NULL, CV_DRIVER, NULL); 135 return (0); 136 } 137 138 /*ARGSUSED1*/ 139 void 140 sda_cmd_dtor(void *cbuf, void *arg) 141 { 142 sda_cmd_impl_t *c = cbuf; 143 144 cv_destroy(&c->c_cv); 145 mutex_destroy(&c->c_lock); 146 } 147 148 void * 149 sda_cmd_data(sda_cmd_t *cmdp) 150 { 151 return (CIP(cmdp)->c_private); 152 } 153 154 sda_err_t 155 sda_cmd_errno(sda_cmd_t *cmdp) 156 { 157 return (CIP(cmdp)->c_errno); 158 } 159 160 void 161 sda_cmd_notify(sda_cmd_t *cmdp, uint16_t flags, sda_err_t errno) 162 { 163 sda_cmd_impl_t *c = CIP(cmdp); 164 165 /* 166 * Now we need to make sure that we wake anyone waiting on this 167 * command to complete, if it is complete. 168 */ 169 mutex_enter(&c->c_lock); 170 c->c_flags &= ~(flags); 171 /* 172 * Don't overwrite an earlier error. 173 */ 174 if (c->c_errno == SDA_EOK) { 175 c->c_errno = errno; 176 } 177 if ((c->c_flags & (SDA_CMDF_BUSY | SDA_CMDF_DAT)) == 0) { 178 179 if (c->c_done != NULL) { 180 mutex_exit(&c->c_lock); 181 c->c_done(cmdp); 182 } else { 183 cv_broadcast(&c->c_cv); 184 mutex_exit(&c->c_lock); 185 } 186 } else { 187 mutex_exit(&c->c_lock); 188 } 189 } 190 191 void 192 sda_cmd_wait(sda_cmd_t *cmdp) 193 { 194 sda_cmd_impl_t *c = CIP(cmdp); 195 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); 200 } 201 202 void 203 sda_cmd_submit(sda_slot_t *slot, sda_cmd_t *cmdp, void (*done)(sda_cmd_t *)) 204 { 205 sda_cmd_impl_t *c = CIP(cmdp); 206 sda_err_t errno = 0; 207 208 mutex_enter(&c->c_lock); 209 c->c_done = done; 210 c->c_flags |= SDA_CMDF_BUSY; 211 mutex_exit(&c->c_lock); 212 213 sda_slot_enter(slot); 214 215 /* checks for cases where the slot can't accept the command */ 216 if (slot->s_failed) { 217 errno = SDA_EFAULT; 218 } 219 if (!slot->s_inserted) { 220 errno = SDA_ENODEV; 221 } 222 if (errno != SDA_EOK) { 223 /* 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. 228 * 229 * NB: using 0 for flags ensures that we don't execute 230 * the notification callback yet, we're just stashing 231 * the errno. 232 */ 233 sda_cmd_notify(cmdp, 0, errno); 234 list_insert_tail(&slot->s_abortlist, cmdp); 235 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); 239 } else { 240 list_insert_tail(&slot->s_cmdlist, c); 241 } 242 sda_slot_exit(slot); 243 244 sda_slot_wakeup(slot); 245 } 246 247 void 248 sda_cmd_resubmit_acmd(sda_slot_t *slot, sda_cmd_t *cmdp) 249 { 250 sda_cmd_impl_t *c = CIP(cmdp); 251 252 ASSERT(sda_slot_owned(slot)); 253 254 c->c_index = c->c_acmd; 255 c->c_argument = c->c_aarg; 256 c->c_rtype = c->c_artype; 257 c->c_acmd = 0; 258 259 list_insert_head(&slot->s_cmdlist, c); 260 } 261 262 sda_cmd_t * 263 sda_cmd_alloc(sda_slot_t *slot, sda_index_t index, uint32_t argument, 264 sda_rtype_t rtype, void *data, int kmflag) 265 { 266 sda_cmd_impl_t *c; 267 268 c = kmem_cache_alloc(sda_cmd_cache, kmflag); 269 if (c == NULL) { 270 return (NULL); 271 } 272 c->c_index = index; 273 c->c_rtype = rtype; 274 c->c_argument = argument; 275 c->c_resid = 0; 276 c->c_nblks = 0; 277 c->c_blksz = 0; 278 279 c->c_kvaddr = 0; 280 c->c_dmah = 0; 281 c->c_ndmac = 0; 282 c->c_dmah = NULL; 283 bzero(&c->c_dmac, sizeof (c->c_dmac)); 284 c->c_flags = 0; 285 286 c->c_slot = slot; 287 c->c_errno = SDA_EOK; 288 c->c_done = NULL; 289 c->c_private = data; 290 c->c_acmd = 0; 291 292 return (&(c->c_public)); 293 } 294 295 sda_cmd_t * 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) 298 { 299 sda_cmd_impl_t *c; 300 301 c = kmem_cache_alloc(sda_cmd_cache, kmflag); 302 if (c == NULL) { 303 return (NULL); 304 } 305 c->c_index = CMD_APP_CMD; 306 c->c_argument = index == ACMD_SD_SEND_OCR ? 0 : slot->s_rca << 16; 307 c->c_rtype = R1; 308 c->c_acmd = index; 309 c->c_artype = rtype; 310 c->c_aarg = argument; 311 c->c_resid = 0; 312 c->c_nblks = 0; 313 c->c_blksz = 0; 314 315 c->c_kvaddr = 0; 316 c->c_ndmac = 0; 317 c->c_dmah = NULL; 318 bzero(&c->c_dmac, sizeof (c->c_dmac)); 319 c->c_flags = 0; 320 321 c->c_slot = slot; 322 c->c_errno = SDA_EOK; 323 c->c_done = NULL; 324 c->c_private = data; 325 326 return (&(c->c_public)); 327 } 328 329 void 330 sda_cmd_free(sda_cmd_t *cmdp) 331 { 332 kmem_cache_free(sda_cmd_cache, cmdp); 333 } 334 335 sda_err_t 336 sda_cmd_exec(sda_slot_t *slot, sda_cmd_t *cmdp, uint32_t *resp) 337 { 338 int errno; 339 340 if ((cmdp->sc_rtype & Rb) || (cmdp->sc_nblks != 0)) { 341 cmdp->sc_flags |= SDA_CMDF_DAT; 342 } 343 sda_cmd_submit(slot, cmdp, NULL); 344 345 sda_cmd_wait(cmdp); 346 347 if (resp != NULL) { 348 switch (cmdp->sc_rtype) { 349 case R0: 350 break; 351 case R2: 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]; 356 break; 357 default: 358 resp[0] = cmdp->sc_response[0]; 359 break; 360 } 361 } 362 363 errno = CIP(cmdp)->c_errno; 364 365 return (errno); 366 } 367