10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
70Sstevel@tonic-gate * with the License.
80Sstevel@tonic-gate *
90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate * See the License for the specific language governing permissions
120Sstevel@tonic-gate * and limitations under the License.
130Sstevel@tonic-gate *
140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate *
200Sstevel@tonic-gate * CDDL HEADER END
210Sstevel@tonic-gate */
220Sstevel@tonic-gate /*
23*638Sap25164 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24*638Sap25164 * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
280Sstevel@tonic-gate
290Sstevel@tonic-gate /*
300Sstevel@tonic-gate * hci1394_q.c
310Sstevel@tonic-gate * This code decouples some of the OpenHCI async descriptor logic/structures
320Sstevel@tonic-gate * from the async processing. The goal was to combine as much of the
330Sstevel@tonic-gate * duplicate code as possible for the different type of async transfers
340Sstevel@tonic-gate * without going too overboard.
350Sstevel@tonic-gate *
360Sstevel@tonic-gate * There are two parts to the Q, the descriptor buffer and the data buffer.
370Sstevel@tonic-gate * For the most part, data to be transmitted and data which is received go
380Sstevel@tonic-gate * in the data buffers. The information of where to get the data and put
390Sstevel@tonic-gate * the data reside in the descriptor buffers. There are exceptions to this.
400Sstevel@tonic-gate */
410Sstevel@tonic-gate
420Sstevel@tonic-gate
430Sstevel@tonic-gate #include <sys/types.h>
440Sstevel@tonic-gate #include <sys/conf.h>
450Sstevel@tonic-gate #include <sys/ddi.h>
460Sstevel@tonic-gate #include <sys/modctl.h>
470Sstevel@tonic-gate #include <sys/stat.h>
480Sstevel@tonic-gate #include <sys/sunddi.h>
490Sstevel@tonic-gate #include <sys/cmn_err.h>
500Sstevel@tonic-gate #include <sys/kmem.h>
510Sstevel@tonic-gate #include <sys/note.h>
520Sstevel@tonic-gate
530Sstevel@tonic-gate #include <sys/1394/adapters/hci1394.h>
540Sstevel@tonic-gate
550Sstevel@tonic-gate
560Sstevel@tonic-gate static int hci1394_q_reserve(hci1394_q_buf_t *qbuf, uint_t size,
570Sstevel@tonic-gate uint32_t *io_addr);
580Sstevel@tonic-gate static void hci1394_q_unreserve(hci1394_q_buf_t *qbuf);
590Sstevel@tonic-gate static void hci1394_q_buf_setup(hci1394_q_buf_t *qbuf);
600Sstevel@tonic-gate static void hci1394_q_reset(hci1394_q_handle_t q_handle);
610Sstevel@tonic-gate static void hci1394_q_next_buf(hci1394_q_buf_t *qbuf);
620Sstevel@tonic-gate
630Sstevel@tonic-gate static void hci1394_q_at_write_OLI(hci1394_q_handle_t q_handle,
640Sstevel@tonic-gate hci1394_q_buf_t *qbuf, hci1394_q_cmd_t *cmd, hci1394_basic_pkt_t *hdr,
650Sstevel@tonic-gate uint_t hdrsize);
660Sstevel@tonic-gate static void hci1394_q_at_write_OMI(hci1394_q_handle_t q_handle,
670Sstevel@tonic-gate hci1394_q_buf_t *qbuf, hci1394_q_cmd_t *cmd, hci1394_basic_pkt_t *hdr,
680Sstevel@tonic-gate uint_t hdrsize);
690Sstevel@tonic-gate static void hci1394_q_at_write_OL(hci1394_q_handle_t q_handle,
700Sstevel@tonic-gate hci1394_q_buf_t *qbuf, hci1394_q_cmd_t *cmd, uint32_t io_addr,
710Sstevel@tonic-gate uint_t datasize);
720Sstevel@tonic-gate static void hci1394_q_at_rep_put8(hci1394_q_buf_t *qbuf, hci1394_q_cmd_t *cmd,
730Sstevel@tonic-gate uint8_t *data, uint_t datasize);
740Sstevel@tonic-gate static void hci1394_q_at_copy_from_mblk(hci1394_q_buf_t *qbuf,
750Sstevel@tonic-gate hci1394_q_cmd_t *cmd, h1394_mblk_t *mblk);
760Sstevel@tonic-gate
770Sstevel@tonic-gate static void hci1394_q_ar_write_IM(hci1394_q_handle_t q_handle,
780Sstevel@tonic-gate hci1394_q_buf_t *qbuf, uint32_t io_addr, uint_t datasize);
790Sstevel@tonic-gate
800Sstevel@tonic-gate _NOTE(SCHEME_PROTECTS_DATA("unique", msgb))
810Sstevel@tonic-gate
820Sstevel@tonic-gate /*
830Sstevel@tonic-gate * hci1394_q_init()
840Sstevel@tonic-gate * Initialize a Q. A Q consists of a descriptor buffer and a data buffer and
850Sstevel@tonic-gate * can be either an AT or AR Q. hci1394_q_init() returns a handle which
860Sstevel@tonic-gate * should be used for the reset of the hci1394_q_* calls.
870Sstevel@tonic-gate */
880Sstevel@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)890Sstevel@tonic-gate hci1394_q_init(hci1394_drvinfo_t *drvinfo,
900Sstevel@tonic-gate hci1394_ohci_handle_t ohci_handle, hci1394_q_info_t *qinfo,
910Sstevel@tonic-gate hci1394_q_handle_t *q_handle)
920Sstevel@tonic-gate {
930Sstevel@tonic-gate hci1394_q_buf_t *desc;
940Sstevel@tonic-gate hci1394_q_buf_t *data;
950Sstevel@tonic-gate hci1394_buf_parms_t parms;
960Sstevel@tonic-gate hci1394_q_t *q;
970Sstevel@tonic-gate int status;
980Sstevel@tonic-gate int index;
990Sstevel@tonic-gate
1000Sstevel@tonic-gate
1010Sstevel@tonic-gate ASSERT(drvinfo != NULL);
1020Sstevel@tonic-gate ASSERT(qinfo != NULL);
1030Sstevel@tonic-gate ASSERT(q_handle != NULL);
1040Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_init_enter, HCI1394_TNF_HAL_STACK, "");
1050Sstevel@tonic-gate
1060Sstevel@tonic-gate /*
1070Sstevel@tonic-gate * allocate the memory to track this Q. Initialize the internal Q
1080Sstevel@tonic-gate * structure.
1090Sstevel@tonic-gate */
1100Sstevel@tonic-gate q = kmem_alloc(sizeof (hci1394_q_t), KM_SLEEP);
1110Sstevel@tonic-gate q->q_drvinfo = drvinfo;
1120Sstevel@tonic-gate q->q_info = *qinfo;
1130Sstevel@tonic-gate q->q_ohci = ohci_handle;
1140Sstevel@tonic-gate mutex_init(&q->q_mutex, NULL, MUTEX_DRIVER, drvinfo->di_iblock_cookie);
1150Sstevel@tonic-gate desc = &q->q_desc;
1160Sstevel@tonic-gate data = &q->q_data;
1170Sstevel@tonic-gate
1180Sstevel@tonic-gate /*
1190Sstevel@tonic-gate * Allocate the Descriptor buffer.
1200Sstevel@tonic-gate *
1210Sstevel@tonic-gate * XXX - Only want 1 cookie for now. Change this to OHCI_MAX_COOKIE
1220Sstevel@tonic-gate * after we have tested the multiple cookie code on x86.
1230Sstevel@tonic-gate */
1240Sstevel@tonic-gate parms.bp_length = qinfo->qi_desc_size;
1250Sstevel@tonic-gate parms.bp_max_cookies = 1;
1260Sstevel@tonic-gate parms.bp_alignment = 16;
1270Sstevel@tonic-gate status = hci1394_buf_alloc(drvinfo, &parms, &desc->qb_buf,
1280Sstevel@tonic-gate &desc->qb_buf_handle);
1290Sstevel@tonic-gate if (status != DDI_SUCCESS) {
1300Sstevel@tonic-gate mutex_destroy(&q->q_mutex);
1310Sstevel@tonic-gate kmem_free(q, sizeof (hci1394_q_t));
1320Sstevel@tonic-gate *q_handle = NULL;
1330Sstevel@tonic-gate TNF_PROBE_0(hci1394_q_init_bae_fail, HCI1394_TNF_HAL_ERROR, "");
1340Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_init_exit, HCI1394_TNF_HAL_STACK,
1350Sstevel@tonic-gate "");
1360Sstevel@tonic-gate return (DDI_FAILURE);
1370Sstevel@tonic-gate }
1380Sstevel@tonic-gate
1390Sstevel@tonic-gate /* Copy in buffer cookies into our local cookie array */
1400Sstevel@tonic-gate desc->qb_cookie[0] = desc->qb_buf.bi_cookie;
1410Sstevel@tonic-gate for (index = 1; index < desc->qb_buf.bi_cookie_count; index++) {
1420Sstevel@tonic-gate ddi_dma_nextcookie(desc->qb_buf.bi_dma_handle,
1430Sstevel@tonic-gate &desc->qb_buf.bi_cookie);
1440Sstevel@tonic-gate desc->qb_cookie[index] = desc->qb_buf.bi_cookie;
1450Sstevel@tonic-gate }
1460Sstevel@tonic-gate
1470Sstevel@tonic-gate /*
1480Sstevel@tonic-gate * Allocate the Data buffer.
1490Sstevel@tonic-gate *
1500Sstevel@tonic-gate * XXX - Only want 1 cookie for now. Change this to OHCI_MAX_COOKIE
1510Sstevel@tonic-gate * after we have tested the multiple cookie code on x86.
1520Sstevel@tonic-gate */
1530Sstevel@tonic-gate parms.bp_length = qinfo->qi_data_size;
1540Sstevel@tonic-gate parms.bp_max_cookies = 1;
1550Sstevel@tonic-gate parms.bp_alignment = 16;
1560Sstevel@tonic-gate status = hci1394_buf_alloc(drvinfo, &parms, &data->qb_buf,
1570Sstevel@tonic-gate &data->qb_buf_handle);
1580Sstevel@tonic-gate if (status != DDI_SUCCESS) {
159*638Sap25164 /* Free the allocated Descriptor buffer */
160*638Sap25164 hci1394_buf_free(&desc->qb_buf_handle);
161*638Sap25164
1620Sstevel@tonic-gate mutex_destroy(&q->q_mutex);
1630Sstevel@tonic-gate kmem_free(q, sizeof (hci1394_q_t));
1640Sstevel@tonic-gate *q_handle = NULL;
1650Sstevel@tonic-gate TNF_PROBE_0(hci1394_q_init_baa_fail, HCI1394_TNF_HAL_ERROR, "");
1660Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_init_exit, HCI1394_TNF_HAL_STACK,
1670Sstevel@tonic-gate "");
1680Sstevel@tonic-gate return (DDI_FAILURE);
1690Sstevel@tonic-gate }
1700Sstevel@tonic-gate
1710Sstevel@tonic-gate /*
1720Sstevel@tonic-gate * We must have at least 2 ARQ data buffers, If we only have one, we
1730Sstevel@tonic-gate * will artificially create 2. We must have 2 so that we always have a
1740Sstevel@tonic-gate * descriptor with free data space to write AR data to. When one is
1750Sstevel@tonic-gate * empty, it will take us a bit to get a new descriptor back into the
1760Sstevel@tonic-gate * chain.
1770Sstevel@tonic-gate */
1780Sstevel@tonic-gate if ((qinfo->qi_mode == HCI1394_ARQ) &&
1790Sstevel@tonic-gate (data->qb_buf.bi_cookie_count == 1)) {
1800Sstevel@tonic-gate data->qb_buf.bi_cookie_count = 2;
1810Sstevel@tonic-gate data->qb_cookie[0] = data->qb_buf.bi_cookie;
1820Sstevel@tonic-gate data->qb_cookie[0].dmac_size /= 2;
1830Sstevel@tonic-gate data->qb_cookie[1] = data->qb_cookie[0];
1840Sstevel@tonic-gate data->qb_cookie[1].dmac_laddress =
1850Sstevel@tonic-gate data->qb_cookie[0].dmac_laddress +
1860Sstevel@tonic-gate data->qb_cookie[0].dmac_size;
1870Sstevel@tonic-gate data->qb_cookie[1].dmac_address =
1880Sstevel@tonic-gate data->qb_cookie[0].dmac_address +
1890Sstevel@tonic-gate data->qb_cookie[0].dmac_size;
1900Sstevel@tonic-gate
1910Sstevel@tonic-gate /* We have more than 1 cookie or we are an AT Q */
1920Sstevel@tonic-gate } else {
1930Sstevel@tonic-gate /* Copy in buffer cookies into our local cookie array */
1940Sstevel@tonic-gate data->qb_cookie[0] = data->qb_buf.bi_cookie;
1950Sstevel@tonic-gate for (index = 1; index < data->qb_buf.bi_cookie_count; index++) {
1960Sstevel@tonic-gate ddi_dma_nextcookie(data->qb_buf.bi_dma_handle,
1970Sstevel@tonic-gate &data->qb_buf.bi_cookie);
1980Sstevel@tonic-gate data->qb_cookie[index] = data->qb_buf.bi_cookie;
1990Sstevel@tonic-gate }
2000Sstevel@tonic-gate }
2010Sstevel@tonic-gate
2020Sstevel@tonic-gate /* The top and bottom of the Q are only set once */
2030Sstevel@tonic-gate desc->qb_ptrs.qp_top = desc->qb_buf.bi_kaddr;
2040Sstevel@tonic-gate desc->qb_ptrs.qp_bottom = desc->qb_buf.bi_kaddr +
2050Sstevel@tonic-gate desc->qb_buf.bi_real_length - 1;
2060Sstevel@tonic-gate data->qb_ptrs.qp_top = data->qb_buf.bi_kaddr;
2070Sstevel@tonic-gate data->qb_ptrs.qp_bottom = data->qb_buf.bi_kaddr +
2080Sstevel@tonic-gate data->qb_buf.bi_real_length - 1;
2090Sstevel@tonic-gate
2100Sstevel@tonic-gate /*
2110Sstevel@tonic-gate * reset the Q pointers to their original settings. Setup IM
2120Sstevel@tonic-gate * descriptors if this is an AR Q.
2130Sstevel@tonic-gate */
2140Sstevel@tonic-gate hci1394_q_reset(q);
2150Sstevel@tonic-gate
2160Sstevel@tonic-gate /* if this is an AT Q, create a queued list for the AT descriptors */
2170Sstevel@tonic-gate if (qinfo->qi_mode == HCI1394_ATQ) {
2180Sstevel@tonic-gate hci1394_tlist_init(drvinfo, NULL, &q->q_queued_list);
2190Sstevel@tonic-gate }
2200Sstevel@tonic-gate
2210Sstevel@tonic-gate *q_handle = q;
2220Sstevel@tonic-gate
2230Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_init_exit, HCI1394_TNF_HAL_STACK, "");
2240Sstevel@tonic-gate
2250Sstevel@tonic-gate return (DDI_SUCCESS);
2260Sstevel@tonic-gate }
2270Sstevel@tonic-gate
2280Sstevel@tonic-gate
2290Sstevel@tonic-gate /*
2300Sstevel@tonic-gate * hci1394_q_fini()
2310Sstevel@tonic-gate * Cleanup after a successful hci1394_q_init(). Notice that a pointer to the
2320Sstevel@tonic-gate * handle is used for the parameter. fini() will set your handle to NULL
2330Sstevel@tonic-gate * before returning.
2340Sstevel@tonic-gate */
2350Sstevel@tonic-gate void
hci1394_q_fini(hci1394_q_handle_t * q_handle)2360Sstevel@tonic-gate hci1394_q_fini(hci1394_q_handle_t *q_handle)
2370Sstevel@tonic-gate {
2380Sstevel@tonic-gate hci1394_q_t *q;
2390Sstevel@tonic-gate
2400Sstevel@tonic-gate ASSERT(q_handle != NULL);
2410Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_fini_enter, HCI1394_TNF_HAL_STACK, "");
2420Sstevel@tonic-gate
2430Sstevel@tonic-gate q = *q_handle;
2440Sstevel@tonic-gate if (q->q_info.qi_mode == HCI1394_ATQ) {
2450Sstevel@tonic-gate hci1394_tlist_fini(&q->q_queued_list);
2460Sstevel@tonic-gate }
2470Sstevel@tonic-gate mutex_destroy(&q->q_mutex);
2480Sstevel@tonic-gate hci1394_buf_free(&q->q_desc.qb_buf_handle);
2490Sstevel@tonic-gate hci1394_buf_free(&q->q_data.qb_buf_handle);
2500Sstevel@tonic-gate kmem_free(q, sizeof (hci1394_q_t));
2510Sstevel@tonic-gate *q_handle = NULL;
2520Sstevel@tonic-gate
2530Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_fini_exit, HCI1394_TNF_HAL_STACK, "");
2540Sstevel@tonic-gate }
2550Sstevel@tonic-gate
2560Sstevel@tonic-gate
2570Sstevel@tonic-gate /*
2580Sstevel@tonic-gate * hci1394_q_buf_setup()
2590Sstevel@tonic-gate * Initialization of buffer pointers which are present in both the descriptor
2600Sstevel@tonic-gate * buffer and data buffer (No reason to duplicate the code)
2610Sstevel@tonic-gate */
2620Sstevel@tonic-gate static void
hci1394_q_buf_setup(hci1394_q_buf_t * qbuf)2630Sstevel@tonic-gate hci1394_q_buf_setup(hci1394_q_buf_t *qbuf)
2640Sstevel@tonic-gate {
2650Sstevel@tonic-gate ASSERT(qbuf != NULL);
2660Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_buf_setup_enter, HCI1394_TNF_HAL_STACK, "");
2670Sstevel@tonic-gate
2680Sstevel@tonic-gate /* start with the first cookie */
2690Sstevel@tonic-gate qbuf->qb_ptrs.qp_current_buf = 0;
2700Sstevel@tonic-gate qbuf->qb_ptrs.qp_begin = qbuf->qb_ptrs.qp_top;
2710Sstevel@tonic-gate qbuf->qb_ptrs.qp_end = qbuf->qb_ptrs.qp_begin +
2720Sstevel@tonic-gate qbuf->qb_cookie[qbuf->qb_ptrs.qp_current_buf].dmac_size - 1;
2730Sstevel@tonic-gate qbuf->qb_ptrs.qp_current = qbuf->qb_ptrs.qp_begin;
2740Sstevel@tonic-gate qbuf->qb_ptrs.qp_offset = 0;
2750Sstevel@tonic-gate
2760Sstevel@tonic-gate /*
2770Sstevel@tonic-gate * The free_buf and free pointer will change everytime an ACK (of some
2780Sstevel@tonic-gate * type) is processed. Free is the last byte in the last cookie.
2790Sstevel@tonic-gate */
2800Sstevel@tonic-gate qbuf->qb_ptrs.qp_free_buf = qbuf->qb_buf.bi_cookie_count - 1;
2810Sstevel@tonic-gate qbuf->qb_ptrs.qp_free = qbuf->qb_ptrs.qp_bottom;
2820Sstevel@tonic-gate
2830Sstevel@tonic-gate /*
2840Sstevel@tonic-gate * Start with no space to write descriptors. We first need to call
2850Sstevel@tonic-gate * hci1394_q_reserve() before calling hci1394_q_at_write_O*().
2860Sstevel@tonic-gate */
2870Sstevel@tonic-gate qbuf->qb_ptrs.qp_resv_size = 0;
2880Sstevel@tonic-gate
2890Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_buf_setup_exit, HCI1394_TNF_HAL_STACK, "");
2900Sstevel@tonic-gate }
2910Sstevel@tonic-gate
2920Sstevel@tonic-gate
2930Sstevel@tonic-gate /*
2940Sstevel@tonic-gate * hci1394_q_reset()
2950Sstevel@tonic-gate * Resets the buffers to an initial state. This should be called during
2960Sstevel@tonic-gate * attach and resume.
2970Sstevel@tonic-gate */
2980Sstevel@tonic-gate static void
hci1394_q_reset(hci1394_q_handle_t q_handle)2990Sstevel@tonic-gate hci1394_q_reset(hci1394_q_handle_t q_handle)
3000Sstevel@tonic-gate {
3010Sstevel@tonic-gate hci1394_q_buf_t *desc;
3020Sstevel@tonic-gate hci1394_q_buf_t *data;
3030Sstevel@tonic-gate int index;
3040Sstevel@tonic-gate
3050Sstevel@tonic-gate ASSERT(q_handle != NULL);
3060Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_reset_enter, HCI1394_TNF_HAL_STACK, "");
3070Sstevel@tonic-gate
3080Sstevel@tonic-gate mutex_enter(&q_handle->q_mutex);
3090Sstevel@tonic-gate desc = &q_handle->q_desc;
3100Sstevel@tonic-gate data = &q_handle->q_data;
3110Sstevel@tonic-gate
3120Sstevel@tonic-gate hci1394_q_buf_setup(desc);
3130Sstevel@tonic-gate hci1394_q_buf_setup(data);
3140Sstevel@tonic-gate
3150Sstevel@tonic-gate /* DMA starts off stopped, no previous descriptor to link from */
3160Sstevel@tonic-gate q_handle->q_dma_running = B_FALSE;
3170Sstevel@tonic-gate q_handle->q_block_cnt = 0;
3180Sstevel@tonic-gate q_handle->q_previous = NULL;
3190Sstevel@tonic-gate
3200Sstevel@tonic-gate /* If this is an AR Q, setup IM's for the data buffers that we have */
3210Sstevel@tonic-gate if (q_handle->q_info.qi_mode == HCI1394_ARQ) {
3220Sstevel@tonic-gate /*
3230Sstevel@tonic-gate * This points to where to find the first IM descriptor. Since
3240Sstevel@tonic-gate * we just reset the pointers in hci1394_q_buf_setup(), the
3250Sstevel@tonic-gate * first IM we write below will be found at the top of the Q.
3260Sstevel@tonic-gate */
3270Sstevel@tonic-gate q_handle->q_head = desc->qb_ptrs.qp_top;
3280Sstevel@tonic-gate
3290Sstevel@tonic-gate for (index = 0; index < data->qb_buf.bi_cookie_count; index++) {
3300Sstevel@tonic-gate hci1394_q_ar_write_IM(q_handle, desc,
3310Sstevel@tonic-gate data->qb_cookie[index].dmac_address,
3320Sstevel@tonic-gate data->qb_cookie[index].dmac_size);
3330Sstevel@tonic-gate }
3340Sstevel@tonic-gate
3350Sstevel@tonic-gate /*
3360Sstevel@tonic-gate * The space left in the current IM is the size of the buffer.
3370Sstevel@tonic-gate * The current buffer is the first buffer added to the AR Q.
3380Sstevel@tonic-gate */
3390Sstevel@tonic-gate q_handle->q_space_left = data->qb_cookie[0].dmac_size;
3400Sstevel@tonic-gate }
3410Sstevel@tonic-gate
3420Sstevel@tonic-gate mutex_exit(&q_handle->q_mutex);
3430Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_reset_exit, HCI1394_TNF_HAL_STACK, "");
3440Sstevel@tonic-gate }
3450Sstevel@tonic-gate
3460Sstevel@tonic-gate
3470Sstevel@tonic-gate /*
3480Sstevel@tonic-gate * hci1394_q_resume()
3490Sstevel@tonic-gate * This is called during a resume (after a successful suspend). Currently
3500Sstevel@tonic-gate * we only call reset. Since this is not a time critical function, we will
3510Sstevel@tonic-gate * leave this as a separate function to increase readability.
3520Sstevel@tonic-gate */
3530Sstevel@tonic-gate void
hci1394_q_resume(hci1394_q_handle_t q_handle)3540Sstevel@tonic-gate hci1394_q_resume(hci1394_q_handle_t q_handle)
3550Sstevel@tonic-gate {
3560Sstevel@tonic-gate ASSERT(q_handle != NULL);
3570Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_resume_enter, HCI1394_TNF_HAL_STACK, "");
3580Sstevel@tonic-gate hci1394_q_reset(q_handle);
3590Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_resume_exit, HCI1394_TNF_HAL_STACK, "");
3600Sstevel@tonic-gate }
3610Sstevel@tonic-gate
3620Sstevel@tonic-gate
3630Sstevel@tonic-gate /*
3640Sstevel@tonic-gate * hci1394_q_stop()
3650Sstevel@tonic-gate * This call informs us that a DMA engine has been stopped. It does not
3660Sstevel@tonic-gate * perform the actual stop. We need to know this so that when we add a
3670Sstevel@tonic-gate * new descriptor, we do a start instead of a wake.
3680Sstevel@tonic-gate */
3690Sstevel@tonic-gate void
hci1394_q_stop(hci1394_q_handle_t q_handle)3700Sstevel@tonic-gate hci1394_q_stop(hci1394_q_handle_t q_handle)
3710Sstevel@tonic-gate {
3720Sstevel@tonic-gate ASSERT(q_handle != NULL);
3730Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_stop_enter, HCI1394_TNF_HAL_STACK, "");
3740Sstevel@tonic-gate mutex_enter(&q_handle->q_mutex);
3750Sstevel@tonic-gate q_handle->q_dma_running = B_FALSE;
3760Sstevel@tonic-gate mutex_exit(&q_handle->q_mutex);
3770Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_stop_exit, HCI1394_TNF_HAL_STACK, "");
3780Sstevel@tonic-gate }
3790Sstevel@tonic-gate
3800Sstevel@tonic-gate
3810Sstevel@tonic-gate /*
3820Sstevel@tonic-gate * hci1394_q_reserve()
3830Sstevel@tonic-gate * Reserve space in the AT descriptor or data buffer. This ensures that we
3840Sstevel@tonic-gate * can get a contiguous buffer. Descriptors have to be in a contiguous
3850Sstevel@tonic-gate * buffer. Data does not have to be in a contiguous buffer but we do this to
3860Sstevel@tonic-gate * reduce complexity. For systems with small page sizes (e.g. x86), this
3870Sstevel@tonic-gate * could result in inefficient use of the data buffers when sending large
3880Sstevel@tonic-gate * data blocks (this only applies to non-physical block write ATREQs and
3890Sstevel@tonic-gate * block read ATRESP). Since it looks like most protocols that use large data
3900Sstevel@tonic-gate * blocks (like SPB-2), use physical transfers to do this (due to their
3910Sstevel@tonic-gate * efficiency), this will probably not be a real world problem. If it turns
3920Sstevel@tonic-gate * out to be a problem, the options are to force a single cookie for the data
3930Sstevel@tonic-gate * buffer, allow multiple cookies and have a larger data space, or change the
3940Sstevel@tonic-gate * data code to use a OMI, OM, OL descriptor sequence (instead of OMI, OL).
3950Sstevel@tonic-gate */
3960Sstevel@tonic-gate static int
hci1394_q_reserve(hci1394_q_buf_t * qbuf,uint_t size,uint32_t * io_addr)3970Sstevel@tonic-gate hci1394_q_reserve(hci1394_q_buf_t *qbuf, uint_t size, uint32_t *io_addr)
3980Sstevel@tonic-gate {
3990Sstevel@tonic-gate uint_t aligned_size;
4000Sstevel@tonic-gate
4010Sstevel@tonic-gate
4020Sstevel@tonic-gate ASSERT(qbuf != NULL);
4030Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_reserve_enter, HCI1394_TNF_HAL_STACK, "");
4040Sstevel@tonic-gate
4050Sstevel@tonic-gate /* Save backup of pointers in case we have to unreserve */
4060Sstevel@tonic-gate qbuf->qb_backup_ptrs = qbuf->qb_ptrs;
4070Sstevel@tonic-gate
4080Sstevel@tonic-gate /*
4090Sstevel@tonic-gate * Make sure all alloc's are quadlet aligned. The data doesn't have to
4100Sstevel@tonic-gate * be, so we will force it to be.
4110Sstevel@tonic-gate */
4120Sstevel@tonic-gate aligned_size = HCI1394_ALIGN_QUAD(size);
4130Sstevel@tonic-gate
4140Sstevel@tonic-gate /*
4150Sstevel@tonic-gate * if the free pointer is in the current buffer and the free pointer
4160Sstevel@tonic-gate * is below the current pointer (i.e. has not wrapped around)
4170Sstevel@tonic-gate */
4180Sstevel@tonic-gate if ((qbuf->qb_ptrs.qp_current_buf == qbuf->qb_ptrs.qp_free_buf) &&
4190Sstevel@tonic-gate (qbuf->qb_ptrs.qp_free >= qbuf->qb_ptrs.qp_current)) {
4200Sstevel@tonic-gate /*
4210Sstevel@tonic-gate * The free pointer is in this buffer below the current pointer.
4220Sstevel@tonic-gate * Check to see if we have enough free space left.
4230Sstevel@tonic-gate */
4240Sstevel@tonic-gate if ((qbuf->qb_ptrs.qp_current + aligned_size) <=
4250Sstevel@tonic-gate qbuf->qb_ptrs.qp_free) {
4260Sstevel@tonic-gate /* Setup up our reserved size, return the IO address */
4270Sstevel@tonic-gate qbuf->qb_ptrs.qp_resv_size = aligned_size;
4280Sstevel@tonic-gate *io_addr = (uint32_t)(qbuf->qb_cookie[
4290Sstevel@tonic-gate qbuf->qb_ptrs.qp_current_buf].dmac_address +
4300Sstevel@tonic-gate qbuf->qb_ptrs.qp_offset);
4310Sstevel@tonic-gate
4320Sstevel@tonic-gate /*
4330Sstevel@tonic-gate * The free pointer is in this buffer below the current pointer.
4340Sstevel@tonic-gate * We do not have enough free space for the alloc. Return
4350Sstevel@tonic-gate * failure.
4360Sstevel@tonic-gate */
4370Sstevel@tonic-gate } else {
4380Sstevel@tonic-gate qbuf->qb_ptrs.qp_resv_size = 0;
4390Sstevel@tonic-gate TNF_PROBE_0(hci1394_q_reserve_ns_fail,
4400Sstevel@tonic-gate HCI1394_TNF_HAL_ERROR, "");
4410Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_reserve_exit,
4420Sstevel@tonic-gate HCI1394_TNF_HAL_STACK, "");
4430Sstevel@tonic-gate return (DDI_FAILURE);
4440Sstevel@tonic-gate }
4450Sstevel@tonic-gate
4460Sstevel@tonic-gate /*
4470Sstevel@tonic-gate * If there is not enough room to fit in the current buffer (not
4480Sstevel@tonic-gate * including wrap around), we will go to the next buffer and check
4490Sstevel@tonic-gate * there. If we only have one buffer (i.e. one cookie), we will end up
4500Sstevel@tonic-gate * staying at the current buffer and wrapping the address back to the
4510Sstevel@tonic-gate * top.
4520Sstevel@tonic-gate */
4530Sstevel@tonic-gate } else if ((qbuf->qb_ptrs.qp_current + aligned_size) >
4540Sstevel@tonic-gate qbuf->qb_ptrs.qp_end) {
4550Sstevel@tonic-gate /* Go to the next buffer (or the top of ours for one cookie) */
4560Sstevel@tonic-gate hci1394_q_next_buf(qbuf);
4570Sstevel@tonic-gate
4580Sstevel@tonic-gate /* If the free pointer is in the new current buffer */
4590Sstevel@tonic-gate if (qbuf->qb_ptrs.qp_current_buf == qbuf->qb_ptrs.qp_free_buf) {
4600Sstevel@tonic-gate /*
4610Sstevel@tonic-gate * The free pointer is in this buffer. If we do not have
4620Sstevel@tonic-gate * enough free space for the alloc. Return failure.
4630Sstevel@tonic-gate */
4640Sstevel@tonic-gate if ((qbuf->qb_ptrs.qp_current + aligned_size) >
4650Sstevel@tonic-gate qbuf->qb_ptrs.qp_free) {
4660Sstevel@tonic-gate qbuf->qb_ptrs.qp_resv_size = 0;
4670Sstevel@tonic-gate TNF_PROBE_0(hci1394_q_reserve_ns_fail,
4680Sstevel@tonic-gate HCI1394_TNF_HAL_ERROR, "");
4690Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_reserve_exit,
4700Sstevel@tonic-gate HCI1394_TNF_HAL_STACK, "");
4710Sstevel@tonic-gate return (DDI_FAILURE);
4720Sstevel@tonic-gate /*
4730Sstevel@tonic-gate * The free pointer is in this buffer. We have enough
4740Sstevel@tonic-gate * free space left.
4750Sstevel@tonic-gate */
4760Sstevel@tonic-gate } else {
4770Sstevel@tonic-gate /*
4780Sstevel@tonic-gate * Setup up our reserved size, return the IO
4790Sstevel@tonic-gate * address
4800Sstevel@tonic-gate */
4810Sstevel@tonic-gate qbuf->qb_ptrs.qp_resv_size = aligned_size;
4820Sstevel@tonic-gate *io_addr = (uint32_t)(qbuf->qb_cookie[
4830Sstevel@tonic-gate qbuf->qb_ptrs.qp_current_buf].dmac_address +
4840Sstevel@tonic-gate qbuf->qb_ptrs.qp_offset);
4850Sstevel@tonic-gate }
4860Sstevel@tonic-gate
4870Sstevel@tonic-gate /*
4880Sstevel@tonic-gate * We switched buffers and the free pointer is still in another
4890Sstevel@tonic-gate * buffer. We have sufficient space in this buffer for the alloc
4900Sstevel@tonic-gate * after changing buffers.
4910Sstevel@tonic-gate */
4920Sstevel@tonic-gate } else {
4930Sstevel@tonic-gate /* Setup up our reserved size, return the IO address */
4940Sstevel@tonic-gate qbuf->qb_ptrs.qp_resv_size = aligned_size;
4950Sstevel@tonic-gate *io_addr = (uint32_t)(qbuf->qb_cookie[
4960Sstevel@tonic-gate qbuf->qb_ptrs.qp_current_buf].dmac_address +
4970Sstevel@tonic-gate qbuf->qb_ptrs.qp_offset);
4980Sstevel@tonic-gate }
4990Sstevel@tonic-gate /*
5000Sstevel@tonic-gate * The free pointer is in another buffer. We have sufficient space in
5010Sstevel@tonic-gate * this buffer for the alloc.
5020Sstevel@tonic-gate */
5030Sstevel@tonic-gate } else {
5040Sstevel@tonic-gate /* Setup up our reserved size, return the IO address */
5050Sstevel@tonic-gate qbuf->qb_ptrs.qp_resv_size = aligned_size;
5060Sstevel@tonic-gate *io_addr = (uint32_t)(qbuf->qb_cookie[
5070Sstevel@tonic-gate qbuf->qb_ptrs.qp_current_buf].dmac_address +
5080Sstevel@tonic-gate qbuf->qb_ptrs.qp_offset);
5090Sstevel@tonic-gate }
5100Sstevel@tonic-gate
5110Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_reserve_exit, HCI1394_TNF_HAL_STACK, "");
5120Sstevel@tonic-gate
5130Sstevel@tonic-gate return (DDI_SUCCESS);
5140Sstevel@tonic-gate }
5150Sstevel@tonic-gate
5160Sstevel@tonic-gate /*
5170Sstevel@tonic-gate * hci1394_q_unreserve()
5180Sstevel@tonic-gate * Set the buffer pointer to what they were before hci1394_reserve(). This
5190Sstevel@tonic-gate * will be called when we encounter errors during hci1394_q_at*().
5200Sstevel@tonic-gate */
5210Sstevel@tonic-gate static void
hci1394_q_unreserve(hci1394_q_buf_t * qbuf)5220Sstevel@tonic-gate hci1394_q_unreserve(hci1394_q_buf_t *qbuf)
5230Sstevel@tonic-gate {
5240Sstevel@tonic-gate ASSERT(qbuf != NULL);
5250Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_unreserve_enter, HCI1394_TNF_HAL_STACK, "");
5260Sstevel@tonic-gate
5270Sstevel@tonic-gate /* Go back to pointer setting before the reserve */
5280Sstevel@tonic-gate qbuf->qb_ptrs = qbuf->qb_backup_ptrs;
5290Sstevel@tonic-gate
5300Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_unreserve_exit, HCI1394_TNF_HAL_STACK, "");
5310Sstevel@tonic-gate }
5320Sstevel@tonic-gate
5330Sstevel@tonic-gate
5340Sstevel@tonic-gate /*
5350Sstevel@tonic-gate * hci1394_q_next_buf()
5360Sstevel@tonic-gate * Set our current buffer to the next cookie. If we only have one cookie, we
5370Sstevel@tonic-gate * will go back to the top of our buffer.
5380Sstevel@tonic-gate */
5390Sstevel@tonic-gate void
hci1394_q_next_buf(hci1394_q_buf_t * qbuf)5400Sstevel@tonic-gate hci1394_q_next_buf(hci1394_q_buf_t *qbuf)
5410Sstevel@tonic-gate {
5420Sstevel@tonic-gate ASSERT(qbuf != NULL);
5430Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_next_buf_enter, HCI1394_TNF_HAL_STACK, "");
5440Sstevel@tonic-gate
5450Sstevel@tonic-gate /*
5460Sstevel@tonic-gate * go to the next cookie, if we are >= the cookie count, go back to the
5470Sstevel@tonic-gate * first cookie.
5480Sstevel@tonic-gate */
5490Sstevel@tonic-gate qbuf->qb_ptrs.qp_current_buf++;
5500Sstevel@tonic-gate if (qbuf->qb_ptrs.qp_current_buf >= qbuf->qb_buf.bi_cookie_count) {
5510Sstevel@tonic-gate qbuf->qb_ptrs.qp_current_buf = 0;
5520Sstevel@tonic-gate }
5530Sstevel@tonic-gate
5540Sstevel@tonic-gate /* adjust the begin, end, current, and offset pointers */
5550Sstevel@tonic-gate qbuf->qb_ptrs.qp_begin = qbuf->qb_ptrs.qp_end + 1;
5560Sstevel@tonic-gate if (qbuf->qb_ptrs.qp_begin > qbuf->qb_ptrs.qp_bottom) {
5570Sstevel@tonic-gate qbuf->qb_ptrs.qp_begin = qbuf->qb_ptrs.qp_top;
5580Sstevel@tonic-gate }
5590Sstevel@tonic-gate qbuf->qb_ptrs.qp_end = qbuf->qb_ptrs.qp_begin +
5600Sstevel@tonic-gate qbuf->qb_cookie[qbuf->qb_ptrs.qp_current_buf].dmac_size - 1;
5610Sstevel@tonic-gate qbuf->qb_ptrs.qp_current = qbuf->qb_ptrs.qp_begin;
5620Sstevel@tonic-gate qbuf->qb_ptrs.qp_offset = 0;
5630Sstevel@tonic-gate
5640Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_next_buf_exit, HCI1394_TNF_HAL_STACK, "");
5650Sstevel@tonic-gate }
5660Sstevel@tonic-gate
5670Sstevel@tonic-gate
5680Sstevel@tonic-gate /*
5690Sstevel@tonic-gate * hci1394_q_at()
5700Sstevel@tonic-gate * Place an AT command that does NOT need the data buffer into the DMA chain.
5710Sstevel@tonic-gate * Some examples of this are quadlet read/write, PHY packets, ATREQ Block
5720Sstevel@tonic-gate * Read, and ATRESP block write. result is only valid on failure.
5730Sstevel@tonic-gate */
5740Sstevel@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)5750Sstevel@tonic-gate hci1394_q_at(hci1394_q_handle_t q_handle, hci1394_q_cmd_t *cmd,
5760Sstevel@tonic-gate hci1394_basic_pkt_t *hdr, uint_t hdrsize, int *result)
5770Sstevel@tonic-gate {
5780Sstevel@tonic-gate int status;
5790Sstevel@tonic-gate uint32_t ioaddr;
5800Sstevel@tonic-gate
5810Sstevel@tonic-gate
5820Sstevel@tonic-gate ASSERT(q_handle != NULL);
5830Sstevel@tonic-gate ASSERT(cmd != NULL);
5840Sstevel@tonic-gate ASSERT(hdr != NULL);
5850Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_enter, HCI1394_TNF_HAL_STACK, "");
5860Sstevel@tonic-gate
5870Sstevel@tonic-gate mutex_enter(&q_handle->q_mutex);
5880Sstevel@tonic-gate
5890Sstevel@tonic-gate /*
5900Sstevel@tonic-gate * Check the HAL state and generation when the AT Q is locked. This
5910Sstevel@tonic-gate * will make sure that we get all the commands when we flush the Q's
5920Sstevel@tonic-gate * during a reset or shutdown.
5930Sstevel@tonic-gate */
5940Sstevel@tonic-gate if ((hci1394_state(q_handle->q_drvinfo) != HCI1394_NORMAL) ||
5950Sstevel@tonic-gate (hci1394_ohci_current_busgen(q_handle->q_ohci) !=
5960Sstevel@tonic-gate cmd->qc_generation)) {
5970Sstevel@tonic-gate *result = H1394_STATUS_INVALID_BUSGEN;
5980Sstevel@tonic-gate mutex_exit(&q_handle->q_mutex);
5990Sstevel@tonic-gate TNF_PROBE_0(hci1394_q_at_st_fail, HCI1394_TNF_HAL_ERROR, "");
6000Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_exit, HCI1394_TNF_HAL_STACK,
6010Sstevel@tonic-gate "");
6020Sstevel@tonic-gate return (DDI_FAILURE);
6030Sstevel@tonic-gate }
6040Sstevel@tonic-gate
6050Sstevel@tonic-gate /* save away the argument to pass up when this command completes */
6060Sstevel@tonic-gate cmd->qc_node.tln_addr = cmd;
6070Sstevel@tonic-gate
6080Sstevel@tonic-gate /* we have not written any 16 byte blocks to the descriptor yet */
6090Sstevel@tonic-gate q_handle->q_block_cnt = 0;
6100Sstevel@tonic-gate
6110Sstevel@tonic-gate /* Reserve space for an OLI in the descriptor buffer */
6120Sstevel@tonic-gate status = hci1394_q_reserve(&q_handle->q_desc,
6130Sstevel@tonic-gate sizeof (hci1394_desc_imm_t), &ioaddr);
6140Sstevel@tonic-gate if (status != DDI_SUCCESS) {
6150Sstevel@tonic-gate *result = H1394_STATUS_NOMORE_SPACE;
6160Sstevel@tonic-gate mutex_exit(&q_handle->q_mutex);
6170Sstevel@tonic-gate TNF_PROBE_0(hci1394_q_at_qre_fail, HCI1394_TNF_HAL_ERROR, "");
6180Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_exit, HCI1394_TNF_HAL_STACK,
6190Sstevel@tonic-gate "");
6200Sstevel@tonic-gate return (DDI_FAILURE);
6210Sstevel@tonic-gate }
6220Sstevel@tonic-gate
6230Sstevel@tonic-gate /* write the OLI to the descriptor buffer */
6240Sstevel@tonic-gate hci1394_q_at_write_OLI(q_handle, &q_handle->q_desc, cmd, hdr, hdrsize);
6250Sstevel@tonic-gate
6260Sstevel@tonic-gate /* Add the AT command to the queued list */
6270Sstevel@tonic-gate hci1394_tlist_add(q_handle->q_queued_list, &cmd->qc_node);
6280Sstevel@tonic-gate
6290Sstevel@tonic-gate mutex_exit(&q_handle->q_mutex);
6300Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_exit, HCI1394_TNF_HAL_STACK, "");
6310Sstevel@tonic-gate
6320Sstevel@tonic-gate return (DDI_SUCCESS);
6330Sstevel@tonic-gate }
6340Sstevel@tonic-gate
6350Sstevel@tonic-gate
6360Sstevel@tonic-gate /*
6370Sstevel@tonic-gate * XXX - NOTE: POSSIBLE FUTURE OPTIMIZATION
6380Sstevel@tonic-gate * ATREQ Block read and write's that go through software are not very
6390Sstevel@tonic-gate * efficient (one of the reasons to use physical space). A copy is forced
6400Sstevel@tonic-gate * on all block reads due to the design of OpenHCI. Writes do not have this
6410Sstevel@tonic-gate * same restriction. This design forces a copy for writes too (we always
6420Sstevel@tonic-gate * copy into a data buffer before sending). There are many reasons for this
6430Sstevel@tonic-gate * including complexity reduction. There is a data size threshold where a
6440Sstevel@tonic-gate * copy is more expensive than mapping the data buffer address (or worse
6450Sstevel@tonic-gate * case a big enough difference where it pays to do it). However, we move
6460Sstevel@tonic-gate * block data around in mblks which means that our data may be scattered
6470Sstevel@tonic-gate * over many buffers. This adds to the complexity of mapping and setting
6480Sstevel@tonic-gate * up the OpenHCI descriptors.
6490Sstevel@tonic-gate *
6500Sstevel@tonic-gate * If someone really needs a speedup on block write ATREQs, my recommendation
6510Sstevel@tonic-gate * would be to add an additional command type at the target interface for a
6520Sstevel@tonic-gate * fast block write. The target driver would pass a mapped io addr to use.
6530Sstevel@tonic-gate * A function like "hci1394_q_at_with_ioaddr()" could be created which would
6540Sstevel@tonic-gate * be almost an exact copy of hci1394_q_at_with_data() without the
6550Sstevel@tonic-gate * hci1394_q_reserve() and hci1394_q_at_rep_put8() for the data buffer.
6560Sstevel@tonic-gate */
6570Sstevel@tonic-gate
6580Sstevel@tonic-gate
6590Sstevel@tonic-gate /*
6600Sstevel@tonic-gate * hci1394_q_at_with_data()
6610Sstevel@tonic-gate * Place an AT command that does need the data buffer into the DMA chain.
6620Sstevel@tonic-gate * The data is passed as a pointer to a kernel virtual address. An example of
6630Sstevel@tonic-gate * this is the lock operations. result is only valid on failure.
6640Sstevel@tonic-gate */
6650Sstevel@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)6660Sstevel@tonic-gate hci1394_q_at_with_data(hci1394_q_handle_t q_handle, hci1394_q_cmd_t *cmd,
6670Sstevel@tonic-gate hci1394_basic_pkt_t *hdr, uint_t hdrsize, uint8_t *data, uint_t datasize,
6680Sstevel@tonic-gate int *result)
6690Sstevel@tonic-gate {
6700Sstevel@tonic-gate uint32_t desc_ioaddr;
6710Sstevel@tonic-gate uint32_t data_ioaddr;
6720Sstevel@tonic-gate int status;
6730Sstevel@tonic-gate
6740Sstevel@tonic-gate
6750Sstevel@tonic-gate ASSERT(q_handle != NULL);
6760Sstevel@tonic-gate ASSERT(cmd != NULL);
6770Sstevel@tonic-gate ASSERT(hdr != NULL);
6780Sstevel@tonic-gate ASSERT(data != NULL);
6790Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_with_data_enter, HCI1394_TNF_HAL_STACK,
6800Sstevel@tonic-gate "");
6810Sstevel@tonic-gate
6820Sstevel@tonic-gate mutex_enter(&q_handle->q_mutex);
6830Sstevel@tonic-gate
6840Sstevel@tonic-gate /*
6850Sstevel@tonic-gate * Check the HAL state and generation when the AT Q is locked. This
6860Sstevel@tonic-gate * will make sure that we get all the commands when we flush the Q's
6870Sstevel@tonic-gate * during a reset or shutdown.
6880Sstevel@tonic-gate */
6890Sstevel@tonic-gate if ((hci1394_state(q_handle->q_drvinfo) != HCI1394_NORMAL) ||
6900Sstevel@tonic-gate (hci1394_ohci_current_busgen(q_handle->q_ohci) !=
6910Sstevel@tonic-gate cmd->qc_generation)) {
6920Sstevel@tonic-gate *result = H1394_STATUS_INVALID_BUSGEN;
6930Sstevel@tonic-gate mutex_exit(&q_handle->q_mutex);
6940Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_wd_st_fail,
6950Sstevel@tonic-gate HCI1394_TNF_HAL_STACK, "");
6960Sstevel@tonic-gate return (DDI_FAILURE);
6970Sstevel@tonic-gate }
6980Sstevel@tonic-gate
6990Sstevel@tonic-gate /* save away the argument to pass up when this command completes */
7000Sstevel@tonic-gate cmd->qc_node.tln_addr = cmd;
7010Sstevel@tonic-gate
7020Sstevel@tonic-gate /* we have not written any 16 byte blocks to the descriptor yet */
7030Sstevel@tonic-gate q_handle->q_block_cnt = 0;
7040Sstevel@tonic-gate
7050Sstevel@tonic-gate /* Reserve space for an OMI and OL in the descriptor buffer */
7060Sstevel@tonic-gate status = hci1394_q_reserve(&q_handle->q_desc,
7070Sstevel@tonic-gate (sizeof (hci1394_desc_imm_t) + sizeof (hci1394_desc_t)),
7080Sstevel@tonic-gate &desc_ioaddr);
7090Sstevel@tonic-gate if (status != DDI_SUCCESS) {
7100Sstevel@tonic-gate *result = H1394_STATUS_NOMORE_SPACE;
7110Sstevel@tonic-gate mutex_exit(&q_handle->q_mutex);
7120Sstevel@tonic-gate TNF_PROBE_0(hci1394_q_at_wd_qre_fail,
7130Sstevel@tonic-gate HCI1394_TNF_HAL_ERROR, "");
7140Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_with_data_exit,
7150Sstevel@tonic-gate HCI1394_TNF_HAL_STACK, "");
7160Sstevel@tonic-gate return (DDI_FAILURE);
7170Sstevel@tonic-gate }
7180Sstevel@tonic-gate
7190Sstevel@tonic-gate /* allocate space for data in the data buffer */
7200Sstevel@tonic-gate status = hci1394_q_reserve(&q_handle->q_data, datasize, &data_ioaddr);
7210Sstevel@tonic-gate if (status != DDI_SUCCESS) {
7220Sstevel@tonic-gate *result = H1394_STATUS_NOMORE_SPACE;
7230Sstevel@tonic-gate hci1394_q_unreserve(&q_handle->q_desc);
7240Sstevel@tonic-gate mutex_exit(&q_handle->q_mutex);
7250Sstevel@tonic-gate TNF_PROBE_0(hci1394_q_at_wd_qra_fail,
7260Sstevel@tonic-gate HCI1394_TNF_HAL_ERROR, "");
7270Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_with_data_exit,
7280Sstevel@tonic-gate HCI1394_TNF_HAL_STACK, "");
7290Sstevel@tonic-gate return (DDI_FAILURE);
7300Sstevel@tonic-gate }
7310Sstevel@tonic-gate
7320Sstevel@tonic-gate /* Copy data into data buffer */
7330Sstevel@tonic-gate hci1394_q_at_rep_put8(&q_handle->q_data, cmd, data, datasize);
7340Sstevel@tonic-gate
7350Sstevel@tonic-gate /* write the OMI to the descriptor buffer */
7360Sstevel@tonic-gate hci1394_q_at_write_OMI(q_handle, &q_handle->q_desc, cmd, hdr, hdrsize);
7370Sstevel@tonic-gate
7380Sstevel@tonic-gate /* write the OL to the descriptor buffer */
7390Sstevel@tonic-gate hci1394_q_at_write_OL(q_handle, &q_handle->q_desc, cmd, data_ioaddr,
7400Sstevel@tonic-gate datasize);
7410Sstevel@tonic-gate
7420Sstevel@tonic-gate /* Add the AT command to the queued list */
7430Sstevel@tonic-gate hci1394_tlist_add(q_handle->q_queued_list, &cmd->qc_node);
7440Sstevel@tonic-gate
7450Sstevel@tonic-gate mutex_exit(&q_handle->q_mutex);
7460Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_with_data_exit, HCI1394_TNF_HAL_STACK,
7470Sstevel@tonic-gate "");
7480Sstevel@tonic-gate
7490Sstevel@tonic-gate return (DDI_SUCCESS);
7500Sstevel@tonic-gate }
7510Sstevel@tonic-gate
7520Sstevel@tonic-gate
7530Sstevel@tonic-gate /*
7540Sstevel@tonic-gate * hci1394_q_at_with_mblk()
7550Sstevel@tonic-gate * Place an AT command that does need the data buffer into the DMA chain.
7560Sstevel@tonic-gate * The data is passed in mblk_t(s). Examples of this are a block write
7570Sstevel@tonic-gate * ATREQ and a block read ATRESP. The services layer and the hal use a
7580Sstevel@tonic-gate * private structure (h1394_mblk_t) to keep track of how much of the mblk
7590Sstevel@tonic-gate * to send since we may have to break the transfer up into smaller blocks.
7600Sstevel@tonic-gate * (i.e. a 1MByte block write would go out in 2KByte chunks. result is only
7610Sstevel@tonic-gate * valid on failure.
7620Sstevel@tonic-gate */
7630Sstevel@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)7640Sstevel@tonic-gate hci1394_q_at_with_mblk(hci1394_q_handle_t q_handle, hci1394_q_cmd_t *cmd,
7650Sstevel@tonic-gate hci1394_basic_pkt_t *hdr, uint_t hdrsize, h1394_mblk_t *mblk, int *result)
7660Sstevel@tonic-gate {
7670Sstevel@tonic-gate uint32_t desc_ioaddr;
7680Sstevel@tonic-gate uint32_t data_ioaddr;
7690Sstevel@tonic-gate int status;
7700Sstevel@tonic-gate
7710Sstevel@tonic-gate
7720Sstevel@tonic-gate ASSERT(q_handle != NULL);
7730Sstevel@tonic-gate ASSERT(cmd != NULL);
7740Sstevel@tonic-gate ASSERT(hdr != NULL);
7750Sstevel@tonic-gate ASSERT(mblk != NULL);
7760Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_with_mblk_enter, HCI1394_TNF_HAL_STACK,
7770Sstevel@tonic-gate "");
7780Sstevel@tonic-gate
7790Sstevel@tonic-gate mutex_enter(&q_handle->q_mutex);
7800Sstevel@tonic-gate
7810Sstevel@tonic-gate /*
7820Sstevel@tonic-gate * Check the HAL state and generation when the AT Q is locked. This
7830Sstevel@tonic-gate * will make sure that we get all the commands when we flush the Q's
7840Sstevel@tonic-gate * during a reset or shutdown.
7850Sstevel@tonic-gate */
7860Sstevel@tonic-gate if ((hci1394_state(q_handle->q_drvinfo) != HCI1394_NORMAL) ||
7870Sstevel@tonic-gate (hci1394_ohci_current_busgen(q_handle->q_ohci) !=
7880Sstevel@tonic-gate cmd->qc_generation)) {
7890Sstevel@tonic-gate *result = H1394_STATUS_INVALID_BUSGEN;
7900Sstevel@tonic-gate mutex_exit(&q_handle->q_mutex);
7910Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_wm_st_fail,
7920Sstevel@tonic-gate HCI1394_TNF_HAL_STACK, "");
7930Sstevel@tonic-gate return (DDI_FAILURE);
7940Sstevel@tonic-gate }
7950Sstevel@tonic-gate
7960Sstevel@tonic-gate /* save away the argument to pass up when this command completes */
7970Sstevel@tonic-gate cmd->qc_node.tln_addr = cmd;
7980Sstevel@tonic-gate
7990Sstevel@tonic-gate /* we have not written any 16 byte blocks to the descriptor yet */
8000Sstevel@tonic-gate q_handle->q_block_cnt = 0;
8010Sstevel@tonic-gate
8020Sstevel@tonic-gate /* Reserve space for an OMI and OL in the descriptor buffer */
8030Sstevel@tonic-gate status = hci1394_q_reserve(&q_handle->q_desc,
8040Sstevel@tonic-gate (sizeof (hci1394_desc_imm_t) + sizeof (hci1394_desc_t)),
8050Sstevel@tonic-gate &desc_ioaddr);
8060Sstevel@tonic-gate if (status != DDI_SUCCESS) {
8070Sstevel@tonic-gate *result = H1394_STATUS_NOMORE_SPACE;
8080Sstevel@tonic-gate mutex_exit(&q_handle->q_mutex);
8090Sstevel@tonic-gate TNF_PROBE_0(hci1394_q_at_wm_qre_fail,
8100Sstevel@tonic-gate HCI1394_TNF_HAL_ERROR, "");
8110Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_with_mblk_exit,
8120Sstevel@tonic-gate HCI1394_TNF_HAL_STACK, "");
8130Sstevel@tonic-gate return (DDI_FAILURE);
8140Sstevel@tonic-gate }
8150Sstevel@tonic-gate
8160Sstevel@tonic-gate /* Reserve space for data in the data buffer */
8170Sstevel@tonic-gate status = hci1394_q_reserve(&q_handle->q_data, mblk->length,
8180Sstevel@tonic-gate &data_ioaddr);
8190Sstevel@tonic-gate if (status != DDI_SUCCESS) {
8200Sstevel@tonic-gate *result = H1394_STATUS_NOMORE_SPACE;
8210Sstevel@tonic-gate hci1394_q_unreserve(&q_handle->q_desc);
8220Sstevel@tonic-gate mutex_exit(&q_handle->q_mutex);
8230Sstevel@tonic-gate TNF_PROBE_0(hci1394_q_at_wm_qra_fail,
8240Sstevel@tonic-gate HCI1394_TNF_HAL_ERROR, "");
8250Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_with_mblk_exit,
8260Sstevel@tonic-gate HCI1394_TNF_HAL_STACK, "");
8270Sstevel@tonic-gate return (DDI_FAILURE);
8280Sstevel@tonic-gate }
8290Sstevel@tonic-gate
8300Sstevel@tonic-gate /* Copy mblk data into data buffer */
8310Sstevel@tonic-gate hci1394_q_at_copy_from_mblk(&q_handle->q_data, cmd, mblk);
8320Sstevel@tonic-gate
8330Sstevel@tonic-gate /* write the OMI to the descriptor buffer */
8340Sstevel@tonic-gate hci1394_q_at_write_OMI(q_handle, &q_handle->q_desc, cmd, hdr, hdrsize);
8350Sstevel@tonic-gate
8360Sstevel@tonic-gate /* write the OL to the descriptor buffer */
8370Sstevel@tonic-gate hci1394_q_at_write_OL(q_handle, &q_handle->q_desc, cmd, data_ioaddr,
8380Sstevel@tonic-gate mblk->length);
8390Sstevel@tonic-gate
8400Sstevel@tonic-gate /* Add the AT command to the queued list */
8410Sstevel@tonic-gate hci1394_tlist_add(q_handle->q_queued_list, &cmd->qc_node);
8420Sstevel@tonic-gate
8430Sstevel@tonic-gate mutex_exit(&q_handle->q_mutex);
8440Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_with_mblk_exit, HCI1394_TNF_HAL_STACK,
8450Sstevel@tonic-gate "");
8460Sstevel@tonic-gate
8470Sstevel@tonic-gate return (DDI_SUCCESS);
8480Sstevel@tonic-gate }
8490Sstevel@tonic-gate
8500Sstevel@tonic-gate
8510Sstevel@tonic-gate /*
8520Sstevel@tonic-gate * hci1394_q_at_next()
8530Sstevel@tonic-gate * Return the next completed AT command in cmd. If flush_q is true, we will
8540Sstevel@tonic-gate * return the command regardless if it finished or not. We will flush
8550Sstevel@tonic-gate * during bus reset processing, shutdown, and detach.
8560Sstevel@tonic-gate */
8570Sstevel@tonic-gate void
hci1394_q_at_next(hci1394_q_handle_t q_handle,boolean_t flush_q,hci1394_q_cmd_t ** cmd)8580Sstevel@tonic-gate hci1394_q_at_next(hci1394_q_handle_t q_handle, boolean_t flush_q,
8590Sstevel@tonic-gate hci1394_q_cmd_t **cmd)
8600Sstevel@tonic-gate {
8610Sstevel@tonic-gate hci1394_q_buf_t *desc;
8620Sstevel@tonic-gate hci1394_q_buf_t *data;
8630Sstevel@tonic-gate hci1394_tlist_node_t *node;
8640Sstevel@tonic-gate uint32_t cmd_status;
8650Sstevel@tonic-gate
8660Sstevel@tonic-gate
8670Sstevel@tonic-gate ASSERT(q_handle != NULL);
8680Sstevel@tonic-gate ASSERT(cmd != NULL);
8690Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_next_enter, HCI1394_TNF_HAL_STACK, "");
8700Sstevel@tonic-gate
8710Sstevel@tonic-gate mutex_enter(&q_handle->q_mutex);
8720Sstevel@tonic-gate
8730Sstevel@tonic-gate desc = &q_handle->q_desc;
8740Sstevel@tonic-gate data = &q_handle->q_data;
8750Sstevel@tonic-gate
8760Sstevel@tonic-gate /* Sync descriptor buffer */
8770Sstevel@tonic-gate (void) ddi_dma_sync(desc->qb_buf.bi_dma_handle, 0,
8780Sstevel@tonic-gate desc->qb_buf.bi_length, DDI_DMA_SYNC_FORKERNEL);
8790Sstevel@tonic-gate
8800Sstevel@tonic-gate /* Look at the top cmd on the queued list (without removing it) */
8810Sstevel@tonic-gate hci1394_tlist_peek(q_handle->q_queued_list, &node);
8820Sstevel@tonic-gate if (node == NULL) {
8830Sstevel@tonic-gate /* There are no more commands left on the queued list */
8840Sstevel@tonic-gate *cmd = NULL;
8850Sstevel@tonic-gate mutex_exit(&q_handle->q_mutex);
8860Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_next_exit, HCI1394_TNF_HAL_STACK,
8870Sstevel@tonic-gate "");
8880Sstevel@tonic-gate return;
8890Sstevel@tonic-gate }
8900Sstevel@tonic-gate
8910Sstevel@tonic-gate /*
8920Sstevel@tonic-gate * There is a command on the list, read its status and timestamp when
8930Sstevel@tonic-gate * it was sent
8940Sstevel@tonic-gate */
8950Sstevel@tonic-gate *cmd = (hci1394_q_cmd_t *)node->tln_addr;
8960Sstevel@tonic-gate cmd_status = ddi_get32(desc->qb_buf.bi_handle, (*cmd)->qc_status_addr);
8970Sstevel@tonic-gate (*cmd)->qc_timestamp = cmd_status & DESC_ST_TIMESTAMP_MASK;
8980Sstevel@tonic-gate cmd_status = HCI1394_DESC_EVT_GET(cmd_status);
8990Sstevel@tonic-gate
9000Sstevel@tonic-gate /*
9010Sstevel@tonic-gate * If we are flushing the q (e.g. due to a bus reset), we will return
9020Sstevel@tonic-gate * the command regardless of its completion status. If we are not
9030Sstevel@tonic-gate * flushing the Q and we do not have status on the command (e.g. status
9040Sstevel@tonic-gate * = 0), we are done with this Q for now.
9050Sstevel@tonic-gate */
9060Sstevel@tonic-gate if (flush_q == B_FALSE) {
9070Sstevel@tonic-gate if (cmd_status == 0) {
9080Sstevel@tonic-gate *cmd = NULL;
9090Sstevel@tonic-gate mutex_exit(&q_handle->q_mutex);
9100Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_next_exit,
9110Sstevel@tonic-gate HCI1394_TNF_HAL_STACK, "");
9120Sstevel@tonic-gate return;
9130Sstevel@tonic-gate }
9140Sstevel@tonic-gate }
9150Sstevel@tonic-gate
9160Sstevel@tonic-gate /*
9170Sstevel@tonic-gate * The command completed, remove it from the queued list. There is not
9180Sstevel@tonic-gate * a race condition to delete the node in the list here. This is the
9190Sstevel@tonic-gate * only place the node will be deleted so we do not need to check the
9200Sstevel@tonic-gate * return status.
9210Sstevel@tonic-gate */
9220Sstevel@tonic-gate (void) hci1394_tlist_delete(q_handle->q_queued_list, node);
9230Sstevel@tonic-gate
9240Sstevel@tonic-gate /*
9250Sstevel@tonic-gate * Free the space used by the command in the descriptor and data
9260Sstevel@tonic-gate * buffers.
9270Sstevel@tonic-gate */
9280Sstevel@tonic-gate desc->qb_ptrs.qp_free_buf = (*cmd)->qc_descriptor_buf;
9290Sstevel@tonic-gate desc->qb_ptrs.qp_free = (*cmd)->qc_descriptor_end;
9300Sstevel@tonic-gate if ((*cmd)->qc_data_used == B_TRUE) {
9310Sstevel@tonic-gate data->qb_ptrs.qp_free_buf = (*cmd)->qc_data_buf;
9320Sstevel@tonic-gate data->qb_ptrs.qp_free = (*cmd)->qc_data_end;
9330Sstevel@tonic-gate }
9340Sstevel@tonic-gate
9350Sstevel@tonic-gate /* return command status */
9360Sstevel@tonic-gate (*cmd)->qc_status = cmd_status;
9370Sstevel@tonic-gate
9380Sstevel@tonic-gate mutex_exit(&q_handle->q_mutex);
9390Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_next_exit, HCI1394_TNF_HAL_STACK, "");
9400Sstevel@tonic-gate }
9410Sstevel@tonic-gate
9420Sstevel@tonic-gate
9430Sstevel@tonic-gate /*
9440Sstevel@tonic-gate * hci1394_q_at_write_OMI()
9450Sstevel@tonic-gate * Write an OMI descriptor into the AT descriptor buffer passed in as qbuf.
9460Sstevel@tonic-gate * Buffer state information is stored in cmd. Use the hdr and hdr size for
9470Sstevel@tonic-gate * the additional information attached to an immediate descriptor.
9480Sstevel@tonic-gate */
9490Sstevel@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)9500Sstevel@tonic-gate hci1394_q_at_write_OMI(hci1394_q_handle_t q_handle, hci1394_q_buf_t *qbuf,
9510Sstevel@tonic-gate hci1394_q_cmd_t *cmd, hci1394_basic_pkt_t *hdr, uint_t hdrsize)
9520Sstevel@tonic-gate {
9530Sstevel@tonic-gate hci1394_desc_imm_t *desc;
9540Sstevel@tonic-gate uint32_t data;
9550Sstevel@tonic-gate
9560Sstevel@tonic-gate
9570Sstevel@tonic-gate ASSERT(qbuf != NULL);
9580Sstevel@tonic-gate ASSERT(cmd != NULL);
9590Sstevel@tonic-gate ASSERT(hdr != NULL);
9600Sstevel@tonic-gate ASSERT(MUTEX_HELD(&q_handle->q_mutex));
9610Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_write_OMI_enter, HCI1394_TNF_HAL_STACK,
9620Sstevel@tonic-gate "");
9630Sstevel@tonic-gate
9640Sstevel@tonic-gate /* The only valid "header" sizes for an OMI are 8 bytes or 16 bytes */
9650Sstevel@tonic-gate ASSERT((hdrsize == 8) || (hdrsize == 16));
9660Sstevel@tonic-gate
9670Sstevel@tonic-gate /* Make sure enough room for OMI */
9680Sstevel@tonic-gate ASSERT(qbuf->qb_ptrs.qp_resv_size >= sizeof (hci1394_desc_imm_t));
9690Sstevel@tonic-gate
9700Sstevel@tonic-gate /* Store the offset of the top of this descriptor block */
9710Sstevel@tonic-gate qbuf->qb_ptrs.qp_offset = (uint32_t)(qbuf->qb_ptrs.qp_current -
9720Sstevel@tonic-gate qbuf->qb_ptrs.qp_begin);
9730Sstevel@tonic-gate
9740Sstevel@tonic-gate /* Setup OpenHCI OMI Header */
9750Sstevel@tonic-gate desc = (hci1394_desc_imm_t *)qbuf->qb_ptrs.qp_current;
9760Sstevel@tonic-gate data = DESC_AT_OMI | (hdrsize & DESC_HDR_REQCOUNT_MASK);
9770Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle, &desc->hdr, data);
9780Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle, &desc->data_addr, 0);
9790Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle, &desc->branch, 0);
9800Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle, &desc->status, cmd->qc_timestamp);
9810Sstevel@tonic-gate
9820Sstevel@tonic-gate /*
9830Sstevel@tonic-gate * Copy in 1394 header. Size is in bytes, convert it to a 32-bit word
9840Sstevel@tonic-gate * count.
9850Sstevel@tonic-gate */
9860Sstevel@tonic-gate ddi_rep_put32(qbuf->qb_buf.bi_handle, &hdr->q1, &desc->q1,
9870Sstevel@tonic-gate hdrsize >> 2, DDI_DEV_AUTOINCR);
9880Sstevel@tonic-gate
9890Sstevel@tonic-gate /*
9900Sstevel@tonic-gate * We wrote 2 16 byte blocks in the descriptor buffer, update the count
9910Sstevel@tonic-gate * accordingly. Update the reserved size and current pointer.
9920Sstevel@tonic-gate */
9930Sstevel@tonic-gate q_handle->q_block_cnt += 2;
9940Sstevel@tonic-gate qbuf->qb_ptrs.qp_resv_size -= sizeof (hci1394_desc_imm_t);
9950Sstevel@tonic-gate qbuf->qb_ptrs.qp_current += sizeof (hci1394_desc_imm_t);
9960Sstevel@tonic-gate
9970Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_write_OMI_exit, HCI1394_TNF_HAL_STACK,
9980Sstevel@tonic-gate "");
9990Sstevel@tonic-gate }
10000Sstevel@tonic-gate
10010Sstevel@tonic-gate
10020Sstevel@tonic-gate /*
10030Sstevel@tonic-gate * hci1394_q_at_write_OLI()
10040Sstevel@tonic-gate * Write an OLI descriptor into the AT descriptor buffer passed in as qbuf.
10050Sstevel@tonic-gate * Buffer state information is stored in cmd. Use the hdr and hdr size for
10060Sstevel@tonic-gate * the additional information attached to an immediate descriptor.
10070Sstevel@tonic-gate */
10080Sstevel@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)10090Sstevel@tonic-gate hci1394_q_at_write_OLI(hci1394_q_handle_t q_handle, hci1394_q_buf_t *qbuf,
10100Sstevel@tonic-gate hci1394_q_cmd_t *cmd, hci1394_basic_pkt_t *hdr, uint_t hdrsize)
10110Sstevel@tonic-gate {
10120Sstevel@tonic-gate hci1394_desc_imm_t *desc;
10130Sstevel@tonic-gate uint32_t data;
10140Sstevel@tonic-gate uint32_t command_ptr;
10150Sstevel@tonic-gate uint32_t tcode;
10160Sstevel@tonic-gate
10170Sstevel@tonic-gate
10180Sstevel@tonic-gate ASSERT(qbuf != NULL);
10190Sstevel@tonic-gate ASSERT(cmd != NULL);
10200Sstevel@tonic-gate ASSERT(hdr != NULL);
10210Sstevel@tonic-gate ASSERT(MUTEX_HELD(&q_handle->q_mutex));
10220Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_write_OLI_enter, HCI1394_TNF_HAL_STACK,
10230Sstevel@tonic-gate "");
10240Sstevel@tonic-gate
10250Sstevel@tonic-gate /* The only valid "header" sizes for an OLI are 8, 12, 16 bytes */
10260Sstevel@tonic-gate ASSERT((hdrsize == 8) || (hdrsize == 12) || (hdrsize == 16));
10270Sstevel@tonic-gate
10280Sstevel@tonic-gate /* make sure enough room for 1 OLI */
10290Sstevel@tonic-gate ASSERT(qbuf->qb_ptrs.qp_resv_size >= sizeof (hci1394_desc_imm_t));
10300Sstevel@tonic-gate
10310Sstevel@tonic-gate /* Store the offset of the top of this descriptor block */
10320Sstevel@tonic-gate qbuf->qb_ptrs.qp_offset = (uint32_t)(qbuf->qb_ptrs.qp_current -
10330Sstevel@tonic-gate qbuf->qb_ptrs.qp_begin);
10340Sstevel@tonic-gate
10350Sstevel@tonic-gate /* Setup OpenHCI OLI Header */
10360Sstevel@tonic-gate desc = (hci1394_desc_imm_t *)qbuf->qb_ptrs.qp_current;
10370Sstevel@tonic-gate data = DESC_AT_OLI | (hdrsize & DESC_HDR_REQCOUNT_MASK);
10380Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle, &desc->hdr, data);
10390Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle, &desc->data_addr, 0);
10400Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle, &desc->branch, 0);
10410Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle, &desc->status, cmd->qc_timestamp);
10420Sstevel@tonic-gate
10430Sstevel@tonic-gate /* Setup 1394 Header */
10440Sstevel@tonic-gate tcode = (hdr->q1 & DESC_PKT_TCODE_MASK) >> DESC_PKT_TCODE_SHIFT;
10450Sstevel@tonic-gate if ((tcode == IEEE1394_TCODE_WRITE_QUADLET) ||
10460Sstevel@tonic-gate (tcode == IEEE1394_TCODE_READ_QUADLET_RESP)) {
10470Sstevel@tonic-gate /*
10480Sstevel@tonic-gate * if the tcode = a quadlet write, move the last quadlet as
10490Sstevel@tonic-gate * 8-bit data. All data is treated as 8-bit data (even quadlet
10500Sstevel@tonic-gate * reads and writes). Therefore, target drivers MUST take that
10510Sstevel@tonic-gate * into consideration when accessing device registers.
10520Sstevel@tonic-gate */
10530Sstevel@tonic-gate ddi_rep_put32(qbuf->qb_buf.bi_handle, &hdr->q1, &desc->q1, 3,
10540Sstevel@tonic-gate DDI_DEV_AUTOINCR);
10550Sstevel@tonic-gate ddi_rep_put8(qbuf->qb_buf.bi_handle, (uint8_t *)&hdr->q4,
10560Sstevel@tonic-gate (uint8_t *)&desc->q4, 4, DDI_DEV_AUTOINCR);
10570Sstevel@tonic-gate } else {
10580Sstevel@tonic-gate ddi_rep_put32(qbuf->qb_buf.bi_handle, &hdr->q1, &desc->q1,
10590Sstevel@tonic-gate hdrsize >> 2, DDI_DEV_AUTOINCR);
10600Sstevel@tonic-gate }
10610Sstevel@tonic-gate
10620Sstevel@tonic-gate /*
10630Sstevel@tonic-gate * We wrote 2 16 byte blocks in the descriptor buffer, update the count
10640Sstevel@tonic-gate * accordingly.
10650Sstevel@tonic-gate */
10660Sstevel@tonic-gate q_handle->q_block_cnt += 2;
10670Sstevel@tonic-gate
10680Sstevel@tonic-gate /*
10690Sstevel@tonic-gate * Sync buffer in case DMA engine currently running. This must be done
10700Sstevel@tonic-gate * before writing the command pointer in the previous descriptor.
10710Sstevel@tonic-gate */
10720Sstevel@tonic-gate (void) ddi_dma_sync(qbuf->qb_buf.bi_dma_handle, 0,
10730Sstevel@tonic-gate qbuf->qb_buf.bi_length, DDI_DMA_SYNC_FORDEV);
10740Sstevel@tonic-gate
10750Sstevel@tonic-gate /* save away the status address for quick access in at_next() */
10760Sstevel@tonic-gate cmd->qc_status_addr = &desc->status;
10770Sstevel@tonic-gate
10780Sstevel@tonic-gate /*
10790Sstevel@tonic-gate * Setup the command pointer. This tells the HW where to get the
10800Sstevel@tonic-gate * descriptor we just setup. This includes the IO address along with
10810Sstevel@tonic-gate * a 4 bit 16 byte block count
10820Sstevel@tonic-gate */
10830Sstevel@tonic-gate command_ptr = (uint32_t)((qbuf->qb_cookie[qbuf->qb_ptrs.qp_current_buf
10840Sstevel@tonic-gate ].dmac_address + qbuf->qb_ptrs.qp_offset) | (q_handle->q_block_cnt &
10850Sstevel@tonic-gate DESC_Z_MASK));
10860Sstevel@tonic-gate
10870Sstevel@tonic-gate /*
10880Sstevel@tonic-gate * if we previously setup a descriptor, add this new descriptor into
10890Sstevel@tonic-gate * the previous descriptor's "next" pointer.
10900Sstevel@tonic-gate */
10910Sstevel@tonic-gate if (q_handle->q_previous != NULL) {
10920Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle, &q_handle->q_previous->branch,
10930Sstevel@tonic-gate command_ptr);
10940Sstevel@tonic-gate /* Sync buffer again, this gets the command pointer */
10950Sstevel@tonic-gate (void) ddi_dma_sync(qbuf->qb_buf.bi_dma_handle, 0,
10960Sstevel@tonic-gate qbuf->qb_buf.bi_length, DDI_DMA_SYNC_FORDEV);
10970Sstevel@tonic-gate }
10980Sstevel@tonic-gate
10990Sstevel@tonic-gate /*
11000Sstevel@tonic-gate * this is now the previous descriptor. Update the current pointer,
11010Sstevel@tonic-gate * clear the block count and reserved size since this is the end of
11020Sstevel@tonic-gate * this command.
11030Sstevel@tonic-gate */
11040Sstevel@tonic-gate q_handle->q_previous = (hci1394_desc_t *)desc;
11050Sstevel@tonic-gate qbuf->qb_ptrs.qp_current += sizeof (hci1394_desc_imm_t);
11060Sstevel@tonic-gate q_handle->q_block_cnt = 0;
11070Sstevel@tonic-gate qbuf->qb_ptrs.qp_resv_size = 0;
11080Sstevel@tonic-gate
11090Sstevel@tonic-gate /* save away cleanup info when we are done with the command */
11100Sstevel@tonic-gate cmd->qc_descriptor_buf = qbuf->qb_ptrs.qp_current_buf;
11110Sstevel@tonic-gate cmd->qc_descriptor_end = qbuf->qb_ptrs.qp_current - 1;
11120Sstevel@tonic-gate
11130Sstevel@tonic-gate /* If the DMA is not running, start it */
11140Sstevel@tonic-gate if (q_handle->q_dma_running == B_FALSE) {
11150Sstevel@tonic-gate q_handle->q_info.qi_start(q_handle->q_info.qi_callback_arg,
11160Sstevel@tonic-gate command_ptr);
11170Sstevel@tonic-gate q_handle->q_dma_running = B_TRUE;
11180Sstevel@tonic-gate /* the DMA is running, wake it up */
11190Sstevel@tonic-gate } else {
11200Sstevel@tonic-gate q_handle->q_info.qi_wake(q_handle->q_info.qi_callback_arg);
11210Sstevel@tonic-gate }
11220Sstevel@tonic-gate
11230Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_write_OLI_exit, HCI1394_TNF_HAL_STACK,
11240Sstevel@tonic-gate "");
11250Sstevel@tonic-gate }
11260Sstevel@tonic-gate
11270Sstevel@tonic-gate
11280Sstevel@tonic-gate /*
11290Sstevel@tonic-gate * hci1394_q_at_write_OL()
11300Sstevel@tonic-gate * Write an OL descriptor into the AT descriptor buffer passed in as qbuf.
11310Sstevel@tonic-gate * Buffer state information is stored in cmd. The IO address of the data
11320Sstevel@tonic-gate * buffer is passed in io_addr. Size is the size of the data to be
11330Sstevel@tonic-gate * transferred.
11340Sstevel@tonic-gate */
11350Sstevel@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)11360Sstevel@tonic-gate hci1394_q_at_write_OL(hci1394_q_handle_t q_handle, hci1394_q_buf_t *qbuf,
11370Sstevel@tonic-gate hci1394_q_cmd_t *cmd, uint32_t io_addr, uint_t size)
11380Sstevel@tonic-gate {
11390Sstevel@tonic-gate hci1394_desc_t *desc;
11400Sstevel@tonic-gate uint32_t data;
11410Sstevel@tonic-gate uint32_t command_ptr;
11420Sstevel@tonic-gate
11430Sstevel@tonic-gate
11440Sstevel@tonic-gate ASSERT(q_handle != NULL);
11450Sstevel@tonic-gate ASSERT(qbuf != NULL);
11460Sstevel@tonic-gate ASSERT(cmd != NULL);
11470Sstevel@tonic-gate ASSERT(MUTEX_HELD(&q_handle->q_mutex));
11480Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_write_OL_enter, HCI1394_TNF_HAL_STACK,
11490Sstevel@tonic-gate "");
11500Sstevel@tonic-gate
11510Sstevel@tonic-gate /* make sure enough room for OL */
11520Sstevel@tonic-gate ASSERT(qbuf->qb_ptrs.qp_resv_size >= sizeof (hci1394_desc_t));
11530Sstevel@tonic-gate
11540Sstevel@tonic-gate /* Setup OpenHCI OL Header */
11550Sstevel@tonic-gate desc = (hci1394_desc_t *)qbuf->qb_ptrs.qp_current;
11560Sstevel@tonic-gate data = DESC_AT_OL | (size & DESC_HDR_REQCOUNT_MASK);
11570Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle, &desc->hdr, data);
11580Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle, &desc->data_addr, io_addr);
11590Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle, &desc->branch, 0);
11600Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle, &desc->status, 0);
11610Sstevel@tonic-gate
11620Sstevel@tonic-gate /*
11630Sstevel@tonic-gate * We wrote 1 16 byte block in the descriptor buffer, update the count
11640Sstevel@tonic-gate * accordingly.
11650Sstevel@tonic-gate */
11660Sstevel@tonic-gate q_handle->q_block_cnt++;
11670Sstevel@tonic-gate
11680Sstevel@tonic-gate /*
11690Sstevel@tonic-gate * Sync buffer in case DMA engine currently running. This must be done
11700Sstevel@tonic-gate * before writing the command pointer in the previous descriptor.
11710Sstevel@tonic-gate */
11720Sstevel@tonic-gate (void) ddi_dma_sync(qbuf->qb_buf.bi_dma_handle, 0,
11730Sstevel@tonic-gate qbuf->qb_buf.bi_length, DDI_DMA_SYNC_FORDEV);
11740Sstevel@tonic-gate
11750Sstevel@tonic-gate /* save away the status address for quick access in at_next() */
11760Sstevel@tonic-gate cmd->qc_status_addr = &desc->status;
11770Sstevel@tonic-gate
11780Sstevel@tonic-gate /*
11790Sstevel@tonic-gate * Setup the command pointer. This tells the HW where to get the
11800Sstevel@tonic-gate * descriptor we just setup. This includes the IO address along with
11810Sstevel@tonic-gate * a 4 bit 16 byte block count
11820Sstevel@tonic-gate */
11830Sstevel@tonic-gate command_ptr = (uint32_t)((qbuf->qb_cookie[qbuf->qb_ptrs.qp_current_buf
11840Sstevel@tonic-gate ].dmac_address + qbuf->qb_ptrs.qp_offset) | (q_handle->q_block_cnt &
11850Sstevel@tonic-gate DESC_Z_MASK));
11860Sstevel@tonic-gate
11870Sstevel@tonic-gate /*
11880Sstevel@tonic-gate * if we previously setup a descriptor, add this new descriptor into
11890Sstevel@tonic-gate * the previous descriptor's "next" pointer.
11900Sstevel@tonic-gate */
11910Sstevel@tonic-gate if (q_handle->q_previous != NULL) {
11920Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle, &q_handle->q_previous->branch,
11930Sstevel@tonic-gate command_ptr);
11940Sstevel@tonic-gate /* Sync buffer again, this gets the command pointer */
11950Sstevel@tonic-gate (void) ddi_dma_sync(qbuf->qb_buf.bi_dma_handle, 0,
11960Sstevel@tonic-gate qbuf->qb_buf.bi_length, DDI_DMA_SYNC_FORDEV);
11970Sstevel@tonic-gate }
11980Sstevel@tonic-gate
11990Sstevel@tonic-gate /*
12000Sstevel@tonic-gate * this is now the previous descriptor. Update the current pointer,
12010Sstevel@tonic-gate * clear the block count and reserved size since this is the end of
12020Sstevel@tonic-gate * this command.
12030Sstevel@tonic-gate */
12040Sstevel@tonic-gate q_handle->q_previous = desc;
12050Sstevel@tonic-gate qbuf->qb_ptrs.qp_current += sizeof (hci1394_desc_t);
12060Sstevel@tonic-gate q_handle->q_block_cnt = 0;
12070Sstevel@tonic-gate qbuf->qb_ptrs.qp_resv_size = 0;
12080Sstevel@tonic-gate
12090Sstevel@tonic-gate /* save away cleanup info when we are done with the command */
12100Sstevel@tonic-gate cmd->qc_descriptor_buf = qbuf->qb_ptrs.qp_current_buf;
12110Sstevel@tonic-gate cmd->qc_descriptor_end = qbuf->qb_ptrs.qp_current - 1;
12120Sstevel@tonic-gate
12130Sstevel@tonic-gate /* If the DMA is not running, start it */
12140Sstevel@tonic-gate if (q_handle->q_dma_running == B_FALSE) {
12150Sstevel@tonic-gate q_handle->q_info.qi_start(q_handle->q_info.qi_callback_arg,
12160Sstevel@tonic-gate command_ptr);
12170Sstevel@tonic-gate q_handle->q_dma_running = B_TRUE;
12180Sstevel@tonic-gate /* the DMA is running, wake it up */
12190Sstevel@tonic-gate } else {
12200Sstevel@tonic-gate q_handle->q_info.qi_wake(q_handle->q_info.qi_callback_arg);
12210Sstevel@tonic-gate }
12220Sstevel@tonic-gate
12230Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_write_OL_exit, HCI1394_TNF_HAL_STACK,
12240Sstevel@tonic-gate "");
12250Sstevel@tonic-gate }
12260Sstevel@tonic-gate
12270Sstevel@tonic-gate
12280Sstevel@tonic-gate /*
12290Sstevel@tonic-gate * hci1394_q_at_rep_put8()
12300Sstevel@tonic-gate * Copy a byte stream from a kernel virtual address (data) to a IO mapped
12310Sstevel@tonic-gate * data buffer (qbuf). Copy datasize bytes. State information for the
12320Sstevel@tonic-gate * data buffer is kept in cmd.
12330Sstevel@tonic-gate */
12340Sstevel@tonic-gate void
hci1394_q_at_rep_put8(hci1394_q_buf_t * qbuf,hci1394_q_cmd_t * cmd,uint8_t * data,uint_t datasize)12350Sstevel@tonic-gate hci1394_q_at_rep_put8(hci1394_q_buf_t *qbuf, hci1394_q_cmd_t *cmd,
12360Sstevel@tonic-gate uint8_t *data, uint_t datasize)
12370Sstevel@tonic-gate {
12380Sstevel@tonic-gate ASSERT(qbuf != NULL);
12390Sstevel@tonic-gate ASSERT(cmd != NULL);
12400Sstevel@tonic-gate ASSERT(data != NULL);
12410Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_rep_put8_enter, HCI1394_TNF_HAL_STACK,
12420Sstevel@tonic-gate "");
12430Sstevel@tonic-gate
12440Sstevel@tonic-gate /* Make sure enough room for data */
12450Sstevel@tonic-gate ASSERT(qbuf->qb_ptrs.qp_resv_size >= datasize);
12460Sstevel@tonic-gate
12470Sstevel@tonic-gate /* Copy in data into the data buffer */
12480Sstevel@tonic-gate ddi_rep_put8(qbuf->qb_buf.bi_handle, data,
12490Sstevel@tonic-gate (uint8_t *)qbuf->qb_ptrs.qp_current, datasize, DDI_DEV_AUTOINCR);
12500Sstevel@tonic-gate
12510Sstevel@tonic-gate /* Update the current pointer, offset, and reserved size */
12520Sstevel@tonic-gate qbuf->qb_ptrs.qp_current += datasize;
12530Sstevel@tonic-gate qbuf->qb_ptrs.qp_offset = (uint32_t)(qbuf->qb_ptrs.qp_current -
12540Sstevel@tonic-gate qbuf->qb_ptrs.qp_begin);
12550Sstevel@tonic-gate qbuf->qb_ptrs.qp_resv_size -= datasize;
12560Sstevel@tonic-gate
12570Sstevel@tonic-gate /* save away cleanup info when we are done with the command */
12580Sstevel@tonic-gate cmd->qc_data_used = B_TRUE;
12590Sstevel@tonic-gate cmd->qc_data_buf = qbuf->qb_ptrs.qp_current_buf;
12600Sstevel@tonic-gate cmd->qc_data_end = qbuf->qb_ptrs.qp_current - 1;
12610Sstevel@tonic-gate
12620Sstevel@tonic-gate /* Sync data buffer */
12630Sstevel@tonic-gate (void) ddi_dma_sync(qbuf->qb_buf.bi_dma_handle, 0,
12640Sstevel@tonic-gate qbuf->qb_buf.bi_length, DDI_DMA_SYNC_FORDEV);
12650Sstevel@tonic-gate
12660Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_rep_put8_exit, HCI1394_TNF_HAL_STACK,
12670Sstevel@tonic-gate "");
12680Sstevel@tonic-gate }
12690Sstevel@tonic-gate
12700Sstevel@tonic-gate
12710Sstevel@tonic-gate /*
12720Sstevel@tonic-gate * hci1394_q_at_copy_from_mblk()
12730Sstevel@tonic-gate * Copy a byte stream from a mblk(s) to a IO mapped data buffer (qbuf).
12740Sstevel@tonic-gate * Copy mblk->length bytes. The services layer and the hal use a private
12750Sstevel@tonic-gate * structure (h1394_mblk_t) to keep track of how much of the mblk to send
12760Sstevel@tonic-gate * since we may have to break the transfer up into smaller blocks. (i.e. a
12770Sstevel@tonic-gate * 1MByte block write would go out in 2KByte chunks. State information for
12780Sstevel@tonic-gate * the data buffer is kept in cmd.
12790Sstevel@tonic-gate */
12800Sstevel@tonic-gate static void
hci1394_q_at_copy_from_mblk(hci1394_q_buf_t * qbuf,hci1394_q_cmd_t * cmd,h1394_mblk_t * mblk)12810Sstevel@tonic-gate hci1394_q_at_copy_from_mblk(hci1394_q_buf_t *qbuf, hci1394_q_cmd_t *cmd,
12820Sstevel@tonic-gate h1394_mblk_t *mblk)
12830Sstevel@tonic-gate {
12840Sstevel@tonic-gate uint_t bytes_left;
12850Sstevel@tonic-gate uint_t length;
12860Sstevel@tonic-gate
12870Sstevel@tonic-gate
12880Sstevel@tonic-gate ASSERT(qbuf != NULL);
12890Sstevel@tonic-gate ASSERT(cmd != NULL);
12900Sstevel@tonic-gate ASSERT(mblk != NULL);
12910Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_copy_from_mblk_enter,
12920Sstevel@tonic-gate HCI1394_TNF_HAL_STACK, "");
12930Sstevel@tonic-gate
12940Sstevel@tonic-gate /* We return these variables to the Services Layer when we are done */
12950Sstevel@tonic-gate mblk->next_offset = mblk->curr_offset;
12960Sstevel@tonic-gate mblk->next_mblk = mblk->curr_mblk;
12970Sstevel@tonic-gate bytes_left = mblk->length;
12980Sstevel@tonic-gate
12990Sstevel@tonic-gate /* do while there are bytes left to copy */
13000Sstevel@tonic-gate do {
13010Sstevel@tonic-gate /*
13020Sstevel@tonic-gate * If the entire data portion of the current block transfer is
13030Sstevel@tonic-gate * contained within a single mblk.
13040Sstevel@tonic-gate */
13050Sstevel@tonic-gate if ((mblk->next_offset + bytes_left) <=
13060Sstevel@tonic-gate (mblk->next_mblk->b_wptr)) {
13070Sstevel@tonic-gate /* Copy the data into the data Q */
13080Sstevel@tonic-gate hci1394_q_at_rep_put8(qbuf, cmd,
13090Sstevel@tonic-gate (uint8_t *)mblk->next_offset, bytes_left);
13100Sstevel@tonic-gate
13110Sstevel@tonic-gate /* increment the mblk offset */
13120Sstevel@tonic-gate mblk->next_offset += bytes_left;
13130Sstevel@tonic-gate
13140Sstevel@tonic-gate /* we have no more bytes to put into the buffer */
13150Sstevel@tonic-gate bytes_left = 0;
13160Sstevel@tonic-gate
13170Sstevel@tonic-gate /*
13180Sstevel@tonic-gate * If our offset is at the end of data in this mblk, go
13190Sstevel@tonic-gate * to the next mblk.
13200Sstevel@tonic-gate */
13210Sstevel@tonic-gate if (mblk->next_offset >= mblk->next_mblk->b_wptr) {
13220Sstevel@tonic-gate mblk->next_mblk = mblk->next_mblk->b_cont;
13230Sstevel@tonic-gate if (mblk->next_mblk != NULL) {
13240Sstevel@tonic-gate mblk->next_offset =
13250Sstevel@tonic-gate mblk->next_mblk->b_rptr;
13260Sstevel@tonic-gate }
13270Sstevel@tonic-gate }
13280Sstevel@tonic-gate
13290Sstevel@tonic-gate /*
13300Sstevel@tonic-gate * The data portion of the current block transfer is spread
13310Sstevel@tonic-gate * across two or more mblk's
13320Sstevel@tonic-gate */
13330Sstevel@tonic-gate } else {
13340Sstevel@tonic-gate /*
13350Sstevel@tonic-gate * Figure out how much data is in this mblk.
13360Sstevel@tonic-gate */
13370Sstevel@tonic-gate length = mblk->next_mblk->b_wptr - mblk->next_offset;
13380Sstevel@tonic-gate
13390Sstevel@tonic-gate /* Copy the data into the atreq data Q */
13400Sstevel@tonic-gate hci1394_q_at_rep_put8(qbuf, cmd,
13410Sstevel@tonic-gate (uint8_t *)mblk->next_offset, length);
13420Sstevel@tonic-gate
13430Sstevel@tonic-gate /* update the bytes left count, go to the next mblk */
13440Sstevel@tonic-gate bytes_left = bytes_left - length;
13450Sstevel@tonic-gate mblk->next_mblk = mblk->next_mblk->b_cont;
13460Sstevel@tonic-gate ASSERT(mblk->next_mblk != NULL);
13470Sstevel@tonic-gate mblk->next_offset = mblk->next_mblk->b_rptr;
13480Sstevel@tonic-gate }
13490Sstevel@tonic-gate } while (bytes_left > 0);
13500Sstevel@tonic-gate
13510Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_copy_from_mblk_exit,
13520Sstevel@tonic-gate HCI1394_TNF_HAL_STACK, "");
13530Sstevel@tonic-gate }
13540Sstevel@tonic-gate
13550Sstevel@tonic-gate
13560Sstevel@tonic-gate /*
13570Sstevel@tonic-gate * hci1394_q_ar_next()
13580Sstevel@tonic-gate * Return an address to the next received AR packet. If there are no more
13590Sstevel@tonic-gate * AR packets in the buffer, q_addr will be set to NULL.
13600Sstevel@tonic-gate */
13610Sstevel@tonic-gate void
hci1394_q_ar_next(hci1394_q_handle_t q_handle,uint32_t ** q_addr)13620Sstevel@tonic-gate hci1394_q_ar_next(hci1394_q_handle_t q_handle, uint32_t **q_addr)
13630Sstevel@tonic-gate {
13640Sstevel@tonic-gate hci1394_desc_t *desc;
13650Sstevel@tonic-gate hci1394_q_buf_t *descb;
13660Sstevel@tonic-gate hci1394_q_buf_t *datab;
13670Sstevel@tonic-gate uint32_t residual_count;
13680Sstevel@tonic-gate
13690Sstevel@tonic-gate
13700Sstevel@tonic-gate ASSERT(q_handle != NULL);
13710Sstevel@tonic-gate ASSERT(q_addr != NULL);
13720Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_ar_next_enter, HCI1394_TNF_HAL_STACK, "");
13730Sstevel@tonic-gate
13740Sstevel@tonic-gate descb = &q_handle->q_desc;
13750Sstevel@tonic-gate datab = &q_handle->q_data;
13760Sstevel@tonic-gate
13770Sstevel@tonic-gate /* Sync Descriptor buffer */
13780Sstevel@tonic-gate (void) ddi_dma_sync(descb->qb_buf.bi_dma_handle, 0,
13790Sstevel@tonic-gate descb->qb_buf.bi_length, DDI_DMA_SYNC_FORKERNEL);
13800Sstevel@tonic-gate
13810Sstevel@tonic-gate /*
13820Sstevel@tonic-gate * Check residual in current IM count vs q_space_left to see if we have
13830Sstevel@tonic-gate * received any more responses
13840Sstevel@tonic-gate */
13850Sstevel@tonic-gate desc = (hci1394_desc_t *)q_handle->q_head;
13860Sstevel@tonic-gate residual_count = ddi_get32(descb->qb_buf.bi_handle, &desc->status);
13870Sstevel@tonic-gate residual_count &= DESC_ST_RESCOUNT_MASK;
13880Sstevel@tonic-gate if (residual_count >= q_handle->q_space_left) {
13890Sstevel@tonic-gate /* No new packets received */
13900Sstevel@tonic-gate *q_addr = NULL;
13910Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_ar_next_exit,
13920Sstevel@tonic-gate HCI1394_TNF_HAL_STACK, "");
13930Sstevel@tonic-gate return;
13940Sstevel@tonic-gate }
13950Sstevel@tonic-gate
13960Sstevel@tonic-gate /* Sync Data Q */
13970Sstevel@tonic-gate (void) ddi_dma_sync(datab->qb_buf.bi_dma_handle, 0,
13980Sstevel@tonic-gate datab->qb_buf.bi_length, DDI_DMA_SYNC_FORKERNEL);
13990Sstevel@tonic-gate
14000Sstevel@tonic-gate /*
14010Sstevel@tonic-gate * We have a new packet, return the address of the start of the
14020Sstevel@tonic-gate * packet.
14030Sstevel@tonic-gate */
14040Sstevel@tonic-gate *q_addr = (uint32_t *)datab->qb_ptrs.qp_current;
14050Sstevel@tonic-gate
14060Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_ar_next_exit, HCI1394_TNF_HAL_STACK, "");
14070Sstevel@tonic-gate }
14080Sstevel@tonic-gate
14090Sstevel@tonic-gate
14100Sstevel@tonic-gate /*
14110Sstevel@tonic-gate * hci1394_q_ar_free()
14120Sstevel@tonic-gate * Free the space used by the AR packet at the top of the data buffer. AR
14130Sstevel@tonic-gate * packets are processed in the order that they are received. This will
14140Sstevel@tonic-gate * free the oldest received packet which has not yet been freed. size is
14150Sstevel@tonic-gate * how much space the packet takes up.
14160Sstevel@tonic-gate */
14170Sstevel@tonic-gate void
hci1394_q_ar_free(hci1394_q_handle_t q_handle,uint_t size)14180Sstevel@tonic-gate hci1394_q_ar_free(hci1394_q_handle_t q_handle, uint_t size)
14190Sstevel@tonic-gate {
14200Sstevel@tonic-gate hci1394_q_buf_t *descb;
14210Sstevel@tonic-gate hci1394_q_buf_t *datab;
14220Sstevel@tonic-gate
14230Sstevel@tonic-gate
14240Sstevel@tonic-gate ASSERT(q_handle != NULL);
14250Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_ar_free_enter, HCI1394_TNF_HAL_STACK, "");
14260Sstevel@tonic-gate
14270Sstevel@tonic-gate descb = &q_handle->q_desc;
14280Sstevel@tonic-gate datab = &q_handle->q_data;
14290Sstevel@tonic-gate
14300Sstevel@tonic-gate /*
14310Sstevel@tonic-gate * Packet is in multiple buffers. Theoretically a buffer could be broken
14320Sstevel@tonic-gate * in more than two buffers for an ARRESP. Since the buffers should be
14330Sstevel@tonic-gate * in at least 4K increments this will not happen since the max packet
14340Sstevel@tonic-gate * size is 2KBytes.
14350Sstevel@tonic-gate */
14360Sstevel@tonic-gate if ((datab->qb_ptrs.qp_current + size) > datab->qb_ptrs.qp_end) {
14370Sstevel@tonic-gate /* Add IM descriptor for used buffer back into Q */
14380Sstevel@tonic-gate hci1394_q_ar_write_IM(q_handle, descb,
14390Sstevel@tonic-gate datab->qb_cookie[datab->qb_ptrs.qp_current_buf
14400Sstevel@tonic-gate ].dmac_address,
14410Sstevel@tonic-gate datab->qb_cookie[datab->qb_ptrs.qp_current_buf].dmac_size);
14420Sstevel@tonic-gate
14430Sstevel@tonic-gate /* Go to the next buffer */
14440Sstevel@tonic-gate hci1394_q_next_buf(datab);
14450Sstevel@tonic-gate
14460Sstevel@tonic-gate /* Update next buffers pointers for partial packet */
14470Sstevel@tonic-gate size -= q_handle->q_space_left;
14480Sstevel@tonic-gate datab->qb_ptrs.qp_current += size;
14490Sstevel@tonic-gate q_handle->q_space_left =
14500Sstevel@tonic-gate datab->qb_cookie[datab->qb_ptrs.qp_current_buf].dmac_size -
14510Sstevel@tonic-gate size;
14520Sstevel@tonic-gate
14530Sstevel@tonic-gate /* Change the head pointer to the next IM descriptor */
14540Sstevel@tonic-gate q_handle->q_head += sizeof (hci1394_desc_t);
14550Sstevel@tonic-gate if ((q_handle->q_head + sizeof (hci1394_desc_t)) >
14560Sstevel@tonic-gate (descb->qb_ptrs.qp_bottom + 1)) {
14570Sstevel@tonic-gate q_handle->q_head = descb->qb_ptrs.qp_top;
14580Sstevel@tonic-gate }
14590Sstevel@tonic-gate
14600Sstevel@tonic-gate /* Packet is only in one buffer */
14610Sstevel@tonic-gate } else {
14620Sstevel@tonic-gate q_handle->q_space_left -= size;
14630Sstevel@tonic-gate datab->qb_ptrs.qp_current += size;
14640Sstevel@tonic-gate }
14650Sstevel@tonic-gate
14660Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_ar_free_exit, HCI1394_TNF_HAL_STACK, "");
14670Sstevel@tonic-gate }
14680Sstevel@tonic-gate
14690Sstevel@tonic-gate
14700Sstevel@tonic-gate /*
14710Sstevel@tonic-gate * hci1394_q_ar_get32()
14720Sstevel@tonic-gate * Read a quadlet of data regardless if it is in the current buffer or has
14730Sstevel@tonic-gate * wrapped to the top buffer. If the address passed to this routine is
14740Sstevel@tonic-gate * passed the bottom of the data buffer, this routine will automatically
14750Sstevel@tonic-gate * wrap back to the top of the Q and look in the correct offset from the
14760Sstevel@tonic-gate * top. Copy the data into the kernel virtual address provided.
14770Sstevel@tonic-gate */
14780Sstevel@tonic-gate uint32_t
hci1394_q_ar_get32(hci1394_q_handle_t q_handle,uint32_t * addr)14790Sstevel@tonic-gate hci1394_q_ar_get32(hci1394_q_handle_t q_handle, uint32_t *addr)
14800Sstevel@tonic-gate {
14810Sstevel@tonic-gate hci1394_q_buf_t *data;
14820Sstevel@tonic-gate uintptr_t new_addr;
14830Sstevel@tonic-gate uint32_t data32;
14840Sstevel@tonic-gate
14850Sstevel@tonic-gate
14860Sstevel@tonic-gate ASSERT(q_handle != NULL);
14870Sstevel@tonic-gate ASSERT(addr != NULL);
14880Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_get32_enter, HCI1394_TNF_HAL_STACK, "");
14890Sstevel@tonic-gate
14900Sstevel@tonic-gate data = &q_handle->q_data;
14910Sstevel@tonic-gate
14920Sstevel@tonic-gate /*
14930Sstevel@tonic-gate * if the data has wrapped to the top of the buffer, adjust the address.
14940Sstevel@tonic-gate */
14950Sstevel@tonic-gate if ((uintptr_t)addr > (uintptr_t)data->qb_ptrs.qp_bottom) {
14960Sstevel@tonic-gate new_addr = (uintptr_t)data->qb_ptrs.qp_top + ((uintptr_t)addr -
14970Sstevel@tonic-gate ((uintptr_t)data->qb_ptrs.qp_bottom + (uintptr_t)1));
14980Sstevel@tonic-gate data32 = ddi_get32(data->qb_buf.bi_handle,
14990Sstevel@tonic-gate (uint32_t *)new_addr);
15000Sstevel@tonic-gate
15010Sstevel@tonic-gate /* data is before end of buffer */
15020Sstevel@tonic-gate } else {
15030Sstevel@tonic-gate data32 = ddi_get32(data->qb_buf.bi_handle, addr);
15040Sstevel@tonic-gate }
15050Sstevel@tonic-gate
15060Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_get32_exit, HCI1394_TNF_HAL_STACK, "");
15070Sstevel@tonic-gate
15080Sstevel@tonic-gate return (data32);
15090Sstevel@tonic-gate }
15100Sstevel@tonic-gate
15110Sstevel@tonic-gate
15120Sstevel@tonic-gate /*
15130Sstevel@tonic-gate * hci1394_q_ar_rep_get8()
15140Sstevel@tonic-gate * Read a byte stream of data regardless if it is contiguous or has partially
15150Sstevel@tonic-gate * or fully wrapped to the top buffer. If the address passed to this routine
15160Sstevel@tonic-gate * is passed the bottom of the data buffer, or address + size is past the
15170Sstevel@tonic-gate * bottom of the data buffer. this routine will automatically wrap back to
15180Sstevel@tonic-gate * the top of the Q and look in the correct offset from the top. Copy the
15190Sstevel@tonic-gate * data into the kernel virtual address provided.
15200Sstevel@tonic-gate */
15210Sstevel@tonic-gate void
hci1394_q_ar_rep_get8(hci1394_q_handle_t q_handle,uint8_t * dest,uint8_t * q_addr,uint_t size)15220Sstevel@tonic-gate hci1394_q_ar_rep_get8(hci1394_q_handle_t q_handle, uint8_t *dest,
15230Sstevel@tonic-gate uint8_t *q_addr, uint_t size)
15240Sstevel@tonic-gate {
15250Sstevel@tonic-gate hci1394_q_buf_t *data;
15260Sstevel@tonic-gate uintptr_t new_addr;
15270Sstevel@tonic-gate uint_t new_size;
15280Sstevel@tonic-gate uintptr_t new_dest;
15290Sstevel@tonic-gate
15300Sstevel@tonic-gate
15310Sstevel@tonic-gate ASSERT(q_handle != NULL);
15320Sstevel@tonic-gate ASSERT(dest != NULL);
15330Sstevel@tonic-gate ASSERT(q_addr != NULL);
15340Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_ar_rep_get8_enter, HCI1394_TNF_HAL_STACK,
15350Sstevel@tonic-gate "");
15360Sstevel@tonic-gate
15370Sstevel@tonic-gate data = &q_handle->q_data;
15380Sstevel@tonic-gate
15390Sstevel@tonic-gate /*
15400Sstevel@tonic-gate * There are three cases:
15410Sstevel@tonic-gate * 1) All of the data has wrapped.
15420Sstevel@tonic-gate * 2) Some of the data has not wrapped and some has wrapped.
15430Sstevel@tonic-gate * 3) None of the data has wrapped.
15440Sstevel@tonic-gate */
15450Sstevel@tonic-gate
15460Sstevel@tonic-gate /* All of the data has wrapped, just adjust the starting address */
15470Sstevel@tonic-gate if ((uintptr_t)q_addr > (uintptr_t)data->qb_ptrs.qp_bottom) {
15480Sstevel@tonic-gate new_addr = (uintptr_t)data->qb_ptrs.qp_top +
15490Sstevel@tonic-gate ((uintptr_t)q_addr - ((uintptr_t)data->qb_ptrs.qp_bottom +
15500Sstevel@tonic-gate (uintptr_t)1));
15510Sstevel@tonic-gate ddi_rep_get8(data->qb_buf.bi_handle, dest, (uint8_t *)new_addr,
15520Sstevel@tonic-gate size, DDI_DEV_AUTOINCR);
15530Sstevel@tonic-gate
15540Sstevel@tonic-gate /*
15550Sstevel@tonic-gate * Some of the data has wrapped. Copy the data that hasn't wrapped,
15560Sstevel@tonic-gate * adjust the address, then copy the rest.
15570Sstevel@tonic-gate */
15580Sstevel@tonic-gate } else if (((uintptr_t)q_addr + (uintptr_t)size) >
15590Sstevel@tonic-gate ((uintptr_t)data->qb_ptrs.qp_bottom + (uintptr_t)1)) {
15600Sstevel@tonic-gate /* Copy first half */
15610Sstevel@tonic-gate new_size = (uint_t)(((uintptr_t)data->qb_ptrs.qp_bottom +
15620Sstevel@tonic-gate (uintptr_t)1) - (uintptr_t)q_addr);
15630Sstevel@tonic-gate ddi_rep_get8(data->qb_buf.bi_handle, dest, q_addr, new_size,
15640Sstevel@tonic-gate DDI_DEV_AUTOINCR);
15650Sstevel@tonic-gate
15660Sstevel@tonic-gate /* copy second half */
15670Sstevel@tonic-gate new_dest = (uintptr_t)dest + (uintptr_t)new_size;
15680Sstevel@tonic-gate new_size = size - new_size;
15690Sstevel@tonic-gate new_addr = (uintptr_t)data->qb_ptrs.qp_top;
15700Sstevel@tonic-gate ddi_rep_get8(data->qb_buf.bi_handle, (uint8_t *)new_dest,
15710Sstevel@tonic-gate (uint8_t *)new_addr, new_size, DDI_DEV_AUTOINCR);
15720Sstevel@tonic-gate
15730Sstevel@tonic-gate /* None of the data has wrapped */
15740Sstevel@tonic-gate } else {
15750Sstevel@tonic-gate ddi_rep_get8(data->qb_buf.bi_handle, dest, q_addr, size,
15760Sstevel@tonic-gate DDI_DEV_AUTOINCR);
15770Sstevel@tonic-gate }
15780Sstevel@tonic-gate
15790Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_ar_rep_get8_exit, HCI1394_TNF_HAL_STACK,
15800Sstevel@tonic-gate "");
15810Sstevel@tonic-gate }
15820Sstevel@tonic-gate
15830Sstevel@tonic-gate
15840Sstevel@tonic-gate /*
15850Sstevel@tonic-gate * hci1394_q_ar_copy_to_mblk()
15860Sstevel@tonic-gate * Read a byte stream of data regardless if it is contiguous or has partially
15870Sstevel@tonic-gate * or fully wrapped to the top buffer. If the address passed to this routine
15880Sstevel@tonic-gate * is passed the bottom of the data buffer, or address + size is passed the
15890Sstevel@tonic-gate * bottom of the data buffer. this routine will automatically wrap back to
15900Sstevel@tonic-gate * the top of the Q and look in the correct offset from the top. Copy the
15910Sstevel@tonic-gate * data into the mblk provided. The services layer and the hal use a private
15920Sstevel@tonic-gate * structure (h1394_mblk_t) to keep track of how much of the mblk to receive
15930Sstevel@tonic-gate * into since we may have to break the transfer up into smaller blocks.
15940Sstevel@tonic-gate * (i.e. a 1MByte block read would go out in 2KByte requests.
15950Sstevel@tonic-gate */
15960Sstevel@tonic-gate void
hci1394_q_ar_copy_to_mblk(hci1394_q_handle_t q_handle,uint8_t * addr,h1394_mblk_t * mblk)15970Sstevel@tonic-gate hci1394_q_ar_copy_to_mblk(hci1394_q_handle_t q_handle, uint8_t *addr,
15980Sstevel@tonic-gate h1394_mblk_t *mblk)
15990Sstevel@tonic-gate {
16000Sstevel@tonic-gate uint8_t *new_addr;
16010Sstevel@tonic-gate uint_t bytes_left;
16020Sstevel@tonic-gate uint_t length;
16030Sstevel@tonic-gate
16040Sstevel@tonic-gate
16050Sstevel@tonic-gate ASSERT(q_handle != NULL);
16060Sstevel@tonic-gate ASSERT(addr != NULL);
16070Sstevel@tonic-gate ASSERT(mblk != NULL);
16080Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_copy_to_mblk_enter,
16090Sstevel@tonic-gate HCI1394_TNF_HAL_STACK, "");
16100Sstevel@tonic-gate
16110Sstevel@tonic-gate /* We return these variables to the Services Layer when we are done */
16120Sstevel@tonic-gate mblk->next_offset = mblk->curr_offset;
16130Sstevel@tonic-gate mblk->next_mblk = mblk->curr_mblk;
16140Sstevel@tonic-gate bytes_left = mblk->length;
16150Sstevel@tonic-gate
16160Sstevel@tonic-gate /* the address we copy from will change as we change mblks */
16170Sstevel@tonic-gate new_addr = addr;
16180Sstevel@tonic-gate
16190Sstevel@tonic-gate /* do while there are bytes left to copy */
16200Sstevel@tonic-gate do {
16210Sstevel@tonic-gate /*
16220Sstevel@tonic-gate * If the entire data portion of the current block transfer is
16230Sstevel@tonic-gate * contained within a single mblk.
16240Sstevel@tonic-gate */
16250Sstevel@tonic-gate if ((mblk->next_offset + bytes_left) <=
16260Sstevel@tonic-gate (mblk->next_mblk->b_datap->db_lim)) {
16270Sstevel@tonic-gate /* Copy the data into the mblk */
16280Sstevel@tonic-gate hci1394_q_ar_rep_get8(q_handle,
16290Sstevel@tonic-gate (uint8_t *)mblk->next_offset, new_addr, bytes_left);
16300Sstevel@tonic-gate
16310Sstevel@tonic-gate /* increment the offset */
16320Sstevel@tonic-gate mblk->next_offset += bytes_left;
16330Sstevel@tonic-gate mblk->next_mblk->b_wptr = mblk->next_offset;
16340Sstevel@tonic-gate
16350Sstevel@tonic-gate /* we have no more bytes to put into the buffer */
16360Sstevel@tonic-gate bytes_left = 0;
16370Sstevel@tonic-gate
16380Sstevel@tonic-gate /*
16390Sstevel@tonic-gate * If our offset is at the end of data in this mblk, go
16400Sstevel@tonic-gate * to the next mblk.
16410Sstevel@tonic-gate */
16420Sstevel@tonic-gate if (mblk->next_offset >=
16430Sstevel@tonic-gate mblk->next_mblk->b_datap->db_lim) {
16440Sstevel@tonic-gate mblk->next_mblk = mblk->next_mblk->b_cont;
16450Sstevel@tonic-gate if (mblk->next_mblk != NULL) {
16460Sstevel@tonic-gate mblk->next_offset =
16470Sstevel@tonic-gate mblk->next_mblk->b_wptr;
16480Sstevel@tonic-gate }
16490Sstevel@tonic-gate }
16500Sstevel@tonic-gate
16510Sstevel@tonic-gate /*
16520Sstevel@tonic-gate * The data portion of the current block transfer is spread
16530Sstevel@tonic-gate * across two or more mblk's
16540Sstevel@tonic-gate */
16550Sstevel@tonic-gate } else {
16560Sstevel@tonic-gate /* Figure out how much data is in this mblk */
16570Sstevel@tonic-gate length = mblk->next_mblk->b_datap->db_lim -
16580Sstevel@tonic-gate mblk->next_offset;
16590Sstevel@tonic-gate
16600Sstevel@tonic-gate /* Copy the data into the mblk */
16610Sstevel@tonic-gate hci1394_q_ar_rep_get8(q_handle,
16620Sstevel@tonic-gate (uint8_t *)mblk->next_offset, new_addr, length);
16630Sstevel@tonic-gate mblk->next_mblk->b_wptr =
16640Sstevel@tonic-gate mblk->next_mblk->b_datap->db_lim;
16650Sstevel@tonic-gate
16660Sstevel@tonic-gate /*
16670Sstevel@tonic-gate * update the bytes left and address to copy from, go
16680Sstevel@tonic-gate * to the next mblk.
16690Sstevel@tonic-gate */
16700Sstevel@tonic-gate bytes_left = bytes_left - length;
16710Sstevel@tonic-gate new_addr = (uint8_t *)((uintptr_t)new_addr +
16720Sstevel@tonic-gate (uintptr_t)length);
16730Sstevel@tonic-gate mblk->next_mblk = mblk->next_mblk->b_cont;
16740Sstevel@tonic-gate ASSERT(mblk->next_mblk != NULL);
16750Sstevel@tonic-gate mblk->next_offset = mblk->next_mblk->b_wptr;
16760Sstevel@tonic-gate }
16770Sstevel@tonic-gate } while (bytes_left > 0);
16780Sstevel@tonic-gate
16790Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_copy_to_mblk_exit,
16800Sstevel@tonic-gate HCI1394_TNF_HAL_STACK, "");
16810Sstevel@tonic-gate }
16820Sstevel@tonic-gate
16830Sstevel@tonic-gate
16840Sstevel@tonic-gate /*
16850Sstevel@tonic-gate * hci1394_q_ar_write_IM()
16860Sstevel@tonic-gate * Write an IM descriptor into the AR descriptor buffer passed in as qbuf.
16870Sstevel@tonic-gate * The IO address of the data buffer is passed in io_addr. datasize is the
16880Sstevel@tonic-gate * size of the data data buffer to receive into.
16890Sstevel@tonic-gate */
16900Sstevel@tonic-gate void
hci1394_q_ar_write_IM(hci1394_q_handle_t q_handle,hci1394_q_buf_t * qbuf,uint32_t io_addr,uint_t datasize)16910Sstevel@tonic-gate hci1394_q_ar_write_IM(hci1394_q_handle_t q_handle, hci1394_q_buf_t *qbuf,
16920Sstevel@tonic-gate uint32_t io_addr, uint_t datasize)
16930Sstevel@tonic-gate {
16940Sstevel@tonic-gate hci1394_desc_t *desc;
16950Sstevel@tonic-gate uint32_t data;
16960Sstevel@tonic-gate uint32_t command_ptr;
16970Sstevel@tonic-gate
16980Sstevel@tonic-gate
16990Sstevel@tonic-gate ASSERT(q_handle != NULL);
17000Sstevel@tonic-gate ASSERT(qbuf != NULL);
17010Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_ar_write_IM_enter, HCI1394_TNF_HAL_STACK,
17020Sstevel@tonic-gate "");
17030Sstevel@tonic-gate
17040Sstevel@tonic-gate /* Make sure enough room for IM */
17050Sstevel@tonic-gate if ((qbuf->qb_ptrs.qp_current + sizeof (hci1394_desc_t)) >
17060Sstevel@tonic-gate (qbuf->qb_ptrs.qp_bottom + 1)) {
17070Sstevel@tonic-gate hci1394_q_next_buf(qbuf);
17080Sstevel@tonic-gate } else {
17090Sstevel@tonic-gate /* Store the offset of the top of this descriptor block */
17100Sstevel@tonic-gate qbuf->qb_ptrs.qp_offset = (uint32_t)(qbuf->qb_ptrs.qp_current -
17110Sstevel@tonic-gate qbuf->qb_ptrs.qp_begin);
17120Sstevel@tonic-gate }
17130Sstevel@tonic-gate
17140Sstevel@tonic-gate /* Setup OpenHCI IM Header */
17150Sstevel@tonic-gate desc = (hci1394_desc_t *)qbuf->qb_ptrs.qp_current;
17160Sstevel@tonic-gate data = DESC_AR_IM | (datasize & DESC_HDR_REQCOUNT_MASK);
17170Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle, &desc->hdr, data);
17180Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle, &desc->data_addr, io_addr);
17190Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle, &desc->branch, 0);
17200Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle, &desc->status, datasize &
17210Sstevel@tonic-gate DESC_ST_RESCOUNT_MASK);
17220Sstevel@tonic-gate
17230Sstevel@tonic-gate /*
17240Sstevel@tonic-gate * Sync buffer in case DMA engine currently running. This must be done
17250Sstevel@tonic-gate * before writing the command pointer in the previous descriptor.
17260Sstevel@tonic-gate */
17270Sstevel@tonic-gate (void) ddi_dma_sync(qbuf->qb_buf.bi_dma_handle, 0,
17280Sstevel@tonic-gate qbuf->qb_buf.bi_length, DDI_DMA_SYNC_FORDEV);
17290Sstevel@tonic-gate
17300Sstevel@tonic-gate /*
17310Sstevel@tonic-gate * Setup the command pointer. This tells the HW where to get the
17320Sstevel@tonic-gate * descriptor we just setup. This includes the IO address along with
17330Sstevel@tonic-gate * a 4 bit 16 byte block count. We only wrote 1 16 byte block.
17340Sstevel@tonic-gate */
17350Sstevel@tonic-gate command_ptr = (uint32_t)((qbuf->qb_cookie[qbuf->qb_ptrs.qp_current_buf
17360Sstevel@tonic-gate ].dmac_address + qbuf->qb_ptrs.qp_offset) | 1);
17370Sstevel@tonic-gate
17380Sstevel@tonic-gate /*
17390Sstevel@tonic-gate * if we previously setup a descriptor, add this new descriptor into
17400Sstevel@tonic-gate * the previous descriptor's "next" pointer.
17410Sstevel@tonic-gate */
17420Sstevel@tonic-gate if (q_handle->q_previous != NULL) {
17430Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle,
17440Sstevel@tonic-gate &q_handle->q_previous->branch, command_ptr);
17450Sstevel@tonic-gate /* Sync buffer again, this gets the command pointer */
17460Sstevel@tonic-gate (void) ddi_dma_sync(qbuf->qb_buf.bi_dma_handle, 0,
17470Sstevel@tonic-gate qbuf->qb_buf.bi_length, DDI_DMA_SYNC_FORDEV);
17480Sstevel@tonic-gate }
17490Sstevel@tonic-gate
17500Sstevel@tonic-gate /* this is the new previous descriptor. Update the current pointer */
17510Sstevel@tonic-gate q_handle->q_previous = desc;
17520Sstevel@tonic-gate qbuf->qb_ptrs.qp_current += sizeof (hci1394_desc_t);
17530Sstevel@tonic-gate
17540Sstevel@tonic-gate /* If the DMA is not running, start it */
17550Sstevel@tonic-gate if (q_handle->q_dma_running == B_FALSE) {
17560Sstevel@tonic-gate q_handle->q_info.qi_start(q_handle->q_info.qi_callback_arg,
17570Sstevel@tonic-gate command_ptr);
17580Sstevel@tonic-gate q_handle->q_dma_running = B_TRUE;
17590Sstevel@tonic-gate /* the DMA is running, wake it up */
17600Sstevel@tonic-gate } else {
17610Sstevel@tonic-gate q_handle->q_info.qi_wake(q_handle->q_info.qi_callback_arg);
17620Sstevel@tonic-gate }
17630Sstevel@tonic-gate
17640Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_ar_write_IM_exit, HCI1394_TNF_HAL_STACK,
17650Sstevel@tonic-gate "");
17660Sstevel@tonic-gate }
1767