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
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
23*ef7b5c7bSap  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*ef7b5c7bSap  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate /*
307c478bd9Sstevel@tonic-gate  * hci1394_q.c
317c478bd9Sstevel@tonic-gate  *    This code decouples some of the OpenHCI async descriptor logic/structures
327c478bd9Sstevel@tonic-gate  *    from the async processing.  The goal was to combine as much of the
337c478bd9Sstevel@tonic-gate  *    duplicate code as possible for the different type of async transfers
347c478bd9Sstevel@tonic-gate  *    without going too overboard.
357c478bd9Sstevel@tonic-gate  *
367c478bd9Sstevel@tonic-gate  *    There are two parts to the Q, the descriptor buffer and the data buffer.
377c478bd9Sstevel@tonic-gate  *    For the most part, data to be transmitted and data which is received go
387c478bd9Sstevel@tonic-gate  *    in the data buffers.  The information of where to get the data and put
397c478bd9Sstevel@tonic-gate  *    the data reside in the descriptor buffers. There are exceptions to this.
407c478bd9Sstevel@tonic-gate  */
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate #include <sys/types.h>
447c478bd9Sstevel@tonic-gate #include <sys/conf.h>
457c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
467c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
477c478bd9Sstevel@tonic-gate #include <sys/stat.h>
487c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
497c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
507c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
517c478bd9Sstevel@tonic-gate #include <sys/note.h>
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate #include <sys/1394/adapters/hci1394.h>
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate static int hci1394_q_reserve(hci1394_q_buf_t *qbuf, uint_t size,
577c478bd9Sstevel@tonic-gate     uint32_t *io_addr);
587c478bd9Sstevel@tonic-gate static void hci1394_q_unreserve(hci1394_q_buf_t *qbuf);
597c478bd9Sstevel@tonic-gate static void hci1394_q_buf_setup(hci1394_q_buf_t *qbuf);
607c478bd9Sstevel@tonic-gate static void hci1394_q_reset(hci1394_q_handle_t q_handle);
617c478bd9Sstevel@tonic-gate static void hci1394_q_next_buf(hci1394_q_buf_t *qbuf);
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate static void hci1394_q_at_write_OLI(hci1394_q_handle_t q_handle,
647c478bd9Sstevel@tonic-gate     hci1394_q_buf_t *qbuf, hci1394_q_cmd_t *cmd, hci1394_basic_pkt_t *hdr,
657c478bd9Sstevel@tonic-gate     uint_t hdrsize);
667c478bd9Sstevel@tonic-gate static void hci1394_q_at_write_OMI(hci1394_q_handle_t q_handle,
677c478bd9Sstevel@tonic-gate     hci1394_q_buf_t *qbuf, hci1394_q_cmd_t *cmd, hci1394_basic_pkt_t *hdr,
687c478bd9Sstevel@tonic-gate     uint_t hdrsize);
697c478bd9Sstevel@tonic-gate static void hci1394_q_at_write_OL(hci1394_q_handle_t q_handle,
707c478bd9Sstevel@tonic-gate     hci1394_q_buf_t *qbuf, hci1394_q_cmd_t *cmd, uint32_t io_addr,
717c478bd9Sstevel@tonic-gate     uint_t datasize);
727c478bd9Sstevel@tonic-gate static void hci1394_q_at_rep_put8(hci1394_q_buf_t *qbuf, hci1394_q_cmd_t *cmd,
737c478bd9Sstevel@tonic-gate     uint8_t *data, uint_t datasize);
747c478bd9Sstevel@tonic-gate static void hci1394_q_at_copy_from_mblk(hci1394_q_buf_t *qbuf,
757c478bd9Sstevel@tonic-gate     hci1394_q_cmd_t *cmd, h1394_mblk_t *mblk);
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate static void hci1394_q_ar_write_IM(hci1394_q_handle_t q_handle,
787c478bd9Sstevel@tonic-gate     hci1394_q_buf_t *qbuf, uint32_t io_addr, uint_t datasize);
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate _NOTE(SCHEME_PROTECTS_DATA("unique", msgb))
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate /*
837c478bd9Sstevel@tonic-gate  * hci1394_q_init()
847c478bd9Sstevel@tonic-gate  *    Initialize a Q.  A Q consists of a descriptor buffer and a data buffer and
857c478bd9Sstevel@tonic-gate  *    can be either an AT or AR Q. hci1394_q_init() returns a handle which
867c478bd9Sstevel@tonic-gate  *    should be used for the reset of the hci1394_q_* calls.
877c478bd9Sstevel@tonic-gate  */
887c478bd9Sstevel@tonic-gate int
hci1394_q_init(hci1394_drvinfo_t * drvinfo,hci1394_ohci_handle_t ohci_handle,hci1394_q_info_t * qinfo,hci1394_q_handle_t * q_handle)897c478bd9Sstevel@tonic-gate hci1394_q_init(hci1394_drvinfo_t *drvinfo,
907c478bd9Sstevel@tonic-gate     hci1394_ohci_handle_t ohci_handle, hci1394_q_info_t *qinfo,
917c478bd9Sstevel@tonic-gate     hci1394_q_handle_t *q_handle)
927c478bd9Sstevel@tonic-gate {
937c478bd9Sstevel@tonic-gate 	hci1394_q_buf_t *desc;
947c478bd9Sstevel@tonic-gate 	hci1394_q_buf_t *data;
957c478bd9Sstevel@tonic-gate 	hci1394_buf_parms_t parms;
967c478bd9Sstevel@tonic-gate 	hci1394_q_t *q;
977c478bd9Sstevel@tonic-gate 	int status;
987c478bd9Sstevel@tonic-gate 	int index;
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate 	ASSERT(drvinfo != NULL);
1027c478bd9Sstevel@tonic-gate 	ASSERT(qinfo != NULL);
1037c478bd9Sstevel@tonic-gate 	ASSERT(q_handle != NULL);
1047c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_q_init_enter, HCI1394_TNF_HAL_STACK, "");
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate 	/*
1077c478bd9Sstevel@tonic-gate 	 * allocate the memory to track this Q.  Initialize the internal Q
1087c478bd9Sstevel@tonic-gate 	 * structure.
1097c478bd9Sstevel@tonic-gate 	 */
1107c478bd9Sstevel@tonic-gate 	q = kmem_alloc(sizeof (hci1394_q_t), KM_SLEEP);
1117c478bd9Sstevel@tonic-gate 	q->q_drvinfo = drvinfo;
1127c478bd9Sstevel@tonic-gate 	q->q_info = *qinfo;
1137c478bd9Sstevel@tonic-gate 	q->q_ohci = ohci_handle;
1147c478bd9Sstevel@tonic-gate 	mutex_init(&q->q_mutex, NULL, MUTEX_DRIVER, drvinfo->di_iblock_cookie);
1157c478bd9Sstevel@tonic-gate 	desc = &q->q_desc;
1167c478bd9Sstevel@tonic-gate 	data = &q->q_data;
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate 	/*
1197c478bd9Sstevel@tonic-gate 	 * Allocate the Descriptor buffer.
1207c478bd9Sstevel@tonic-gate 	 *
1217c478bd9Sstevel@tonic-gate 	 * XXX - Only want 1 cookie for now. Change this to OHCI_MAX_COOKIE
1227c478bd9Sstevel@tonic-gate 	 * after we have tested the multiple cookie code on x86.
1237c478bd9Sstevel@tonic-gate 	 */
1247c478bd9Sstevel@tonic-gate 	parms.bp_length = qinfo->qi_desc_size;
1257c478bd9Sstevel@tonic-gate 	parms.bp_max_cookies = 1;
1267c478bd9Sstevel@tonic-gate 	parms.bp_alignment = 16;
1277c478bd9Sstevel@tonic-gate 	status = hci1394_buf_alloc(drvinfo, &parms, &desc->qb_buf,
1287c478bd9Sstevel@tonic-gate 	    &desc->qb_buf_handle);
1297c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
1307c478bd9Sstevel@tonic-gate 		mutex_destroy(&q->q_mutex);
1317c478bd9Sstevel@tonic-gate 		kmem_free(q, sizeof (hci1394_q_t));
1327c478bd9Sstevel@tonic-gate 		*q_handle = NULL;
1337c478bd9Sstevel@tonic-gate 		TNF_PROBE_0(hci1394_q_init_bae_fail, HCI1394_TNF_HAL_ERROR, "");
1347c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(hci1394_q_init_exit, HCI1394_TNF_HAL_STACK,
1357c478bd9Sstevel@tonic-gate 		    "");
1367c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
1377c478bd9Sstevel@tonic-gate 	}
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate 	/* Copy in buffer cookies into our local cookie array */
1407c478bd9Sstevel@tonic-gate 	desc->qb_cookie[0] = desc->qb_buf.bi_cookie;
1417c478bd9Sstevel@tonic-gate 	for (index = 1; index < desc->qb_buf.bi_cookie_count; index++) {
1427c478bd9Sstevel@tonic-gate 		ddi_dma_nextcookie(desc->qb_buf.bi_dma_handle,
1437c478bd9Sstevel@tonic-gate 		    &desc->qb_buf.bi_cookie);
1447c478bd9Sstevel@tonic-gate 		desc->qb_cookie[index] = desc->qb_buf.bi_cookie;
1457c478bd9Sstevel@tonic-gate 	}
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate 	/*
1487c478bd9Sstevel@tonic-gate 	 * Allocate the Data buffer.
1497c478bd9Sstevel@tonic-gate 	 *
1507c478bd9Sstevel@tonic-gate 	 * XXX - Only want 1 cookie for now. Change this to OHCI_MAX_COOKIE
1517c478bd9Sstevel@tonic-gate 	 * after we have tested the multiple cookie code on x86.
1527c478bd9Sstevel@tonic-gate 	 */
1537c478bd9Sstevel@tonic-gate 	parms.bp_length = qinfo->qi_data_size;
1547c478bd9Sstevel@tonic-gate 	parms.bp_max_cookies = 1;
1557c478bd9Sstevel@tonic-gate 	parms.bp_alignment = 16;
1567c478bd9Sstevel@tonic-gate 	status = hci1394_buf_alloc(drvinfo, &parms, &data->qb_buf,
1577c478bd9Sstevel@tonic-gate 	    &data->qb_buf_handle);
1587c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
159*ef7b5c7bSap 		/* Free the allocated Descriptor buffer */
160*ef7b5c7bSap 		hci1394_buf_free(&desc->qb_buf_handle);
161*ef7b5c7bSap 
1627c478bd9Sstevel@tonic-gate 		mutex_destroy(&q->q_mutex);
1637c478bd9Sstevel@tonic-gate 		kmem_free(q, sizeof (hci1394_q_t));
1647c478bd9Sstevel@tonic-gate 		*q_handle = NULL;
1657c478bd9Sstevel@tonic-gate 		TNF_PROBE_0(hci1394_q_init_baa_fail, HCI1394_TNF_HAL_ERROR, "");
1667c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(hci1394_q_init_exit, HCI1394_TNF_HAL_STACK,
1677c478bd9Sstevel@tonic-gate 		    "");
1687c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
1697c478bd9Sstevel@tonic-gate 	}
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate 	/*
1727c478bd9Sstevel@tonic-gate 	 * We must have at least 2 ARQ data buffers, If we only have one, we
1737c478bd9Sstevel@tonic-gate 	 * will artificially create 2. We must have 2 so that we always have a
1747c478bd9Sstevel@tonic-gate 	 * descriptor with free data space to write AR data to. When one is
1757c478bd9Sstevel@tonic-gate 	 * empty, it will take us a bit to get a new descriptor back into the
1767c478bd9Sstevel@tonic-gate 	 * chain.
1777c478bd9Sstevel@tonic-gate 	 */
1787c478bd9Sstevel@tonic-gate 	if ((qinfo->qi_mode == HCI1394_ARQ) &&
1797c478bd9Sstevel@tonic-gate 	    (data->qb_buf.bi_cookie_count == 1)) {
1807c478bd9Sstevel@tonic-gate 		data->qb_buf.bi_cookie_count = 2;
1817c478bd9Sstevel@tonic-gate 		data->qb_cookie[0] = data->qb_buf.bi_cookie;
1827c478bd9Sstevel@tonic-gate 		data->qb_cookie[0].dmac_size /= 2;
1837c478bd9Sstevel@tonic-gate 		data->qb_cookie[1] = data->qb_cookie[0];
1847c478bd9Sstevel@tonic-gate 		data->qb_cookie[1].dmac_laddress =
1857c478bd9Sstevel@tonic-gate 		    data->qb_cookie[0].dmac_laddress +
1867c478bd9Sstevel@tonic-gate 		    data->qb_cookie[0].dmac_size;
1877c478bd9Sstevel@tonic-gate 		data->qb_cookie[1].dmac_address =
1887c478bd9Sstevel@tonic-gate 		    data->qb_cookie[0].dmac_address +
1897c478bd9Sstevel@tonic-gate 		    data->qb_cookie[0].dmac_size;
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate 	/* We have more than 1 cookie or we are an AT Q */
1927c478bd9Sstevel@tonic-gate 	} else {
1937c478bd9Sstevel@tonic-gate 		/* Copy in buffer cookies into our local cookie array */
1947c478bd9Sstevel@tonic-gate 		data->qb_cookie[0] = data->qb_buf.bi_cookie;
1957c478bd9Sstevel@tonic-gate 		for (index = 1; index < data->qb_buf.bi_cookie_count; index++) {
1967c478bd9Sstevel@tonic-gate 			ddi_dma_nextcookie(data->qb_buf.bi_dma_handle,
1977c478bd9Sstevel@tonic-gate 			    &data->qb_buf.bi_cookie);
1987c478bd9Sstevel@tonic-gate 			data->qb_cookie[index] = data->qb_buf.bi_cookie;
1997c478bd9Sstevel@tonic-gate 		}
2007c478bd9Sstevel@tonic-gate 	}
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate 	/* The top and bottom of the Q are only set once */
2037c478bd9Sstevel@tonic-gate 	desc->qb_ptrs.qp_top = desc->qb_buf.bi_kaddr;
2047c478bd9Sstevel@tonic-gate 	desc->qb_ptrs.qp_bottom = desc->qb_buf.bi_kaddr +
2057c478bd9Sstevel@tonic-gate 	    desc->qb_buf.bi_real_length - 1;
2067c478bd9Sstevel@tonic-gate 	data->qb_ptrs.qp_top = data->qb_buf.bi_kaddr;
2077c478bd9Sstevel@tonic-gate 	data->qb_ptrs.qp_bottom = data->qb_buf.bi_kaddr +
2087c478bd9Sstevel@tonic-gate 	    data->qb_buf.bi_real_length - 1;
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate 	/*
2117c478bd9Sstevel@tonic-gate 	 * reset the Q pointers to their original settings.  Setup IM
2127c478bd9Sstevel@tonic-gate 	 * descriptors if this is an AR Q.
2137c478bd9Sstevel@tonic-gate 	 */
2147c478bd9Sstevel@tonic-gate 	hci1394_q_reset(q);
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate 	/* if this is an AT Q, create a queued list for the AT descriptors */
2177c478bd9Sstevel@tonic-gate 	if (qinfo->qi_mode == HCI1394_ATQ) {
2187c478bd9Sstevel@tonic-gate 		hci1394_tlist_init(drvinfo, NULL, &q->q_queued_list);
2197c478bd9Sstevel@tonic-gate 	}
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate 	*q_handle = q;
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_q_init_exit, HCI1394_TNF_HAL_STACK, "");
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
2267c478bd9Sstevel@tonic-gate }
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate /*
2307c478bd9Sstevel@tonic-gate  * hci1394_q_fini()
2317c478bd9Sstevel@tonic-gate  *    Cleanup after a successful hci1394_q_init(). Notice that a pointer to the
2327c478bd9Sstevel@tonic-gate  *    handle is used for the parameter.  fini() will set your handle to NULL
2337c478bd9Sstevel@tonic-gate  *    before returning.
2347c478bd9Sstevel@tonic-gate  */
2357c478bd9Sstevel@tonic-gate void
hci1394_q_fini(hci1394_q_handle_t * q_handle)2367c478bd9Sstevel@tonic-gate hci1394_q_fini(hci1394_q_handle_t *q_handle)
2377c478bd9Sstevel@tonic-gate {
2387c478bd9Sstevel@tonic-gate 	hci1394_q_t *q;
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate 	ASSERT(q_handle != NULL);
2417c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_q_fini_enter, HCI1394_TNF_HAL_STACK, "");
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate 	q = *q_handle;
2447c478bd9Sstevel@tonic-gate 	if (q->q_info.qi_mode == HCI1394_ATQ) {
2457c478bd9Sstevel@tonic-gate 		hci1394_tlist_fini(&q->q_queued_list);
2467c478bd9Sstevel@tonic-gate 	}
2477c478bd9Sstevel@tonic-gate 	mutex_destroy(&q->q_mutex);
2487c478bd9Sstevel@tonic-gate 	hci1394_buf_free(&q->q_desc.qb_buf_handle);
2497c478bd9Sstevel@tonic-gate 	hci1394_buf_free(&q->q_data.qb_buf_handle);
2507c478bd9Sstevel@tonic-gate 	kmem_free(q, sizeof (hci1394_q_t));
2517c478bd9Sstevel@tonic-gate 	*q_handle = NULL;
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_q_fini_exit, HCI1394_TNF_HAL_STACK, "");
2547c478bd9Sstevel@tonic-gate }
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate /*
2587c478bd9Sstevel@tonic-gate  * hci1394_q_buf_setup()
2597c478bd9Sstevel@tonic-gate  *    Initialization of buffer pointers which are present in both the descriptor
2607c478bd9Sstevel@tonic-gate  *    buffer and data buffer (No reason to duplicate the code)
2617c478bd9Sstevel@tonic-gate  */
2627c478bd9Sstevel@tonic-gate static void
hci1394_q_buf_setup(hci1394_q_buf_t * qbuf)2637c478bd9Sstevel@tonic-gate hci1394_q_buf_setup(hci1394_q_buf_t *qbuf)
2647c478bd9Sstevel@tonic-gate {
2657c478bd9Sstevel@tonic-gate 	ASSERT(qbuf != NULL);
2667c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_q_buf_setup_enter, HCI1394_TNF_HAL_STACK, "");
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 	/* start with the first cookie */
2697c478bd9Sstevel@tonic-gate 	qbuf->qb_ptrs.qp_current_buf = 0;
2707c478bd9Sstevel@tonic-gate 	qbuf->qb_ptrs.qp_begin = qbuf->qb_ptrs.qp_top;
2717c478bd9Sstevel@tonic-gate 	qbuf->qb_ptrs.qp_end = qbuf->qb_ptrs.qp_begin +
2727c478bd9Sstevel@tonic-gate 	    qbuf->qb_cookie[qbuf->qb_ptrs.qp_current_buf].dmac_size - 1;
2737c478bd9Sstevel@tonic-gate 	qbuf->qb_ptrs.qp_current = qbuf->qb_ptrs.qp_begin;
2747c478bd9Sstevel@tonic-gate 	qbuf->qb_ptrs.qp_offset = 0;
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate 	/*
2777c478bd9Sstevel@tonic-gate 	 * The free_buf and free pointer will change everytime an ACK (of some
2787c478bd9Sstevel@tonic-gate 	 * type) is processed.  Free is the last byte in the last cookie.
2797c478bd9Sstevel@tonic-gate 	 */
2807c478bd9Sstevel@tonic-gate 	qbuf->qb_ptrs.qp_free_buf = qbuf->qb_buf.bi_cookie_count - 1;
2817c478bd9Sstevel@tonic-gate 	qbuf->qb_ptrs.qp_free = qbuf->qb_ptrs.qp_bottom;
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate 	/*
2847c478bd9Sstevel@tonic-gate 	 * Start with no space to write descriptors.  We first need to call
2857c478bd9Sstevel@tonic-gate 	 * hci1394_q_reserve() before calling hci1394_q_at_write_O*().
2867c478bd9Sstevel@tonic-gate 	 */
2877c478bd9Sstevel@tonic-gate 	qbuf->qb_ptrs.qp_resv_size = 0;
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_q_buf_setup_exit, HCI1394_TNF_HAL_STACK, "");
2907c478bd9Sstevel@tonic-gate }
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate /*
2947c478bd9Sstevel@tonic-gate  * hci1394_q_reset()
2957c478bd9Sstevel@tonic-gate  *    Resets the buffers to an initial state.  This should be called during
2967c478bd9Sstevel@tonic-gate  *    attach and resume.
2977c478bd9Sstevel@tonic-gate  */
2987c478bd9Sstevel@tonic-gate static void
hci1394_q_reset(hci1394_q_handle_t q_handle)2997c478bd9Sstevel@tonic-gate hci1394_q_reset(hci1394_q_handle_t q_handle)
3007c478bd9Sstevel@tonic-gate {
3017c478bd9Sstevel@tonic-gate 	hci1394_q_buf_t *desc;
3027c478bd9Sstevel@tonic-gate 	hci1394_q_buf_t *data;
3037c478bd9Sstevel@tonic-gate 	int index;
3047c478bd9Sstevel@tonic-gate 
3057c478bd9Sstevel@tonic-gate 	ASSERT(q_handle != NULL);
3067c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_q_reset_enter, HCI1394_TNF_HAL_STACK, "");
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate 	mutex_enter(&q_handle->q_mutex);
3097c478bd9Sstevel@tonic-gate 	desc = &q_handle->q_desc;
3107c478bd9Sstevel@tonic-gate 	data = &q_handle->q_data;
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate 	hci1394_q_buf_setup(desc);
3137c478bd9Sstevel@tonic-gate 	hci1394_q_buf_setup(data);
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate 	/* DMA starts off stopped, no previous descriptor to link from */
3167c478bd9Sstevel@tonic-gate 	q_handle->q_dma_running = B_FALSE;
3177c478bd9Sstevel@tonic-gate 	q_handle->q_block_cnt = 0;
3187c478bd9Sstevel@tonic-gate 	q_handle->q_previous = NULL;
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate 	/* If this is an AR Q, setup IM's for the data buffers that we have */
3217c478bd9Sstevel@tonic-gate 	if (q_handle->q_info.qi_mode == HCI1394_ARQ) {
3227c478bd9Sstevel@tonic-gate 		/*
3237c478bd9Sstevel@tonic-gate 		 * This points to where to find the first IM descriptor.  Since
3247c478bd9Sstevel@tonic-gate 		 * we just reset the pointers in hci1394_q_buf_setup(), the
3257c478bd9Sstevel@tonic-gate 		 * first IM we write below will be found at the top of the Q.
3267c478bd9Sstevel@tonic-gate 		 */
3277c478bd9Sstevel@tonic-gate 		q_handle->q_head = desc->qb_ptrs.qp_top;
3287c478bd9Sstevel@tonic-gate 
3297c478bd9Sstevel@tonic-gate 		for (index = 0; index < data->qb_buf.bi_cookie_count; index++) {
3307c478bd9Sstevel@tonic-gate 			hci1394_q_ar_write_IM(q_handle, desc,
3317c478bd9Sstevel@tonic-gate 			    data->qb_cookie[index].dmac_address,
3327c478bd9Sstevel@tonic-gate 			    data->qb_cookie[index].dmac_size);
3337c478bd9Sstevel@tonic-gate 		}
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate 		/*
3367c478bd9Sstevel@tonic-gate 		 * The space left in the current IM is the size of the buffer.
3377c478bd9Sstevel@tonic-gate 		 * The current buffer is the first buffer added to the AR Q.
3387c478bd9Sstevel@tonic-gate 		 */
3397c478bd9Sstevel@tonic-gate 		q_handle->q_space_left = data->qb_cookie[0].dmac_size;
3407c478bd9Sstevel@tonic-gate 	}
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate 	mutex_exit(&q_handle->q_mutex);
3437c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_q_reset_exit, HCI1394_TNF_HAL_STACK, "");
3447c478bd9Sstevel@tonic-gate }
3457c478bd9Sstevel@tonic-gate 
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate /*
3487c478bd9Sstevel@tonic-gate  * hci1394_q_resume()
3497c478bd9Sstevel@tonic-gate  *    This is called during a resume (after a successful suspend). Currently
3507c478bd9Sstevel@tonic-gate  *    we only call reset.  Since this is not a time critical function, we will
3517c478bd9Sstevel@tonic-gate  *    leave this as a separate function to increase readability.
3527c478bd9Sstevel@tonic-gate  */
3537c478bd9Sstevel@tonic-gate void
hci1394_q_resume(hci1394_q_handle_t q_handle)3547c478bd9Sstevel@tonic-gate hci1394_q_resume(hci1394_q_handle_t q_handle)
3557c478bd9Sstevel@tonic-gate {
3567c478bd9Sstevel@tonic-gate 	ASSERT(q_handle != NULL);
3577c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_q_resume_enter, HCI1394_TNF_HAL_STACK, "");
3587c478bd9Sstevel@tonic-gate 	hci1394_q_reset(q_handle);
3597c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_q_resume_exit, HCI1394_TNF_HAL_STACK, "");
3607c478bd9Sstevel@tonic-gate }
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate /*
3647c478bd9Sstevel@tonic-gate  * hci1394_q_stop()
3657c478bd9Sstevel@tonic-gate  *    This call informs us that a DMA engine has been stopped.  It does not
3667c478bd9Sstevel@tonic-gate  *    perform the actual stop. We need to know this so that when we add a
3677c478bd9Sstevel@tonic-gate  *    new descriptor, we do a start instead of a wake.
3687c478bd9Sstevel@tonic-gate  */
3697c478bd9Sstevel@tonic-gate void
hci1394_q_stop(hci1394_q_handle_t q_handle)3707c478bd9Sstevel@tonic-gate hci1394_q_stop(hci1394_q_handle_t q_handle)
3717c478bd9Sstevel@tonic-gate {
3727c478bd9Sstevel@tonic-gate 	ASSERT(q_handle != NULL);
3737c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_q_stop_enter, HCI1394_TNF_HAL_STACK, "");
3747c478bd9Sstevel@tonic-gate 	mutex_enter(&q_handle->q_mutex);
3757c478bd9Sstevel@tonic-gate 	q_handle->q_dma_running = B_FALSE;
3767c478bd9Sstevel@tonic-gate 	mutex_exit(&q_handle->q_mutex);
3777c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_q_stop_exit, HCI1394_TNF_HAL_STACK, "");
3787c478bd9Sstevel@tonic-gate }
3797c478bd9Sstevel@tonic-gate 
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate /*
3827c478bd9Sstevel@tonic-gate  * hci1394_q_reserve()
3837c478bd9Sstevel@tonic-gate  *    Reserve space in the AT descriptor or data buffer. This ensures that we
3847c478bd9Sstevel@tonic-gate  *    can get a contiguous buffer. Descriptors have to be in a contiguous
3857c478bd9Sstevel@tonic-gate  *    buffer. Data does not have to be in a contiguous buffer but we do this to
3867c478bd9Sstevel@tonic-gate  *    reduce complexity. For systems with small page sizes (e.g. x86), this
3877c478bd9Sstevel@tonic-gate  *    could result in inefficient use of the data buffers when sending large
3887c478bd9Sstevel@tonic-gate  *    data blocks (this only applies to non-physical block write ATREQs and
3897c478bd9Sstevel@tonic-gate  *    block read ATRESP). Since it looks like most protocols that use large data
3907c478bd9Sstevel@tonic-gate  *    blocks (like SPB-2), use physical transfers to do this (due to their
3917c478bd9Sstevel@tonic-gate  *    efficiency), this will probably not be a real world problem.  If it turns
3927c478bd9Sstevel@tonic-gate  *    out to be a problem, the options are to force a single cookie for the data
3937c478bd9Sstevel@tonic-gate  *    buffer, allow multiple cookies and have a larger data space, or change the
3947c478bd9Sstevel@tonic-gate  *    data code to use a OMI, OM, OL descriptor sequence (instead of OMI, OL).
3957c478bd9Sstevel@tonic-gate  */
3967c478bd9Sstevel@tonic-gate static int
hci1394_q_reserve(hci1394_q_buf_t * qbuf,uint_t size,uint32_t * io_addr)3977c478bd9Sstevel@tonic-gate hci1394_q_reserve(hci1394_q_buf_t *qbuf, uint_t size, uint32_t *io_addr)
3987c478bd9Sstevel@tonic-gate {
3997c478bd9Sstevel@tonic-gate 	uint_t aligned_size;
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate 	ASSERT(qbuf != NULL);
4037c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_q_reserve_enter, HCI1394_TNF_HAL_STACK, "");
4047c478bd9Sstevel@tonic-gate 
4057c478bd9Sstevel@tonic-gate 	/* Save backup of pointers in case we have to unreserve */
4067c478bd9Sstevel@tonic-gate 	qbuf->qb_backup_ptrs = qbuf->qb_ptrs;
4077c478bd9Sstevel@tonic-gate 
4087c478bd9Sstevel@tonic-gate 	/*
4097c478bd9Sstevel@tonic-gate 	 * Make sure all alloc's are quadlet aligned. The data doesn't have to
4107c478bd9Sstevel@tonic-gate 	 * be, so we will force it to be.
4117c478bd9Sstevel@tonic-gate 	 */
4127c478bd9Sstevel@tonic-gate 	aligned_size = HCI1394_ALIGN_QUAD(size);
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate 	/*
4157c478bd9Sstevel@tonic-gate 	 * if the free pointer is in the current buffer and the free pointer
4167c478bd9Sstevel@tonic-gate 	 * is below the current pointer (i.e. has not wrapped around)
4177c478bd9Sstevel@tonic-gate 	 */
4187c478bd9Sstevel@tonic-gate 	if ((qbuf->qb_ptrs.qp_current_buf == qbuf->qb_ptrs.qp_free_buf) &&
4197c478bd9Sstevel@tonic-gate 	    (qbuf->qb_ptrs.qp_free >= qbuf->qb_ptrs.qp_current)) {
4207c478bd9Sstevel@tonic-gate 		/*
4217c478bd9Sstevel@tonic-gate 		 * The free pointer is in this buffer below the current pointer.
4227c478bd9Sstevel@tonic-gate 		 * Check to see if we have enough free space left.
4237c478bd9Sstevel@tonic-gate 		 */
4247c478bd9Sstevel@tonic-gate 		if ((qbuf->qb_ptrs.qp_current + aligned_size) <=
4257c478bd9Sstevel@tonic-gate 		    qbuf->qb_ptrs.qp_free) {
4267c478bd9Sstevel@tonic-gate 			/* Setup up our reserved size, return the IO address */
4277c478bd9Sstevel@tonic-gate 			qbuf->qb_ptrs.qp_resv_size = aligned_size;
4287c478bd9Sstevel@tonic-gate 			*io_addr = (uint32_t)(qbuf->qb_cookie[
4297c478bd9Sstevel@tonic-gate 			    qbuf->qb_ptrs.qp_current_buf].dmac_address +
4307c478bd9Sstevel@tonic-gate 			    qbuf->qb_ptrs.qp_offset);
4317c478bd9Sstevel@tonic-gate 
4327c478bd9Sstevel@tonic-gate 		/*
4337c478bd9Sstevel@tonic-gate 		 * The free pointer is in this buffer below the current pointer.
4347c478bd9Sstevel@tonic-gate 		 * We do not have enough free space for the alloc. Return
4357c478bd9Sstevel@tonic-gate 		 * failure.
4367c478bd9Sstevel@tonic-gate 		 */
4377c478bd9Sstevel@tonic-gate 		} else {
4387c478bd9Sstevel@tonic-gate 			qbuf->qb_ptrs.qp_resv_size = 0;
4397c478bd9Sstevel@tonic-gate 			TNF_PROBE_0(hci1394_q_reserve_ns_fail,
4407c478bd9Sstevel@tonic-gate 			    HCI1394_TNF_HAL_ERROR, "");
4417c478bd9Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(hci1394_q_reserve_exit,
4427c478bd9Sstevel@tonic-gate 			    HCI1394_TNF_HAL_STACK, "");
4437c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
4447c478bd9Sstevel@tonic-gate 		}
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate 	/*
4477c478bd9Sstevel@tonic-gate 	 * If there is not enough room to fit in the current buffer (not
4487c478bd9Sstevel@tonic-gate 	 * including wrap around), we will go to the next buffer and check
4497c478bd9Sstevel@tonic-gate 	 * there. If we only have one buffer (i.e. one cookie), we will end up
4507c478bd9Sstevel@tonic-gate 	 * staying at the current buffer and wrapping the address back to the
4517c478bd9Sstevel@tonic-gate 	 * top.
4527c478bd9Sstevel@tonic-gate 	 */
4537c478bd9Sstevel@tonic-gate 	} else if ((qbuf->qb_ptrs.qp_current + aligned_size) >
4547c478bd9Sstevel@tonic-gate 	    qbuf->qb_ptrs.qp_end) {
4557c478bd9Sstevel@tonic-gate 		/* Go to the next buffer (or the top of ours for one cookie) */
4567c478bd9Sstevel@tonic-gate 		hci1394_q_next_buf(qbuf);
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate 		/* If the free pointer is in the new current buffer */
4597c478bd9Sstevel@tonic-gate 		if (qbuf->qb_ptrs.qp_current_buf == qbuf->qb_ptrs.qp_free_buf) {
4607c478bd9Sstevel@tonic-gate 			/*
4617c478bd9Sstevel@tonic-gate 			 * The free pointer is in this buffer. If we do not have
4627c478bd9Sstevel@tonic-gate 			 * enough free space for the alloc. Return failure.
4637c478bd9Sstevel@tonic-gate 			 */
4647c478bd9Sstevel@tonic-gate 			if ((qbuf->qb_ptrs.qp_current + aligned_size) >
4657c478bd9Sstevel@tonic-gate 			    qbuf->qb_ptrs.qp_free) {
4667c478bd9Sstevel@tonic-gate 				qbuf->qb_ptrs.qp_resv_size = 0;
4677c478bd9Sstevel@tonic-gate 				TNF_PROBE_0(hci1394_q_reserve_ns_fail,
4687c478bd9Sstevel@tonic-gate 				    HCI1394_TNF_HAL_ERROR, "");
4697c478bd9Sstevel@tonic-gate 				TNF_PROBE_0_DEBUG(hci1394_q_reserve_exit,
4707c478bd9Sstevel@tonic-gate 				    HCI1394_TNF_HAL_STACK, "");
4717c478bd9Sstevel@tonic-gate 				return (DDI_FAILURE);
4727c478bd9Sstevel@tonic-gate 			/*
4737c478bd9Sstevel@tonic-gate 			 * The free pointer is in this buffer. We have enough
4747c478bd9Sstevel@tonic-gate 			 * free space left.
4757c478bd9Sstevel@tonic-gate 			 */
4767c478bd9Sstevel@tonic-gate 			} else {
4777c478bd9Sstevel@tonic-gate 				/*
4787c478bd9Sstevel@tonic-gate 				 * Setup up our reserved size, return the IO
4797c478bd9Sstevel@tonic-gate 				 * address
4807c478bd9Sstevel@tonic-gate 				 */
4817c478bd9Sstevel@tonic-gate 				qbuf->qb_ptrs.qp_resv_size = aligned_size;
4827c478bd9Sstevel@tonic-gate 				*io_addr = (uint32_t)(qbuf->qb_cookie[
4837c478bd9Sstevel@tonic-gate 				    qbuf->qb_ptrs.qp_current_buf].dmac_address +
4847c478bd9Sstevel@tonic-gate 				    qbuf->qb_ptrs.qp_offset);
4857c478bd9Sstevel@tonic-gate 			}
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate 		/*
4887c478bd9Sstevel@tonic-gate 		 * We switched buffers and the free pointer is still in another
4897c478bd9Sstevel@tonic-gate 		 * buffer. We have sufficient space in this buffer for the alloc
4907c478bd9Sstevel@tonic-gate 		 * after changing buffers.
4917c478bd9Sstevel@tonic-gate 		 */
4927c478bd9Sstevel@tonic-gate 		} else {
4937c478bd9Sstevel@tonic-gate 			/* Setup up our reserved size, return the IO address */
4947c478bd9Sstevel@tonic-gate 			qbuf->qb_ptrs.qp_resv_size = aligned_size;
4957c478bd9Sstevel@tonic-gate 			*io_addr = (uint32_t)(qbuf->qb_cookie[
4967c478bd9Sstevel@tonic-gate 			    qbuf->qb_ptrs.qp_current_buf].dmac_address +
4977c478bd9Sstevel@tonic-gate 			    qbuf->qb_ptrs.qp_offset);
4987c478bd9Sstevel@tonic-gate 		}
4997c478bd9Sstevel@tonic-gate 	/*
5007c478bd9Sstevel@tonic-gate 	 * The free pointer is in another buffer. We have sufficient space in
5017c478bd9Sstevel@tonic-gate 	 * this buffer for the alloc.
5027c478bd9Sstevel@tonic-gate 	 */
5037c478bd9Sstevel@tonic-gate 	} else {
5047c478bd9Sstevel@tonic-gate 		/* Setup up our reserved size, return the IO address */
5057c478bd9Sstevel@tonic-gate 		qbuf->qb_ptrs.qp_resv_size = aligned_size;
5067c478bd9Sstevel@tonic-gate 		*io_addr = (uint32_t)(qbuf->qb_cookie[
5077c478bd9Sstevel@tonic-gate 		    qbuf->qb_ptrs.qp_current_buf].dmac_address +
5087c478bd9Sstevel@tonic-gate 		    qbuf->qb_ptrs.qp_offset);
5097c478bd9Sstevel@tonic-gate 	}
5107c478bd9Sstevel@tonic-gate 
5117c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_q_reserve_exit, HCI1394_TNF_HAL_STACK, "");
5127c478bd9Sstevel@tonic-gate 
5137c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
5147c478bd9Sstevel@tonic-gate }
5157c478bd9Sstevel@tonic-gate 
5167c478bd9Sstevel@tonic-gate /*
5177c478bd9Sstevel@tonic-gate  * hci1394_q_unreserve()
5187c478bd9Sstevel@tonic-gate  *    Set the buffer pointer to what they were before hci1394_reserve().  This
5197c478bd9Sstevel@tonic-gate  *    will be called when we encounter errors during hci1394_q_at*().
5207c478bd9Sstevel@tonic-gate  */
5217c478bd9Sstevel@tonic-gate static void
hci1394_q_unreserve(hci1394_q_buf_t * qbuf)5227c478bd9Sstevel@tonic-gate hci1394_q_unreserve(hci1394_q_buf_t *qbuf)
5237c478bd9Sstevel@tonic-gate {
5247c478bd9Sstevel@tonic-gate 	ASSERT(qbuf != NULL);
5257c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_q_unreserve_enter, HCI1394_TNF_HAL_STACK, "");
5267c478bd9Sstevel@tonic-gate 
5277c478bd9Sstevel@tonic-gate 	/* Go back to pointer setting before the reserve */
5287c478bd9Sstevel@tonic-gate 	qbuf->qb_ptrs = qbuf->qb_backup_ptrs;
5297c478bd9Sstevel@tonic-gate 
5307c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_q_unreserve_exit, HCI1394_TNF_HAL_STACK, "");
5317c478bd9Sstevel@tonic-gate }
5327c478bd9Sstevel@tonic-gate 
5337c478bd9Sstevel@tonic-gate 
5347c478bd9Sstevel@tonic-gate /*
5357c478bd9Sstevel@tonic-gate  * hci1394_q_next_buf()
5367c478bd9Sstevel@tonic-gate  *    Set our current buffer to the next cookie.  If we only have one cookie, we
5377c478bd9Sstevel@tonic-gate  *    will go back to the top of our buffer.
5387c478bd9Sstevel@tonic-gate  */
5397c478bd9Sstevel@tonic-gate void
hci1394_q_next_buf(hci1394_q_buf_t * qbuf)5407c478bd9Sstevel@tonic-gate hci1394_q_next_buf(hci1394_q_buf_t *qbuf)
5417c478bd9Sstevel@tonic-gate {
5427c478bd9Sstevel@tonic-gate 	ASSERT(qbuf != NULL);
5437c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_q_next_buf_enter, HCI1394_TNF_HAL_STACK, "");
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate 	/*
5467c478bd9Sstevel@tonic-gate 	 * go to the next cookie, if we are >= the cookie count, go back to the
5477c478bd9Sstevel@tonic-gate 	 * first cookie.
5487c478bd9Sstevel@tonic-gate 	 */
5497c478bd9Sstevel@tonic-gate 	qbuf->qb_ptrs.qp_current_buf++;
5507c478bd9Sstevel@tonic-gate 	if (qbuf->qb_ptrs.qp_current_buf >= qbuf->qb_buf.bi_cookie_count) {
5517c478bd9Sstevel@tonic-gate 		qbuf->qb_ptrs.qp_current_buf = 0;
5527c478bd9Sstevel@tonic-gate 	}
5537c478bd9Sstevel@tonic-gate 
5547c478bd9Sstevel@tonic-gate 	/* adjust the begin, end, current, and offset pointers */
5557c478bd9Sstevel@tonic-gate 	qbuf->qb_ptrs.qp_begin = qbuf->qb_ptrs.qp_end + 1;
5567c478bd9Sstevel@tonic-gate 	if (qbuf->qb_ptrs.qp_begin > qbuf->qb_ptrs.qp_bottom) {
5577c478bd9Sstevel@tonic-gate 		qbuf->qb_ptrs.qp_begin = qbuf->qb_ptrs.qp_top;
5587c478bd9Sstevel@tonic-gate 	}
5597c478bd9Sstevel@tonic-gate 	qbuf->qb_ptrs.qp_end = qbuf->qb_ptrs.qp_begin +
5607c478bd9Sstevel@tonic-gate 	    qbuf->qb_cookie[qbuf->qb_ptrs.qp_current_buf].dmac_size - 1;
5617c478bd9Sstevel@tonic-gate 	qbuf->qb_ptrs.qp_current = qbuf->qb_ptrs.qp_begin;
5627c478bd9Sstevel@tonic-gate 	qbuf->qb_ptrs.qp_offset = 0;
5637c478bd9Sstevel@tonic-gate 
5647c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_q_next_buf_exit, HCI1394_TNF_HAL_STACK, "");
5657c478bd9Sstevel@tonic-gate }
5667c478bd9Sstevel@tonic-gate 
5677c478bd9Sstevel@tonic-gate 
5687c478bd9Sstevel@tonic-gate /*
5697c478bd9Sstevel@tonic-gate  * hci1394_q_at()
5707c478bd9Sstevel@tonic-gate  *    Place an AT command that does NOT need the data buffer into the DMA chain.
5717c478bd9Sstevel@tonic-gate  *    Some examples of this are quadlet read/write, PHY packets, ATREQ Block
5727c478bd9Sstevel@tonic-gate  *    Read, and ATRESP block write. result is only valid on failure.
5737c478bd9Sstevel@tonic-gate  */
5747c478bd9Sstevel@tonic-gate int
hci1394_q_at(hci1394_q_handle_t q_handle,hci1394_q_cmd_t * cmd,hci1394_basic_pkt_t * hdr,uint_t hdrsize,int * result)5757c478bd9Sstevel@tonic-gate hci1394_q_at(hci1394_q_handle_t q_handle, hci1394_q_cmd_t *cmd,
5767c478bd9Sstevel@tonic-gate     hci1394_basic_pkt_t *hdr, uint_t hdrsize, int *result)
5777c478bd9Sstevel@tonic-gate {
5787c478bd9Sstevel@tonic-gate 	int status;
5797c478bd9Sstevel@tonic-gate 	uint32_t ioaddr;
5807c478bd9Sstevel@tonic-gate 
5817c478bd9Sstevel@tonic-gate 
5827c478bd9Sstevel@tonic-gate 	ASSERT(q_handle != NULL);
5837c478bd9Sstevel@tonic-gate 	ASSERT(cmd != NULL);
5847c478bd9Sstevel@tonic-gate 	ASSERT(hdr != NULL);
5857c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_q_at_enter, HCI1394_TNF_HAL_STACK, "");
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate 	mutex_enter(&q_handle->q_mutex);
5887c478bd9Sstevel@tonic-gate 
5897c478bd9Sstevel@tonic-gate 	/*
5907c478bd9Sstevel@tonic-gate 	 * Check the HAL state and generation when the AT Q is locked.  This
5917c478bd9Sstevel@tonic-gate 	 * will make sure that we get all the commands when we flush the Q's
5927c478bd9Sstevel@tonic-gate 	 * during a reset or shutdown.
5937c478bd9Sstevel@tonic-gate 	 */
5947c478bd9Sstevel@tonic-gate 	if ((hci1394_state(q_handle->q_drvinfo) != HCI1394_NORMAL) ||
5957c478bd9Sstevel@tonic-gate 	    (hci1394_ohci_current_busgen(q_handle->q_ohci) !=
5967c478bd9Sstevel@tonic-gate 	    cmd->qc_generation)) {
5977c478bd9Sstevel@tonic-gate 		*result = H1394_STATUS_INVALID_BUSGEN;
5987c478bd9Sstevel@tonic-gate 		mutex_exit(&q_handle->q_mutex);
5997c478bd9Sstevel@tonic-gate 		TNF_PROBE_0(hci1394_q_at_st_fail, HCI1394_TNF_HAL_ERROR, "");
6007c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(hci1394_q_at_exit, HCI1394_TNF_HAL_STACK,
6017c478bd9Sstevel@tonic-gate 		    "");
6027c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
6037c478bd9Sstevel@tonic-gate 	}
6047c478bd9Sstevel@tonic-gate 
6057c478bd9Sstevel@tonic-gate 	/* save away the argument to pass up when this command completes */
6067c478bd9Sstevel@tonic-gate 	cmd->qc_node.tln_addr = cmd;
6077c478bd9Sstevel@tonic-gate 
6087c478bd9Sstevel@tonic-gate 	/* we have not written any 16 byte blocks to the descriptor yet */
6097c478bd9Sstevel@tonic-gate 	q_handle->q_block_cnt = 0;
6107c478bd9Sstevel@tonic-gate 
6117c478bd9Sstevel@tonic-gate 	/* Reserve space for an OLI in the descriptor buffer */
6127c478bd9Sstevel@tonic-gate 	status = hci1394_q_reserve(&q_handle->q_desc,
6137c478bd9Sstevel@tonic-gate 	    sizeof (hci1394_desc_imm_t), &ioaddr);
6147c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
6157c478bd9Sstevel@tonic-gate 		*result = H1394_STATUS_NOMORE_SPACE;
6167c478bd9Sstevel@tonic-gate 		mutex_exit(&q_handle->q_mutex);
6177c478bd9Sstevel@tonic-gate 		TNF_PROBE_0(hci1394_q_at_qre_fail, HCI1394_TNF_HAL_ERROR, "");
6187c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(hci1394_q_at_exit, HCI1394_TNF_HAL_STACK,
6197c478bd9Sstevel@tonic-gate 		    "");
6207c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
6217c478bd9Sstevel@tonic-gate 	}
6227c478bd9Sstevel@tonic-gate 
6237c478bd9Sstevel@tonic-gate 	/* write the OLI to the descriptor buffer */
6247c478bd9Sstevel@tonic-gate 	hci1394_q_at_write_OLI(q_handle, &q_handle->q_desc, cmd, hdr, hdrsize);
6257c478bd9Sstevel@tonic-gate 
6267c478bd9Sstevel@tonic-gate 	/* Add the AT command to the queued list */
6277c478bd9Sstevel@tonic-gate 	hci1394_tlist_add(q_handle->q_queued_list, &cmd->qc_node);
6287c478bd9Sstevel@tonic-gate 
6297c478bd9Sstevel@tonic-gate 	mutex_exit(&q_handle->q_mutex);
6307c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_q_at_exit, HCI1394_TNF_HAL_STACK, "");
6317c478bd9Sstevel@tonic-gate 
6327c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
6337c478bd9Sstevel@tonic-gate }
6347c478bd9Sstevel@tonic-gate 
6357c478bd9Sstevel@tonic-gate 
6367c478bd9Sstevel@tonic-gate /*
6377c478bd9Sstevel@tonic-gate  * XXX - NOTE: POSSIBLE FUTURE OPTIMIZATION
6387c478bd9Sstevel@tonic-gate  *    ATREQ Block read and write's that go through software are not very
6397c478bd9Sstevel@tonic-gate  *    efficient (one of the reasons to use physical space). A copy is forced
6407c478bd9Sstevel@tonic-gate  *    on all block reads due to the design of OpenHCI. Writes do not have this
6417c478bd9Sstevel@tonic-gate  *    same restriction.  This design forces a copy for writes too (we always
6427c478bd9Sstevel@tonic-gate  *    copy into a data buffer before sending). There are many reasons for this
6437c478bd9Sstevel@tonic-gate  *    including complexity reduction.  There is a data size threshold where a
6447c478bd9Sstevel@tonic-gate  *    copy is more expensive than mapping the data buffer address (or worse
6457c478bd9Sstevel@tonic-gate  *    case a big enough difference where it pays to do it). However, we move
6467c478bd9Sstevel@tonic-gate  *    block data around in mblks which means that our data may be scattered
6477c478bd9Sstevel@tonic-gate  *    over many buffers.  This adds to the complexity of mapping and setting
6487c478bd9Sstevel@tonic-gate  *    up the OpenHCI descriptors.
6497c478bd9Sstevel@tonic-gate  *
6507c478bd9Sstevel@tonic-gate  *    If someone really needs a speedup on block write ATREQs, my recommendation
6517c478bd9Sstevel@tonic-gate  *    would be to add an additional command type at the target interface for a
6527c478bd9Sstevel@tonic-gate  *    fast block write.  The target driver would pass a mapped io addr to use.
6537c478bd9Sstevel@tonic-gate  *    A function like "hci1394_q_at_with_ioaddr()" could be created which would
6547c478bd9Sstevel@tonic-gate  *    be almost an exact copy of hci1394_q_at_with_data() without the
6557c478bd9Sstevel@tonic-gate  *    hci1394_q_reserve() and hci1394_q_at_rep_put8() for the data buffer.
6567c478bd9Sstevel@tonic-gate  */
6577c478bd9Sstevel@tonic-gate 
6587c478bd9Sstevel@tonic-gate 
6597c478bd9Sstevel@tonic-gate /*
6607c478bd9Sstevel@tonic-gate  * hci1394_q_at_with_data()
6617c478bd9Sstevel@tonic-gate  *    Place an AT command that does need the data buffer into the DMA chain.
6627c478bd9Sstevel@tonic-gate  *    The data is passed as a pointer to a kernel virtual address. An example of
6637c478bd9Sstevel@tonic-gate  *    this is the lock operations. result is only valid on failure.
6647c478bd9Sstevel@tonic-gate  */
6657c478bd9Sstevel@tonic-gate int
hci1394_q_at_with_data(hci1394_q_handle_t q_handle,hci1394_q_cmd_t * cmd,hci1394_basic_pkt_t * hdr,uint_t hdrsize,uint8_t * data,uint_t datasize,int * result)6667c478bd9Sstevel@tonic-gate hci1394_q_at_with_data(hci1394_q_handle_t q_handle, hci1394_q_cmd_t *cmd,
6677c478bd9Sstevel@tonic-gate     hci1394_basic_pkt_t *hdr, uint_t hdrsize, uint8_t *data, uint_t datasize,
6687c478bd9Sstevel@tonic-gate     int *result)
6697c478bd9Sstevel@tonic-gate {
6707c478bd9Sstevel@tonic-gate 	uint32_t desc_ioaddr;
6717c478bd9Sstevel@tonic-gate 	uint32_t data_ioaddr;
6727c478bd9Sstevel@tonic-gate 	int status;
6737c478bd9Sstevel@tonic-gate 
6747c478bd9Sstevel@tonic-gate 
6757c478bd9Sstevel@tonic-gate 	ASSERT(q_handle != NULL);
6767c478bd9Sstevel@tonic-gate 	ASSERT(cmd != NULL);
6777c478bd9Sstevel@tonic-gate 	ASSERT(hdr != NULL);
6787c478bd9Sstevel@tonic-gate 	ASSERT(data != NULL);
6797c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_q_at_with_data_enter, HCI1394_TNF_HAL_STACK,
6807c478bd9Sstevel@tonic-gate 	    "");
6817c478bd9Sstevel@tonic-gate 
6827c478bd9Sstevel@tonic-gate 	mutex_enter(&q_handle->q_mutex);
6837c478bd9Sstevel@tonic-gate 
6847c478bd9Sstevel@tonic-gate 	/*
6857c478bd9Sstevel@tonic-gate 	 * Check the HAL state and generation when the AT Q is locked.  This
6867c478bd9Sstevel@tonic-gate 	 * will make sure that we get all the commands when we flush the Q's
6877c478bd9Sstevel@tonic-gate 	 * during a reset or shutdown.
6887c478bd9Sstevel@tonic-gate 	 */
6897c478bd9Sstevel@tonic-gate 	if ((hci1394_state(q_handle->q_drvinfo) != HCI1394_NORMAL) ||
6907c478bd9Sstevel@tonic-gate 	    (hci1394_ohci_current_busgen(q_handle->q_ohci) !=
6917c478bd9Sstevel@tonic-gate 	    cmd->qc_generation)) {
6927c478bd9Sstevel@tonic-gate 		*result = H1394_STATUS_INVALID_BUSGEN;
6937c478bd9Sstevel@tonic-gate 		mutex_exit(&q_handle->q_mutex);
6947c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(hci1394_q_at_wd_st_fail,
6957c478bd9Sstevel@tonic-gate 		    HCI1394_TNF_HAL_STACK, "");
6967c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
6977c478bd9Sstevel@tonic-gate 	}
6987c478bd9Sstevel@tonic-gate 
6997c478bd9Sstevel@tonic-gate 	/* save away the argument to pass up when this command completes */
7007c478bd9Sstevel@tonic-gate 	cmd->qc_node.tln_addr = cmd;
7017c478bd9Sstevel@tonic-gate 
7027c478bd9Sstevel@tonic-gate 	/* we have not written any 16 byte blocks to the descriptor yet */
7037c478bd9Sstevel@tonic-gate 	q_handle->q_block_cnt = 0;
7047c478bd9Sstevel@tonic-gate 
7057c478bd9Sstevel@tonic-gate 	/* Reserve space for an OMI and OL in the descriptor buffer */
7067c478bd9Sstevel@tonic-gate 	status = hci1394_q_reserve(&q_handle->q_desc,
7077c478bd9Sstevel@tonic-gate 	    (sizeof (hci1394_desc_imm_t) + sizeof (hci1394_desc_t)),
7087c478bd9Sstevel@tonic-gate 	    &desc_ioaddr);
7097c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
7107c478bd9Sstevel@tonic-gate 		*result = H1394_STATUS_NOMORE_SPACE;
7117c478bd9Sstevel@tonic-gate 		mutex_exit(&q_handle->q_mutex);
7127c478bd9Sstevel@tonic-gate 		TNF_PROBE_0(hci1394_q_at_wd_qre_fail,
7137c478bd9Sstevel@tonic-gate 		    HCI1394_TNF_HAL_ERROR, "");
7147c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(hci1394_q_at_with_data_exit,
7157c478bd9Sstevel@tonic-gate 		    HCI1394_TNF_HAL_STACK, "");
7167c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
7177c478bd9Sstevel@tonic-gate 	}
7187c478bd9Sstevel@tonic-gate 
7197c478bd9Sstevel@tonic-gate 	/* allocate space for data in the data buffer */
7207c478bd9Sstevel@tonic-gate 	status = hci1394_q_reserve(&q_handle->q_data, datasize, &data_ioaddr);
7217c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
7227c478bd9Sstevel@tonic-gate 		*result = H1394_STATUS_NOMORE_SPACE;
7237c478bd9Sstevel@tonic-gate 		hci1394_q_unreserve(&q_handle->q_desc);
7247c478bd9Sstevel@tonic-gate 		mutex_exit(&q_handle->q_mutex);
7257c478bd9Sstevel@tonic-gate 		TNF_PROBE_0(hci1394_q_at_wd_qra_fail,
7267c478bd9Sstevel@tonic-gate 		    HCI1394_TNF_HAL_ERROR, "");
7277c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(hci1394_q_at_with_data_exit,
7287c478bd9Sstevel@tonic-gate 		    HCI1394_TNF_HAL_STACK, "");
7297c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
7307c478bd9Sstevel@tonic-gate 	}
7317c478bd9Sstevel@tonic-gate 
7327c478bd9Sstevel@tonic-gate 	/* Copy data into data buffer */
7337c478bd9Sstevel@tonic-gate 	hci1394_q_at_rep_put8(&q_handle->q_data, cmd, data, datasize);
7347c478bd9Sstevel@tonic-gate 
7357c478bd9Sstevel@tonic-gate 	/* write the OMI to the descriptor buffer */
7367c478bd9Sstevel@tonic-gate 	hci1394_q_at_write_OMI(q_handle, &q_handle->q_desc, cmd, hdr, hdrsize);
7377c478bd9Sstevel@tonic-gate 
7387c478bd9Sstevel@tonic-gate 	/* write the OL to the descriptor buffer */
7397c478bd9Sstevel@tonic-gate 	hci1394_q_at_write_OL(q_handle, &q_handle->q_desc, cmd, data_ioaddr,
7407c478bd9Sstevel@tonic-gate 	    datasize);
7417c478bd9Sstevel@tonic-gate 
7427c478bd9Sstevel@tonic-gate 	/* Add the AT command to the queued list */
7437c478bd9Sstevel@tonic-gate 	hci1394_tlist_add(q_handle->q_queued_list, &cmd->qc_node);
7447c478bd9Sstevel@tonic-gate 
7457c478bd9Sstevel@tonic-gate 	mutex_exit(&q_handle->q_mutex);
7467c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_q_at_with_data_exit, HCI1394_TNF_HAL_STACK,
7477c478bd9Sstevel@tonic-gate 	    "");
7487c478bd9Sstevel@tonic-gate 
7497c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
7507c478bd9Sstevel@tonic-gate }
7517c478bd9Sstevel@tonic-gate 
7527c478bd9Sstevel@tonic-gate 
7537c478bd9Sstevel@tonic-gate /*
7547c478bd9Sstevel@tonic-gate  * hci1394_q_at_with_mblk()
7557c478bd9Sstevel@tonic-gate  *    Place an AT command that does need the data buffer into the DMA chain.
7567c478bd9Sstevel@tonic-gate  *    The data is passed in mblk_t(s). Examples of this are a block write
7577c478bd9Sstevel@tonic-gate  *    ATREQ and a block read ATRESP. The services layer and the hal use a
7587c478bd9Sstevel@tonic-gate  *    private structure (h1394_mblk_t) to keep track of how much of the mblk
7597c478bd9Sstevel@tonic-gate  *    to send since we may have to break the transfer up into smaller blocks.
7607c478bd9Sstevel@tonic-gate  *    (i.e. a 1MByte block write would go out in 2KByte chunks. result is only
7617c478bd9Sstevel@tonic-gate  *    valid on failure.
7627c478bd9Sstevel@tonic-gate  */
7637c478bd9Sstevel@tonic-gate int
hci1394_q_at_with_mblk(hci1394_q_handle_t q_handle,hci1394_q_cmd_t * cmd,hci1394_basic_pkt_t * hdr,uint_t hdrsize,h1394_mblk_t * mblk,int * result)7647c478bd9Sstevel@tonic-gate hci1394_q_at_with_mblk(hci1394_q_handle_t q_handle, hci1394_q_cmd_t *cmd,
7657c478bd9Sstevel@tonic-gate     hci1394_basic_pkt_t *hdr, uint_t hdrsize, h1394_mblk_t *mblk, int *result)
7667c478bd9Sstevel@tonic-gate {
7677c478bd9Sstevel@tonic-gate 	uint32_t desc_ioaddr;
7687c478bd9Sstevel@tonic-gate 	uint32_t data_ioaddr;
7697c478bd9Sstevel@tonic-gate 	int status;
7707c478bd9Sstevel@tonic-gate 
7717c478bd9Sstevel@tonic-gate 
7727c478bd9Sstevel@tonic-gate 	ASSERT(q_handle != NULL);
7737c478bd9Sstevel@tonic-gate 	ASSERT(cmd != NULL);
7747c478bd9Sstevel@tonic-gate 	ASSERT(hdr != NULL);
7757c478bd9Sstevel@tonic-gate 	ASSERT(mblk != NULL);
7767c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_q_at_with_mblk_enter, HCI1394_TNF_HAL_STACK,
7777c478bd9Sstevel@tonic-gate 	    "");
7787c478bd9Sstevel@tonic-gate 
7797c478bd9Sstevel@tonic-gate 	mutex_enter(&q_handle->q_mutex);
7807c478bd9Sstevel@tonic-gate 
7817c478bd9Sstevel@tonic-gate 	/*
7827c478bd9Sstevel@tonic-gate 	 * Check the HAL state and generation when the AT Q is locked.  This
7837c478bd9Sstevel@tonic-gate 	 * will make sure that we get all the commands when we flush the Q's
7847c478bd9Sstevel@tonic-gate 	 * during a reset or shutdown.
7857c478bd9Sstevel@tonic-gate 	 */
7867c478bd9Sstevel@tonic-gate 	if ((hci1394_state(q_handle->q_drvinfo) != HCI1394_NORMAL) ||
7877c478bd9Sstevel@tonic-gate 	    (hci1394_ohci_current_busgen(q_handle->q_ohci) !=
7887c478bd9Sstevel@tonic-gate 	    cmd->qc_generation)) {
7897c478bd9Sstevel@tonic-gate 		*result = H1394_STATUS_INVALID_BUSGEN;
7907c478bd9Sstevel@tonic-gate 		mutex_exit(&q_handle->q_mutex);
7917c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(hci1394_q_at_wm_st_fail,
7927c478bd9Sstevel@tonic-gate 		    HCI1394_TNF_HAL_STACK, "");
7937c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
7947c478bd9Sstevel@tonic-gate 	}
7957c478bd9Sstevel@tonic-gate 
7967c478bd9Sstevel@tonic-gate 	/* save away the argument to pass up when this command completes */
7977c478bd9Sstevel@tonic-gate 	cmd->qc_node.tln_addr = cmd;
7987c478bd9Sstevel@tonic-gate 
7997c478bd9Sstevel@tonic-gate 	/* we have not written any 16 byte blocks to the descriptor yet */
8007c478bd9Sstevel@tonic-gate 	q_handle->q_block_cnt = 0;
8017c478bd9Sstevel@tonic-gate 
8027c478bd9Sstevel@tonic-gate 	/* Reserve space for an OMI and OL in the descriptor buffer */
8037c478bd9Sstevel@tonic-gate 	status = hci1394_q_reserve(&q_handle->q_desc,
8047c478bd9Sstevel@tonic-gate 	    (sizeof (hci1394_desc_imm_t) + sizeof (hci1394_desc_t)),
8057c478bd9Sstevel@tonic-gate 	    &desc_ioaddr);
8067c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
8077c478bd9Sstevel@tonic-gate 		*result = H1394_STATUS_NOMORE_SPACE;
8087c478bd9Sstevel@tonic-gate 		mutex_exit(&q_handle->q_mutex);
8097c478bd9Sstevel@tonic-gate 		TNF_PROBE_0(hci1394_q_at_wm_qre_fail,
8107c478bd9Sstevel@tonic-gate 		    HCI1394_TNF_HAL_ERROR, "");
8117c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(hci1394_q_at_with_mblk_exit,
8127c478bd9Sstevel@tonic-gate 		    HCI1394_TNF_HAL_STACK, "");
8137c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
8147c478bd9Sstevel@tonic-gate 	}
8157c478bd9Sstevel@tonic-gate 
8167c478bd9Sstevel@tonic-gate 	/* Reserve space for data in the data buffer */
8177c478bd9Sstevel@tonic-gate 	status = hci1394_q_reserve(&q_handle->q_data, mblk->length,
8187c478bd9Sstevel@tonic-gate 	    &data_ioaddr);
8197c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
8207c478bd9Sstevel@tonic-gate 		*result = H1394_STATUS_NOMORE_SPACE;
8217c478bd9Sstevel@tonic-gate 		hci1394_q_unreserve(&q_handle->q_desc);
8227c478bd9Sstevel@tonic-gate 		mutex_exit(&q_handle->q_mutex);
8237c478bd9Sstevel@tonic-gate 		TNF_PROBE_0(hci1394_q_at_wm_qra_fail,
8247c478bd9Sstevel@tonic-gate 		    HCI1394_TNF_HAL_ERROR, "");
8257c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(hci1394_q_at_with_mblk_exit,
8267c478bd9Sstevel@tonic-gate 		    HCI1394_TNF_HAL_STACK, "");
8277c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
8287c478bd9Sstevel@tonic-gate 	}
8297c478bd9Sstevel@tonic-gate 
8307c478bd9Sstevel@tonic-gate 	/* Copy mblk data into data buffer */
8317c478bd9Sstevel@tonic-gate 	hci1394_q_at_copy_from_mblk(&q_handle->q_data, cmd, mblk);
8327c478bd9Sstevel@tonic-gate 
8337c478bd9Sstevel@tonic-gate 	/* write the OMI to the descriptor buffer */
8347c478bd9Sstevel@tonic-gate 	hci1394_q_at_write_OMI(q_handle, &q_handle->q_desc, cmd, hdr, hdrsize);
8357c478bd9Sstevel@tonic-gate 
8367c478bd9Sstevel@tonic-gate 	/* write the OL to the descriptor buffer */
8377c478bd9Sstevel@tonic-gate 	hci1394_q_at_write_OL(q_handle, &q_handle->q_desc, cmd, data_ioaddr,
8387c478bd9Sstevel@tonic-gate 	    mblk->length);
8397c478bd9Sstevel@tonic-gate 
8407c478bd9Sstevel@tonic-gate 	/* Add the AT command to the queued list */
8417c478bd9Sstevel@tonic-gate 	hci1394_tlist_add(q_handle->q_queued_list, &cmd->qc_node);
8427c478bd9Sstevel@tonic-gate 
8437c478bd9Sstevel@tonic-gate 	mutex_exit(&q_handle->q_mutex);
8447c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_q_at_with_mblk_exit, HCI1394_TNF_HAL_STACK,
8457c478bd9Sstevel@tonic-gate 	    "");
8467c478bd9Sstevel@tonic-gate 
8477c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
8487c478bd9Sstevel@tonic-gate }
8497c478bd9Sstevel@tonic-gate 
8507c478bd9Sstevel@tonic-gate 
8517c478bd9Sstevel@tonic-gate /*
8527c478bd9Sstevel@tonic-gate  * hci1394_q_at_next()
8537c478bd9Sstevel@tonic-gate  *    Return the next completed AT command in cmd.  If flush_q is true, we will
8547c478bd9Sstevel@tonic-gate  *    return the command regardless if it finished or not.  We will flush
8557c478bd9Sstevel@tonic-gate  *    during bus reset processing, shutdown, and detach.
8567c478bd9Sstevel@tonic-gate  */
8577c478bd9Sstevel@tonic-gate void
hci1394_q_at_next(hci1394_q_handle_t q_handle,boolean_t flush_q,hci1394_q_cmd_t ** cmd)8587c478bd9Sstevel@tonic-gate hci1394_q_at_next(hci1394_q_handle_t q_handle, boolean_t flush_q,
8597c478bd9Sstevel@tonic-gate     hci1394_q_cmd_t **cmd)
8607c478bd9Sstevel@tonic-gate {
8617c478bd9Sstevel@tonic-gate 	hci1394_q_buf_t *desc;
8627c478bd9Sstevel@tonic-gate 	hci1394_q_buf_t *data;
8637c478bd9Sstevel@tonic-gate 	hci1394_tlist_node_t *node;
8647c478bd9Sstevel@tonic-gate 	uint32_t cmd_status;
8657c478bd9Sstevel@tonic-gate 
8667c478bd9Sstevel@tonic-gate 
8677c478bd9Sstevel@tonic-gate 	ASSERT(q_handle != NULL);
8687c478bd9Sstevel@tonic-gate 	ASSERT(cmd != NULL);
8697c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_q_at_next_enter, HCI1394_TNF_HAL_STACK, "");
8707c478bd9Sstevel@tonic-gate 
8717c478bd9Sstevel@tonic-gate 	mutex_enter(&q_handle->q_mutex);
8727c478bd9Sstevel@tonic-gate 
8737c478bd9Sstevel@tonic-gate 	desc = &q_handle->q_desc;
8747c478bd9Sstevel@tonic-gate 	data = &q_handle->q_data;
8757c478bd9Sstevel@tonic-gate 
8767c478bd9Sstevel@tonic-gate 	/* Sync descriptor buffer */
8777c478bd9Sstevel@tonic-gate 	(void) ddi_dma_sync(desc->qb_buf.bi_dma_handle, 0,
8787c478bd9Sstevel@tonic-gate 	    desc->qb_buf.bi_length, DDI_DMA_SYNC_FORKERNEL);
8797c478bd9Sstevel@tonic-gate 
8807c478bd9Sstevel@tonic-gate 	/* Look at the top cmd on the queued list (without removing it) */
8817c478bd9Sstevel@tonic-gate 	hci1394_tlist_peek(q_handle->q_queued_list, &node);
8827c478bd9Sstevel@tonic-gate 	if (node == NULL) {
8837c478bd9Sstevel@tonic-gate 		/* There are no more commands left on the queued list */
8847c478bd9Sstevel@tonic-gate 		*cmd = NULL;
8857c478bd9Sstevel@tonic-gate 		mutex_exit(&q_handle->q_mutex);
8867c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(hci1394_q_at_next_exit, HCI1394_TNF_HAL_STACK,
8877c478bd9Sstevel@tonic-gate 		    "");
8887c478bd9Sstevel@tonic-gate 		return;
8897c478bd9Sstevel@tonic-gate 	}
8907c478bd9Sstevel@tonic-gate 
8917c478bd9Sstevel@tonic-gate 	/*
8927c478bd9Sstevel@tonic-gate 	 * There is a command on the list, read its status and timestamp when
8937c478bd9Sstevel@tonic-gate 	 * it was sent
8947c478bd9Sstevel@tonic-gate 	 */
8957c478bd9Sstevel@tonic-gate 	*cmd = (hci1394_q_cmd_t *)node->tln_addr;
8967c478bd9Sstevel@tonic-gate 	cmd_status = ddi_get32(desc->qb_buf.bi_handle, (*cmd)->qc_status_addr);
8977c478bd9Sstevel@tonic-gate 	(*cmd)->qc_timestamp = cmd_status & DESC_ST_TIMESTAMP_MASK;
8987c478bd9Sstevel@tonic-gate 	cmd_status = HCI1394_DESC_EVT_GET(cmd_status);
8997c478bd9Sstevel@tonic-gate 
9007c478bd9Sstevel@tonic-gate 	/*
9017c478bd9Sstevel@tonic-gate 	 * If we are flushing the q (e.g. due to a bus reset), we will return
9027c478bd9Sstevel@tonic-gate 	 * the command regardless of its completion status. If we are not
9037c478bd9Sstevel@tonic-gate 	 * flushing the Q and we do not have status on the command (e.g. status
9047c478bd9Sstevel@tonic-gate 	 * = 0), we are done with this Q for now.
9057c478bd9Sstevel@tonic-gate 	 */
9067c478bd9Sstevel@tonic-gate 	if (flush_q == B_FALSE) {
9077c478bd9Sstevel@tonic-gate 		if (cmd_status == 0) {
9087c478bd9Sstevel@tonic-gate 			*cmd = NULL;
9097c478bd9Sstevel@tonic-gate 			mutex_exit(&q_handle->q_mutex);
9107c478bd9Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(hci1394_q_at_next_exit,
9117c478bd9Sstevel@tonic-gate 			    HCI1394_TNF_HAL_STACK, "");
9127c478bd9Sstevel@tonic-gate 			return;
9137c478bd9Sstevel@tonic-gate 		}
9147c478bd9Sstevel@tonic-gate 	}
9157c478bd9Sstevel@tonic-gate 
9167c478bd9Sstevel@tonic-gate 	/*
9177c478bd9Sstevel@tonic-gate 	 * The command completed, remove it from the queued list. There is not
9187c478bd9Sstevel@tonic-gate 	 * a race condition to delete the node in the list here.  This is the
9197c478bd9Sstevel@tonic-gate 	 * only place the node will be deleted so we do not need to check the
9207c478bd9Sstevel@tonic-gate 	 * return status.
9217c478bd9Sstevel@tonic-gate 	 */
9227c478bd9Sstevel@tonic-gate 	(void) hci1394_tlist_delete(q_handle->q_queued_list, node);
9237c478bd9Sstevel@tonic-gate 
9247c478bd9Sstevel@tonic-gate 	/*
9257c478bd9Sstevel@tonic-gate 	 * Free the space used by the command in the descriptor and data
9267c478bd9Sstevel@tonic-gate 	 * buffers.
9277c478bd9Sstevel@tonic-gate 	 */
9287c478bd9Sstevel@tonic-gate 	desc->qb_ptrs.qp_free_buf = (*cmd)->qc_descriptor_buf;
9297c478bd9Sstevel@tonic-gate 	desc->qb_ptrs.qp_free = (*cmd)->qc_descriptor_end;
9307c478bd9Sstevel@tonic-gate 	if ((*cmd)->qc_data_used == B_TRUE) {
9317c478bd9Sstevel@tonic-gate 		data->qb_ptrs.qp_free_buf = (*cmd)->qc_data_buf;
9327c478bd9Sstevel@tonic-gate 		data->qb_ptrs.qp_free = (*cmd)->qc_data_end;
9337c478bd9Sstevel@tonic-gate 	}
9347c478bd9Sstevel@tonic-gate 
9357c478bd9Sstevel@tonic-gate 	/* return command status */
9367c478bd9Sstevel@tonic-gate 	(*cmd)->qc_status = cmd_status;
9377c478bd9Sstevel@tonic-gate 
9387c478bd9Sstevel@tonic-gate 	mutex_exit(&q_handle->q_mutex);
9397c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_q_at_next_exit, HCI1394_TNF_HAL_STACK, "");
9407c478bd9Sstevel@tonic-gate }
9417c478bd9Sstevel@tonic-gate 
9427c478bd9Sstevel@tonic-gate 
9437c478bd9Sstevel@tonic-gate /*
9447c478bd9Sstevel@tonic-gate  * hci1394_q_at_write_OMI()
9457c478bd9Sstevel@tonic-gate  *    Write an OMI descriptor into the AT descriptor buffer passed in as qbuf.
9467c478bd9Sstevel@tonic-gate  *    Buffer state information is stored in cmd.  Use the hdr and hdr size for
9477c478bd9Sstevel@tonic-gate  *    the additional information attached to an immediate descriptor.
9487c478bd9Sstevel@tonic-gate  */
9497c478bd9Sstevel@tonic-gate void
hci1394_q_at_write_OMI(hci1394_q_handle_t q_handle,hci1394_q_buf_t * qbuf,hci1394_q_cmd_t * cmd,hci1394_basic_pkt_t * hdr,uint_t hdrsize)9507c478bd9Sstevel@tonic-gate hci1394_q_at_write_OMI(hci1394_q_handle_t q_handle, hci1394_q_buf_t *qbuf,
9517c478bd9Sstevel@tonic-gate     hci1394_q_cmd_t *cmd, hci1394_basic_pkt_t *hdr, uint_t hdrsize)
9527c478bd9Sstevel@tonic-gate {
9537c478bd9Sstevel@tonic-gate 	hci1394_desc_imm_t *desc;
9547c478bd9Sstevel@tonic-gate 	uint32_t data;
9557c478bd9Sstevel@tonic-gate 
9567c478bd9Sstevel@tonic-gate 
9577c478bd9Sstevel@tonic-gate 	ASSERT(qbuf != NULL);
9587c478bd9Sstevel@tonic-gate 	ASSERT(cmd != NULL);
9597c478bd9Sstevel@tonic-gate 	ASSERT(hdr != NULL);
9607c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&q_handle->q_mutex));
9617c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_q_at_write_OMI_enter, HCI1394_TNF_HAL_STACK,
9627c478bd9Sstevel@tonic-gate 	    "");
9637c478bd9Sstevel@tonic-gate 
9647c478bd9Sstevel@tonic-gate 	/* The only valid "header" sizes for an OMI are 8 bytes or 16 bytes */
9657c478bd9Sstevel@tonic-gate 	ASSERT((hdrsize == 8) || (hdrsize == 16));
9667c478bd9Sstevel@tonic-gate 
9677c478bd9Sstevel@tonic-gate 	/* Make sure enough room for OMI */
9687c478bd9Sstevel@tonic-gate 	ASSERT(qbuf->qb_ptrs.qp_resv_size >= sizeof (hci1394_desc_imm_t));
9697c478bd9Sstevel@tonic-gate 
9707c478bd9Sstevel@tonic-gate 	/* Store the offset of the top of this descriptor block */
9717c478bd9Sstevel@tonic-gate 	qbuf->qb_ptrs.qp_offset = (uint32_t)(qbuf->qb_ptrs.qp_current -
9727c478bd9Sstevel@tonic-gate 	    qbuf->qb_ptrs.qp_begin);
9737c478bd9Sstevel@tonic-gate 
9747c478bd9Sstevel@tonic-gate 	/* Setup OpenHCI OMI Header */
9757c478bd9Sstevel@tonic-gate 	desc = (hci1394_desc_imm_t *)qbuf->qb_ptrs.qp_current;
9767c478bd9Sstevel@tonic-gate 	data = DESC_AT_OMI | (hdrsize & DESC_HDR_REQCOUNT_MASK);
9777c478bd9Sstevel@tonic-gate 	ddi_put32(qbuf->qb_buf.bi_handle, &desc->hdr, data);
9787c478bd9Sstevel@tonic-gate 	ddi_put32(qbuf->qb_buf.bi_handle, &desc->data_addr, 0);
9797c478bd9Sstevel@tonic-gate 	ddi_put32(qbuf->qb_buf.bi_handle, &desc->branch, 0);
9807c478bd9Sstevel@tonic-gate 	ddi_put32(qbuf->qb_buf.bi_handle, &desc->status, cmd->qc_timestamp);
9817c478bd9Sstevel@tonic-gate 
9827c478bd9Sstevel@tonic-gate 	/*
9837c478bd9Sstevel@tonic-gate 	 * Copy in 1394 header. Size is in bytes, convert it to a 32-bit word
9847c478bd9Sstevel@tonic-gate 	 * count.
9857c478bd9Sstevel@tonic-gate 	 */
9867c478bd9Sstevel@tonic-gate 	ddi_rep_put32(qbuf->qb_buf.bi_handle, &hdr->q1, &desc->q1,
9877c478bd9Sstevel@tonic-gate 	    hdrsize >> 2, DDI_DEV_AUTOINCR);
9887c478bd9Sstevel@tonic-gate 
9897c478bd9Sstevel@tonic-gate 	/*
9907c478bd9Sstevel@tonic-gate 	 * We wrote 2 16 byte blocks in the descriptor buffer, update the count
9917c478bd9Sstevel@tonic-gate 	 * accordingly.  Update the reserved size and current pointer.
9927c478bd9Sstevel@tonic-gate 	 */
9937c478bd9Sstevel@tonic-gate 	q_handle->q_block_cnt += 2;
9947c478bd9Sstevel@tonic-gate 	qbuf->qb_ptrs.qp_resv_size -= sizeof (hci1394_desc_imm_t);
9957c478bd9Sstevel@tonic-gate 	qbuf->qb_ptrs.qp_current += sizeof (hci1394_desc_imm_t);
9967c478bd9Sstevel@tonic-gate 
9977c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_q_at_write_OMI_exit, HCI1394_TNF_HAL_STACK,
9987c478bd9Sstevel@tonic-gate 	    "");
9997c478bd9Sstevel@tonic-gate }
10007c478bd9Sstevel@tonic-gate 
10017c478bd9Sstevel@tonic-gate 
10027c478bd9Sstevel@tonic-gate /*
10037c478bd9Sstevel@tonic-gate  * hci1394_q_at_write_OLI()
10047c478bd9Sstevel@tonic-gate  *    Write an OLI descriptor into the AT descriptor buffer passed in as qbuf.
10057c478bd9Sstevel@tonic-gate  *    Buffer state information is stored in cmd.  Use the hdr and hdr size for
10067c478bd9Sstevel@tonic-gate  *    the additional information attached to an immediate descriptor.
10077c478bd9Sstevel@tonic-gate  */
10087c478bd9Sstevel@tonic-gate void
hci1394_q_at_write_OLI(hci1394_q_handle_t q_handle,hci1394_q_buf_t * qbuf,hci1394_q_cmd_t * cmd,hci1394_basic_pkt_t * hdr,uint_t hdrsize)10097c478bd9Sstevel@tonic-gate hci1394_q_at_write_OLI(hci1394_q_handle_t q_handle, hci1394_q_buf_t *qbuf,
10107c478bd9Sstevel@tonic-gate     hci1394_q_cmd_t *cmd, hci1394_basic_pkt_t *hdr, uint_t hdrsize)
10117c478bd9Sstevel@tonic-gate {
10127c478bd9Sstevel@tonic-gate 	hci1394_desc_imm_t *desc;
10137c478bd9Sstevel@tonic-gate 	uint32_t data;
10147c478bd9Sstevel@tonic-gate 	uint32_t command_ptr;
10157c478bd9Sstevel@tonic-gate 	uint32_t tcode;
10167c478bd9Sstevel@tonic-gate 
10177c478bd9Sstevel@tonic-gate 
10187c478bd9Sstevel@tonic-gate 	ASSERT(qbuf != NULL);
10197c478bd9Sstevel@tonic-gate 	ASSERT(cmd != NULL);
10207c478bd9Sstevel@tonic-gate 	ASSERT(hdr != NULL);
10217c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&q_handle->q_mutex));
10227c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_q_at_write_OLI_enter, HCI1394_TNF_HAL_STACK,
10237c478bd9Sstevel@tonic-gate 	    "");
10247c478bd9Sstevel@tonic-gate 
10257c478bd9Sstevel@tonic-gate 	/* The only valid "header" sizes for an OLI are 8, 12, 16 bytes */
10267c478bd9Sstevel@tonic-gate 	ASSERT((hdrsize == 8) || (hdrsize == 12) || (hdrsize == 16));
10277c478bd9Sstevel@tonic-gate 
10287c478bd9Sstevel@tonic-gate 	/* make sure enough room for 1 OLI */
10297c478bd9Sstevel@tonic-gate 	ASSERT(qbuf->qb_ptrs.qp_resv_size >= sizeof (hci1394_desc_imm_t));
10307c478bd9Sstevel@tonic-gate 
10317c478bd9Sstevel@tonic-gate 	/* Store the offset of the top of this descriptor block */
10327c478bd9Sstevel@tonic-gate 	qbuf->qb_ptrs.qp_offset = (uint32_t)(qbuf->qb_ptrs.qp_current -
10337c478bd9Sstevel@tonic-gate 	    qbuf->qb_ptrs.qp_begin);
10347c478bd9Sstevel@tonic-gate 
10357c478bd9Sstevel@tonic-gate 	/* Setup OpenHCI OLI Header */
10367c478bd9Sstevel@tonic-gate 	desc = (hci1394_desc_imm_t *)qbuf->qb_ptrs.qp_current;
10377c478bd9Sstevel@tonic-gate 	data = DESC_AT_OLI | (hdrsize & DESC_HDR_REQCOUNT_MASK);
10387c478bd9Sstevel@tonic-gate 	ddi_put32(qbuf->qb_buf.bi_handle, &desc->hdr, data);
10397c478bd9Sstevel@tonic-gate 	ddi_put32(qbuf->qb_buf.bi_handle, &desc->data_addr, 0);
10407c478bd9Sstevel@tonic-gate 	ddi_put32(qbuf->qb_buf.bi_handle, &desc->branch, 0);
10417c478bd9Sstevel@tonic-gate 	ddi_put32(qbuf->qb_buf.bi_handle, &desc->status, cmd->qc_timestamp);
10427c478bd9Sstevel@tonic-gate 
10437c478bd9Sstevel@tonic-gate 	/* Setup 1394 Header */
10447c478bd9Sstevel@tonic-gate 	tcode = (hdr->q1 & DESC_PKT_TCODE_MASK) >> DESC_PKT_TCODE_SHIFT;
10457c478bd9Sstevel@tonic-gate 	if ((tcode == IEEE1394_TCODE_WRITE_QUADLET) ||
10467c478bd9Sstevel@tonic-gate 	    (tcode == IEEE1394_TCODE_READ_QUADLET_RESP)) {
10477c478bd9Sstevel@tonic-gate 		/*
10487c478bd9Sstevel@tonic-gate 		 * if the tcode = a quadlet write, move the last quadlet as
10497c478bd9Sstevel@tonic-gate 		 * 8-bit data.  All data is treated as 8-bit data (even quadlet
10507c478bd9Sstevel@tonic-gate 		 * reads and writes). Therefore, target drivers MUST take that
10517c478bd9Sstevel@tonic-gate 		 * into consideration when accessing device registers.
10527c478bd9Sstevel@tonic-gate 		 */
10537c478bd9Sstevel@tonic-gate 		ddi_rep_put32(qbuf->qb_buf.bi_handle, &hdr->q1, &desc->q1, 3,
10547c478bd9Sstevel@tonic-gate 		    DDI_DEV_AUTOINCR);
10557c478bd9Sstevel@tonic-gate 		ddi_rep_put8(qbuf->qb_buf.bi_handle, (uint8_t *)&hdr->q4,
10567c478bd9Sstevel@tonic-gate 		    (uint8_t *)&desc->q4, 4, DDI_DEV_AUTOINCR);
10577c478bd9Sstevel@tonic-gate 	} else {
10587c478bd9Sstevel@tonic-gate 		ddi_rep_put32(qbuf->qb_buf.bi_handle, &hdr->q1, &desc->q1,
10597c478bd9Sstevel@tonic-gate 		    hdrsize >> 2, DDI_DEV_AUTOINCR);
10607c478bd9Sstevel@tonic-gate 	}
10617c478bd9Sstevel@tonic-gate 
10627c478bd9Sstevel@tonic-gate 	/*
10637c478bd9Sstevel@tonic-gate 	 * We wrote 2 16 byte blocks in the descriptor buffer, update the count
10647c478bd9Sstevel@tonic-gate 	 * accordingly.
10657c478bd9Sstevel@tonic-gate 	 */
10667c478bd9Sstevel@tonic-gate 	q_handle->q_block_cnt += 2;
10677c478bd9Sstevel@tonic-gate 
10687c478bd9Sstevel@tonic-gate 	/*
10697c478bd9Sstevel@tonic-gate 	 * Sync buffer in case DMA engine currently running. This must be done
10707c478bd9Sstevel@tonic-gate 	 * before writing the command pointer in the previous descriptor.
10717c478bd9Sstevel@tonic-gate 	 */
10727c478bd9Sstevel@tonic-gate 	(void) ddi_dma_sync(qbuf->qb_buf.bi_dma_handle, 0,
10737c478bd9Sstevel@tonic-gate 	    qbuf->qb_buf.bi_length, DDI_DMA_SYNC_FORDEV);
10747c478bd9Sstevel@tonic-gate 
10757c478bd9Sstevel@tonic-gate 	/* save away the status address for quick access in at_next() */
10767c478bd9Sstevel@tonic-gate 	cmd->qc_status_addr = &desc->status;
10777c478bd9Sstevel@tonic-gate 
10787c478bd9Sstevel@tonic-gate 	/*
10797c478bd9Sstevel@tonic-gate 	 * Setup the command pointer.  This tells the HW where to get the
10807c478bd9Sstevel@tonic-gate 	 * descriptor we just setup.  This includes the IO address along with
10817c478bd9Sstevel@tonic-gate 	 * a 4 bit 16 byte block count
10827c478bd9Sstevel@tonic-gate 	 */
10837c478bd9Sstevel@tonic-gate 	command_ptr = (uint32_t)((qbuf->qb_cookie[qbuf->qb_ptrs.qp_current_buf
10847c478bd9Sstevel@tonic-gate 	    ].dmac_address + qbuf->qb_ptrs.qp_offset) | (q_handle->q_block_cnt &
10857c478bd9Sstevel@tonic-gate 	    DESC_Z_MASK));
10867c478bd9Sstevel@tonic-gate 
10877c478bd9Sstevel@tonic-gate 	/*
10887c478bd9Sstevel@tonic-gate 	 * if we previously setup a descriptor, add this new descriptor into
10897c478bd9Sstevel@tonic-gate 	 * the previous descriptor's "next" pointer.
10907c478bd9Sstevel@tonic-gate 	 */
10917c478bd9Sstevel@tonic-gate 	if (q_handle->q_previous != NULL) {
10927c478bd9Sstevel@tonic-gate 		ddi_put32(qbuf->qb_buf.bi_handle, &q_handle->q_previous->branch,
10937c478bd9Sstevel@tonic-gate 		    command_ptr);
10947c478bd9Sstevel@tonic-gate 		/* Sync buffer again, this gets the command pointer */
10957c478bd9Sstevel@tonic-gate 		(void) ddi_dma_sync(qbuf->qb_buf.bi_dma_handle, 0,
10967c478bd9Sstevel@tonic-gate 		    qbuf->qb_buf.bi_length, DDI_DMA_SYNC_FORDEV);
10977c478bd9Sstevel@tonic-gate 	}
10987c478bd9Sstevel@tonic-gate 
10997c478bd9Sstevel@tonic-gate 	/*
11007c478bd9Sstevel@tonic-gate 	 * this is now the previous descriptor.  Update the current pointer,
11017c478bd9Sstevel@tonic-gate 	 * clear the block count and reserved size since this is the end of
11027c478bd9Sstevel@tonic-gate 	 * this command.
11037c478bd9Sstevel@tonic-gate 	 */
11047c478bd9Sstevel@tonic-gate 	q_handle->q_previous = (hci1394_desc_t *)desc;
11057c478bd9Sstevel@tonic-gate 	qbuf->qb_ptrs.qp_current += sizeof (hci1394_desc_imm_t);
11067c478bd9Sstevel@tonic-gate 	q_handle->q_block_cnt = 0;
11077c478bd9Sstevel@tonic-gate 	qbuf->qb_ptrs.qp_resv_size = 0;
11087c478bd9Sstevel@tonic-gate 
11097c478bd9Sstevel@tonic-gate 	/* save away cleanup info when we are done with the command */
11107c478bd9Sstevel@tonic-gate 	cmd->qc_descriptor_buf = qbuf->qb_ptrs.qp_current_buf;
11117c478bd9Sstevel@tonic-gate 	cmd->qc_descriptor_end = qbuf->qb_ptrs.qp_current - 1;
11127c478bd9Sstevel@tonic-gate 
11137c478bd9Sstevel@tonic-gate 	/* If the DMA is not running, start it */
11147c478bd9Sstevel@tonic-gate 	if (q_handle->q_dma_running == B_FALSE) {
11157c478bd9Sstevel@tonic-gate 		q_handle->q_info.qi_start(q_handle->q_info.qi_callback_arg,
11167c478bd9Sstevel@tonic-gate 		    command_ptr);
11177c478bd9Sstevel@tonic-gate 		q_handle->q_dma_running = B_TRUE;
11187c478bd9Sstevel@tonic-gate 	/* the DMA is running, wake it up */
11197c478bd9Sstevel@tonic-gate 	} else {
11207c478bd9Sstevel@tonic-gate 		q_handle->q_info.qi_wake(q_handle->q_info.qi_callback_arg);
11217c478bd9Sstevel@tonic-gate 	}
11227c478bd9Sstevel@tonic-gate 
11237c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_q_at_write_OLI_exit, HCI1394_TNF_HAL_STACK,
11247c478bd9Sstevel@tonic-gate 	    "");
11257c478bd9Sstevel@tonic-gate }
11267c478bd9Sstevel@tonic-gate 
11277c478bd9Sstevel@tonic-gate 
11287c478bd9Sstevel@tonic-gate /*
11297c478bd9Sstevel@tonic-gate  * hci1394_q_at_write_OL()
11307c478bd9Sstevel@tonic-gate  *    Write an OL descriptor into the AT descriptor buffer passed in as qbuf.
11317c478bd9Sstevel@tonic-gate  *    Buffer state information is stored in cmd.  The IO address of the data
11327c478bd9Sstevel@tonic-gate  *    buffer is passed in io_addr.  Size is the size of the data to be
11337c478bd9Sstevel@tonic-gate  *    transferred.
11347c478bd9Sstevel@tonic-gate  */
11357c478bd9Sstevel@tonic-gate void
hci1394_q_at_write_OL(hci1394_q_handle_t q_handle,hci1394_q_buf_t * qbuf,hci1394_q_cmd_t * cmd,uint32_t io_addr,uint_t size)11367c478bd9Sstevel@tonic-gate hci1394_q_at_write_OL(hci1394_q_handle_t q_handle, hci1394_q_buf_t *qbuf,
11377c478bd9Sstevel@tonic-gate     hci1394_q_cmd_t *cmd, uint32_t io_addr, uint_t size)
11387c478bd9Sstevel@tonic-gate {
11397c478bd9Sstevel@tonic-gate 	hci1394_desc_t *desc;
11407c478bd9Sstevel@tonic-gate 	uint32_t data;
11417c478bd9Sstevel@tonic-gate 	uint32_t command_ptr;
11427c478bd9Sstevel@tonic-gate 
11437c478bd9