17302Sgdamore@opensolaris.org /*
27302Sgdamore@opensolaris.org * CDDL HEADER START
37302Sgdamore@opensolaris.org *
47302Sgdamore@opensolaris.org * The contents of this file are subject to the terms of the
57302Sgdamore@opensolaris.org * Common Development and Distribution License (the "License").
67302Sgdamore@opensolaris.org * You may not use this file except in compliance with the License.
77302Sgdamore@opensolaris.org *
87302Sgdamore@opensolaris.org * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97302Sgdamore@opensolaris.org * or http://www.opensolaris.org/os/licensing.
107302Sgdamore@opensolaris.org * See the License for the specific language governing permissions
117302Sgdamore@opensolaris.org * and limitations under the License.
127302Sgdamore@opensolaris.org *
137302Sgdamore@opensolaris.org * When distributing Covered Code, include this CDDL HEADER in each
147302Sgdamore@opensolaris.org * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157302Sgdamore@opensolaris.org * If applicable, add the following below this CDDL HEADER, with the
167302Sgdamore@opensolaris.org * fields enclosed by brackets "[]" replaced with your own identifying
177302Sgdamore@opensolaris.org * information: Portions Copyright [yyyy] [name of copyright owner]
187302Sgdamore@opensolaris.org *
197302Sgdamore@opensolaris.org * CDDL HEADER END
207302Sgdamore@opensolaris.org */
217302Sgdamore@opensolaris.org /*
22*12426Sgdamore@opensolaris.org * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
237302Sgdamore@opensolaris.org */
247302Sgdamore@opensolaris.org
257302Sgdamore@opensolaris.org /*
267302Sgdamore@opensolaris.org * SD card host support. This is the API that host drivers access.
277302Sgdamore@opensolaris.org */
287302Sgdamore@opensolaris.org
297302Sgdamore@opensolaris.org #include <sys/types.h>
307302Sgdamore@opensolaris.org #include <sys/conf.h>
317302Sgdamore@opensolaris.org #include <sys/cmn_err.h>
327302Sgdamore@opensolaris.org #include <sys/varargs.h>
337302Sgdamore@opensolaris.org #include <sys/ddi.h>
347302Sgdamore@opensolaris.org #include <sys/sunddi.h>
357302Sgdamore@opensolaris.org #include <sys/sdcard/sda.h>
367302Sgdamore@opensolaris.org #include <sys/sdcard/sda_impl.h>
377302Sgdamore@opensolaris.org
387302Sgdamore@opensolaris.org /*
397302Sgdamore@opensolaris.org * Implementation.
407302Sgdamore@opensolaris.org */
417302Sgdamore@opensolaris.org
427302Sgdamore@opensolaris.org void
sda_host_init_ops(struct dev_ops * devops)437302Sgdamore@opensolaris.org sda_host_init_ops(struct dev_ops *devops)
447302Sgdamore@opensolaris.org {
45*12426Sgdamore@opensolaris.org bd_mod_init(devops);
467302Sgdamore@opensolaris.org }
477302Sgdamore@opensolaris.org
487302Sgdamore@opensolaris.org void
sda_host_fini_ops(struct dev_ops * devops)497302Sgdamore@opensolaris.org sda_host_fini_ops(struct dev_ops *devops)
507302Sgdamore@opensolaris.org {
51*12426Sgdamore@opensolaris.org bd_mod_fini(devops);
527302Sgdamore@opensolaris.org }
537302Sgdamore@opensolaris.org
547302Sgdamore@opensolaris.org sda_host_t *
sda_host_alloc(dev_info_t * dip,int nslot,sda_ops_t * ops,ddi_dma_attr_t * dma)557302Sgdamore@opensolaris.org sda_host_alloc(dev_info_t *dip, int nslot, sda_ops_t *ops, ddi_dma_attr_t *dma)
567302Sgdamore@opensolaris.org {
577302Sgdamore@opensolaris.org sda_host_t *h;
587302Sgdamore@opensolaris.org
597302Sgdamore@opensolaris.org if (ops->so_version != SDA_OPS_VERSION) {
607302Sgdamore@opensolaris.org return (NULL);
617302Sgdamore@opensolaris.org }
627302Sgdamore@opensolaris.org
637302Sgdamore@opensolaris.org h = kmem_zalloc(sizeof (*h), KM_SLEEP);
647302Sgdamore@opensolaris.org h->h_nslot = nslot;
657302Sgdamore@opensolaris.org h->h_slots = kmem_zalloc(sizeof (sda_slot_t) * nslot, KM_SLEEP);
667302Sgdamore@opensolaris.org h->h_dma = dma;
677302Sgdamore@opensolaris.org h->h_dip = dip;
687302Sgdamore@opensolaris.org
697302Sgdamore@opensolaris.org /* initialize each slot */
708289Sgdamore@opensolaris.org for (int i = 0; i < nslot; i++) {
717302Sgdamore@opensolaris.org sda_slot_t *slot = &h->h_slots[i];
727302Sgdamore@opensolaris.org
737686Sgdamore@opensolaris.org slot->s_hostp = h;
747302Sgdamore@opensolaris.org slot->s_slot_num = i;
757302Sgdamore@opensolaris.org slot->s_ops = *ops;
767302Sgdamore@opensolaris.org
777302Sgdamore@opensolaris.org sda_slot_init(slot);
787302Sgdamore@opensolaris.org }
797302Sgdamore@opensolaris.org
807302Sgdamore@opensolaris.org return (h);
817302Sgdamore@opensolaris.org }
827302Sgdamore@opensolaris.org
837302Sgdamore@opensolaris.org void
sda_host_free(sda_host_t * h)847302Sgdamore@opensolaris.org sda_host_free(sda_host_t *h)
857302Sgdamore@opensolaris.org {
868289Sgdamore@opensolaris.org for (int i = 0; i < h->h_nslot; i++) {
877302Sgdamore@opensolaris.org sda_slot_fini(&h->h_slots[i]);
887302Sgdamore@opensolaris.org }
897302Sgdamore@opensolaris.org
907302Sgdamore@opensolaris.org kmem_free(h->h_slots, sizeof (sda_slot_t) * h->h_nslot);
917302Sgdamore@opensolaris.org kmem_free(h, sizeof (*h));
927302Sgdamore@opensolaris.org }
937302Sgdamore@opensolaris.org
947302Sgdamore@opensolaris.org void
sda_host_set_private(sda_host_t * h,int num,void * private)957302Sgdamore@opensolaris.org sda_host_set_private(sda_host_t *h, int num, void *private)
967302Sgdamore@opensolaris.org {
977302Sgdamore@opensolaris.org h->h_slots[num].s_prv = private;
987302Sgdamore@opensolaris.org }
997302Sgdamore@opensolaris.org
1007302Sgdamore@opensolaris.org int
sda_host_attach(sda_host_t * h)1017302Sgdamore@opensolaris.org sda_host_attach(sda_host_t *h)
1027302Sgdamore@opensolaris.org {
1037302Sgdamore@opensolaris.org /*
1047302Sgdamore@opensolaris.org * Attach slots.
1057302Sgdamore@opensolaris.org */
1068289Sgdamore@opensolaris.org for (int i = 0; i < h->h_nslot; i++) {
1077302Sgdamore@opensolaris.org
1087302Sgdamore@opensolaris.org sda_slot_attach(&h->h_slots[i]);
1097302Sgdamore@opensolaris.org
1107302Sgdamore@opensolaris.org /*
1117302Sgdamore@opensolaris.org * Initiate card detection.
1127302Sgdamore@opensolaris.org */
1137302Sgdamore@opensolaris.org sda_host_detect(h, i);
1147302Sgdamore@opensolaris.org }
1157302Sgdamore@opensolaris.org
1167302Sgdamore@opensolaris.org return (DDI_SUCCESS);
1177302Sgdamore@opensolaris.org }
1187302Sgdamore@opensolaris.org
1197302Sgdamore@opensolaris.org void
sda_host_detach(sda_host_t * h)1207302Sgdamore@opensolaris.org sda_host_detach(sda_host_t *h)
1217302Sgdamore@opensolaris.org {
1227302Sgdamore@opensolaris.org /*
1237302Sgdamore@opensolaris.org * Detach slots.
1247302Sgdamore@opensolaris.org */
1258289Sgdamore@opensolaris.org for (int i = 0; i < h->h_nslot; i++) {
1267302Sgdamore@opensolaris.org sda_slot_detach(&h->h_slots[i]);
1277302Sgdamore@opensolaris.org }
1287302Sgdamore@opensolaris.org }
1297302Sgdamore@opensolaris.org
1307302Sgdamore@opensolaris.org void
sda_host_suspend(sda_host_t * h)1318289Sgdamore@opensolaris.org sda_host_suspend(sda_host_t *h)
1328289Sgdamore@opensolaris.org {
1338289Sgdamore@opensolaris.org for (int i = 0; i < h->h_nslot; i++) {
1348289Sgdamore@opensolaris.org sda_slot_suspend(&h->h_slots[i]);
1358289Sgdamore@opensolaris.org }
1368289Sgdamore@opensolaris.org }
1378289Sgdamore@opensolaris.org
1388289Sgdamore@opensolaris.org void
sda_host_resume(sda_host_t * h)1398289Sgdamore@opensolaris.org sda_host_resume(sda_host_t *h)
1408289Sgdamore@opensolaris.org {
1418289Sgdamore@opensolaris.org for (int i = 0; i < h->h_nslot; i++) {
1428289Sgdamore@opensolaris.org sda_slot_resume(&h->h_slots[i]);
1438289Sgdamore@opensolaris.org }
1448289Sgdamore@opensolaris.org }
1458289Sgdamore@opensolaris.org
1468289Sgdamore@opensolaris.org void
sda_host_transfer(sda_host_t * h,int num,sda_err_t errno)1477302Sgdamore@opensolaris.org sda_host_transfer(sda_host_t *h, int num, sda_err_t errno)
1487302Sgdamore@opensolaris.org {
1497302Sgdamore@opensolaris.org sda_slot_transfer(&h->h_slots[num], errno);
1507302Sgdamore@opensolaris.org }
1517302Sgdamore@opensolaris.org
1527302Sgdamore@opensolaris.org void
sda_host_detect(sda_host_t * h,int num)1537302Sgdamore@opensolaris.org sda_host_detect(sda_host_t *h, int num)
1547302Sgdamore@opensolaris.org {
1557302Sgdamore@opensolaris.org sda_slot_detect(&h->h_slots[num]);
1567302Sgdamore@opensolaris.org }
1577302Sgdamore@opensolaris.org
1587302Sgdamore@opensolaris.org void
sda_host_fault(sda_host_t * h,int num,sda_fault_t fail)1597302Sgdamore@opensolaris.org sda_host_fault(sda_host_t *h, int num, sda_fault_t fail)
1607302Sgdamore@opensolaris.org {
1617302Sgdamore@opensolaris.org sda_slot_fault(&h->h_slots[num], fail);
1627302Sgdamore@opensolaris.org }
1637302Sgdamore@opensolaris.org
1647302Sgdamore@opensolaris.org void
sda_host_log(sda_host_t * h,int snum,const char * fmt,...)1657302Sgdamore@opensolaris.org sda_host_log(sda_host_t *h, int snum, const char *fmt, ...)
1667302Sgdamore@opensolaris.org {
1677302Sgdamore@opensolaris.org va_list ap;
1687302Sgdamore@opensolaris.org
1697302Sgdamore@opensolaris.org va_start(ap, fmt);
1707302Sgdamore@opensolaris.org if (h != NULL) {
1717302Sgdamore@opensolaris.org sda_slot_log(&h->h_slots[snum], fmt, ap);
1727302Sgdamore@opensolaris.org } else {
1737302Sgdamore@opensolaris.org sda_slot_log(NULL, fmt, ap);
1747302Sgdamore@opensolaris.org }
1757302Sgdamore@opensolaris.org va_end(ap);
1767302Sgdamore@opensolaris.org }
177