xref: /illumos-gate/usr/src/uts/common/io/sdcard/impl/sda_host.c (revision 3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9)
14bb7efa7SGarrett D'Amore /*
24bb7efa7SGarrett D'Amore  * CDDL HEADER START
34bb7efa7SGarrett D'Amore  *
44bb7efa7SGarrett D'Amore  * The contents of this file are subject to the terms of the
54bb7efa7SGarrett D'Amore  * Common Development and Distribution License (the "License").
64bb7efa7SGarrett D'Amore  * You may not use this file except in compliance with the License.
74bb7efa7SGarrett D'Amore  *
84bb7efa7SGarrett D'Amore  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
94bb7efa7SGarrett D'Amore  * or http://www.opensolaris.org/os/licensing.
104bb7efa7SGarrett D'Amore  * See the License for the specific language governing permissions
114bb7efa7SGarrett D'Amore  * and limitations under the License.
124bb7efa7SGarrett D'Amore  *
134bb7efa7SGarrett D'Amore  * When distributing Covered Code, include this CDDL HEADER in each
144bb7efa7SGarrett D'Amore  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
154bb7efa7SGarrett D'Amore  * If applicable, add the following below this CDDL HEADER, with the
164bb7efa7SGarrett D'Amore  * fields enclosed by brackets "[]" replaced with your own identifying
174bb7efa7SGarrett D'Amore  * information: Portions Copyright [yyyy] [name of copyright owner]
184bb7efa7SGarrett D'Amore  *
194bb7efa7SGarrett D'Amore  * CDDL HEADER END
204bb7efa7SGarrett D'Amore  */
214bb7efa7SGarrett D'Amore /*
22*3f7d54a6SGarrett D'Amore  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
234bb7efa7SGarrett D'Amore  */
244bb7efa7SGarrett D'Amore 
254bb7efa7SGarrett D'Amore /*
264bb7efa7SGarrett D'Amore  * SD card host support.  This is the API that host drivers access.
274bb7efa7SGarrett D'Amore  */
284bb7efa7SGarrett D'Amore 
294bb7efa7SGarrett D'Amore #include <sys/types.h>
304bb7efa7SGarrett D'Amore #include <sys/conf.h>
314bb7efa7SGarrett D'Amore #include <sys/cmn_err.h>
324bb7efa7SGarrett D'Amore #include <sys/varargs.h>
334bb7efa7SGarrett D'Amore #include <sys/ddi.h>
344bb7efa7SGarrett D'Amore #include <sys/sunddi.h>
354bb7efa7SGarrett D'Amore #include <sys/sdcard/sda.h>
364bb7efa7SGarrett D'Amore #include <sys/sdcard/sda_impl.h>
374bb7efa7SGarrett D'Amore 
384bb7efa7SGarrett D'Amore /*
394bb7efa7SGarrett D'Amore  * Implementation.
404bb7efa7SGarrett D'Amore  */
414bb7efa7SGarrett D'Amore 
424bb7efa7SGarrett D'Amore void
sda_host_init_ops(struct dev_ops * devops)434bb7efa7SGarrett D'Amore sda_host_init_ops(struct dev_ops *devops)
444bb7efa7SGarrett D'Amore {
45*3f7d54a6SGarrett D'Amore 	bd_mod_init(devops);
464bb7efa7SGarrett D'Amore }
474bb7efa7SGarrett D'Amore 
484bb7efa7SGarrett D'Amore void
sda_host_fini_ops(struct dev_ops * devops)494bb7efa7SGarrett D'Amore sda_host_fini_ops(struct dev_ops *devops)
504bb7efa7SGarrett D'Amore {
51*3f7d54a6SGarrett D'Amore 	bd_mod_fini(devops);
524bb7efa7SGarrett D'Amore }
534bb7efa7SGarrett D'Amore 
544bb7efa7SGarrett D'Amore sda_host_t *
sda_host_alloc(dev_info_t * dip,int nslot,sda_ops_t * ops,ddi_dma_attr_t * dma)554bb7efa7SGarrett D'Amore sda_host_alloc(dev_info_t *dip, int nslot, sda_ops_t *ops, ddi_dma_attr_t *dma)
564bb7efa7SGarrett D'Amore {
574bb7efa7SGarrett D'Amore 	sda_host_t	*h;
584bb7efa7SGarrett D'Amore 
594bb7efa7SGarrett D'Amore 	if (ops->so_version != SDA_OPS_VERSION) {
604bb7efa7SGarrett D'Amore 		return (NULL);
614bb7efa7SGarrett D'Amore 	}
624bb7efa7SGarrett D'Amore 
634bb7efa7SGarrett D'Amore 	h = kmem_zalloc(sizeof (*h), KM_SLEEP);
644bb7efa7SGarrett D'Amore 	h->h_nslot = nslot;
654bb7efa7SGarrett D'Amore 	h->h_slots = kmem_zalloc(sizeof (sda_slot_t) * nslot, KM_SLEEP);
664bb7efa7SGarrett D'Amore 	h->h_dma = dma;
674bb7efa7SGarrett D'Amore 	h->h_dip = dip;
684bb7efa7SGarrett D'Amore 
694bb7efa7SGarrett D'Amore 	/* initialize each slot */
70f2b90c3cSGarrett D'Amore 	for (int i = 0; i < nslot; i++) {
714bb7efa7SGarrett D'Amore 		sda_slot_t *slot = &h->h_slots[i];
724bb7efa7SGarrett D'Amore 
731cb84fbfSGarrett D'Amore 		slot->s_hostp = h;
744bb7efa7SGarrett D'Amore 		slot->s_slot_num = i;
754bb7efa7SGarrett D'Amore 		slot->s_ops = *ops;
764bb7efa7SGarrett D'Amore 
774bb7efa7SGarrett D'Amore 		sda_slot_init(slot);
784bb7efa7SGarrett D'Amore 	}
794bb7efa7SGarrett D'Amore 
804bb7efa7SGarrett D'Amore 	return (h);
814bb7efa7SGarrett D'Amore }
824bb7efa7SGarrett D'Amore 
834bb7efa7SGarrett D'Amore void
sda_host_free(sda_host_t * h)844bb7efa7SGarrett D'Amore sda_host_free(sda_host_t *h)
854bb7efa7SGarrett D'Amore {
86f2b90c3cSGarrett D'Amore 	for (int i = 0; i < h->h_nslot; i++) {
874bb7efa7SGarrett D'Amore 		sda_slot_fini(&h->h_slots[i]);
884bb7efa7SGarrett D'Amore 	}
894bb7efa7SGarrett D'Amore 
904bb7efa7SGarrett D'Amore 	kmem_free(h->h_slots, sizeof (sda_slot_t) * h->h_nslot);
914bb7efa7SGarrett D'Amore 	kmem_free(h, sizeof (*h));
924bb7efa7SGarrett D'Amore }
934bb7efa7SGarrett D'Amore 
944bb7efa7SGarrett D'Amore void
sda_host_set_private(sda_host_t * h,int num,void * private)954bb7efa7SGarrett D'Amore sda_host_set_private(sda_host_t *h, int num, void *private)
964bb7efa7SGarrett D'Amore {
974bb7efa7SGarrett D'Amore 	h->h_slots[num].s_prv = private;
984bb7efa7SGarrett D'Amore }
994bb7efa7SGarrett D'Amore 
1004bb7efa7SGarrett D'Amore int
sda_host_attach(sda_host_t * h)1014bb7efa7SGarrett D'Amore sda_host_attach(sda_host_t *h)
1024bb7efa7SGarrett D'Amore {
1034bb7efa7SGarrett D'Amore 	/*
1044bb7efa7SGarrett D'Amore 	 * Attach slots.
1054bb7efa7SGarrett D'Amore 	 */
106f2b90c3cSGarrett D'Amore 	for (int i = 0; i < h->h_nslot; i++) {
1074bb7efa7SGarrett D'Amore 
1084bb7efa7SGarrett D'Amore 		sda_slot_attach(&h->h_slots[i]);
1094bb7efa7SGarrett D'Amore 
1104bb7efa7SGarrett D'Amore 		/*
1114bb7efa7SGarrett D'Amore 		 * Initiate card detection.
1124bb7efa7SGarrett D'Amore 		 */
1134bb7efa7SGarrett D'Amore 		sda_host_detect(h, i);
1144bb7efa7SGarrett D'Amore 	}
1154bb7efa7SGarrett D'Amore 
1164bb7efa7SGarrett D'Amore 	return (DDI_SUCCESS);
1174bb7efa7SGarrett D'Amore }
1184bb7efa7SGarrett D'Amore 
1194bb7efa7SGarrett D'Amore void
sda_host_detach(sda_host_t * h)1204bb7efa7SGarrett D'Amore sda_host_detach(sda_host_t *h)
1214bb7efa7SGarrett D'Amore {
1224bb7efa7SGarrett D'Amore 	/*
1234bb7efa7SGarrett D'Amore 	 * Detach slots.
1244bb7efa7SGarrett D'Amore 	 */
125f2b90c3cSGarrett D'Amore 	for (int i = 0; i < h->h_nslot; i++) {
1264bb7efa7SGarrett D'Amore 		sda_slot_detach(&h->h_slots[i]);
1274bb7efa7SGarrett D'Amore 	}
1284bb7efa7SGarrett D'Amore }
1294bb7efa7SGarrett D'Amore 
1304bb7efa7SGarrett D'Amore void
sda_host_suspend(sda_host_t * h)131f2b90c3cSGarrett D'Amore sda_host_suspend(sda_host_t *h)
132f2b90c3cSGarrett D'Amore {
133f2b90c3cSGarrett D'Amore 	for (int i = 0; i < h->h_nslot; i++) {
134f2b90c3cSGarrett D'Amore 		sda_slot_suspend(&h->h_slots[i]);
135f2b90c3cSGarrett D'Amore 	}
136f2b90c3cSGarrett D'Amore }
137f2b90c3cSGarrett D'Amore 
138f2b90c3cSGarrett D'Amore void
sda_host_resume(sda_host_t * h)139f2b90c3cSGarrett D'Amore sda_host_resume(sda_host_t *h)
140f2b90c3cSGarrett D'Amore {
141f2b90c3cSGarrett D'Amore 	for (int i = 0; i < h->h_nslot; i++) {
142f2b90c3cSGarrett D'Amore 		sda_slot_resume(&h->h_slots[i]);
143f2b90c3cSGarrett D'Amore 	}
144f2b90c3cSGarrett D'Amore }
145f2b90c3cSGarrett D'Amore 
146f2b90c3cSGarrett D'Amore void
sda_host_transfer(sda_host_t * h,int num,sda_err_t errno)1474bb7efa7SGarrett D'Amore sda_host_transfer(sda_host_t *h, int num, sda_err_t errno)
1484bb7efa7SGarrett D'Amore {
1494bb7efa7SGarrett D'Amore 	sda_slot_transfer(&h->h_slots[num], errno);
1504bb7efa7SGarrett D'Amore }
1514bb7efa7SGarrett D'Amore 
1524bb7efa7SGarrett D'Amore void
sda_host_detect(sda_host_t * h,int num)1534bb7efa7SGarrett D'Amore sda_host_detect(sda_host_t *h, int num)
1544bb7efa7SGarrett D'Amore {
1554bb7efa7SGarrett D'Amore 	sda_slot_detect(&h->h_slots[num]);
1564bb7efa7SGarrett D'Amore }
1574bb7efa7SGarrett D'Amore 
1584bb7efa7SGarrett D'Amore void
sda_host_fault(sda_host_t * h,int num,sda_fault_t fail)1594bb7efa7SGarrett D'Amore sda_host_fault(sda_host_t *h, int num, sda_fault_t fail)
1604bb7efa7SGarrett D'Amore {
1614bb7efa7SGarrett D'Amore 	sda_slot_fault(&h->h_slots[num], fail);
1624bb7efa7SGarrett D'Amore }
1634bb7efa7SGarrett D'Amore 
1644bb7efa7SGarrett D'Amore void
sda_host_log(sda_host_t * h,int snum,const char * fmt,...)1654bb7efa7SGarrett D'Amore sda_host_log(sda_host_t *h, int snum, const char *fmt, ...)
1664bb7efa7SGarrett D'Amore {
1674bb7efa7SGarrett D'Amore 	va_list	ap;
1684bb7efa7SGarrett D'Amore 
1694bb7efa7SGarrett D'Amore 	va_start(ap, fmt);
1704bb7efa7SGarrett D'Amore 	if (h != NULL) {
1714bb7efa7SGarrett D'Amore 		sda_slot_log(&h->h_slots[snum], fmt, ap);
1724bb7efa7SGarrett D'Amore 	} else {
1734bb7efa7SGarrett D'Amore 		sda_slot_log(NULL, fmt, ap);
1744bb7efa7SGarrett D'Amore 	}
1754bb7efa7SGarrett D'Amore 	va_end(ap);
1764bb7efa7SGarrett D'Amore }
177