xref: /illumos-gate/usr/src/uts/common/io/sdcard/impl/sda_host.c (revision f2b90c3c415ff04d4adb3a54242822b41d74bfd9)
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 /*
224bb7efa7SGarrett D'Amore  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
234bb7efa7SGarrett D'Amore  * Use is subject to license terms.
244bb7efa7SGarrett D'Amore  */
254bb7efa7SGarrett D'Amore 
264bb7efa7SGarrett D'Amore /*
274bb7efa7SGarrett D'Amore  * SD card host support.  This is the API that host drivers access.
284bb7efa7SGarrett D'Amore  */
294bb7efa7SGarrett D'Amore 
304bb7efa7SGarrett D'Amore #include <sys/types.h>
314bb7efa7SGarrett D'Amore #include <sys/conf.h>
324bb7efa7SGarrett D'Amore #include <sys/cmn_err.h>
334bb7efa7SGarrett D'Amore #include <sys/varargs.h>
344bb7efa7SGarrett D'Amore #include <sys/ddi.h>
354bb7efa7SGarrett D'Amore #include <sys/sunddi.h>
364bb7efa7SGarrett D'Amore #include <sys/sdcard/sda.h>
374bb7efa7SGarrett D'Amore #include <sys/sdcard/sda_impl.h>
384bb7efa7SGarrett D'Amore 
394bb7efa7SGarrett D'Amore /*
404bb7efa7SGarrett D'Amore  * Static Variables.
414bb7efa7SGarrett D'Amore  */
424bb7efa7SGarrett D'Amore 
434bb7efa7SGarrett D'Amore static struct bus_ops sda_host_bus_ops = {
444bb7efa7SGarrett D'Amore 	BUSO_REV,			/* busops_rev */
454bb7efa7SGarrett D'Amore 	nullbusmap,			/* bus_map */
464bb7efa7SGarrett D'Amore 	NULL,				/* bus_get_intrspec (OBSOLETE) */
474bb7efa7SGarrett D'Amore 	NULL,				/* bus_add_intrspec (OBSOLETE) */
484bb7efa7SGarrett D'Amore 	NULL,				/* bus_remove_intrspec (OBSOLETE) */
494bb7efa7SGarrett D'Amore 	i_ddi_map_fault,		/* bus_map_fault */
504bb7efa7SGarrett D'Amore 	ddi_dma_map,			/* bus_dma_map */
514bb7efa7SGarrett D'Amore 	ddi_dma_allochdl,		/* bus_dma_allochdl */
524bb7efa7SGarrett D'Amore 	ddi_dma_freehdl,		/* bus_dma_freehdl */
534bb7efa7SGarrett D'Amore 	ddi_dma_bindhdl,		/* bus_dma_bindhdl */
544bb7efa7SGarrett D'Amore 	ddi_dma_unbindhdl,		/* bus_dma_unbindhdl */
554bb7efa7SGarrett D'Amore 	ddi_dma_flush,			/* bus_dma_flush */
564bb7efa7SGarrett D'Amore 	ddi_dma_win,			/* bus_dma_win */
574bb7efa7SGarrett D'Amore 	ddi_dma_mctl,			/* bus_dma_ctl */
584bb7efa7SGarrett D'Amore 	sda_nexus_bus_ctl,		/* bus_ctl */
594bb7efa7SGarrett D'Amore 	ddi_bus_prop_op,		/* bus_prop_op */
604bb7efa7SGarrett D'Amore 	NULL,				/* bus_get_eventcookie */
614bb7efa7SGarrett D'Amore 	NULL,				/* bus_add_eventcall */
624bb7efa7SGarrett D'Amore 	NULL,				/* bus_remove_eventcall */
634bb7efa7SGarrett D'Amore 	NULL,				/* bus_post_event */
644bb7efa7SGarrett D'Amore 	NULL,				/* bus_intr_ctl (OBSOLETE) */
654bb7efa7SGarrett D'Amore 	NULL, /* sda_nexus_bus_config, */		/* bus_config */
664bb7efa7SGarrett D'Amore 	NULL, /* sda_nexus_bus_unconfig, */		/* bus_unconfig */
674bb7efa7SGarrett D'Amore 	NULL,				/* bus_fm_init */
684bb7efa7SGarrett D'Amore 	NULL,				/* bus_fm_fini */
694bb7efa7SGarrett D'Amore 	NULL,				/* bus_fm_access_enter */
704bb7efa7SGarrett D'Amore 	NULL,				/* bus_fm_access_exit */
714bb7efa7SGarrett D'Amore 	NULL,				/* bus_power */
724bb7efa7SGarrett D'Amore 	NULL,				/* bus_intr_op */
734bb7efa7SGarrett D'Amore };
744bb7efa7SGarrett D'Amore 
754bb7efa7SGarrett D'Amore static struct cb_ops sda_host_cb_ops = {
764bb7efa7SGarrett D'Amore 	sda_nexus_open,			/* cb_open */
774bb7efa7SGarrett D'Amore 	sda_nexus_close,		/* cb_close */
784bb7efa7SGarrett D'Amore 	nodev,				/* cb_strategy */
794bb7efa7SGarrett D'Amore 	nodev,				/* cb_print */
804bb7efa7SGarrett D'Amore 	nodev,				/* cb_dump */
814bb7efa7SGarrett D'Amore 	nodev,				/* cb_read */
824bb7efa7SGarrett D'Amore 	nodev,				/* cb_write */
834bb7efa7SGarrett D'Amore 	sda_nexus_ioctl,		/* cb_ioctl */
844bb7efa7SGarrett D'Amore 	nodev,				/* cb_devmap */
854bb7efa7SGarrett D'Amore 	nodev,				/* cb_mmap */
864bb7efa7SGarrett D'Amore 	nodev,				/* cb_segmap */
874bb7efa7SGarrett D'Amore 	nochpoll,			/* cb_poll */
884bb7efa7SGarrett D'Amore 	ddi_prop_op,			/* cb_prop_op */
894bb7efa7SGarrett D'Amore 	NULL,				/* cb_str */
904bb7efa7SGarrett D'Amore 	D_MP,				/* cb_flag */
914bb7efa7SGarrett D'Amore 	CB_REV,				/* cb_rev */
924bb7efa7SGarrett D'Amore 	nodev,				/* cb_aread */
934bb7efa7SGarrett D'Amore 	nodev,				/* cb_awrite */
944bb7efa7SGarrett D'Amore };
954bb7efa7SGarrett D'Amore 
964bb7efa7SGarrett D'Amore /*
974bb7efa7SGarrett D'Amore  * Implementation.
984bb7efa7SGarrett D'Amore  */
994bb7efa7SGarrett D'Amore 
1004bb7efa7SGarrett D'Amore void
1014bb7efa7SGarrett D'Amore sda_host_init_ops(struct dev_ops *devops)
1024bb7efa7SGarrett D'Amore {
1034bb7efa7SGarrett D'Amore 	devops->devo_getinfo = sda_nexus_getinfo;
1044bb7efa7SGarrett D'Amore 	devops->devo_cb_ops = &sda_host_cb_ops;
1054bb7efa7SGarrett D'Amore 	devops->devo_bus_ops = &sda_host_bus_ops;
1064bb7efa7SGarrett D'Amore }
1074bb7efa7SGarrett D'Amore 
1084bb7efa7SGarrett D'Amore void
1094bb7efa7SGarrett D'Amore sda_host_fini_ops(struct dev_ops *devops)
1104bb7efa7SGarrett D'Amore {
1114bb7efa7SGarrett D'Amore 	devops->devo_bus_ops = NULL;
1124bb7efa7SGarrett D'Amore }
1134bb7efa7SGarrett D'Amore 
1144bb7efa7SGarrett D'Amore sda_host_t *
1154bb7efa7SGarrett D'Amore sda_host_alloc(dev_info_t *dip, int nslot, sda_ops_t *ops, ddi_dma_attr_t *dma)
1164bb7efa7SGarrett D'Amore {
1174bb7efa7SGarrett D'Amore 	sda_host_t	*h;
1184bb7efa7SGarrett D'Amore 
1194bb7efa7SGarrett D'Amore 	if (ops->so_version != SDA_OPS_VERSION) {
1204bb7efa7SGarrett D'Amore 		return (NULL);
1214bb7efa7SGarrett D'Amore 	}
1224bb7efa7SGarrett D'Amore 
1234bb7efa7SGarrett D'Amore 	h = kmem_zalloc(sizeof (*h), KM_SLEEP);
1244bb7efa7SGarrett D'Amore 	h->h_nslot = nslot;
1254bb7efa7SGarrett D'Amore 	h->h_slots = kmem_zalloc(sizeof (sda_slot_t) * nslot, KM_SLEEP);
1264bb7efa7SGarrett D'Amore 	h->h_dma = dma;
1274bb7efa7SGarrett D'Amore 	h->h_dip = dip;
1284bb7efa7SGarrett D'Amore 
1294bb7efa7SGarrett D'Amore 	/* initialize each slot */
130*f2b90c3cSGarrett D'Amore 	for (int i = 0; i < nslot; i++) {
1314bb7efa7SGarrett D'Amore 		sda_slot_t *slot = &h->h_slots[i];
1324bb7efa7SGarrett D'Amore 
1331cb84fbfSGarrett D'Amore 		slot->s_hostp = h;
1344bb7efa7SGarrett D'Amore 		slot->s_slot_num = i;
1354bb7efa7SGarrett D'Amore 		slot->s_ops = *ops;
1364bb7efa7SGarrett D'Amore 
1374bb7efa7SGarrett D'Amore 		sda_slot_init(slot);
1384bb7efa7SGarrett D'Amore 	}
1394bb7efa7SGarrett D'Amore 
1404bb7efa7SGarrett D'Amore 	return (h);
1414bb7efa7SGarrett D'Amore }
1424bb7efa7SGarrett D'Amore 
1434bb7efa7SGarrett D'Amore void
1444bb7efa7SGarrett D'Amore sda_host_free(sda_host_t *h)
1454bb7efa7SGarrett D'Amore {
146*f2b90c3cSGarrett D'Amore 	for (int i = 0; i < h->h_nslot; i++) {
1474bb7efa7SGarrett D'Amore 		sda_slot_fini(&h->h_slots[i]);
1484bb7efa7SGarrett D'Amore 	}
1494bb7efa7SGarrett D'Amore 
1504bb7efa7SGarrett D'Amore 	kmem_free(h->h_slots, sizeof (sda_slot_t) * h->h_nslot);
1514bb7efa7SGarrett D'Amore 	kmem_free(h, sizeof (*h));
1524bb7efa7SGarrett D'Amore }
1534bb7efa7SGarrett D'Amore 
1544bb7efa7SGarrett D'Amore void
1554bb7efa7SGarrett D'Amore sda_host_set_private(sda_host_t *h, int num, void *private)
1564bb7efa7SGarrett D'Amore {
1574bb7efa7SGarrett D'Amore 	h->h_slots[num].s_prv = private;
1584bb7efa7SGarrett D'Amore }
1594bb7efa7SGarrett D'Amore 
1604bb7efa7SGarrett D'Amore int
1614bb7efa7SGarrett D'Amore sda_host_attach(sda_host_t *h)
1624bb7efa7SGarrett D'Amore {
1634bb7efa7SGarrett D'Amore 	/*
1644bb7efa7SGarrett D'Amore 	 * Attach slots.
1654bb7efa7SGarrett D'Amore 	 */
166*f2b90c3cSGarrett D'Amore 	for (int i = 0; i < h->h_nslot; i++) {
1674bb7efa7SGarrett D'Amore 
1684bb7efa7SGarrett D'Amore 		sda_slot_attach(&h->h_slots[i]);
1694bb7efa7SGarrett D'Amore 
1704bb7efa7SGarrett D'Amore 		/*
1714bb7efa7SGarrett D'Amore 		 * Initiate card detection.
1724bb7efa7SGarrett D'Amore 		 */
1734bb7efa7SGarrett D'Amore 		sda_host_detect(h, i);
1744bb7efa7SGarrett D'Amore 	}
1754bb7efa7SGarrett D'Amore 
1764bb7efa7SGarrett D'Amore 	/*
1774bb7efa7SGarrett D'Amore 	 * Register (create) nexus minor nodes.
1784bb7efa7SGarrett D'Amore 	 */
1794bb7efa7SGarrett D'Amore 	sda_nexus_register(h);
1804bb7efa7SGarrett D'Amore 
1814bb7efa7SGarrett D'Amore 	return (DDI_SUCCESS);
1824bb7efa7SGarrett D'Amore }
1834bb7efa7SGarrett D'Amore 
1844bb7efa7SGarrett D'Amore void
1854bb7efa7SGarrett D'Amore sda_host_detach(sda_host_t *h)
1864bb7efa7SGarrett D'Amore {
1874bb7efa7SGarrett D'Amore 	/*
1884bb7efa7SGarrett D'Amore 	 * Unregister nexus minor nodes.
1894bb7efa7SGarrett D'Amore 	 */
1904bb7efa7SGarrett D'Amore 	sda_nexus_unregister(h);
1914bb7efa7SGarrett D'Amore 
1924bb7efa7SGarrett D'Amore 	/*
1934bb7efa7SGarrett D'Amore 	 * Detach slots.
1944bb7efa7SGarrett D'Amore 	 */
195*f2b90c3cSGarrett D'Amore 	for (int i = 0; i < h->h_nslot; i++) {
1964bb7efa7SGarrett D'Amore 		sda_slot_detach(&h->h_slots[i]);
1974bb7efa7SGarrett D'Amore 	}
1984bb7efa7SGarrett D'Amore }
1994bb7efa7SGarrett D'Amore 
2004bb7efa7SGarrett D'Amore void
201*f2b90c3cSGarrett D'Amore sda_host_suspend(sda_host_t *h)
202*f2b90c3cSGarrett D'Amore {
203*f2b90c3cSGarrett D'Amore 	for (int i = 0; i < h->h_nslot; i++) {
204*f2b90c3cSGarrett D'Amore 		sda_slot_suspend(&h->h_slots[i]);
205*f2b90c3cSGarrett D'Amore 	}
206*f2b90c3cSGarrett D'Amore }
207*f2b90c3cSGarrett D'Amore 
208*f2b90c3cSGarrett D'Amore void
209*f2b90c3cSGarrett D'Amore sda_host_resume(sda_host_t *h)
210*f2b90c3cSGarrett D'Amore {
211*f2b90c3cSGarrett D'Amore 	for (int i = 0; i < h->h_nslot; i++) {
212*f2b90c3cSGarrett D'Amore 		sda_slot_resume(&h->h_slots[i]);
213*f2b90c3cSGarrett D'Amore 	}
214*f2b90c3cSGarrett D'Amore }
215*f2b90c3cSGarrett D'Amore 
216*f2b90c3cSGarrett D'Amore void
2174bb7efa7SGarrett D'Amore sda_host_transfer(sda_host_t *h, int num, sda_err_t errno)
2184bb7efa7SGarrett D'Amore {
2194bb7efa7SGarrett D'Amore 	sda_slot_transfer(&h->h_slots[num], errno);
2204bb7efa7SGarrett D'Amore }
2214bb7efa7SGarrett D'Amore 
2224bb7efa7SGarrett D'Amore void
2234bb7efa7SGarrett D'Amore sda_host_detect(sda_host_t *h, int num)
2244bb7efa7SGarrett D'Amore {
2254bb7efa7SGarrett D'Amore 	sda_slot_detect(&h->h_slots[num]);
2264bb7efa7SGarrett D'Amore }
2274bb7efa7SGarrett D'Amore 
2284bb7efa7SGarrett D'Amore void
2294bb7efa7SGarrett D'Amore sda_host_fault(sda_host_t *h, int num, sda_fault_t fail)
2304bb7efa7SGarrett D'Amore {
2314bb7efa7SGarrett D'Amore 	sda_slot_fault(&h->h_slots[num], fail);
2324bb7efa7SGarrett D'Amore }
2334bb7efa7SGarrett D'Amore 
2344bb7efa7SGarrett D'Amore void
2354bb7efa7SGarrett D'Amore sda_host_log(sda_host_t *h, int snum, const char *fmt, ...)
2364bb7efa7SGarrett D'Amore {
2374bb7efa7SGarrett D'Amore 	va_list	ap;
2384bb7efa7SGarrett D'Amore 
2394bb7efa7SGarrett D'Amore 	va_start(ap, fmt);
2404bb7efa7SGarrett D'Amore 	if (h != NULL) {
2414bb7efa7SGarrett D'Amore 		sda_slot_log(&h->h_slots[snum], fmt, ap);
2424bb7efa7SGarrett D'Amore 	} else {
2434bb7efa7SGarrett D'Amore 		sda_slot_log(NULL, fmt, ap);
2444bb7efa7SGarrett D'Amore 	}
2454bb7efa7SGarrett D'Amore 	va_end(ap);
2464bb7efa7SGarrett D'Amore }
247