sda_cmd.c revision 4bb7efa72ed531c10f097919636e67724ec4c25a
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe/*
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * CDDL HEADER START
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe *
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * The contents of this file are subject to the terms of the
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * Common Development and Distribution License (the "License").
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * You may not use this file except in compliance with the License.
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe *
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * or http://www.opensolaris.org/os/licensing.
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * See the License for the specific language governing permissions
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * and limitations under the License.
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe *
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * When distributing Covered Code, include this CDDL HEADER in each
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * If applicable, add the following below this CDDL HEADER, with the
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * fields enclosed by brackets "[]" replaced with your own identifying
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * information: Portions Copyright [yyyy] [name of copyright owner]
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe *
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * CDDL HEADER END
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe/*
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * Use is subject to license terms.
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe/*
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * SD card common framework. This module provides most of the common
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * functionality so that SecureDigital host adapters and client devices
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * (such as the sdcard driver) can share common code.
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe *
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * NB that this file contains a fair bit of non-DDI compliant code.
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * But writing a nexus driver would be impossible to do with only DDI
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * compliant interfaces.
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#include <sys/types.h>
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#include <sys/kmem.h>
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#include <sys/sysmacros.h>
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#include <sys/ddi.h>
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#include <sys/sunddi.h>
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#include <sys/sunndi.h>
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#include <sys/sdcard/sda_impl.h>
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe/*
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * Types and Structures.
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowetypedef struct sda_cmd_impl {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe struct sda_cmd c_public;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /*
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * Implementation private stuff.
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe sda_slot_t *c_slot;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe kmutex_t c_lock;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe kcondvar_t c_cv;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe list_node_t c_list;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe sda_err_t c_errno;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe sda_index_t c_acmd; /* saved acmd */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe sda_rtype_t c_artype; /* saved rtype */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe uint32_t c_aarg; /* saved argument */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe void (*c_done)(struct sda_cmd *);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe void *c_private;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe} sda_cmd_impl_t;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#define c_index c_public.sc_index
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#define c_argument c_public.sc_argument
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#define c_rtype c_public.sc_rtype
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#define c_response c_public.sc_response
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#define c_blksz c_public.sc_blksz
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#define c_nblks c_public.sc_nblks
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#define c_resid c_public.sc_resid
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#define c_flags c_public.sc_flags
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#define c_ndmac c_public.sc_ndmac
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#define c_dmacs c_public.sc_dmacs
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#define c_kvaddr c_public.sc_kvaddr
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe/*
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * Local Prototypes.
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowestatic void sda_cmd_wait(sda_cmd_t *);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowestatic int sda_cmd_ctor(void *, void *, int);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowestatic void sda_cmd_dtor(void *, void *);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe/*
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * Static Variables.
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowestatic kmem_cache_t *sda_cmd_cache;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe/*
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * Macros.
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe#define CIP(cmdp) ((sda_cmd_impl_t *)(void *)cmdp)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe/*
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * Implementation.
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowevoid
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowesda_cmd_init(void)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe{
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe sda_cmd_cache = kmem_cache_create("sda_cmd_cache",
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe sizeof (struct sda_cmd_impl), 0, sda_cmd_ctor, sda_cmd_dtor,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe NULL, NULL, NULL, 0);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe}
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowevoid
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowesda_cmd_fini(void)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe{
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe kmem_cache_destroy(sda_cmd_cache);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe}
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowevoid
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowesda_cmd_list_init(list_t *list)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe{
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe list_create(list, sizeof (struct sda_cmd_impl),
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe offsetof(struct sda_cmd_impl, c_list));
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe}
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowevoid
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowesda_cmd_list_fini(list_t *list)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe{
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe list_destroy(list);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe}
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe/*ARGSUSED1*/
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Loweint
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowesda_cmd_ctor(void *cbuf, void *arg, int kmflags)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe{
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe sda_cmd_impl_t *c = cbuf;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe mutex_init(&c->c_lock, NULL, MUTEX_DRIVER, NULL);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe cv_init(&c->c_cv, NULL, CV_DRIVER, NULL);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe return (0);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe}
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe/*ARGSUSED1*/
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowevoid
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowesda_cmd_dtor(void *cbuf, void *arg)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe{
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe sda_cmd_impl_t *c = cbuf;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe cv_destroy(&c->c_cv);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe mutex_destroy(&c->c_lock);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe}
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowevoid *
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowesda_cmd_data(sda_cmd_t *cmdp)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe{
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe return (CIP(cmdp)->c_private);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe}
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowesda_err_t
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowesda_cmd_errno(sda_cmd_t *cmdp)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe{
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe return (CIP(cmdp)->c_errno);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe}
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowevoid
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowesda_cmd_notify(sda_cmd_t *cmdp, uint16_t flags, sda_err_t errno)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe{
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe sda_cmd_impl_t *c = CIP(cmdp);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /*
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * Now we need to make sure that we wake anyone waiting on this
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * command to complete, if it is complete.
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe mutex_enter(&c->c_lock);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_flags &= ~(flags);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /*
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe * Don't overwrite an earlier error.
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (c->c_errno == SDA_EOK) {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_errno = errno;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if ((c->c_flags & (SDA_CMDF_BUSY | SDA_CMDF_DAT)) == 0) {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (c->c_done != NULL) {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe mutex_exit(&c->c_lock);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_done(cmdp);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe } else {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe cv_broadcast(&c->c_cv);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe mutex_exit(&c->c_lock);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe } else {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe mutex_exit(&c->c_lock);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe}
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowevoid
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowesda_cmd_wait(sda_cmd_t *cmdp)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe{
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe sda_cmd_impl_t *c = CIP(cmdp);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe mutex_enter(&c->c_lock);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe while ((c->c_flags & (SDA_CMDF_BUSY | SDA_CMDF_DAT)) != 0)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe cv_wait(&c->c_cv, &c->c_lock);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe mutex_exit(&c->c_lock);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe}
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowevoid
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowesda_cmd_submit(sda_slot_t *slot, sda_cmd_t *cmdp, void (*done)(sda_cmd_t *))
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe{
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe sda_cmd_impl_t *c = CIP(cmdp);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe sda_err_t errno = 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe mutex_enter(&c->c_lock);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_done = done;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_flags |= SDA_CMDF_BUSY;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe mutex_exit(&c->c_lock);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe sda_slot_enter(slot);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* checks for cases where the slot can't accept the command */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (slot->s_failed) {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe errno = SDA_EFAULT;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (!slot->s_inserted) {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe errno = SDA_ENODEV;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (errno != SDA_EOK) {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe sda_slot_exit(slot);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe /* fail it synchronously */
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe sda_cmd_notify(cmdp, SDA_CMDF_DAT | SDA_CMDF_BUSY, errno);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe return;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe list_insert_tail(&slot->s_cmdlist, c);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe sda_slot_exit(slot);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe sda_slot_wakeup(slot);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe}
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowevoid
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowesda_cmd_resubmit_acmd(sda_slot_t *slot, sda_cmd_t *cmdp)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe{
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe sda_cmd_impl_t *c = CIP(cmdp);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe ASSERT(sda_slot_owned(slot));
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_index = c->c_acmd;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_argument = c->c_aarg;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_rtype = c->c_artype;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_acmd = 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe list_insert_head(&slot->s_cmdlist, c);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe}
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowesda_cmd_t *
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowesda_cmd_alloc(sda_slot_t *slot, sda_index_t index, uint32_t argument,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe sda_rtype_t rtype, void *data, int kmflag)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe{
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe sda_cmd_impl_t *c;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c = kmem_cache_alloc(sda_cmd_cache, kmflag);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (c == NULL) {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe return (NULL);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_index = index;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_rtype = rtype;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_argument = argument;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_resid = 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_nblks = 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_blksz = 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_kvaddr = 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_ndmac = 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_dmacs = NULL;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_flags = 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_slot = slot;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_errno = SDA_EOK;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_done = NULL;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_private = data;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_acmd = 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe return (&(c->c_public));
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe}
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowesda_cmd_t *
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowesda_cmd_alloc_acmd(sda_slot_t *slot, sda_index_t index, uint32_t argument,
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe sda_rtype_t rtype, void *data, int kmflag)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe{
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe sda_cmd_impl_t *c;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c = kmem_cache_alloc(sda_cmd_cache, kmflag);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (c == NULL) {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe return (NULL);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_index = CMD_APP_CMD;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_argument = index == ACMD_SD_SEND_OCR ? 0 : slot->s_rca << 16;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_rtype = R1;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_acmd = index;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_artype = rtype;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_aarg = argument;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_resid = 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_nblks = 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_blksz = 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_kvaddr = 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_ndmac = 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_dmacs = NULL;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_flags = 0;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_slot = slot;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_errno = SDA_EOK;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_done = NULL;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe c->c_private = data;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe return (&(c->c_public));
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe}
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowevoid
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowesda_cmd_free(sda_cmd_t *cmdp)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe{
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe kmem_cache_free(sda_cmd_cache, cmdp);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe}
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowesda_err_t
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowesda_cmd_exec(sda_slot_t *slot, sda_cmd_t *cmdp, uint32_t *resp)
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe{
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe int errno;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if ((cmdp->sc_rtype & Rb) || (cmdp->sc_nblks != 0)) {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe cmdp->sc_flags |= SDA_CMDF_DAT;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe sda_cmd_submit(slot, cmdp, NULL);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe sda_cmd_wait(cmdp);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe if (resp != NULL) {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe switch (cmdp->sc_rtype) {
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe case R0:
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe break;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe case R2:
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe resp[0] = cmdp->sc_response[0];
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe resp[1] = cmdp->sc_response[1];
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe resp[2] = cmdp->sc_response[2];
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe resp[3] = cmdp->sc_response[3];
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe break;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe default:
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe resp[0] = cmdp->sc_response[0];
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe break;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe }
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe errno = CIP(cmdp)->c_errno;
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe return (errno);
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe}
10d63b7db37a83b39c7f511cf9426c9d03ea0760Richard Lowe