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.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore/*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * SD card host support. This is the API that host drivers access.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore#include <sys/types.h>
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore#include <sys/conf.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.h>
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore#include <sys/sdcard/sda_impl.h>
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore/*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * Implementation.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorevoid
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_host_init_ops(struct dev_ops *devops)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_mod_init(devops);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore}
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorevoid
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_host_fini_ops(struct dev_ops *devops)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_mod_fini(devops);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore}
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_host_t *
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_host_alloc(dev_info_t *dip, int nslot, sda_ops_t *ops, ddi_dma_attr_t *dma)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore{
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_host_t *h;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore if (ops->so_version != SDA_OPS_VERSION) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore return (NULL);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore h = kmem_zalloc(sizeof (*h), KM_SLEEP);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore h->h_nslot = nslot;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore h->h_slots = kmem_zalloc(sizeof (sda_slot_t) * nslot, KM_SLEEP);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore h->h_dma = dma;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore h->h_dip = dip;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /* initialize each slot */
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore for (int i = 0; i < nslot; i++) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_t *slot = &h->h_slots[i];
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
1cb84fbf006414a451b65e461cfdb78736884f53Garrett D'Amore slot->s_hostp = h;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_slot_num = i;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore slot->s_ops = *ops;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_init(slot);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore return (h);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore}
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorevoid
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_host_free(sda_host_t *h)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore{
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore for (int i = 0; i < h->h_nslot; i++) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_fini(&h->h_slots[i]);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore kmem_free(h->h_slots, sizeof (sda_slot_t) * h->h_nslot);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore kmem_free(h, sizeof (*h));
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore}
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorevoid
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_host_set_private(sda_host_t *h, int num, void *private)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore{
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore h->h_slots[num].s_prv = private;
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore}
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoreint
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_host_attach(sda_host_t *h)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore{
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * Attach slots.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore for (int i = 0; i < h->h_nslot; i++) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_attach(&h->h_slots[i]);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * Initiate card detection.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_host_detect(h, i);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore return (DDI_SUCCESS);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore}
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorevoid
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_host_detach(sda_host_t *h)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore{
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore /*
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore * Detach slots.
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore */
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore for (int i = 0; i < h->h_nslot; i++) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_detach(&h->h_slots[i]);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore}
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amorevoid
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amoresda_host_suspend(sda_host_t *h)
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore{
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore for (int i = 0; i < h->h_nslot; i++) {
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore sda_slot_suspend(&h->h_slots[i]);
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore }
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore}
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amorevoid
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amoresda_host_resume(sda_host_t *h)
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore{
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore for (int i = 0; i < h->h_nslot; i++) {
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore sda_slot_resume(&h->h_slots[i]);
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore }
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore}
f2b90c3c415ff04d4adb3a54242822b41d74bfd9Garrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorevoid
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_host_transfer(sda_host_t *h, int num, sda_err_t errno)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore{
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_transfer(&h->h_slots[num], errno);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore}
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorevoid
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_host_detect(sda_host_t *h, int num)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore{
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_detect(&h->h_slots[num]);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore}
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorevoid
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_host_fault(sda_host_t *h, int num, sda_fault_t fail)
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore{
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_fault(&h->h_slots[num], fail);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore}
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amorevoid
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amoresda_host_log(sda_host_t *h, int snum, 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 if (h != NULL) {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_log(&h->h_slots[snum], fmt, ap);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore } else {
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore sda_slot_log(NULL, fmt, ap);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore }
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore va_end(ap);
4bb7efa72ed531c10f097919636e67724ec4c25aGarrett D'Amore}