4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore/*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * CDDL HEADER START
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore *
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * The contents of this file are subject to the terms of the
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * Common Development and Distribution License (the "License").
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * You may not use this file except in compliance with the License.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore *
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * or http://www.opensolaris.org/os/licensing.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * See the License for the specific language governing permissions
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * and limitations under the License.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore *
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * When distributing Covered Code, include this CDDL HEADER in each
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * If applicable, add the following below this CDDL HEADER, with the
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * fields enclosed by brackets "[]" replaced with your own identifying
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * information: Portions Copyright [yyyy] [name of copyright owner]
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore *
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * CDDL HEADER END
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore/*
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore/*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * SD card slot support.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore#include <sys/types.h>
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore#include <sys/cmn_err.h>
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore#include <sys/varargs.h>
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore#include <sys/ddi.h>
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore#include <sys/sunddi.h>
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore#include <sys/sdcard/sda_impl.h>
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore/*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * Prototypes.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorestatic void sda_slot_insert(void *);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorestatic sda_err_t sda_slot_check_response(sda_cmd_t *);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorestatic void sda_slot_handle_detect(sda_slot_t *);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorestatic void sda_slot_handle_transfer(sda_slot_t *, sda_err_t);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorestatic void sda_slot_handle_fault(sda_slot_t *, sda_fault_t);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorestatic void sda_slot_abort(sda_slot_t *, sda_err_t);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorestatic void sda_slot_halt(sda_slot_t *);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorestatic void sda_slot_thread(void *);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorestatic void sda_slot_vprintf(sda_slot_t *, int, const char *, va_list);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore/*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * Static Variables.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorestatic struct {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_fault_t fault;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore const char *msg;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore} sda_slot_faults[] = {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore { SDA_FAULT_TIMEOUT, "Data transfer timed out" },
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore { SDA_FAULT_ACMD12, "Auto CMD12 failure" },
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore { SDA_FAULT_CRC7, "CRC7 failure on CMD/DAT line" },
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore { SDA_FAULT_PROTO, "SD/MMC protocol signaling error" },
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore { SDA_FAULT_INIT, "Card initialization failure" },
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore { SDA_FAULT_HOST, "Internal host or slot failure" },
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore { SDA_FAULT_CURRENT, "Current overlimit detected" },
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore { SDA_FAULT_RESET, "Failed to reset slot" },
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore { SDA_FAULT_NONE, NULL }, /* sentinel, must be last! */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore};
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore/*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * Internal implementation.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore/*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * These allow for recursive entry. This is necessary to facilitate
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * simpler locking with things like the fault handler, where a caller
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * might already be "holding" the slot.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore *
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * This is modeled in part after ndi_devi_enter and ndi_devi_exit.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorevoid
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_slot_enter(sda_slot_t *slot)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore{
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore kt_did_t self = ddi_get_kt_did();
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore mutex_enter(&slot->s_lock);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if (slot->s_owner == self) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_circular++;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore } else {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore while ((slot->s_owner != 0) && (slot->s_owner != self)) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore cv_wait(&slot->s_cv, &slot->s_lock);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_owner = self;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_circular++;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore mutex_exit(&slot->s_lock);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore}
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorevoid
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_slot_exit(sda_slot_t *slot)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore{
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore ASSERT(sda_slot_owned(slot));
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore mutex_enter(&slot->s_lock);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_circular--;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if (slot->s_circular == 0) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_owner = 0;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore cv_broadcast(&slot->s_cv);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore mutex_exit(&slot->s_lock);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore}
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoreboolean_t
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_slot_owned(sda_slot_t *slot)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore{
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore return (slot->s_owner == ddi_get_kt_did());
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore}
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_err_t
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_slot_check_response(sda_cmd_t *cmdp)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore{
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore uint32_t errs;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore switch (cmdp->sc_rtype & 0xf) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore case R1:
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if ((errs = (cmdp->sc_response[0] & R1_ERRS)) != 0) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if (errs & (R1_WP_VIOLATION | R1_CSD_OVERWRITE)) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore return (SDA_EWPROTECT);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if (errs & (R1_ADDRESS_ERROR | R1_BLOCK_LEN_ERROR |
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore R1_OUT_OF_RANGE | R1_ERASE_PARAM)) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore return (SDA_EINVAL);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore return (SDA_EIO);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore break;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore case R5:
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if ((errs = (cmdp->sc_response[0] & R5_ERRS)) != 0) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore return (SDA_EIO);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore break;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore return (SDA_EOK);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore}
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorevoid
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_slot_halt(sda_slot_t *slot)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore{
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_enter(slot);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_ops.so_halt(slot->s_prv);
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore /* We need to wait 1 msec for power down. */
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore drv_usecwait(1000);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_exit(slot);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore}
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorevoid
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_slot_reset(sda_slot_t *slot)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore{
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_enter(slot);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if (slot->s_ops.so_reset(slot->s_prv) != 0) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_fault(slot, SDA_FAULT_RESET);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_exit(slot);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore}
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoreint
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_slot_power_on(sda_slot_t *slot)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore{
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore int rv;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore uint32_t ocr;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_enter(slot);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * Get the voltage supplied by the host. Note that we expect
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * hosts will include a range of 2.7-3.7 in their supported
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * voltage ranges. The spec does not allow for hosts that
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * cannot supply a voltage in this range, yet.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if ((rv = sda_getprop(slot, SDA_PROP_OCR, &ocr)) != 0) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_err(slot, "Failed to get host OCR (%d)", rv);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore goto done;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if ((ocr & OCR_HI_MASK) == 0) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_err(slot, "Host does not support standard voltages.");
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore rv = ENOTSUP;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore goto done;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * We prefer 3.3V, 3.0V, and failing that, just use the
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * maximum that the host supports. 3.3V is preferable,
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * because it is the typical common voltage that just about
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * everything supports. Otherwise we just pick the highest
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * supported voltage. This facilitates initial power up.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if (ocr & OCR_32_33V) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_cur_ocr = OCR_32_33V;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore } else if (ocr & OCR_29_30V) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_cur_ocr = OCR_29_30V;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore } else {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_cur_ocr = (1U << (ddi_fls(ocr) - 1));
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * Turn on the power.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if ((rv = sda_setprop(slot, SDA_PROP_OCR, slot->s_cur_ocr)) != 0) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_err(slot, "Failed to set OCR %x (%d)",
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_cur_ocr, rv);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore goto done;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_exit(slot);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * Wait 250 msec (per spec) for power ramp to complete.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore delay(drv_usectohz(250000));
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore return (0);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoredone:
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_exit(slot);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore return (rv);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore}
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorevoid
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_slot_power_off(sda_slot_t *slot)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore{
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_enter(slot);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore (void) sda_setprop(slot, SDA_PROP_OCR, 0);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /* XXX: FMA: on failure this should cause a fault to be generated */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /* spec requires voltage to stay low for at least 1 msec */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore drv_usecwait(1000);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_exit(slot);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore}
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorevoid
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_slot_insert(void *arg)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore{
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_t *slot = arg;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if (sda_init_card(slot) != SDA_EOK) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * Remove power from the slot. If a more severe fault
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * occurred, then a manual reset with cfgadm will be needed.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_err(slot, "Unable to initialize card!");
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_enter(slot);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_power_off(slot);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_abort(slot, SDA_ENODEV);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_exit(slot);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore } else if ((slot->s_flags & SLOTF_MEMORY) == 0) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore /*
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * SDIO: For SDIO, we can write the card's
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * MANFID tuple in CIS to the UUID. Until we
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * support SDIO, we just suppress creating
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * devinfo nodes.
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore sda_slot_err(slot, "Non-memory target not supported");
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore } else {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore sda_slot_enter(slot);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (sda_mem_parse_cid_csd(slot) != DDI_SUCCESS) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore sda_slot_err(slot,
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore "Unable to parse card identification");
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore } else {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore slot->s_warn = B_FALSE;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore slot->s_ready = B_TRUE;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore sda_slot_exit(slot);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore slot->s_stamp = ddi_get_time();
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore slot->s_intransit = 0;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_state_change(slot->s_bdh);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore}
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorevoid
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_slot_abort(sda_slot_t *slot, sda_err_t errno)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore{
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_cmd_t *cmdp;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore ASSERT(sda_slot_owned(slot));
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if ((cmdp = slot->s_xfrp) != NULL) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_xfrp = NULL;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore sda_cmd_notify(cmdp, 0, errno);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore list_insert_tail(&slot->s_abortlist, cmdp);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore while ((cmdp = list_head(&slot->s_cmdlist)) != NULL) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore list_remove(&slot->s_cmdlist, cmdp);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_cmd_notify(cmdp, 0, errno);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore list_insert_tail(&slot->s_abortlist, cmdp);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_wakeup(slot);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore}
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorevoid
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_slot_handle_transfer(sda_slot_t *slot, sda_err_t errno)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore{
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_cmd_t *cmdp;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_enter(slot);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if ((cmdp = slot->s_xfrp) != NULL) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_xfrp = NULL;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_xfrtmo = 0;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore (void) sda_setprop(slot, SDA_PROP_LED, 0);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_exit(slot);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_wakeup(slot);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_cmd_notify(cmdp, SDA_CMDF_DAT, errno);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore } else {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_exit(slot);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore}
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorevoid
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_slot_handle_fault(sda_slot_t *slot, sda_fault_t fault)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore{
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore const char *msg;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore int i;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_enter(slot);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if ((fault == SDA_FAULT_TIMEOUT) && (slot->s_init)) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * Timeouts during initialization are quite normal.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_exit(slot);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore return;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_failed = B_TRUE;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_abort(slot, SDA_EFAULT);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore msg = "Unknown fault (%d)";
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore for (i = 0; sda_slot_faults[i].msg != NULL; i++) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if (sda_slot_faults[i].fault == fault) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore msg = sda_slot_faults[i].msg;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore break;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * FMA would be a better choice here.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_err(slot, msg, fault);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * Shut down the slot. Interaction from userland via cfgadm
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * can revive it.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore *
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * FMA can help here.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_halt(slot);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_exit(slot);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore}
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorevoid
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_slot_handle_detect(sda_slot_t *slot)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore{
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore uint32_t inserted;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_enter(slot);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_stamp = ddi_get_time();
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_intransit = 1;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_flags = 0;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_rca = 0;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_ready = B_FALSE;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_getprop(slot, SDA_PROP_INSERTED, &inserted);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_inserted = (inserted != 0);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if (slot->s_inserted && !slot->s_failed) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * We need to initialize the card, so we only support
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * hipri commands for now.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_init = B_TRUE;
0a96f64e3185cf2fb9959e528ba7f454ca681484Garrett D'Amore sda_slot_exit(slot);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * Card insertion occurred. We have to run this on
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * another task, to avoid deadlock as the task may
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * need to dispatch commands.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
0a96f64e3185cf2fb9959e528ba7f454ca681484Garrett D'Amore
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore (void) ddi_taskq_dispatch(slot->s_hp_tq, sda_slot_insert, slot,
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore DDI_SLEEP);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore } else {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * Nuke in-flight commands.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_abort(slot, SDA_ENODEV);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * Restart the slot (incl. power cycle). This gets the
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * slot to a known good state.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_reset(slot);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_intransit = 0;
0a96f64e3185cf2fb9959e528ba7f454ca681484Garrett D'Amore sda_slot_exit(slot);
0a96f64e3185cf2fb9959e528ba7f454ca681484Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_state_change(slot->s_bdh);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_wakeup(slot);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore}
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorevoid
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_slot_transfer(sda_slot_t *slot, sda_err_t errno)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore{
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore mutex_enter(&slot->s_evlock);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_errno = errno;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_xfrdone = B_TRUE;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore cv_broadcast(&slot->s_evcv);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore mutex_exit(&slot->s_evlock);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore}
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorevoid
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_slot_detect(sda_slot_t *slot)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore{
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore mutex_enter(&slot->s_evlock);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_detect = B_TRUE;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore cv_broadcast(&slot->s_evcv);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore mutex_exit(&slot->s_evlock);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore}
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorevoid
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_slot_fault(sda_slot_t *slot, sda_fault_t fault)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore{
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore mutex_enter(&slot->s_evlock);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_fault = fault;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore cv_broadcast(&slot->s_evcv);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore mutex_exit(&slot->s_evlock);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore}
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorevoid
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_slot_wakeup(sda_slot_t *slot)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore{
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore mutex_enter(&slot->s_evlock);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_wake = B_TRUE;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore cv_broadcast(&slot->s_evcv);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore mutex_exit(&slot->s_evlock);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore}
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorevoid
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_slot_init(sda_slot_t *slot)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore{
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore mutex_init(&slot->s_lock, NULL, MUTEX_DRIVER, NULL);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore cv_init(&slot->s_cv, NULL, CV_DRIVER, NULL);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore mutex_init(&slot->s_evlock, NULL, MUTEX_DRIVER, NULL);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore cv_init(&slot->s_evcv, NULL, CV_DRIVER, NULL);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_cmd_list_init(&slot->s_cmdlist);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_cmd_list_init(&slot->s_abortlist);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore}
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorevoid
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_slot_fini(sda_slot_t *slot)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore{
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_cmd_list_fini(&slot->s_cmdlist);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_cmd_list_fini(&slot->s_abortlist);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore mutex_destroy(&slot->s_lock);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore mutex_destroy(&slot->s_evlock);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore cv_destroy(&slot->s_cv);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore cv_destroy(&slot->s_evcv);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore}
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic bd_ops_t sda_bd_ops = {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore BD_OPS_VERSION_0,
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore sda_mem_bd_driveinfo,
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore sda_mem_bd_mediainfo,
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore NULL, /* devid_init */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore NULL, /* sync_cache */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore sda_mem_bd_read,
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore sda_mem_bd_write,
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore};
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorevoid
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_slot_attach(sda_slot_t *slot)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore{
1cb84fbf006414a451b65e461cfdb78736884f53Garrett D'Amore sda_host_t *h = slot->s_hostp;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore char name[16];
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore uint32_t cap;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /*
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore * We have two taskqs. The first taskq is used for
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * card initialization.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore *
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore * The second is used for the main processing loop.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore *
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * The reason for a separate taskq is that initialization
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * needs to acquire locks which may be held by the slot
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * thread, or by device driver context... use of the separate
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * taskq breaks the deadlock. Additionally, the
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * initialization task may need to sleep quite a while during
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * card initialization.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore slot->s_bdh = bd_alloc_handle(slot, &sda_bd_ops, h->h_dma, KM_SLEEP);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ASSERT(slot->s_bdh);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_enter(slot);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore (void) snprintf(name, sizeof (name), "slot_%d_hp_tq",
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore slot->s_slot_num);
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore slot->s_hp_tq = ddi_taskq_create(h->h_dip, name, 1,
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore TASKQ_DEFAULTPRI, 0);
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore if (slot->s_hp_tq == NULL) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /* Generally, this failure should never occur */
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore sda_slot_err(slot, "Unable to create hotplug slot taskq");
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_exit(slot);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_free_handle(slot->s_bdh);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore slot->s_bdh = NULL;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore return;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /* create the main processing thread */
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore (void) snprintf(name, sizeof (name), "slot_%d_main_tq",
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore slot->s_slot_num);
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore slot->s_main_tq = ddi_taskq_create(h->h_dip, name, 1,
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore TASKQ_DEFAULTPRI, 0);
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore if (slot->s_main_tq == NULL) {
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore /* Generally, this failure should never occur */
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore sda_slot_err(slot, "Unable to create main slot taskq");
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore sda_slot_exit(slot);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_free_handle(slot->s_bdh);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore slot->s_bdh = NULL;
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore return;
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore }
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore (void) ddi_taskq_dispatch(slot->s_main_tq, sda_slot_thread, slot,
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore DDI_SLEEP);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * Determine slot capabilities.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_caps = 0;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if ((sda_getprop(slot, SDA_PROP_CAP_NOPIO, &cap) == 0) && (cap != 0)) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_caps |= SLOT_CAP_NOPIO;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if ((sda_getprop(slot, SDA_PROP_CAP_4BITS, &cap) == 0) && (cap != 0)) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_caps |= SLOT_CAP_4BITS;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if ((sda_getprop(slot, SDA_PROP_CAP_HISPEED, &cap) == 0) &&
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore (cap != 0)) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_caps |= SLOT_CAP_HISPEED;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /* make sure that the host is started up */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if (slot->s_ops.so_reset(slot->s_prv) != 0) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_fault(slot, SDA_FAULT_RESET);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_exit(slot);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore (void) bd_attach_handle(h->h_dip, slot->s_bdh);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore}
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorevoid
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_slot_detach(sda_slot_t *slot)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore{
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * Shut down the thread.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore (void) bd_detach_handle(slot->s_bdh);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore mutex_enter(&slot->s_evlock);
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore slot->s_detach = B_TRUE;
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore cv_broadcast(&slot->s_evcv);
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore mutex_exit(&slot->s_evlock);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /*
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore * Nuke the taskqs. We do this after stopping the background
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore * thread to avoid deadlock.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore if (slot->s_main_tq)
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore ddi_taskq_destroy(slot->s_main_tq);
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore if (slot->s_hp_tq)
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore ddi_taskq_destroy(slot->s_hp_tq);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_free_handle(slot->s_bdh);
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore}
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amorevoid
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amoresda_slot_suspend(sda_slot_t *slot)
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore{
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore mutex_enter(&slot->s_evlock);
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore slot->s_suspend = B_TRUE;
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore cv_broadcast(&slot->s_evcv);
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore mutex_exit(&slot->s_evlock);
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore ddi_taskq_wait(slot->s_main_tq);
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore}
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amorevoid
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amoresda_slot_resume(sda_slot_t *slot)
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore{
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore mutex_enter(&slot->s_evlock);
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore slot->s_suspend = B_FALSE;
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore /*
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore * A card change event may have occurred, and in any case we need
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore * to reinitialize the card.
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore */
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore slot->s_detect = B_TRUE;
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore mutex_exit(&slot->s_evlock);
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore /* Start up a new instance of the main processing task. */
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore (void) ddi_taskq_dispatch(slot->s_main_tq, sda_slot_thread, slot,
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore DDI_SLEEP);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore}
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorevoid
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_slot_thread(void *arg)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore{
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_t *slot = arg;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore for (;;) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_cmd_t *cmdp;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore boolean_t datline;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_err_t rv;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore mutex_enter(&slot->s_evlock);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * Process any abort list first.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if ((cmdp = list_head(&slot->s_abortlist)) != NULL) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore list_remove(&slot->s_abortlist, cmdp);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore mutex_exit(&slot->s_evlock);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * EOK used here, to avoid clobbering previous
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * error code.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_cmd_notify(cmdp, SDA_CMDF_BUSY | SDA_CMDF_DAT,
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore SDA_EOK);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore continue;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if (slot->s_detach) {
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore /* Parent is detaching the slot, bail out. */
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore break;
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore }
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore if ((slot->s_suspend) && (slot->s_xfrp == NULL)) {
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore /*
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore * Host wants to suspend, but don't do it if
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore * we have a transfer outstanding.
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore break;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if (slot->s_detect) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_detect = B_FALSE;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore mutex_exit(&slot->s_evlock);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_handle_detect(slot);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore continue;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if (slot->s_xfrdone) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_err_t errno;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore errno = slot->s_errno;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_errno = SDA_EOK;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_xfrdone = B_FALSE;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore mutex_exit(&slot->s_evlock);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_handle_transfer(slot, errno);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore continue;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if (slot->s_fault != SDA_FAULT_NONE) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_fault_t fault;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore fault = slot->s_fault;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_fault = SDA_FAULT_NONE;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore mutex_exit(&slot->s_evlock);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_handle_fault(slot, fault);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore continue;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if ((slot->s_xfrp != NULL) && (gethrtime() > slot->s_xfrtmo)) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * The device stalled processing the data request.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * At this point, we really have no choice but to
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * nuke the request, and flag a fault.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore mutex_exit(&slot->s_evlock);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_handle_transfer(slot, SDA_ETIME);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_fault(slot, SDA_FAULT_TIMEOUT);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore continue;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore /*
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore * If the slot has suspended, then we can't process
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore * any new commands yet.
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore */
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore if ((slot->s_suspend) || (!slot->s_wake)) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * We use a timed wait if we are waiting for a
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * data transfer to complete. Otherwise we
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * avoid the timed wait to avoid waking CPU
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * (power savings.)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if ((slot->s_xfrp != NULL) || (slot->s_reap)) {
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore /* Wait 3 sec (reap attempts). */
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (void) cv_reltimedwait(&slot->s_evcv,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni &slot->s_evlock, drv_usectohz(3000000),
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni TR_CLOCK_TICK);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore } else {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore (void) cv_wait(&slot->s_evcv, &slot->s_evlock);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore mutex_exit(&slot->s_evlock);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore continue;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_wake = B_FALSE;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore mutex_exit(&slot->s_evlock);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * We're awake now, so look for work to do. First
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * acquire access to the slot.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_enter(slot);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * If no more commands to process, go back to sleep.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if ((cmdp = list_head(&slot->s_cmdlist)) == NULL) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_exit(slot);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore continue;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore /*
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore * If the current command is not an initialization
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore * command, but we are initializing, go back to sleep.
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore * (This happens potentially during a card reset or
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore * suspend/resume cycle, where the card has not been
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore * removed, but a reset is in progress.)
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore */
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore if (slot->s_init && !(cmdp->sc_flags & SDA_CMDF_INIT)) {
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore sda_slot_exit(slot);
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore continue;
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore }
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore datline = ((cmdp->sc_flags & SDA_CMDF_DAT) != 0);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if (datline) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * If the current command has a data phase
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * while a transfer is in progress, then go
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * back to sleep.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if (slot->s_xfrp != NULL) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_exit(slot);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore continue;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * Note that APP_CMD doesn't have a data phase,
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * although the associated ACMD might.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if (cmdp->sc_index != CMD_APP_CMD) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_xfrp = cmdp;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * All commands should complete in
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * less than 5 seconds. The worst
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * case is actually somewhere around 4
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * seconds, but that is when the clock
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * is only 100 kHz.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_xfrtmo = gethrtime() +
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore 5000000000ULL;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore (void) sda_setprop(slot, SDA_PROP_LED, 1);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * We're committed to dispatching this command now,
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * so remove it from the list.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore list_remove(&slot->s_cmdlist, cmdp);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * There could be more commands after this one, so we
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * mark ourself so we stay awake for another cycle.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_wakeup(slot);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * Submit the command. Note that we are holding the
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * slot lock here, so it is critical that the caller
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * *not* call back up into the framework. The caller
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * must break context. But doing it this way prevents
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * a critical race on card removal.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore *
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * Note that we don't resubmit memory to the device if
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * it isn't flagged as ready (e.g. if the wrong device
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * was inserted!)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore if ((!slot->s_ready) && (cmdp->sc_flags & SDA_CMDF_MEM)) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore rv = SDA_ENODEV;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore } else {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore rv = slot->s_ops.so_cmd(slot->s_prv, cmdp);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if (rv == SDA_EOK)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore rv = sda_slot_check_response(cmdp);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if (rv == SDA_EOK) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * If APP_CMD completed properly, then
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * resubmit with ACMD index. Note wake was
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * already set above.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if (cmdp->sc_index == CMD_APP_CMD) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if ((cmdp->sc_response[0] & R1_APP_CMD) == 0) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_log(slot, "APP_CMD not set!");
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_cmd_resubmit_acmd(slot, cmdp);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_exit(slot);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore continue;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore } else if (datline) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * If an error occurred and we were expecting
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * a transfer phase, we have to clean up.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore (void) sda_setprop(slot, SDA_PROP_LED, 0);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_xfrp = NULL;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_xfrtmo = 0;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * And notify any waiter.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_exit(slot);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_cmd_notify(cmdp, SDA_CMDF_BUSY | SDA_CMDF_DAT, rv);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore continue;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * Wake any waiter.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_exit(slot);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_cmd_notify(cmdp, SDA_CMDF_BUSY, rv);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore mutex_exit(&slot->s_evlock);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore}
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorevoid
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_slot_vprintf(sda_slot_t *s, int level, const char *fmt, va_list ap)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore{
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore char msgbuf[256];
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore const char *pfx, *sfx;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if (level == CE_CONT) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore pfx = "!";
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sfx = "\n";
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore } else {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore pfx = sfx = "";
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if (s != NULL) {
1cb84fbf006414a451b65e461cfdb78736884f53Garrett D'Amore dev_info_t *dip = s->s_hostp->h_dip;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore (void) snprintf(msgbuf, sizeof (msgbuf),
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore "%s%s%d: slot %d: %s%s", pfx,
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore ddi_driver_name(dip), ddi_get_instance(dip),
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore s->s_slot_num, fmt, sfx);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore } else {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore (void) snprintf(msgbuf, sizeof (msgbuf), "%ssda: %s%s",
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore pfx, fmt, sfx);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore vcmn_err(level, msgbuf, ap);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore}
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorevoid
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_slot_err(sda_slot_t *s, const char *fmt, ...)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore{
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore va_list ap;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore va_start(ap, fmt);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_vprintf(s, CE_WARN, fmt, ap);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore va_end(ap);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore}
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorevoid
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_slot_log(sda_slot_t *s, const char *fmt, ...)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore{
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore va_list ap;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore va_start(ap, fmt);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_vprintf(s, CE_CONT, fmt, ap);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore va_end(ap);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore}