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