xref: /onnv-gate/usr/src/uts/common/io/sdcard/impl/sda_host.c (revision 12426:cdff5d2ea989)
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