xref: /illumos-gate/usr/src/uts/sun/io/dada/impl/dcd_hba.c (revision cd210bb4)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*cd210bb4SChris Horne  * Common Development and Distribution License (the "License").
6*cd210bb4SChris Horne  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*cd210bb4SChris Horne  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <sys/note.h>
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate /*
297c478bd9Sstevel@tonic-gate  * Generic SCSI Host Bus Adapter interface implementation
307c478bd9Sstevel@tonic-gate  */
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #include <sys/dada/dada.h>
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate extern int dcd_options;
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate static kmutex_t	dcd_hba_mutex;
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate kmutex_t	dcd_log_mutex;
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate struct dcd_hba_inst {
417c478bd9Sstevel@tonic-gate 	dev_info_t	*inst_dip;
427c478bd9Sstevel@tonic-gate 	dcd_hba_tran_t	*inst_hba_tran;
437c478bd9Sstevel@tonic-gate 	struct dcd_hba_inst	*inst_next;
447c478bd9Sstevel@tonic-gate 	struct	dcd_hba_inst	*inst_prev;
457c478bd9Sstevel@tonic-gate };
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate static struct dcd_hba_inst	*dcd_hba_list	= NULL;
487c478bd9Sstevel@tonic-gate static struct dcd_hba_inst	*dcd_hba_list_tail = NULL;
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate _NOTE(READ_ONLY_DATA(dev_ops))
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate kmutex_t	dcd_flag_nointr_mutex;
547c478bd9Sstevel@tonic-gate kcondvar_t	dcd_flag_nointr_cv;
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate /*
587c478bd9Sstevel@tonic-gate  * Called from _init when loading the dcd module.
597c478bd9Sstevel@tonic-gate  */
607c478bd9Sstevel@tonic-gate void
dcd_initialize_hba_interface()617c478bd9Sstevel@tonic-gate dcd_initialize_hba_interface()
627c478bd9Sstevel@tonic-gate {
637c478bd9Sstevel@tonic-gate 	mutex_init(&dcd_hba_mutex, NULL, MUTEX_DRIVER, NULL);
647c478bd9Sstevel@tonic-gate 	mutex_init(&dcd_flag_nointr_mutex, NULL, MUTEX_DRIVER, NULL);
657c478bd9Sstevel@tonic-gate 	cv_init(&dcd_flag_nointr_cv, NULL, CV_DRIVER, NULL);
667c478bd9Sstevel@tonic-gate 	mutex_init(&dcd_log_mutex, NULL, MUTEX_DRIVER, NULL);
677c478bd9Sstevel@tonic-gate }
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate /*
707c478bd9Sstevel@tonic-gate  * Called from fini() when unloading the dcd module.
717c478bd9Sstevel@tonic-gate  */
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate void
dcd_uninitialize_hba_interface()747c478bd9Sstevel@tonic-gate dcd_uninitialize_hba_interface()
757c478bd9Sstevel@tonic-gate {
767c478bd9Sstevel@tonic-gate 	mutex_destroy(&dcd_hba_mutex);
777c478bd9Sstevel@tonic-gate 	cv_destroy(&dcd_flag_nointr_cv);
787c478bd9Sstevel@tonic-gate 	mutex_destroy(&dcd_flag_nointr_mutex);
797c478bd9Sstevel@tonic-gate 	mutex_destroy(&dcd_log_mutex);
807c478bd9Sstevel@tonic-gate }
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate /*
847c478bd9Sstevel@tonic-gate  * Called by an HBA from _init()
857c478bd9Sstevel@tonic-gate  */
867c478bd9Sstevel@tonic-gate /* ARGSUSED */
877c478bd9Sstevel@tonic-gate int
dcd_hba_init(struct modlinkage * modlp)887c478bd9Sstevel@tonic-gate dcd_hba_init(struct modlinkage *modlp)
897c478bd9Sstevel@tonic-gate {
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate 	return (0);
927c478bd9Sstevel@tonic-gate }
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate #ifdef NOTNEEDED
977c478bd9Sstevel@tonic-gate /* ARGSUSED */
987c478bd9Sstevel@tonic-gate int
dcd_hba_attach(dev_info_t * dip,ddi_dma_lim_t * hba_lim,dcd_hba_tran_t * hba_tran,int flags,void * hba_options)997c478bd9Sstevel@tonic-gate dcd_hba_attach(dev_info_t *dip,
1007c478bd9Sstevel@tonic-gate 	ddi_dma_lim_t	*hba_lim,
1017c478bd9Sstevel@tonic-gate 	dcd_hba_tran_t	*hba_tran,
1027c478bd9Sstevel@tonic-gate 	int		flags,
1037c478bd9Sstevel@tonic-gate 	void		*hba_options)
1047c478bd9Sstevel@tonic-gate {
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate 	ddi_dma_attr_t		hba_dma_attr;
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate 	bzero(&hba_dma_attr, sizeof (ddi_dma_attr_t));
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate 	hba_dma_attr.dma_attr_burstsizes = hba_lim->dlim_burstsizes;
1117c478bd9Sstevel@tonic-gate 	hba_dma_attr.dma_attr_minxfer = hba_lim->dlim_minxfer;
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate 	return (dcd_hba_attach_setup(dip, &hba_dma_attr, hba_tran, flags));
1147c478bd9Sstevel@tonic-gate }
1157c478bd9Sstevel@tonic-gate #endif
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate int
dcd_hba_attach(dev_info_t * dip,ddi_dma_attr_t * hba_dma_attr,dcd_hba_tran_t * hba_tran,int flags)1197c478bd9Sstevel@tonic-gate dcd_hba_attach(
1207c478bd9Sstevel@tonic-gate 	dev_info_t	*dip,
1217c478bd9Sstevel@tonic-gate 	ddi_dma_attr_t	*hba_dma_attr,
1227c478bd9Sstevel@tonic-gate 	dcd_hba_tran_t	*hba_tran,
1237c478bd9Sstevel@tonic-gate 	int		flags)
1247c478bd9Sstevel@tonic-gate {
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate 	struct dcd_hba_inst	*elem;
1277c478bd9Sstevel@tonic-gate 	int			value;
1287c478bd9Sstevel@tonic-gate 	int			len;
1297c478bd9Sstevel@tonic-gate 	char			*prop_name;
1307c478bd9Sstevel@tonic-gate 	char			*errmsg =
131*cd210bb4SChris Horne 	    "dcd_hba_attach: cannott create property '%s' for %s%d\n";
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate 	/*
1347c478bd9Sstevel@tonic-gate 	 * Link this instance into the list
1357c478bd9Sstevel@tonic-gate 	 */
1367c478bd9Sstevel@tonic-gate 	elem = kmem_alloc(sizeof (struct dcd_hba_inst), KM_SLEEP);
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate 	elem->inst_dip = dip;
1397c478bd9Sstevel@tonic-gate 	elem->inst_hba_tran = hba_tran;
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate 	mutex_enter(&dcd_hba_mutex);
1427c478bd9Sstevel@tonic-gate 	elem->inst_next = NULL;
1437c478bd9Sstevel@tonic-gate 	elem->inst_prev = dcd_hba_list_tail;
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate 	if (dcd_hba_list == NULL) {
1467c478bd9Sstevel@tonic-gate 		dcd_hba_list = elem;
1477c478bd9Sstevel@tonic-gate 	}
1487c478bd9Sstevel@tonic-gate 	if (dcd_hba_list_tail) {
1497c478bd9Sstevel@tonic-gate 		dcd_hba_list_tail->inst_next = elem;
1507c478bd9Sstevel@tonic-gate 	}
1517c478bd9Sstevel@tonic-gate 	dcd_hba_list_tail = elem;
1527c478bd9Sstevel@tonic-gate 	mutex_exit(&dcd_hba_mutex);
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate 	/*
1567c478bd9Sstevel@tonic-gate 	 * Save all the improtant HBA information that must be accessed
1577c478bd9Sstevel@tonic-gate 	 * later.
1587c478bd9Sstevel@tonic-gate 	 */
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate 	hba_tran->tran_hba_dip = dip;
1617c478bd9Sstevel@tonic-gate 	hba_tran->tran_hba_flags = flags;
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate 	/*
1647c478bd9Sstevel@tonic-gate 	 * Note: We only need dma_attr_minxfer and dma_attr_burstsize
1657c478bd9Sstevel@tonic-gate 	 * from the DMA atrributes
1667c478bd9Sstevel@tonic-gate 	 */
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate 	hba_tran->tran_min_xfer = hba_dma_attr->dma_attr_minxfer;
1697c478bd9Sstevel@tonic-gate 	hba_tran->tran_min_burst_size =
170*cd210bb4SChris Horne 	    (1<<(ddi_ffs(hba_dma_attr->dma_attr_burstsizes)-1));
1717c478bd9Sstevel@tonic-gate 	hba_tran->tran_max_burst_size =
172*cd210bb4SChris Horne 	    (1<<(ddi_fls(hba_dma_attr->dma_attr_burstsizes)-1));
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate 	prop_name = "dcd_options";
1777c478bd9Sstevel@tonic-gate 	len = 0;
1787c478bd9Sstevel@tonic-gate 	if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN, 0, prop_name,
1797c478bd9Sstevel@tonic-gate 	    NULL, &len) == DDI_PROP_NOT_FOUND) {
1807c478bd9Sstevel@tonic-gate 		value = dcd_options;
1817c478bd9Sstevel@tonic-gate 		if (ddi_prop_update_int(DDI_MAJOR_T_UNKNOWN, dip,
1827c478bd9Sstevel@tonic-gate 		    prop_name, value) != DDI_PROP_SUCCESS) {
1837c478bd9Sstevel@tonic-gate 			cmn_err(CE_CONT, errmsg, prop_name,
184*cd210bb4SChris Horne 			    ddi_get_name(dip), ddi_get_instance(dip));
1857c478bd9Sstevel@tonic-gate 		}
1867c478bd9Sstevel@tonic-gate 	}
1877c478bd9Sstevel@tonic-gate 
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate 	/*
1907c478bd9Sstevel@tonic-gate 	 * XXX : This needs to be removed when code cleanup
1917c478bd9Sstevel@tonic-gate 	 * ddi_set_driver_private(dip, (caddr_t)hba_tran);
1927c478bd9Sstevel@tonic-gate 	 */
1937c478bd9Sstevel@tonic-gate #ifdef DEBUG1
1947c478bd9Sstevel@tonic-gate 	printf("Called Set driver private with dip %x, tran %x\n",
195*cd210bb4SChris Horne 	    dip, hba_tran);
1967c478bd9Sstevel@tonic-gate #endif
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
1997c478bd9Sstevel@tonic-gate }
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate /*
2037c478bd9Sstevel@tonic-gate  * called by an HBA to detach an instance of the driver
2047c478bd9Sstevel@tonic-gate  */
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate int
dcd_hba_detach(dev_info_t * dip)2077c478bd9Sstevel@tonic-gate dcd_hba_detach(dev_info_t *dip)
2087c478bd9Sstevel@tonic-gate {
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate 	dcd_hba_tran_t	*hba;
2117c478bd9Sstevel@tonic-gate 	struct dcd_hba_inst 	*elem;
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate 	hba = ddi_get_driver_private(dip);
2147c478bd9Sstevel@tonic-gate 	ddi_set_driver_private(dip, NULL);
2157c478bd9Sstevel@tonic-gate 	ASSERT(hba != NULL);
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate 	hba->tran_hba_dip = (dev_info_t *)NULL;
2187c478bd9Sstevel@tonic-gate 	hba->tran_hba_flags = 0;
2197c478bd9Sstevel@tonic-gate 	hba->tran_min_burst_size = (uchar_t)0;
2207c478bd9Sstevel@tonic-gate 	hba->tran_max_burst_size = (uchar_t)0;
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate 	/*
2247c478bd9Sstevel@tonic-gate 	 * Remove HBA instance from dcd_hba_list
2257c478bd9Sstevel@tonic-gate 	 */
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 	mutex_enter(&dcd_hba_mutex);
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate 	for (elem = dcd_hba_list; elem != (struct dcd_hba_inst *)NULL;
230*cd210bb4SChris Horne 	    elem = elem->inst_next) {
2317c478bd9Sstevel@tonic-gate 		if (elem->inst_dip == dip)
2327c478bd9Sstevel@tonic-gate 			break;
2337c478bd9Sstevel@tonic-gate 	}
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate 	if (elem == (struct dcd_hba_inst *)NULL) {
2367c478bd9Sstevel@tonic-gate 		cmn_err(CE_NOTE, "dcd_hba_attach: Unknown HBA instance\n");
2377c478bd9Sstevel@tonic-gate 		mutex_exit(&dcd_hba_mutex);
2387c478bd9Sstevel@tonic-gate 	}
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate 	if (elem == dcd_hba_list) {
2417c478bd9Sstevel@tonic-gate 		dcd_hba_list = elem->inst_next;
2427c478bd9Sstevel@tonic-gate 		dcd_hba_list->inst_prev = (struct dcd_hba_inst *)NULL;
2437c478bd9Sstevel@tonic-gate 	} else if (elem == dcd_hba_list_tail) {
2447c478bd9Sstevel@tonic-gate 		dcd_hba_list_tail = elem->inst_prev;
2457c478bd9Sstevel@tonic-gate 		dcd_hba_list_tail->inst_next = (struct dcd_hba_inst *)NULL;
2467c478bd9Sstevel@tonic-gate 	} else {
2477c478bd9Sstevel@tonic-gate 		elem->inst_prev->inst_next = elem->inst_next;
2487c478bd9Sstevel@tonic-gate 		elem->inst_next->inst_prev = elem->inst_prev;
2497c478bd9Sstevel@tonic-gate 	}
2507c478bd9Sstevel@tonic-gate 	mutex_exit(&dcd_hba_mutex);
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate 	kmem_free(elem, sizeof (struct dcd_hba_inst));
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
2557c478bd9Sstevel@tonic-gate }
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate void
dcd_hba_fini()2587c478bd9Sstevel@tonic-gate dcd_hba_fini()
2597c478bd9Sstevel@tonic-gate {
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate }
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate /* ARGSUSED */
2647c478bd9Sstevel@tonic-gate dcd_hba_tran_t *
dcd_hba_tran_alloc(dev_info_t * dip,int flags)2657c478bd9Sstevel@tonic-gate dcd_hba_tran_alloc(
2667c478bd9Sstevel@tonic-gate 	dev_info_t	*dip,
2677c478bd9Sstevel@tonic-gate 	int		flags)
2687c478bd9Sstevel@tonic-gate {
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate 	return (kmem_zalloc(sizeof (dcd_hba_tran_t),
271*cd210bb4SChris Horne 	    (flags & DCD_HBA_CANSLEEP) ? KM_SLEEP: KM_NOSLEEP));
2727c478bd9Sstevel@tonic-gate }
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 
2757c478bd9Sstevel@tonic-gate void
dcd_hba_tran_free(dcd_hba_tran_t * hba_tran)2767c478bd9Sstevel@tonic-gate dcd_hba_tran_free(dcd_hba_tran_t	*hba_tran)
2777c478bd9Sstevel@tonic-gate {
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate 	kmem_free(hba_tran, sizeof (dcd_hba_tran_t));
2807c478bd9Sstevel@tonic-gate }
2817c478bd9Sstevel@tonic-gate 
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate /*
2847c478bd9Sstevel@tonic-gate  * XXX: Do we really need the following routines.
2857c478bd9Sstevel@tonic-gate  */
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate /*
2887c478bd9Sstevel@tonic-gate  * private wrapper for dcd_pkt's allocated via scsi_hba_pkt_alloc
2897c478bd9Sstevel@tonic-gate  */
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate struct dcd_pkt_wrapper {
2927c478bd9Sstevel@tonic-gate 	struct dcd_pkt	dcd_pkt;
2937c478bd9Sstevel@tonic-gate 	int		pkt_wrapper_len;
2947c478bd9Sstevel@tonic-gate };
2957c478bd9Sstevel@tonic-gate 
2967c478bd9Sstevel@tonic-gate _NOTE(SCHEME_PROTECTS_DATA("unique per thread", dcd_pkt_wrapper))
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate /*
2997c478bd9Sstevel@tonic-gate  * Round up all allocations so that we can gurentee
3007c478bd9Sstevel@tonic-gate  * long-long alignment. This is the same alignment
3017c478bd9Sstevel@tonic-gate  * provided by kmem_alloc().
3027c478bd9Sstevel@tonic-gate  */
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate #define	ROUNDUP(x)	(((x) + 0x07) & ~0x07)
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate /*
3077c478bd9Sstevel@tonic-gate  * Called by an HBA to allocate a dcd_pkt
3087c478bd9Sstevel@tonic-gate  */
3097c478bd9Sstevel@tonic-gate 
3107c478bd9Sstevel@tonic-gate /* ARGSUSED */
3117c478bd9Sstevel@tonic-gate struct dcd_pkt *
dcd_hba_pkt_alloc(struct dcd_address * ap,int cmdlen,int statuslen,int tgtlen,int hbalen,int (* callback)(caddr_t arg),caddr_t arg)3127c478bd9Sstevel@tonic-gate dcd_hba_pkt_alloc(
3137c478bd9Sstevel@tonic-gate 	struct dcd_address	*ap,
3147c478bd9Sstevel@tonic-gate 	int			cmdlen,
3157c478bd9Sstevel@tonic-gate 	int			statuslen,
3167c478bd9Sstevel@tonic-gate 	int			tgtlen,
3177c478bd9Sstevel@tonic-gate 	int			hbalen,
3187c478bd9Sstevel@tonic-gate 	int			(*callback)(caddr_t arg),
3197c478bd9Sstevel@tonic-gate 	caddr_t			arg)
3207c478bd9Sstevel@tonic-gate {
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate 	struct dcd_pkt	*pkt;
3237c478bd9Sstevel@tonic-gate 	struct dcd_pkt_wrapper	*hba_pkt;
3247c478bd9Sstevel@tonic-gate 	caddr_t		p;
3257c478bd9Sstevel@tonic-gate 	int		pktlen;
3267c478bd9Sstevel@tonic-gate 
3277c478bd9Sstevel@tonic-gate 
3287c478bd9Sstevel@tonic-gate 	/*
3297c478bd9Sstevel@tonic-gate 	 * Sanity check
3307c478bd9Sstevel@tonic-gate 	 */
3317c478bd9Sstevel@tonic-gate 	if (callback != SLEEP_FUNC && callback != NULL_FUNC) {
3327c478bd9Sstevel@tonic-gate 		cmn_err(CE_PANIC, " dcd_hba_pkt_alloc: callback must be"
333*cd210bb4SChris Horne 		    " either SLEEP or NULL\n");
3347c478bd9Sstevel@tonic-gate 	}
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate 	/*
3387c478bd9Sstevel@tonic-gate 	 * Round up so everything gets allocated on long-word boundaries.
3397c478bd9Sstevel@tonic-gate 	 */
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate 	cmdlen = ROUNDUP(cmdlen);
3427c478bd9Sstevel@tonic-gate 	tgtlen = ROUNDUP(tgtlen);
3437c478bd9Sstevel@tonic-gate 	hbalen = ROUNDUP(hbalen);
3447c478bd9Sstevel@tonic-gate 	statuslen = ROUNDUP(statuslen);
345*cd210bb4SChris Horne 	pktlen = sizeof (struct dcd_pkt_wrapper) +
346*cd210bb4SChris Horne 	    cmdlen + tgtlen +hbalen + statuslen;
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate 	hba_pkt = kmem_zalloc(pktlen,
349*cd210bb4SChris Horne 	    (callback = SLEEP_FUNC) ? KM_SLEEP: KM_NOSLEEP);
3507c478bd9Sstevel@tonic-gate 
3517c478bd9Sstevel@tonic-gate 	if (hba_pkt == NULL) {
3527c478bd9Sstevel@tonic-gate 		ASSERT(callback == NULL_FUNC);
3537c478bd9Sstevel@tonic-gate 		return (NULL);
3547c478bd9Sstevel@tonic-gate 	}
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate 	/*
3577c478bd9Sstevel@tonic-gate 	 * Set up or private info on this pkt
3587c478bd9Sstevel@tonic-gate 	 */
3597c478bd9Sstevel@tonic-gate 	hba_pkt->pkt_wrapper_len = pktlen;
3607c478bd9Sstevel@tonic-gate 	pkt = &hba_pkt->dcd_pkt;
3617c478bd9Sstevel@tonic-gate 	p = (caddr_t)(hba_pkt + 1);
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate 	/*
3647c478bd9Sstevel@tonic-gate 	 * set up pointers to private data areas, cdb and status.
3657c478bd9Sstevel@tonic-gate 	 */
3667c478bd9Sstevel@tonic-gate 	if (hbalen > 0) {
3677c478bd9Sstevel@tonic-gate 		pkt->pkt_ha_private = (ataopaque_t)p;
3687c478bd9Sstevel@tonic-gate 		p += hbalen;
3697c478bd9Sstevel@tonic-gate 	}
3707c478bd9Sstevel@tonic-gate 
3717c478bd9Sstevel@tonic-gate 	if (tgtlen > 0) {
3727c478bd9Sstevel@tonic-gate 		pkt->pkt_private = (ataopaque_t)p;
3737c478bd9Sstevel@tonic-gate 		p += tgtlen;
3747c478bd9Sstevel@tonic-gate 	}
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate 	if (statuslen > 0) {
3777c478bd9Sstevel@tonic-gate 		pkt->pkt_scbp = (uchar_t *)p;
3787c478bd9Sstevel@tonic-gate 		p += statuslen;
3797c478bd9Sstevel@tonic-gate 	}
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate 	if (cmdlen > 0) {
3827c478bd9Sstevel@tonic-gate 		pkt->pkt_cdbp = (void *)p;
3837c478bd9Sstevel@tonic-gate 	}
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate 	/*
3867c478bd9Sstevel@tonic-gate 	 * Initialize the pkt's dcd_address
3877c478bd9Sstevel@tonic-gate 	 */
3887c478bd9Sstevel@tonic-gate 	pkt->pkt_address = *ap;
3897c478bd9Sstevel@tonic-gate #ifdef DEBUG1
390*cd210bb4SChris Horne 	printf("da_target %x, da_lun %x, a_hba_tran %x\n",
391*cd210bb4SChris Horne 	    pkt->pkt_address.da_target, pkt->pkt_address.da_lun,
392*cd210bb4SChris Horne 	    pkt->pkt_address.a_hba_tran);
393*cd210bb4SChris Horne 	printf("From address : da_target %x, da_lun %x, a_hba_tran %x\n",
394*cd210bb4SChris Horne 	    ap->da_target, ap->da_lun, ap->a_hba_tran);
3957c478bd9Sstevel@tonic-gate 	printf("Pkt %x\n", pkt);
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate #endif
3987c478bd9Sstevel@tonic-gate 	return (pkt);
3997c478bd9Sstevel@tonic-gate }
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate /* ARGSUSED */
4037c478bd9Sstevel@tonic-gate void
dcd_hba_pkt_free(struct dcd_address * ap,struct dcd_pkt * pkt)4047c478bd9Sstevel@tonic-gate dcd_hba_pkt_free(
4057c478bd9Sstevel@tonic-gate 	struct dcd_address *ap,
4067c478bd9Sstevel@tonic-gate 	struct dcd_pkt	   *pkt)
4077c478bd9Sstevel@tonic-gate {
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate 	kmem_free((struct dcd_pkt_wrapper *)pkt,
410*cd210bb4SChris Horne 	    ((struct dcd_pkt_wrapper *)pkt)->pkt_wrapper_len);
4117c478bd9Sstevel@tonic-gate }
4127c478bd9Sstevel@tonic-gate 
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate /*
4157c478bd9Sstevel@tonic-gate  * Called by an HBA to map strings to capability indices
4167c478bd9Sstevel@tonic-gate  */
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate int
dcd_hba_lookup_capstr(char * capstr)4197c478bd9Sstevel@tonic-gate dcd_hba_lookup_capstr(char		*capstr)
4207c478bd9Sstevel@tonic-gate {
4217c478bd9Sstevel@tonic-gate 
4227c478bd9Sstevel@tonic-gate 	/*
4237c478bd9Sstevel@tonic-gate 	 * Capability strings, masking the '-' vs '_'.
4247c478bd9Sstevel@tonic-gate 	 */
4257c478bd9Sstevel@tonic-gate 	static struct cap_strings {
4267c478bd9Sstevel@tonic-gate 		char *cap_string;
4277c478bd9Sstevel@tonic-gate 		int   cap_index;
4287c478bd9Sstevel@tonic-gate 	} cap_string[] = {
4297c478bd9Sstevel@tonic-gate 		{ "dma-max",		DCD_CAP_DMA_MAX		},
4307c478bd9Sstevel@tonic-gate 		{ "dma_max",		DCD_CAP_DMA_MAX		},
4317c478bd9Sstevel@tonic-gate 		{ "ultraata",		DCD_CAP_ULTRA_ATA	},
4327c478bd9Sstevel@tonic-gate 		{ "busmaster",		DCD_CAP_BUS_MASTER	},
4337c478bd9Sstevel@tonic-gate 		{ "overlap",		DCD_CAP_OVERLAP		},
4347c478bd9Sstevel@tonic-gate 		{ "parity",		DCD_CAP_PARITY		},
4357c478bd9Sstevel@tonic-gate 		{ "sector-size",	DCD_CAP_SECTOR_SIZE	},
4367c478bd9Sstevel@tonic-gate 		{ "total-sectors",	DCD_CAP_TOTAL_SECTORS	},
4377c478bd9Sstevel@tonic-gate 		{ "geometry",		DCD_CAP_GEOMETRY	},
4387c478bd9Sstevel@tonic-gate 		{ "block-mode",		DCD_CAP_BLOCKMODE	},
4397c478bd9Sstevel@tonic-gate 		{ "block-factor",	DCD_CAP_BLOCKFACTOR	},
4407c478bd9Sstevel@tonic-gate 		{ "dma-support",		DCD_CAP_DMA_SUPPORT	},
4417c478bd9Sstevel@tonic-gate 		{ "pio-support", 	DCD_CAP_PIO_SUPPORT	},
4427c478bd9Sstevel@tonic-gate 		{ "lba-addressing",	DCD_CAP_LBA_ADDRESSING  },
4437c478bd9Sstevel@tonic-gate 		{ NULL, 0					}
4447c478bd9Sstevel@tonic-gate 	};
4457c478bd9Sstevel@tonic-gate 	struct cap_strings *cp;
4467c478bd9Sstevel@tonic-gate 
4477c478bd9Sstevel@tonic-gate 	for (cp = cap_string; cp->cap_string != NULL; cp++) {
4487c478bd9Sstevel@tonic-gate 		if (strcmp(cp->cap_string, capstr) == 0) {
4497c478bd9Sstevel@tonic-gate 			return (cp->cap_index);
4507c478bd9Sstevel@tonic-gate 		}
4517c478bd9Sstevel@tonic-gate 	}
4527c478bd9Sstevel@tonic-gate 
4537c478bd9Sstevel@tonic-gate 	return (-1);
4547c478bd9Sstevel@tonic-gate }
455