17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 23*ef7b5c7bSap * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*ef7b5c7bSap * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate /* 307c478bd9Sstevel@tonic-gate * hci1394_q.c 317c478bd9Sstevel@tonic-gate * This code decouples some of the OpenHCI async descriptor logic/structures 327c478bd9Sstevel@tonic-gate * from the async processing. The goal was to combine as much of the 337c478bd9Sstevel@tonic-gate * duplicate code as possible for the different type of async transfers 347c478bd9Sstevel@tonic-gate * without going too overboard. 357c478bd9Sstevel@tonic-gate * 367c478bd9Sstevel@tonic-gate * There are two parts to the Q, the descriptor buffer and the data buffer. 377c478bd9Sstevel@tonic-gate * For the most part, data to be transmitted and data which is received go 387c478bd9Sstevel@tonic-gate * in the data buffers. The information of where to get the data and put 397c478bd9Sstevel@tonic-gate * the data reside in the descriptor buffers. There are exceptions to this. 407c478bd9Sstevel@tonic-gate */ 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate #include <sys/types.h> 447c478bd9Sstevel@tonic-gate #include <sys/conf.h> 457c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 467c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 477c478bd9Sstevel@tonic-gate #include <sys/stat.h> 487c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 497c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 507c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 517c478bd9Sstevel@tonic-gate #include <sys/note.h> 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate #include <sys/1394/adapters/hci1394.h> 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate static int hci1394_q_reserve(hci1394_q_buf_t *qbuf, uint_t size, 577c478bd9Sstevel@tonic-gate uint32_t *io_addr); 587c478bd9Sstevel@tonic-gate static void hci1394_q_unreserve(hci1394_q_buf_t *qbuf); 597c478bd9Sstevel@tonic-gate static void hci1394_q_buf_setup(hci1394_q_buf_t *qbuf); 607c478bd9Sstevel@tonic-gate static void hci1394_q_reset(hci1394_q_handle_t q_handle); 617c478bd9Sstevel@tonic-gate static void hci1394_q_next_buf(hci1394_q_buf_t *qbuf); 627c478bd9Sstevel@tonic-gate 637c478bd9Sstevel@tonic-gate static void hci1394_q_at_write_OLI(hci1394_q_handle_t q_handle, 647c478bd9Sstevel@tonic-gate hci1394_q_buf_t *qbuf, hci1394_q_cmd_t *cmd, hci1394_basic_pkt_t *hdr, 657c478bd9Sstevel@tonic-gate uint_t hdrsize); 667c478bd9Sstevel@tonic-gate static void hci1394_q_at_write_OMI(hci1394_q_handle_t q_handle, 677c478bd9Sstevel@tonic-gate hci1394_q_buf_t *qbuf, hci1394_q_cmd_t *cmd, hci1394_basic_pkt_t *hdr, 687c478bd9Sstevel@tonic-gate uint_t hdrsize); 697c478bd9Sstevel@tonic-gate static void hci1394_q_at_write_OL(hci1394_q_handle_t q_handle, 707c478bd9Sstevel@tonic-gate hci1394_q_buf_t *qbuf, hci1394_q_cmd_t *cmd, uint32_t io_addr, 717c478bd9Sstevel@tonic-gate uint_t datasize); 727c478bd9Sstevel@tonic-gate static void hci1394_q_at_rep_put8(hci1394_q_buf_t *qbuf, hci1394_q_cmd_t *cmd, 737c478bd9Sstevel@tonic-gate uint8_t *data, uint_t datasize); 747c478bd9Sstevel@tonic-gate static void hci1394_q_at_copy_from_mblk(hci1394_q_buf_t *qbuf, 757c478bd9Sstevel@tonic-gate hci1394_q_cmd_t *cmd, h1394_mblk_t *mblk); 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate static void hci1394_q_ar_write_IM(hci1394_q_handle_t q_handle, 787c478bd9Sstevel@tonic-gate hci1394_q_buf_t *qbuf, uint32_t io_addr, uint_t datasize); 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate _NOTE(SCHEME_PROTECTS_DATA("unique", msgb)) 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate /* 837c478bd9Sstevel@tonic-gate * hci1394_q_init() 847c478bd9Sstevel@tonic-gate * Initialize a Q. A Q consists of a descriptor buffer and a data buffer and 857c478bd9Sstevel@tonic-gate * can be either an AT or AR Q. hci1394_q_init() returns a handle which 867c478bd9Sstevel@tonic-gate * should be used for the reset of the hci1394_q_* calls. 877c478bd9Sstevel@tonic-gate */ 887c478bd9Sstevel@tonic-gate int 897c478bd9Sstevel@tonic-gate hci1394_q_init(hci1394_drvinfo_t *drvinfo, 907c478bd9Sstevel@tonic-gate hci1394_ohci_handle_t ohci_handle, hci1394_q_info_t *qinfo, 917c478bd9Sstevel@tonic-gate hci1394_q_handle_t *q_handle) 927c478bd9Sstevel@tonic-gate { 937c478bd9Sstevel@tonic-gate hci1394_q_buf_t *desc; 947c478bd9Sstevel@tonic-gate hci1394_q_buf_t *data; 957c478bd9Sstevel@tonic-gate hci1394_buf_parms_t parms; 967c478bd9Sstevel@tonic-gate hci1394_q_t *q; 977c478bd9Sstevel@tonic-gate int status; 987c478bd9Sstevel@tonic-gate int index; 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate ASSERT(drvinfo != NULL); 1027c478bd9Sstevel@tonic-gate ASSERT(qinfo != NULL); 1037c478bd9Sstevel@tonic-gate ASSERT(q_handle != NULL); 1047c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_init_enter, HCI1394_TNF_HAL_STACK, ""); 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate /* 1077c478bd9Sstevel@tonic-gate * allocate the memory to track this Q. Initialize the internal Q 1087c478bd9Sstevel@tonic-gate * structure. 1097c478bd9Sstevel@tonic-gate */ 1107c478bd9Sstevel@tonic-gate q = kmem_alloc(sizeof (hci1394_q_t), KM_SLEEP); 1117c478bd9Sstevel@tonic-gate q->q_drvinfo = drvinfo; 1127c478bd9Sstevel@tonic-gate q->q_info = *qinfo; 1137c478bd9Sstevel@tonic-gate q->q_ohci = ohci_handle; 1147c478bd9Sstevel@tonic-gate mutex_init(&q->q_mutex, NULL, MUTEX_DRIVER, drvinfo->di_iblock_cookie); 1157c478bd9Sstevel@tonic-gate desc = &q->q_desc; 1167c478bd9Sstevel@tonic-gate data = &q->q_data; 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate /* 1197c478bd9Sstevel@tonic-gate * Allocate the Descriptor buffer. 1207c478bd9Sstevel@tonic-gate * 1217c478bd9Sstevel@tonic-gate * XXX - Only want 1 cookie for now. Change this to OHCI_MAX_COOKIE 1227c478bd9Sstevel@tonic-gate * after we have tested the multiple cookie code on x86. 1237c478bd9Sstevel@tonic-gate */ 1247c478bd9Sstevel@tonic-gate parms.bp_length = qinfo->qi_desc_size; 1257c478bd9Sstevel@tonic-gate parms.bp_max_cookies = 1; 1267c478bd9Sstevel@tonic-gate parms.bp_alignment = 16; 1277c478bd9Sstevel@tonic-gate status = hci1394_buf_alloc(drvinfo, &parms, &desc->qb_buf, 1287c478bd9Sstevel@tonic-gate &desc->qb_buf_handle); 1297c478bd9Sstevel@tonic-gate if (status != DDI_SUCCESS) { 1307c478bd9Sstevel@tonic-gate mutex_destroy(&q->q_mutex); 1317c478bd9Sstevel@tonic-gate kmem_free(q, sizeof (hci1394_q_t)); 1327c478bd9Sstevel@tonic-gate *q_handle = NULL; 1337c478bd9Sstevel@tonic-gate TNF_PROBE_0(hci1394_q_init_bae_fail, HCI1394_TNF_HAL_ERROR, ""); 1347c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_init_exit, HCI1394_TNF_HAL_STACK, 1357c478bd9Sstevel@tonic-gate ""); 1367c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 1377c478bd9Sstevel@tonic-gate } 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate /* Copy in buffer cookies into our local cookie array */ 1407c478bd9Sstevel@tonic-gate desc->qb_cookie[0] = desc->qb_buf.bi_cookie; 1417c478bd9Sstevel@tonic-gate for (index = 1; index < desc->qb_buf.bi_cookie_count; index++) { 1427c478bd9Sstevel@tonic-gate ddi_dma_nextcookie(desc->qb_buf.bi_dma_handle, 1437c478bd9Sstevel@tonic-gate &desc->qb_buf.bi_cookie); 1447c478bd9Sstevel@tonic-gate desc->qb_cookie[index] = desc->qb_buf.bi_cookie; 1457c478bd9Sstevel@tonic-gate } 1467c478bd9Sstevel@tonic-gate 1477c478bd9Sstevel@tonic-gate /* 1487c478bd9Sstevel@tonic-gate * Allocate the Data buffer. 1497c478bd9Sstevel@tonic-gate * 1507c478bd9Sstevel@tonic-gate * XXX - Only want 1 cookie for now. Change this to OHCI_MAX_COOKIE 1517c478bd9Sstevel@tonic-gate * after we have tested the multiple cookie code on x86. 1527c478bd9Sstevel@tonic-gate */ 1537c478bd9Sstevel@tonic-gate parms.bp_length = qinfo->qi_data_size; 1547c478bd9Sstevel@tonic-gate parms.bp_max_cookies = 1; 1557c478bd9Sstevel@tonic-gate parms.bp_alignment = 16; 1567c478bd9Sstevel@tonic-gate status = hci1394_buf_alloc(drvinfo, &parms, &data->qb_buf, 1577c478bd9Sstevel@tonic-gate &data->qb_buf_handle); 1587c478bd9Sstevel@tonic-gate if (status != DDI_SUCCESS) { 159*ef7b5c7bSap /* Free the allocated Descriptor buffer */ 160*ef7b5c7bSap hci1394_buf_free(&desc->qb_buf_handle); 161*ef7b5c7bSap 1627c478bd9Sstevel@tonic-gate mutex_destroy(&q->q_mutex); 1637c478bd9Sstevel@tonic-gate kmem_free(q, sizeof (hci1394_q_t)); 1647c478bd9Sstevel@tonic-gate *q_handle = NULL; 1657c478bd9Sstevel@tonic-gate TNF_PROBE_0(hci1394_q_init_baa_fail, HCI1394_TNF_HAL_ERROR, ""); 1667c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_init_exit, HCI1394_TNF_HAL_STACK, 1677c478bd9Sstevel@tonic-gate ""); 1687c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 1697c478bd9Sstevel@tonic-gate } 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate /* 1727c478bd9Sstevel@tonic-gate * We must have at least 2 ARQ data buffers, If we only have one, we 1737c478bd9Sstevel@tonic-gate * will artificially create 2. We must have 2 so that we always have a 1747c478bd9Sstevel@tonic-gate * descriptor with free data space to write AR data to. When one is 1757c478bd9Sstevel@tonic-gate * empty, it will take us a bit to get a new descriptor back into the 1767c478bd9Sstevel@tonic-gate * chain. 1777c478bd9Sstevel@tonic-gate */ 1787c478bd9Sstevel@tonic-gate if ((qinfo->qi_mode == HCI1394_ARQ) && 1797c478bd9Sstevel@tonic-gate (data->qb_buf.bi_cookie_count == 1)) { 1807c478bd9Sstevel@tonic-gate data->qb_buf.bi_cookie_count = 2; 1817c478bd9Sstevel@tonic-gate data->qb_cookie[0] = data->qb_buf.bi_cookie; 1827c478bd9Sstevel@tonic-gate data->qb_cookie[0].dmac_size /= 2; 1837c478bd9Sstevel@tonic-gate data->qb_cookie[1] = data->qb_cookie[0]; 1847c478bd9Sstevel@tonic-gate data->qb_cookie[1].dmac_laddress = 1857c478bd9Sstevel@tonic-gate data->qb_cookie[0].dmac_laddress + 1867c478bd9Sstevel@tonic-gate data->qb_cookie[0].dmac_size; 1877c478bd9Sstevel@tonic-gate data->qb_cookie[1].dmac_address = 1887c478bd9Sstevel@tonic-gate data->qb_cookie[0].dmac_address + 1897c478bd9Sstevel@tonic-gate data->qb_cookie[0].dmac_size; 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate /* We have more than 1 cookie or we are an AT Q */ 1927c478bd9Sstevel@tonic-gate } else { 1937c478bd9Sstevel@tonic-gate /* Copy in buffer cookies into our local cookie array */ 1947c478bd9Sstevel@tonic-gate data->qb_cookie[0] = data->qb_buf.bi_cookie; 1957c478bd9Sstevel@tonic-gate for (index = 1; index < data->qb_buf.bi_cookie_count; index++) { 1967c478bd9Sstevel@tonic-gate ddi_dma_nextcookie(data->qb_buf.bi_dma_handle, 1977c478bd9Sstevel@tonic-gate &data->qb_buf.bi_cookie); 1987c478bd9Sstevel@tonic-gate data->qb_cookie[index] = data->qb_buf.bi_cookie; 1997c478bd9Sstevel@tonic-gate } 2007c478bd9Sstevel@tonic-gate } 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate /* The top and bottom of the Q are only set once */ 2037c478bd9Sstevel@tonic-gate desc->qb_ptrs.qp_top = desc->qb_buf.bi_kaddr; 2047c478bd9Sstevel@tonic-gate desc->qb_ptrs.qp_bottom = desc->qb_buf.bi_kaddr + 2057c478bd9Sstevel@tonic-gate desc->qb_buf.bi_real_length - 1; 2067c478bd9Sstevel@tonic-gate data->qb_ptrs.qp_top = data->qb_buf.bi_kaddr; 2077c478bd9Sstevel@tonic-gate data->qb_ptrs.qp_bottom = data->qb_buf.bi_kaddr + 2087c478bd9Sstevel@tonic-gate data->qb_buf.bi_real_length - 1; 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate /* 2117c478bd9Sstevel@tonic-gate * reset the Q pointers to their original settings. Setup IM 2127c478bd9Sstevel@tonic-gate * descriptors if this is an AR Q. 2137c478bd9Sstevel@tonic-gate */ 2147c478bd9Sstevel@tonic-gate hci1394_q_reset(q); 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate /* if this is an AT Q, create a queued list for the AT descriptors */ 2177c478bd9Sstevel@tonic-gate if (qinfo->qi_mode == HCI1394_ATQ) { 2187c478bd9Sstevel@tonic-gate hci1394_tlist_init(drvinfo, NULL, &q->q_queued_list); 2197c478bd9Sstevel@tonic-gate } 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate *q_handle = q; 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_init_exit, HCI1394_TNF_HAL_STACK, ""); 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 2267c478bd9Sstevel@tonic-gate } 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate /* 2307c478bd9Sstevel@tonic-gate * hci1394_q_fini() 2317c478bd9Sstevel@tonic-gate * Cleanup after a successful hci1394_q_init(). Notice that a pointer to the 2327c478bd9Sstevel@tonic-gate * handle is used for the parameter. fini() will set your handle to NULL 2337c478bd9Sstevel@tonic-gate * before returning. 2347c478bd9Sstevel@tonic-gate */ 2357c478bd9Sstevel@tonic-gate void 2367c478bd9Sstevel@tonic-gate hci1394_q_fini(hci1394_q_handle_t *q_handle) 2377c478bd9Sstevel@tonic-gate { 2387c478bd9Sstevel@tonic-gate hci1394_q_t *q; 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate ASSERT(q_handle != NULL); 2417c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_fini_enter, HCI1394_TNF_HAL_STACK, ""); 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate q = *q_handle; 2447c478bd9Sstevel@tonic-gate if (q->q_info.qi_mode == HCI1394_ATQ) { 2457c478bd9Sstevel@tonic-gate hci1394_tlist_fini(&q->q_queued_list); 2467c478bd9Sstevel@tonic-gate } 2477c478bd9Sstevel@tonic-gate mutex_destroy(&q->q_mutex); 2487c478bd9Sstevel@tonic-gate hci1394_buf_free(&q->q_desc.qb_buf_handle); 2497c478bd9Sstevel@tonic-gate hci1394_buf_free(&q->q_data.qb_buf_handle); 2507c478bd9Sstevel@tonic-gate kmem_free(q, sizeof (hci1394_q_t)); 2517c478bd9Sstevel@tonic-gate *q_handle = NULL; 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_fini_exit, HCI1394_TNF_HAL_STACK, ""); 2547c478bd9Sstevel@tonic-gate } 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate 2577c478bd9Sstevel@tonic-gate /* 2587c478bd9Sstevel@tonic-gate * hci1394_q_buf_setup() 2597c478bd9Sstevel@tonic-gate * Initialization of buffer pointers which are present in both the descriptor 2607c478bd9Sstevel@tonic-gate * buffer and data buffer (No reason to duplicate the code) 2617c478bd9Sstevel@tonic-gate */ 2627c478bd9Sstevel@tonic-gate static void 2637c478bd9Sstevel@tonic-gate hci1394_q_buf_setup(hci1394_q_buf_t *qbuf) 2647c478bd9Sstevel@tonic-gate { 2657c478bd9Sstevel@tonic-gate ASSERT(qbuf != NULL); 2667c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_buf_setup_enter, HCI1394_TNF_HAL_STACK, ""); 2677c478bd9Sstevel@tonic-gate 2687c478bd9Sstevel@tonic-gate /* start with the first cookie */ 2697c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_current_buf = 0; 2707c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_begin = qbuf->qb_ptrs.qp_top; 2717c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_end = qbuf->qb_ptrs.qp_begin + 2727c478bd9Sstevel@tonic-gate qbuf->qb_cookie[qbuf->qb_ptrs.qp_current_buf].dmac_size - 1; 2737c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_current = qbuf->qb_ptrs.qp_begin; 2747c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_offset = 0; 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate /* 2777c478bd9Sstevel@tonic-gate * The free_buf and free pointer will change everytime an ACK (of some 2787c478bd9Sstevel@tonic-gate * type) is processed. Free is the last byte in the last cookie. 2797c478bd9Sstevel@tonic-gate */ 2807c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_free_buf = qbuf->qb_buf.bi_cookie_count - 1; 2817c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_free = qbuf->qb_ptrs.qp_bottom; 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate /* 2847c478bd9Sstevel@tonic-gate * Start with no space to write descriptors. We first need to call 2857c478bd9Sstevel@tonic-gate * hci1394_q_reserve() before calling hci1394_q_at_write_O*(). 2867c478bd9Sstevel@tonic-gate */ 2877c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_resv_size = 0; 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_buf_setup_exit, HCI1394_TNF_HAL_STACK, ""); 2907c478bd9Sstevel@tonic-gate } 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate /* 2947c478bd9Sstevel@tonic-gate * hci1394_q_reset() 2957c478bd9Sstevel@tonic-gate * Resets the buffers to an initial state. This should be called during 2967c478bd9Sstevel@tonic-gate * attach and resume. 2977c478bd9Sstevel@tonic-gate */ 2987c478bd9Sstevel@tonic-gate static void 2997c478bd9Sstevel@tonic-gate hci1394_q_reset(hci1394_q_handle_t q_handle) 3007c478bd9Sstevel@tonic-gate { 3017c478bd9Sstevel@tonic-gate hci1394_q_buf_t *desc; 3027c478bd9Sstevel@tonic-gate hci1394_q_buf_t *data; 3037c478bd9Sstevel@tonic-gate int index; 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate ASSERT(q_handle != NULL); 3067c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_reset_enter, HCI1394_TNF_HAL_STACK, ""); 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate mutex_enter(&q_handle->q_mutex); 3097c478bd9Sstevel@tonic-gate desc = &q_handle->q_desc; 3107c478bd9Sstevel@tonic-gate data = &q_handle->q_data; 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate hci1394_q_buf_setup(desc); 3137c478bd9Sstevel@tonic-gate hci1394_q_buf_setup(data); 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate /* DMA starts off stopped, no previous descriptor to link from */ 3167c478bd9Sstevel@tonic-gate q_handle->q_dma_running = B_FALSE; 3177c478bd9Sstevel@tonic-gate q_handle->q_block_cnt = 0; 3187c478bd9Sstevel@tonic-gate q_handle->q_previous = NULL; 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate /* If this is an AR Q, setup IM's for the data buffers that we have */ 3217c478bd9Sstevel@tonic-gate if (q_handle->q_info.qi_mode == HCI1394_ARQ) { 3227c478bd9Sstevel@tonic-gate /* 3237c478bd9Sstevel@tonic-gate * This points to where to find the first IM descriptor. Since 3247c478bd9Sstevel@tonic-gate * we just reset the pointers in hci1394_q_buf_setup(), the 3257c478bd9Sstevel@tonic-gate * first IM we write below will be found at the top of the Q. 3267c478bd9Sstevel@tonic-gate */ 3277c478bd9Sstevel@tonic-gate q_handle->q_head = desc->qb_ptrs.qp_top; 3287c478bd9Sstevel@tonic-gate 3297c478bd9Sstevel@tonic-gate for (index = 0; index < data->qb_buf.bi_cookie_count; index++) { 3307c478bd9Sstevel@tonic-gate hci1394_q_ar_write_IM(q_handle, desc, 3317c478bd9Sstevel@tonic-gate data->qb_cookie[index].dmac_address, 3327c478bd9Sstevel@tonic-gate data->qb_cookie[index].dmac_size); 3337c478bd9Sstevel@tonic-gate } 3347c478bd9Sstevel@tonic-gate 3357c478bd9Sstevel@tonic-gate /* 3367c478bd9Sstevel@tonic-gate * The space left in the current IM is the size of the buffer. 3377c478bd9Sstevel@tonic-gate * The current buffer is the first buffer added to the AR Q. 3387c478bd9Sstevel@tonic-gate */ 3397c478bd9Sstevel@tonic-gate q_handle->q_space_left = data->qb_cookie[0].dmac_size; 3407c478bd9Sstevel@tonic-gate } 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate mutex_exit(&q_handle->q_mutex); 3437c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_reset_exit, HCI1394_TNF_HAL_STACK, ""); 3447c478bd9Sstevel@tonic-gate } 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate /* 3487c478bd9Sstevel@tonic-gate * hci1394_q_resume() 3497c478bd9Sstevel@tonic-gate * This is called during a resume (after a successful suspend). Currently 3507c478bd9Sstevel@tonic-gate * we only call reset. Since this is not a time critical function, we will 3517c478bd9Sstevel@tonic-gate * leave this as a separate function to increase readability. 3527c478bd9Sstevel@tonic-gate */ 3537c478bd9Sstevel@tonic-gate void 3547c478bd9Sstevel@tonic-gate hci1394_q_resume(hci1394_q_handle_t q_handle) 3557c478bd9Sstevel@tonic-gate { 3567c478bd9Sstevel@tonic-gate ASSERT(q_handle != NULL); 3577c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_resume_enter, HCI1394_TNF_HAL_STACK, ""); 3587c478bd9Sstevel@tonic-gate hci1394_q_reset(q_handle); 3597c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_resume_exit, HCI1394_TNF_HAL_STACK, ""); 3607c478bd9Sstevel@tonic-gate } 3617c478bd9Sstevel@tonic-gate 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate /* 3647c478bd9Sstevel@tonic-gate * hci1394_q_stop() 3657c478bd9Sstevel@tonic-gate * This call informs us that a DMA engine has been stopped. It does not 3667c478bd9Sstevel@tonic-gate * perform the actual stop. We need to know this so that when we add a 3677c478bd9Sstevel@tonic-gate * new descriptor, we do a start instead of a wake. 3687c478bd9Sstevel@tonic-gate */ 3697c478bd9Sstevel@tonic-gate void 3707c478bd9Sstevel@tonic-gate hci1394_q_stop(hci1394_q_handle_t q_handle) 3717c478bd9Sstevel@tonic-gate { 3727c478bd9Sstevel@tonic-gate ASSERT(q_handle != NULL); 3737c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_stop_enter, HCI1394_TNF_HAL_STACK, ""); 3747c478bd9Sstevel@tonic-gate mutex_enter(&q_handle->q_mutex); 3757c478bd9Sstevel@tonic-gate q_handle->q_dma_running = B_FALSE; 3767c478bd9Sstevel@tonic-gate mutex_exit(&q_handle->q_mutex); 3777c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_stop_exit, HCI1394_TNF_HAL_STACK, ""); 3787c478bd9Sstevel@tonic-gate } 3797c478bd9Sstevel@tonic-gate 3807c478bd9Sstevel@tonic-gate 3817c478bd9Sstevel@tonic-gate /* 3827c478bd9Sstevel@tonic-gate * hci1394_q_reserve() 3837c478bd9Sstevel@tonic-gate * Reserve space in the AT descriptor or data buffer. This ensures that we 3847c478bd9Sstevel@tonic-gate * can get a contiguous buffer. Descriptors have to be in a contiguous 3857c478bd9Sstevel@tonic-gate * buffer. Data does not have to be in a contiguous buffer but we do this to 3867c478bd9Sstevel@tonic-gate * reduce complexity. For systems with small page sizes (e.g. x86), this 3877c478bd9Sstevel@tonic-gate * could result in inefficient use of the data buffers when sending large 3887c478bd9Sstevel@tonic-gate * data blocks (this only applies to non-physical block write ATREQs and 3897c478bd9Sstevel@tonic-gate * block read ATRESP). Since it looks like most protocols that use large data 3907c478bd9Sstevel@tonic-gate * blocks (like SPB-2), use physical transfers to do this (due to their 3917c478bd9Sstevel@tonic-gate * efficiency), this will probably not be a real world problem. If it turns 3927c478bd9Sstevel@tonic-gate * out to be a problem, the options are to force a single cookie for the data 3937c478bd9Sstevel@tonic-gate * buffer, allow multiple cookies and have a larger data space, or change the 3947c478bd9Sstevel@tonic-gate * data code to use a OMI, OM, OL descriptor sequence (instead of OMI, OL). 3957c478bd9Sstevel@tonic-gate */ 3967c478bd9Sstevel@tonic-gate static int 3977c478bd9Sstevel@tonic-gate hci1394_q_reserve(hci1394_q_buf_t *qbuf, uint_t size, uint32_t *io_addr) 3987c478bd9Sstevel@tonic-gate { 3997c478bd9Sstevel@tonic-gate uint_t aligned_size; 4007c478bd9Sstevel@tonic-gate 4017c478bd9Sstevel@tonic-gate 4027c478bd9Sstevel@tonic-gate ASSERT(qbuf != NULL); 4037c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_reserve_enter, HCI1394_TNF_HAL_STACK, ""); 4047c478bd9Sstevel@tonic-gate 4057c478bd9Sstevel@tonic-gate /* Save backup of pointers in case we have to unreserve */ 4067c478bd9Sstevel@tonic-gate qbuf->qb_backup_ptrs = qbuf->qb_ptrs; 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate /* 4097c478bd9Sstevel@tonic-gate * Make sure all alloc's are quadlet aligned. The data doesn't have to 4107c478bd9Sstevel@tonic-gate * be, so we will force it to be. 4117c478bd9Sstevel@tonic-gate */ 4127c478bd9Sstevel@tonic-gate aligned_size = HCI1394_ALIGN_QUAD(size); 4137c478bd9Sstevel@tonic-gate 4147c478bd9Sstevel@tonic-gate /* 4157c478bd9Sstevel@tonic-gate * if the free pointer is in the current buffer and the free pointer 4167c478bd9Sstevel@tonic-gate * is below the current pointer (i.e. has not wrapped around) 4177c478bd9Sstevel@tonic-gate */ 4187c478bd9Sstevel@tonic-gate if ((qbuf->qb_ptrs.qp_current_buf == qbuf->qb_ptrs.qp_free_buf) && 4197c478bd9Sstevel@tonic-gate (qbuf->qb_ptrs.qp_free >= qbuf->qb_ptrs.qp_current)) { 4207c478bd9Sstevel@tonic-gate /* 4217c478bd9Sstevel@tonic-gate * The free pointer is in this buffer below the current pointer. 4227c478bd9Sstevel@tonic-gate * Check to see if we have enough free space left. 4237c478bd9Sstevel@tonic-gate */ 4247c478bd9Sstevel@tonic-gate if ((qbuf->qb_ptrs.qp_current + aligned_size) <= 4257c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_free) { 4267c478bd9Sstevel@tonic-gate /* Setup up our reserved size, return the IO address */ 4277c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_resv_size = aligned_size; 4287c478bd9Sstevel@tonic-gate *io_addr = (uint32_t)(qbuf->qb_cookie[ 4297c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_current_buf].dmac_address + 4307c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_offset); 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate /* 4337c478bd9Sstevel@tonic-gate * The free pointer is in this buffer below the current pointer. 4347c478bd9Sstevel@tonic-gate * We do not have enough free space for the alloc. Return 4357c478bd9Sstevel@tonic-gate * failure. 4367c478bd9Sstevel@tonic-gate */ 4377c478bd9Sstevel@tonic-gate } else { 4387c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_resv_size = 0; 4397c478bd9Sstevel@tonic-gate TNF_PROBE_0(hci1394_q_reserve_ns_fail, 4407c478bd9Sstevel@tonic-gate HCI1394_TNF_HAL_ERROR, ""); 4417c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_reserve_exit, 4427c478bd9Sstevel@tonic-gate HCI1394_TNF_HAL_STACK, ""); 4437c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 4447c478bd9Sstevel@tonic-gate } 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate /* 4477c478bd9Sstevel@tonic-gate * If there is not enough room to fit in the current buffer (not 4487c478bd9Sstevel@tonic-gate * including wrap around), we will go to the next buffer and check 4497c478bd9Sstevel@tonic-gate * there. If we only have one buffer (i.e. one cookie), we will end up 4507c478bd9Sstevel@tonic-gate * staying at the current buffer and wrapping the address back to the 4517c478bd9Sstevel@tonic-gate * top. 4527c478bd9Sstevel@tonic-gate */ 4537c478bd9Sstevel@tonic-gate } else if ((qbuf->qb_ptrs.qp_current + aligned_size) > 4547c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_end) { 4557c478bd9Sstevel@tonic-gate /* Go to the next buffer (or the top of ours for one cookie) */ 4567c478bd9Sstevel@tonic-gate hci1394_q_next_buf(qbuf); 4577c478bd9Sstevel@tonic-gate 4587c478bd9Sstevel@tonic-gate /* If the free pointer is in the new current buffer */ 4597c478bd9Sstevel@tonic-gate if (qbuf->qb_ptrs.qp_current_buf == qbuf->qb_ptrs.qp_free_buf) { 4607c478bd9Sstevel@tonic-gate /* 4617c478bd9Sstevel@tonic-gate * The free pointer is in this buffer. If we do not have 4627c478bd9Sstevel@tonic-gate * enough free space for the alloc. Return failure. 4637c478bd9Sstevel@tonic-gate */ 4647c478bd9Sstevel@tonic-gate if ((qbuf->qb_ptrs.qp_current + aligned_size) > 4657c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_free) { 4667c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_resv_size = 0; 4677c478bd9Sstevel@tonic-gate TNF_PROBE_0(hci1394_q_reserve_ns_fail, 4687c478bd9Sstevel@tonic-gate HCI1394_TNF_HAL_ERROR, ""); 4697c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_reserve_exit, 4707c478bd9Sstevel@tonic-gate HCI1394_TNF_HAL_STACK, ""); 4717c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 4727c478bd9Sstevel@tonic-gate /* 4737c478bd9Sstevel@tonic-gate * The free pointer is in this buffer. We have enough 4747c478bd9Sstevel@tonic-gate * free space left. 4757c478bd9Sstevel@tonic-gate */ 4767c478bd9Sstevel@tonic-gate } else { 4777c478bd9Sstevel@tonic-gate /* 4787c478bd9Sstevel@tonic-gate * Setup up our reserved size, return the IO 4797c478bd9Sstevel@tonic-gate * address 4807c478bd9Sstevel@tonic-gate */ 4817c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_resv_size = aligned_size; 4827c478bd9Sstevel@tonic-gate *io_addr = (uint32_t)(qbuf->qb_cookie[ 4837c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_current_buf].dmac_address + 4847c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_offset); 4857c478bd9Sstevel@tonic-gate } 4867c478bd9Sstevel@tonic-gate 4877c478bd9Sstevel@tonic-gate /* 4887c478bd9Sstevel@tonic-gate * We switched buffers and the free pointer is still in another 4897c478bd9Sstevel@tonic-gate * buffer. We have sufficient space in this buffer for the alloc 4907c478bd9Sstevel@tonic-gate * after changing buffers. 4917c478bd9Sstevel@tonic-gate */ 4927c478bd9Sstevel@tonic-gate } else { 4937c478bd9Sstevel@tonic-gate /* Setup up our reserved size, return the IO address */ 4947c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_resv_size = aligned_size; 4957c478bd9Sstevel@tonic-gate *io_addr = (uint32_t)(qbuf->qb_cookie[ 4967c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_current_buf].dmac_address + 4977c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_offset); 4987c478bd9Sstevel@tonic-gate } 4997c478bd9Sstevel@tonic-gate /* 5007c478bd9Sstevel@tonic-gate * The free pointer is in another buffer. We have sufficient space in 5017c478bd9Sstevel@tonic-gate * this buffer for the alloc. 5027c478bd9Sstevel@tonic-gate */ 5037c478bd9Sstevel@tonic-gate } else { 5047c478bd9Sstevel@tonic-gate /* Setup up our reserved size, return the IO address */ 5057c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_resv_size = aligned_size; 5067c478bd9Sstevel@tonic-gate *io_addr = (uint32_t)(qbuf->qb_cookie[ 5077c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_current_buf].dmac_address + 5087c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_offset); 5097c478bd9Sstevel@tonic-gate } 5107c478bd9Sstevel@tonic-gate 5117c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_reserve_exit, HCI1394_TNF_HAL_STACK, ""); 5127c478bd9Sstevel@tonic-gate 5137c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 5147c478bd9Sstevel@tonic-gate } 5157c478bd9Sstevel@tonic-gate 5167c478bd9Sstevel@tonic-gate /* 5177c478bd9Sstevel@tonic-gate * hci1394_q_unreserve() 5187c478bd9Sstevel@tonic-gate * Set the buffer pointer to what they were before hci1394_reserve(). This 5197c478bd9Sstevel@tonic-gate * will be called when we encounter errors during hci1394_q_at*(). 5207c478bd9Sstevel@tonic-gate */ 5217c478bd9Sstevel@tonic-gate static void 5227c478bd9Sstevel@tonic-gate hci1394_q_unreserve(hci1394_q_buf_t *qbuf) 5237c478bd9Sstevel@tonic-gate { 5247c478bd9Sstevel@tonic-gate ASSERT(qbuf != NULL); 5257c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_unreserve_enter, HCI1394_TNF_HAL_STACK, ""); 5267c478bd9Sstevel@tonic-gate 5277c478bd9Sstevel@tonic-gate /* Go back to pointer setting before the reserve */ 5287c478bd9Sstevel@tonic-gate qbuf->qb_ptrs = qbuf->qb_backup_ptrs; 5297c478bd9Sstevel@tonic-gate 5307c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_unreserve_exit, HCI1394_TNF_HAL_STACK, ""); 5317c478bd9Sstevel@tonic-gate } 5327c478bd9Sstevel@tonic-gate 5337c478bd9Sstevel@tonic-gate 5347c478bd9Sstevel@tonic-gate /* 5357c478bd9Sstevel@tonic-gate * hci1394_q_next_buf() 5367c478bd9Sstevel@tonic-gate * Set our current buffer to the next cookie. If we only have one cookie, we 5377c478bd9Sstevel@tonic-gate * will go back to the top of our buffer. 5387c478bd9Sstevel@tonic-gate */ 5397c478bd9Sstevel@tonic-gate void 5407c478bd9Sstevel@tonic-gate hci1394_q_next_buf(hci1394_q_buf_t *qbuf) 5417c478bd9Sstevel@tonic-gate { 5427c478bd9Sstevel@tonic-gate ASSERT(qbuf != NULL); 5437c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_next_buf_enter, HCI1394_TNF_HAL_STACK, ""); 5447c478bd9Sstevel@tonic-gate 5457c478bd9Sstevel@tonic-gate /* 5467c478bd9Sstevel@tonic-gate * go to the next cookie, if we are >= the cookie count, go back to the 5477c478bd9Sstevel@tonic-gate * first cookie. 5487c478bd9Sstevel@tonic-gate */ 5497c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_current_buf++; 5507c478bd9Sstevel@tonic-gate if (qbuf->qb_ptrs.qp_current_buf >= qbuf->qb_buf.bi_cookie_count) { 5517c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_current_buf = 0; 5527c478bd9Sstevel@tonic-gate } 5537c478bd9Sstevel@tonic-gate 5547c478bd9Sstevel@tonic-gate /* adjust the begin, end, current, and offset pointers */ 5557c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_begin = qbuf->qb_ptrs.qp_end + 1; 5567c478bd9Sstevel@tonic-gate if (qbuf->qb_ptrs.qp_begin > qbuf->qb_ptrs.qp_bottom) { 5577c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_begin = qbuf->qb_ptrs.qp_top; 5587c478bd9Sstevel@tonic-gate } 5597c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_end = qbuf->qb_ptrs.qp_begin + 5607c478bd9Sstevel@tonic-gate qbuf->qb_cookie[qbuf->qb_ptrs.qp_current_buf].dmac_size - 1; 5617c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_current = qbuf->qb_ptrs.qp_begin; 5627c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_offset = 0; 5637c478bd9Sstevel@tonic-gate 5647c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_next_buf_exit, HCI1394_TNF_HAL_STACK, ""); 5657c478bd9Sstevel@tonic-gate } 5667c478bd9Sstevel@tonic-gate 5677c478bd9Sstevel@tonic-gate 5687c478bd9Sstevel@tonic-gate /* 5697c478bd9Sstevel@tonic-gate * hci1394_q_at() 5707c478bd9Sstevel@tonic-gate * Place an AT command that does NOT need the data buffer into the DMA chain. 5717c478bd9Sstevel@tonic-gate * Some examples of this are quadlet read/write, PHY packets, ATREQ Block 5727c478bd9Sstevel@tonic-gate * Read, and ATRESP block write. result is only valid on failure. 5737c478bd9Sstevel@tonic-gate */ 5747c478bd9Sstevel@tonic-gate int 5757c478bd9Sstevel@tonic-gate hci1394_q_at(hci1394_q_handle_t q_handle, hci1394_q_cmd_t *cmd, 5767c478bd9Sstevel@tonic-gate hci1394_basic_pkt_t *hdr, uint_t hdrsize, int *result) 5777c478bd9Sstevel@tonic-gate { 5787c478bd9Sstevel@tonic-gate int status; 5797c478bd9Sstevel@tonic-gate uint32_t ioaddr; 5807c478bd9Sstevel@tonic-gate 5817c478bd9Sstevel@tonic-gate 5827c478bd9Sstevel@tonic-gate ASSERT(q_handle != NULL); 5837c478bd9Sstevel@tonic-gate ASSERT(cmd != NULL); 5847c478bd9Sstevel@tonic-gate ASSERT(hdr != NULL); 5857c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_enter, HCI1394_TNF_HAL_STACK, ""); 5867c478bd9Sstevel@tonic-gate 5877c478bd9Sstevel@tonic-gate mutex_enter(&q_handle->q_mutex); 5887c478bd9Sstevel@tonic-gate 5897c478bd9Sstevel@tonic-gate /* 5907c478bd9Sstevel@tonic-gate * Check the HAL state and generation when the AT Q is locked. This 5917c478bd9Sstevel@tonic-gate * will make sure that we get all the commands when we flush the Q's 5927c478bd9Sstevel@tonic-gate * during a reset or shutdown. 5937c478bd9Sstevel@tonic-gate */ 5947c478bd9Sstevel@tonic-gate if ((hci1394_state(q_handle->q_drvinfo) != HCI1394_NORMAL) || 5957c478bd9Sstevel@tonic-gate (hci1394_ohci_current_busgen(q_handle->q_ohci) != 5967c478bd9Sstevel@tonic-gate cmd->qc_generation)) { 5977c478bd9Sstevel@tonic-gate *result = H1394_STATUS_INVALID_BUSGEN; 5987c478bd9Sstevel@tonic-gate mutex_exit(&q_handle->q_mutex); 5997c478bd9Sstevel@tonic-gate TNF_PROBE_0(hci1394_q_at_st_fail, HCI1394_TNF_HAL_ERROR, ""); 6007c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_exit, HCI1394_TNF_HAL_STACK, 6017c478bd9Sstevel@tonic-gate ""); 6027c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 6037c478bd9Sstevel@tonic-gate } 6047c478bd9Sstevel@tonic-gate 6057c478bd9Sstevel@tonic-gate /* save away the argument to pass up when this command completes */ 6067c478bd9Sstevel@tonic-gate cmd->qc_node.tln_addr = cmd; 6077c478bd9Sstevel@tonic-gate 6087c478bd9Sstevel@tonic-gate /* we have not written any 16 byte blocks to the descriptor yet */ 6097c478bd9Sstevel@tonic-gate q_handle->q_block_cnt = 0; 6107c478bd9Sstevel@tonic-gate 6117c478bd9Sstevel@tonic-gate /* Reserve space for an OLI in the descriptor buffer */ 6127c478bd9Sstevel@tonic-gate status = hci1394_q_reserve(&q_handle->q_desc, 6137c478bd9Sstevel@tonic-gate sizeof (hci1394_desc_imm_t), &ioaddr); 6147c478bd9Sstevel@tonic-gate if (status != DDI_SUCCESS) { 6157c478bd9Sstevel@tonic-gate *result = H1394_STATUS_NOMORE_SPACE; 6167c478bd9Sstevel@tonic-gate mutex_exit(&q_handle->q_mutex); 6177c478bd9Sstevel@tonic-gate TNF_PROBE_0(hci1394_q_at_qre_fail, HCI1394_TNF_HAL_ERROR, ""); 6187c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_exit, HCI1394_TNF_HAL_STACK, 6197c478bd9Sstevel@tonic-gate ""); 6207c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 6217c478bd9Sstevel@tonic-gate } 6227c478bd9Sstevel@tonic-gate 6237c478bd9Sstevel@tonic-gate /* write the OLI to the descriptor buffer */ 6247c478bd9Sstevel@tonic-gate hci1394_q_at_write_OLI(q_handle, &q_handle->q_desc, cmd, hdr, hdrsize); 6257c478bd9Sstevel@tonic-gate 6267c478bd9Sstevel@tonic-gate /* Add the AT command to the queued list */ 6277c478bd9Sstevel@tonic-gate hci1394_tlist_add(q_handle->q_queued_list, &cmd->qc_node); 6287c478bd9Sstevel@tonic-gate 6297c478bd9Sstevel@tonic-gate mutex_exit(&q_handle->q_mutex); 6307c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_exit, HCI1394_TNF_HAL_STACK, ""); 6317c478bd9Sstevel@tonic-gate 6327c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 6337c478bd9Sstevel@tonic-gate } 6347c478bd9Sstevel@tonic-gate 6357c478bd9Sstevel@tonic-gate 6367c478bd9Sstevel@tonic-gate /* 6377c478bd9Sstevel@tonic-gate * XXX - NOTE: POSSIBLE FUTURE OPTIMIZATION 6387c478bd9Sstevel@tonic-gate * ATREQ Block read and write's that go through software are not very 6397c478bd9Sstevel@tonic-gate * efficient (one of the reasons to use physical space). A copy is forced 6407c478bd9Sstevel@tonic-gate * on all block reads due to the design of OpenHCI. Writes do not have this 6417c478bd9Sstevel@tonic-gate * same restriction. This design forces a copy for writes too (we always 6427c478bd9Sstevel@tonic-gate * copy into a data buffer before sending). There are many reasons for this 6437c478bd9Sstevel@tonic-gate * including complexity reduction. There is a data size threshold where a 6447c478bd9Sstevel@tonic-gate * copy is more expensive than mapping the data buffer address (or worse 6457c478bd9Sstevel@tonic-gate * case a big enough difference where it pays to do it). However, we move 6467c478bd9Sstevel@tonic-gate * block data around in mblks which means that our data may be scattered 6477c478bd9Sstevel@tonic-gate * over many buffers. This adds to the complexity of mapping and setting 6487c478bd9Sstevel@tonic-gate * up the OpenHCI descriptors. 6497c478bd9Sstevel@tonic-gate * 6507c478bd9Sstevel@tonic-gate * If someone really needs a speedup on block write ATREQs, my recommendation 6517c478bd9Sstevel@tonic-gate * would be to add an additional command type at the target interface for a 6527c478bd9Sstevel@tonic-gate * fast block write. The target driver would pass a mapped io addr to use. 6537c478bd9Sstevel@tonic-gate * A function like "hci1394_q_at_with_ioaddr()" could be created which would 6547c478bd9Sstevel@tonic-gate * be almost an exact copy of hci1394_q_at_with_data() without the 6557c478bd9Sstevel@tonic-gate * hci1394_q_reserve() and hci1394_q_at_rep_put8() for the data buffer. 6567c478bd9Sstevel@tonic-gate */ 6577c478bd9Sstevel@tonic-gate 6587c478bd9Sstevel@tonic-gate 6597c478bd9Sstevel@tonic-gate /* 6607c478bd9Sstevel@tonic-gate * hci1394_q_at_with_data() 6617c478bd9Sstevel@tonic-gate * Place an AT command that does need the data buffer into the DMA chain. 6627c478bd9Sstevel@tonic-gate * The data is passed as a pointer to a kernel virtual address. An example of 6637c478bd9Sstevel@tonic-gate * this is the lock operations. result is only valid on failure. 6647c478bd9Sstevel@tonic-gate */ 6657c478bd9Sstevel@tonic-gate int 6667c478bd9Sstevel@tonic-gate hci1394_q_at_with_data(hci1394_q_handle_t q_handle, hci1394_q_cmd_t *cmd, 6677c478bd9Sstevel@tonic-gate hci1394_basic_pkt_t *hdr, uint_t hdrsize, uint8_t *data, uint_t datasize, 6687c478bd9Sstevel@tonic-gate int *result) 6697c478bd9Sstevel@tonic-gate { 6707c478bd9Sstevel@tonic-gate uint32_t desc_ioaddr; 6717c478bd9Sstevel@tonic-gate uint32_t data_ioaddr; 6727c478bd9Sstevel@tonic-gate int status; 6737c478bd9Sstevel@tonic-gate 6747c478bd9Sstevel@tonic-gate 6757c478bd9Sstevel@tonic-gate ASSERT(q_handle != NULL); 6767c478bd9Sstevel@tonic-gate ASSERT(cmd != NULL); 6777c478bd9Sstevel@tonic-gate ASSERT(hdr != NULL); 6787c478bd9Sstevel@tonic-gate ASSERT(data != NULL); 6797c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_with_data_enter, HCI1394_TNF_HAL_STACK, 6807c478bd9Sstevel@tonic-gate ""); 6817c478bd9Sstevel@tonic-gate 6827c478bd9Sstevel@tonic-gate mutex_enter(&q_handle->q_mutex); 6837c478bd9Sstevel@tonic-gate 6847c478bd9Sstevel@tonic-gate /* 6857c478bd9Sstevel@tonic-gate * Check the HAL state and generation when the AT Q is locked. This 6867c478bd9Sstevel@tonic-gate * will make sure that we get all the commands when we flush the Q's 6877c478bd9Sstevel@tonic-gate * during a reset or shutdown. 6887c478bd9Sstevel@tonic-gate */ 6897c478bd9Sstevel@tonic-gate if ((hci1394_state(q_handle->q_drvinfo) != HCI1394_NORMAL) || 6907c478bd9Sstevel@tonic-gate (hci1394_ohci_current_busgen(q_handle->q_ohci) != 6917c478bd9Sstevel@tonic-gate cmd->qc_generation)) { 6927c478bd9Sstevel@tonic-gate *result = H1394_STATUS_INVALID_BUSGEN; 6937c478bd9Sstevel@tonic-gate mutex_exit(&q_handle->q_mutex); 6947c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_wd_st_fail, 6957c478bd9Sstevel@tonic-gate HCI1394_TNF_HAL_STACK, ""); 6967c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 6977c478bd9Sstevel@tonic-gate } 6987c478bd9Sstevel@tonic-gate 6997c478bd9Sstevel@tonic-gate /* save away the argument to pass up when this command completes */ 7007c478bd9Sstevel@tonic-gate cmd->qc_node.tln_addr = cmd; 7017c478bd9Sstevel@tonic-gate 7027c478bd9Sstevel@tonic-gate /* we have not written any 16 byte blocks to the descriptor yet */ 7037c478bd9Sstevel@tonic-gate q_handle->q_block_cnt = 0; 7047c478bd9Sstevel@tonic-gate 7057c478bd9Sstevel@tonic-gate /* Reserve space for an OMI and OL in the descriptor buffer */ 7067c478bd9Sstevel@tonic-gate status = hci1394_q_reserve(&q_handle->q_desc, 7077c478bd9Sstevel@tonic-gate (sizeof (hci1394_desc_imm_t) + sizeof (hci1394_desc_t)), 7087c478bd9Sstevel@tonic-gate &desc_ioaddr); 7097c478bd9Sstevel@tonic-gate if (status != DDI_SUCCESS) { 7107c478bd9Sstevel@tonic-gate *result = H1394_STATUS_NOMORE_SPACE; 7117c478bd9Sstevel@tonic-gate mutex_exit(&q_handle->q_mutex); 7127c478bd9Sstevel@tonic-gate TNF_PROBE_0(hci1394_q_at_wd_qre_fail, 7137c478bd9Sstevel@tonic-gate HCI1394_TNF_HAL_ERROR, ""); 7147c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_with_data_exit, 7157c478bd9Sstevel@tonic-gate HCI1394_TNF_HAL_STACK, ""); 7167c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 7177c478bd9Sstevel@tonic-gate } 7187c478bd9Sstevel@tonic-gate 7197c478bd9Sstevel@tonic-gate /* allocate space for data in the data buffer */ 7207c478bd9Sstevel@tonic-gate status = hci1394_q_reserve(&q_handle->q_data, datasize, &data_ioaddr); 7217c478bd9Sstevel@tonic-gate if (status != DDI_SUCCESS) { 7227c478bd9Sstevel@tonic-gate *result = H1394_STATUS_NOMORE_SPACE; 7237c478bd9Sstevel@tonic-gate hci1394_q_unreserve(&q_handle->q_desc); 7247c478bd9Sstevel@tonic-gate mutex_exit(&q_handle->q_mutex); 7257c478bd9Sstevel@tonic-gate TNF_PROBE_0(hci1394_q_at_wd_qra_fail, 7267c478bd9Sstevel@tonic-gate HCI1394_TNF_HAL_ERROR, ""); 7277c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_with_data_exit, 7287c478bd9Sstevel@tonic-gate HCI1394_TNF_HAL_STACK, ""); 7297c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 7307c478bd9Sstevel@tonic-gate } 7317c478bd9Sstevel@tonic-gate 7327c478bd9Sstevel@tonic-gate /* Copy data into data buffer */ 7337c478bd9Sstevel@tonic-gate hci1394_q_at_rep_put8(&q_handle->q_data, cmd, data, datasize); 7347c478bd9Sstevel@tonic-gate 7357c478bd9Sstevel@tonic-gate /* write the OMI to the descriptor buffer */ 7367c478bd9Sstevel@tonic-gate hci1394_q_at_write_OMI(q_handle, &q_handle->q_desc, cmd, hdr, hdrsize); 7377c478bd9Sstevel@tonic-gate 7387c478bd9Sstevel@tonic-gate /* write the OL to the descriptor buffer */ 7397c478bd9Sstevel@tonic-gate hci1394_q_at_write_OL(q_handle, &q_handle->q_desc, cmd, data_ioaddr, 7407c478bd9Sstevel@tonic-gate datasize); 7417c478bd9Sstevel@tonic-gate 7427c478bd9Sstevel@tonic-gate /* Add the AT command to the queued list */ 7437c478bd9Sstevel@tonic-gate hci1394_tlist_add(q_handle->q_queued_list, &cmd->qc_node); 7447c478bd9Sstevel@tonic-gate 7457c478bd9Sstevel@tonic-gate mutex_exit(&q_handle->q_mutex); 7467c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_with_data_exit, HCI1394_TNF_HAL_STACK, 7477c478bd9Sstevel@tonic-gate ""); 7487c478bd9Sstevel@tonic-gate 7497c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 7507c478bd9Sstevel@tonic-gate } 7517c478bd9Sstevel@tonic-gate 7527c478bd9Sstevel@tonic-gate 7537c478bd9Sstevel@tonic-gate /* 7547c478bd9Sstevel@tonic-gate * hci1394_q_at_with_mblk() 7557c478bd9Sstevel@tonic-gate * Place an AT command that does need the data buffer into the DMA chain. 7567c478bd9Sstevel@tonic-gate * The data is passed in mblk_t(s). Examples of this are a block write 7577c478bd9Sstevel@tonic-gate * ATREQ and a block read ATRESP. The services layer and the hal use a 7587c478bd9Sstevel@tonic-gate * private structure (h1394_mblk_t) to keep track of how much of the mblk 7597c478bd9Sstevel@tonic-gate * to send since we may have to break the transfer up into smaller blocks. 7607c478bd9Sstevel@tonic-gate * (i.e. a 1MByte block write would go out in 2KByte chunks. result is only 7617c478bd9Sstevel@tonic-gate * valid on failure. 7627c478bd9Sstevel@tonic-gate */ 7637c478bd9Sstevel@tonic-gate int 7647c478bd9Sstevel@tonic-gate hci1394_q_at_with_mblk(hci1394_q_handle_t q_handle, hci1394_q_cmd_t *cmd, 7657c478bd9Sstevel@tonic-gate hci1394_basic_pkt_t *hdr, uint_t hdrsize, h1394_mblk_t *mblk, int *result) 7667c478bd9Sstevel@tonic-gate { 7677c478bd9Sstevel@tonic-gate uint32_t desc_ioaddr; 7687c478bd9Sstevel@tonic-gate uint32_t data_ioaddr; 7697c478bd9Sstevel@tonic-gate int status; 7707c478bd9Sstevel@tonic-gate 7717c478bd9Sstevel@tonic-gate 7727c478bd9Sstevel@tonic-gate ASSERT(q_handle != NULL); 7737c478bd9Sstevel@tonic-gate ASSERT(cmd != NULL); 7747c478bd9Sstevel@tonic-gate ASSERT(hdr != NULL); 7757c478bd9Sstevel@tonic-gate ASSERT(mblk != NULL); 7767c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_with_mblk_enter, HCI1394_TNF_HAL_STACK, 7777c478bd9Sstevel@tonic-gate ""); 7787c478bd9Sstevel@tonic-gate 7797c478bd9Sstevel@tonic-gate mutex_enter(&q_handle->q_mutex); 7807c478bd9Sstevel@tonic-gate 7817c478bd9Sstevel@tonic-gate /* 7827c478bd9Sstevel@tonic-gate * Check the HAL state and generation when the AT Q is locked. This 7837c478bd9Sstevel@tonic-gate * will make sure that we get all the commands when we flush the Q's 7847c478bd9Sstevel@tonic-gate * during a reset or shutdown. 7857c478bd9Sstevel@tonic-gate */ 7867c478bd9Sstevel@tonic-gate if ((hci1394_state(q_handle->q_drvinfo) != HCI1394_NORMAL) || 7877c478bd9Sstevel@tonic-gate (hci1394_ohci_current_busgen(q_handle->q_ohci) != 7887c478bd9Sstevel@tonic-gate cmd->qc_generation)) { 7897c478bd9Sstevel@tonic-gate *result = H1394_STATUS_INVALID_BUSGEN; 7907c478bd9Sstevel@tonic-gate mutex_exit(&q_handle->q_mutex); 7917c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_wm_st_fail, 7927c478bd9Sstevel@tonic-gate HCI1394_TNF_HAL_STACK, ""); 7937c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 7947c478bd9Sstevel@tonic-gate } 7957c478bd9Sstevel@tonic-gate 7967c478bd9Sstevel@tonic-gate /* save away the argument to pass up when this command completes */ 7977c478bd9Sstevel@tonic-gate cmd->qc_node.tln_addr = cmd; 7987c478bd9Sstevel@tonic-gate 7997c478bd9Sstevel@tonic-gate /* we have not written any 16 byte blocks to the descriptor yet */ 8007c478bd9Sstevel@tonic-gate q_handle->q_block_cnt = 0; 8017c478bd9Sstevel@tonic-gate 8027c478bd9Sstevel@tonic-gate /* Reserve space for an OMI and OL in the descriptor buffer */ 8037c478bd9Sstevel@tonic-gate status = hci1394_q_reserve(&q_handle->q_desc, 8047c478bd9Sstevel@tonic-gate (sizeof (hci1394_desc_imm_t) + sizeof (hci1394_desc_t)), 8057c478bd9Sstevel@tonic-gate &desc_ioaddr); 8067c478bd9Sstevel@tonic-gate if (status != DDI_SUCCESS) { 8077c478bd9Sstevel@tonic-gate *result = H1394_STATUS_NOMORE_SPACE; 8087c478bd9Sstevel@tonic-gate mutex_exit(&q_handle->q_mutex); 8097c478bd9Sstevel@tonic-gate TNF_PROBE_0(hci1394_q_at_wm_qre_fail, 8107c478bd9Sstevel@tonic-gate HCI1394_TNF_HAL_ERROR, ""); 8117c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_with_mblk_exit, 8127c478bd9Sstevel@tonic-gate HCI1394_TNF_HAL_STACK, ""); 8137c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 8147c478bd9Sstevel@tonic-gate } 8157c478bd9Sstevel@tonic-gate 8167c478bd9Sstevel@tonic-gate /* Reserve space for data in the data buffer */ 8177c478bd9Sstevel@tonic-gate status = hci1394_q_reserve(&q_handle->q_data, mblk->length, 8187c478bd9Sstevel@tonic-gate &data_ioaddr); 8197c478bd9Sstevel@tonic-gate if (status != DDI_SUCCESS) { 8207c478bd9Sstevel@tonic-gate *result = H1394_STATUS_NOMORE_SPACE; 8217c478bd9Sstevel@tonic-gate hci1394_q_unreserve(&q_handle->q_desc); 8227c478bd9Sstevel@tonic-gate mutex_exit(&q_handle->q_mutex); 8237c478bd9Sstevel@tonic-gate TNF_PROBE_0(hci1394_q_at_wm_qra_fail, 8247c478bd9Sstevel@tonic-gate HCI1394_TNF_HAL_ERROR, ""); 8257c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_with_mblk_exit, 8267c478bd9Sstevel@tonic-gate HCI1394_TNF_HAL_STACK, ""); 8277c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 8287c478bd9Sstevel@tonic-gate } 8297c478bd9Sstevel@tonic-gate 8307c478bd9Sstevel@tonic-gate /* Copy mblk data into data buffer */ 8317c478bd9Sstevel@tonic-gate hci1394_q_at_copy_from_mblk(&q_handle->q_data, cmd, mblk); 8327c478bd9Sstevel@tonic-gate 8337c478bd9Sstevel@tonic-gate /* write the OMI to the descriptor buffer */ 8347c478bd9Sstevel@tonic-gate hci1394_q_at_write_OMI(q_handle, &q_handle->q_desc, cmd, hdr, hdrsize); 8357c478bd9Sstevel@tonic-gate 8367c478bd9Sstevel@tonic-gate /* write the OL to the descriptor buffer */ 8377c478bd9Sstevel@tonic-gate hci1394_q_at_write_OL(q_handle, &q_handle->q_desc, cmd, data_ioaddr, 8387c478bd9Sstevel@tonic-gate mblk->length); 8397c478bd9Sstevel@tonic-gate 8407c478bd9Sstevel@tonic-gate /* Add the AT command to the queued list */ 8417c478bd9Sstevel@tonic-gate hci1394_tlist_add(q_handle->q_queued_list, &cmd->qc_node); 8427c478bd9Sstevel@tonic-gate 8437c478bd9Sstevel@tonic-gate mutex_exit(&q_handle->q_mutex); 8447c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_with_mblk_exit, HCI1394_TNF_HAL_STACK, 8457c478bd9Sstevel@tonic-gate ""); 8467c478bd9Sstevel@tonic-gate 8477c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 8487c478bd9Sstevel@tonic-gate } 8497c478bd9Sstevel@tonic-gate 8507c478bd9Sstevel@tonic-gate 8517c478bd9Sstevel@tonic-gate /* 8527c478bd9Sstevel@tonic-gate * hci1394_q_at_next() 8537c478bd9Sstevel@tonic-gate * Return the next completed AT command in cmd. If flush_q is true, we will 8547c478bd9Sstevel@tonic-gate * return the command regardless if it finished or not. We will flush 8557c478bd9Sstevel@tonic-gate * during bus reset processing, shutdown, and detach. 8567c478bd9Sstevel@tonic-gate */ 8577c478bd9Sstevel@tonic-gate void 8587c478bd9Sstevel@tonic-gate hci1394_q_at_next(hci1394_q_handle_t q_handle, boolean_t flush_q, 8597c478bd9Sstevel@tonic-gate hci1394_q_cmd_t **cmd) 8607c478bd9Sstevel@tonic-gate { 8617c478bd9Sstevel@tonic-gate hci1394_q_buf_t *desc; 8627c478bd9Sstevel@tonic-gate hci1394_q_buf_t *data; 8637c478bd9Sstevel@tonic-gate hci1394_tlist_node_t *node; 8647c478bd9Sstevel@tonic-gate uint32_t cmd_status; 8657c478bd9Sstevel@tonic-gate 8667c478bd9Sstevel@tonic-gate 8677c478bd9Sstevel@tonic-gate ASSERT(q_handle != NULL); 8687c478bd9Sstevel@tonic-gate ASSERT(cmd != NULL); 8697c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_next_enter, HCI1394_TNF_HAL_STACK, ""); 8707c478bd9Sstevel@tonic-gate 8717c478bd9Sstevel@tonic-gate mutex_enter(&q_handle->q_mutex); 8727c478bd9Sstevel@tonic-gate 8737c478bd9Sstevel@tonic-gate desc = &q_handle->q_desc; 8747c478bd9Sstevel@tonic-gate data = &q_handle->q_data; 8757c478bd9Sstevel@tonic-gate 8767c478bd9Sstevel@tonic-gate /* Sync descriptor buffer */ 8777c478bd9Sstevel@tonic-gate (void) ddi_dma_sync(desc->qb_buf.bi_dma_handle, 0, 8787c478bd9Sstevel@tonic-gate desc->qb_buf.bi_length, DDI_DMA_SYNC_FORKERNEL); 8797c478bd9Sstevel@tonic-gate 8807c478bd9Sstevel@tonic-gate /* Look at the top cmd on the queued list (without removing it) */ 8817c478bd9Sstevel@tonic-gate hci1394_tlist_peek(q_handle->q_queued_list, &node); 8827c478bd9Sstevel@tonic-gate if (node == NULL) { 8837c478bd9Sstevel@tonic-gate /* There are no more commands left on the queued list */ 8847c478bd9Sstevel@tonic-gate *cmd = NULL; 8857c478bd9Sstevel@tonic-gate mutex_exit(&q_handle->q_mutex); 8867c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_next_exit, HCI1394_TNF_HAL_STACK, 8877c478bd9Sstevel@tonic-gate ""); 8887c478bd9Sstevel@tonic-gate return; 8897c478bd9Sstevel@tonic-gate } 8907c478bd9Sstevel@tonic-gate 8917c478bd9Sstevel@tonic-gate /* 8927c478bd9Sstevel@tonic-gate * There is a command on the list, read its status and timestamp when 8937c478bd9Sstevel@tonic-gate * it was sent 8947c478bd9Sstevel@tonic-gate */ 8957c478bd9Sstevel@tonic-gate *cmd = (hci1394_q_cmd_t *)node->tln_addr; 8967c478bd9Sstevel@tonic-gate cmd_status = ddi_get32(desc->qb_buf.bi_handle, (*cmd)->qc_status_addr); 8977c478bd9Sstevel@tonic-gate (*cmd)->qc_timestamp = cmd_status & DESC_ST_TIMESTAMP_MASK; 8987c478bd9Sstevel@tonic-gate cmd_status = HCI1394_DESC_EVT_GET(cmd_status); 8997c478bd9Sstevel@tonic-gate 9007c478bd9Sstevel@tonic-gate /* 9017c478bd9Sstevel@tonic-gate * If we are flushing the q (e.g. due to a bus reset), we will return 9027c478bd9Sstevel@tonic-gate * the command regardless of its completion status. If we are not 9037c478bd9Sstevel@tonic-gate * flushing the Q and we do not have status on the command (e.g. status 9047c478bd9Sstevel@tonic-gate * = 0), we are done with this Q for now. 9057c478bd9Sstevel@tonic-gate */ 9067c478bd9Sstevel@tonic-gate if (flush_q == B_FALSE) { 9077c478bd9Sstevel@tonic-gate if (cmd_status == 0) { 9087c478bd9Sstevel@tonic-gate *cmd = NULL; 9097c478bd9Sstevel@tonic-gate mutex_exit(&q_handle->q_mutex); 9107c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_next_exit, 9117c478bd9Sstevel@tonic-gate HCI1394_TNF_HAL_STACK, ""); 9127c478bd9Sstevel@tonic-gate return; 9137c478bd9Sstevel@tonic-gate } 9147c478bd9Sstevel@tonic-gate } 9157c478bd9Sstevel@tonic-gate 9167c478bd9Sstevel@tonic-gate /* 9177c478bd9Sstevel@tonic-gate * The command completed, remove it from the queued list. There is not 9187c478bd9Sstevel@tonic-gate * a race condition to delete the node in the list here. This is the 9197c478bd9Sstevel@tonic-gate * only place the node will be deleted so we do not need to check the 9207c478bd9Sstevel@tonic-gate * return status. 9217c478bd9Sstevel@tonic-gate */ 9227c478bd9Sstevel@tonic-gate (void) hci1394_tlist_delete(q_handle->q_queued_list, node); 9237c478bd9Sstevel@tonic-gate 9247c478bd9Sstevel@tonic-gate /* 9257c478bd9Sstevel@tonic-gate * Free the space used by the command in the descriptor and data 9267c478bd9Sstevel@tonic-gate * buffers. 9277c478bd9Sstevel@tonic-gate */ 9287c478bd9Sstevel@tonic-gate desc->qb_ptrs.qp_free_buf = (*cmd)->qc_descriptor_buf; 9297c478bd9Sstevel@tonic-gate desc->qb_ptrs.qp_free = (*cmd)->qc_descriptor_end; 9307c478bd9Sstevel@tonic-gate if ((*cmd)->qc_data_used == B_TRUE) { 9317c478bd9Sstevel@tonic-gate data->qb_ptrs.qp_free_buf = (*cmd)->qc_data_buf; 9327c478bd9Sstevel@tonic-gate data->qb_ptrs.qp_free = (*cmd)->qc_data_end; 9337c478bd9Sstevel@tonic-gate } 9347c478bd9Sstevel@tonic-gate 9357c478bd9Sstevel@tonic-gate /* return command status */ 9367c478bd9Sstevel@tonic-gate (*cmd)->qc_status = cmd_status; 9377c478bd9Sstevel@tonic-gate 9387c478bd9Sstevel@tonic-gate mutex_exit(&q_handle->q_mutex); 9397c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_next_exit, HCI1394_TNF_HAL_STACK, ""); 9407c478bd9Sstevel@tonic-gate } 9417c478bd9Sstevel@tonic-gate 9427c478bd9Sstevel@tonic-gate 9437c478bd9Sstevel@tonic-gate /* 9447c478bd9Sstevel@tonic-gate * hci1394_q_at_write_OMI() 9457c478bd9Sstevel@tonic-gate * Write an OMI descriptor into the AT descriptor buffer passed in as qbuf. 9467c478bd9Sstevel@tonic-gate * Buffer state information is stored in cmd. Use the hdr and hdr size for 9477c478bd9Sstevel@tonic-gate * the additional information attached to an immediate descriptor. 9487c478bd9Sstevel@tonic-gate */ 9497c478bd9Sstevel@tonic-gate void 9507c478bd9Sstevel@tonic-gate hci1394_q_at_write_OMI(hci1394_q_handle_t q_handle, hci1394_q_buf_t *qbuf, 9517c478bd9Sstevel@tonic-gate hci1394_q_cmd_t *cmd, hci1394_basic_pkt_t *hdr, uint_t hdrsize) 9527c478bd9Sstevel@tonic-gate { 9537c478bd9Sstevel@tonic-gate hci1394_desc_imm_t *desc; 9547c478bd9Sstevel@tonic-gate uint32_t data; 9557c478bd9Sstevel@tonic-gate 9567c478bd9Sstevel@tonic-gate 9577c478bd9Sstevel@tonic-gate ASSERT(qbuf != NULL); 9587c478bd9Sstevel@tonic-gate ASSERT(cmd != NULL); 9597c478bd9Sstevel@tonic-gate ASSERT(hdr != NULL); 9607c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&q_handle->q_mutex)); 9617c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_write_OMI_enter, HCI1394_TNF_HAL_STACK, 9627c478bd9Sstevel@tonic-gate ""); 9637c478bd9Sstevel@tonic-gate 9647c478bd9Sstevel@tonic-gate /* The only valid "header" sizes for an OMI are 8 bytes or 16 bytes */ 9657c478bd9Sstevel@tonic-gate ASSERT((hdrsize == 8) || (hdrsize == 16)); 9667c478bd9Sstevel@tonic-gate 9677c478bd9Sstevel@tonic-gate /* Make sure enough room for OMI */ 9687c478bd9Sstevel@tonic-gate ASSERT(qbuf->qb_ptrs.qp_resv_size >= sizeof (hci1394_desc_imm_t)); 9697c478bd9Sstevel@tonic-gate 9707c478bd9Sstevel@tonic-gate /* Store the offset of the top of this descriptor block */ 9717c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_offset = (uint32_t)(qbuf->qb_ptrs.qp_current - 9727c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_begin); 9737c478bd9Sstevel@tonic-gate 9747c478bd9Sstevel@tonic-gate /* Setup OpenHCI OMI Header */ 9757c478bd9Sstevel@tonic-gate desc = (hci1394_desc_imm_t *)qbuf->qb_ptrs.qp_current; 9767c478bd9Sstevel@tonic-gate data = DESC_AT_OMI | (hdrsize & DESC_HDR_REQCOUNT_MASK); 9777c478bd9Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle, &desc->hdr, data); 9787c478bd9Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle, &desc->data_addr, 0); 9797c478bd9Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle, &desc->branch, 0); 9807c478bd9Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle, &desc->status, cmd->qc_timestamp); 9817c478bd9Sstevel@tonic-gate 9827c478bd9Sstevel@tonic-gate /* 9837c478bd9Sstevel@tonic-gate * Copy in 1394 header. Size is in bytes, convert it to a 32-bit word 9847c478bd9Sstevel@tonic-gate * count. 9857c478bd9Sstevel@tonic-gate */ 9867c478bd9Sstevel@tonic-gate ddi_rep_put32(qbuf->qb_buf.bi_handle, &hdr->q1, &desc->q1, 9877c478bd9Sstevel@tonic-gate hdrsize >> 2, DDI_DEV_AUTOINCR); 9887c478bd9Sstevel@tonic-gate 9897c478bd9Sstevel@tonic-gate /* 9907c478bd9Sstevel@tonic-gate * We wrote 2 16 byte blocks in the descriptor buffer, update the count 9917c478bd9Sstevel@tonic-gate * accordingly. Update the reserved size and current pointer. 9927c478bd9Sstevel@tonic-gate */ 9937c478bd9Sstevel@tonic-gate q_handle->q_block_cnt += 2; 9947c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_resv_size -= sizeof (hci1394_desc_imm_t); 9957c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_current += sizeof (hci1394_desc_imm_t); 9967c478bd9Sstevel@tonic-gate 9977c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_write_OMI_exit, HCI1394_TNF_HAL_STACK, 9987c478bd9Sstevel@tonic-gate ""); 9997c478bd9Sstevel@tonic-gate } 10007c478bd9Sstevel@tonic-gate 10017c478bd9Sstevel@tonic-gate 10027c478bd9Sstevel@tonic-gate /* 10037c478bd9Sstevel@tonic-gate * hci1394_q_at_write_OLI() 10047c478bd9Sstevel@tonic-gate * Write an OLI descriptor into the AT descriptor buffer passed in as qbuf. 10057c478bd9Sstevel@tonic-gate * Buffer state information is stored in cmd. Use the hdr and hdr size for 10067c478bd9Sstevel@tonic-gate * the additional information attached to an immediate descriptor. 10077c478bd9Sstevel@tonic-gate */ 10087c478bd9Sstevel@tonic-gate void 10097c478bd9Sstevel@tonic-gate hci1394_q_at_write_OLI(hci1394_q_handle_t q_handle, hci1394_q_buf_t *qbuf, 10107c478bd9Sstevel@tonic-gate hci1394_q_cmd_t *cmd, hci1394_basic_pkt_t *hdr, uint_t hdrsize) 10117c478bd9Sstevel@tonic-gate { 10127c478bd9Sstevel@tonic-gate hci1394_desc_imm_t *desc; 10137c478bd9Sstevel@tonic-gate uint32_t data; 10147c478bd9Sstevel@tonic-gate uint32_t command_ptr; 10157c478bd9Sstevel@tonic-gate uint32_t tcode; 10167c478bd9Sstevel@tonic-gate 10177c478bd9Sstevel@tonic-gate 10187c478bd9Sstevel@tonic-gate ASSERT(qbuf != NULL); 10197c478bd9Sstevel@tonic-gate ASSERT(cmd != NULL); 10207c478bd9Sstevel@tonic-gate ASSERT(hdr != NULL); 10217c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&q_handle->q_mutex)); 10227c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_write_OLI_enter, HCI1394_TNF_HAL_STACK, 10237c478bd9Sstevel@tonic-gate ""); 10247c478bd9Sstevel@tonic-gate 10257c478bd9Sstevel@tonic-gate /* The only valid "header" sizes for an OLI are 8, 12, 16 bytes */ 10267c478bd9Sstevel@tonic-gate ASSERT((hdrsize == 8) || (hdrsize == 12) || (hdrsize == 16)); 10277c478bd9Sstevel@tonic-gate 10287c478bd9Sstevel@tonic-gate /* make sure enough room for 1 OLI */ 10297c478bd9Sstevel@tonic-gate ASSERT(qbuf->qb_ptrs.qp_resv_size >= sizeof (hci1394_desc_imm_t)); 10307c478bd9Sstevel@tonic-gate 10317c478bd9Sstevel@tonic-gate /* Store the offset of the top of this descriptor block */ 10327c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_offset = (uint32_t)(qbuf->qb_ptrs.qp_current - 10337c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_begin); 10347c478bd9Sstevel@tonic-gate 10357c478bd9Sstevel@tonic-gate /* Setup OpenHCI OLI Header */ 10367c478bd9Sstevel@tonic-gate desc = (hci1394_desc_imm_t *)qbuf->qb_ptrs.qp_current; 10377c478bd9Sstevel@tonic-gate data = DESC_AT_OLI | (hdrsize & DESC_HDR_REQCOUNT_MASK); 10387c478bd9Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle, &desc->hdr, data); 10397c478bd9Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle, &desc->data_addr, 0); 10407c478bd9Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle, &desc->branch, 0); 10417c478bd9Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle, &desc->status, cmd->qc_timestamp); 10427c478bd9Sstevel@tonic-gate 10437c478bd9Sstevel@tonic-gate /* Setup 1394 Header */ 10447c478bd9Sstevel@tonic-gate tcode = (hdr->q1 & DESC_PKT_TCODE_MASK) >> DESC_PKT_TCODE_SHIFT; 10457c478bd9Sstevel@tonic-gate if ((tcode == IEEE1394_TCODE_WRITE_QUADLET) || 10467c478bd9Sstevel@tonic-gate (tcode == IEEE1394_TCODE_READ_QUADLET_RESP)) { 10477c478bd9Sstevel@tonic-gate /* 10487c478bd9Sstevel@tonic-gate * if the tcode = a quadlet write, move the last quadlet as 10497c478bd9Sstevel@tonic-gate * 8-bit data. All data is treated as 8-bit data (even quadlet 10507c478bd9Sstevel@tonic-gate * reads and writes). Therefore, target drivers MUST take that 10517c478bd9Sstevel@tonic-gate * into consideration when accessing device registers. 10527c478bd9Sstevel@tonic-gate */ 10537c478bd9Sstevel@tonic-gate ddi_rep_put32(qbuf->qb_buf.bi_handle, &hdr->q1, &desc->q1, 3, 10547c478bd9Sstevel@tonic-gate DDI_DEV_AUTOINCR); 10557c478bd9Sstevel@tonic-gate ddi_rep_put8(qbuf->qb_buf.bi_handle, (uint8_t *)&hdr->q4, 10567c478bd9Sstevel@tonic-gate (uint8_t *)&desc->q4, 4, DDI_DEV_AUTOINCR); 10577c478bd9Sstevel@tonic-gate } else { 10587c478bd9Sstevel@tonic-gate ddi_rep_put32(qbuf->qb_buf.bi_handle, &hdr->q1, &desc->q1, 10597c478bd9Sstevel@tonic-gate hdrsize >> 2, DDI_DEV_AUTOINCR); 10607c478bd9Sstevel@tonic-gate } 10617c478bd9Sstevel@tonic-gate 10627c478bd9Sstevel@tonic-gate /* 10637c478bd9Sstevel@tonic-gate * We wrote 2 16 byte blocks in the descriptor buffer, update the count 10647c478bd9Sstevel@tonic-gate * accordingly. 10657c478bd9Sstevel@tonic-gate */ 10667c478bd9Sstevel@tonic-gate q_handle->q_block_cnt += 2; 10677c478bd9Sstevel@tonic-gate 10687c478bd9Sstevel@tonic-gate /* 10697c478bd9Sstevel@tonic-gate * Sync buffer in case DMA engine currently running. This must be done 10707c478bd9Sstevel@tonic-gate * before writing the command pointer in the previous descriptor. 10717c478bd9Sstevel@tonic-gate */ 10727c478bd9Sstevel@tonic-gate (void) ddi_dma_sync(qbuf->qb_buf.bi_dma_handle, 0, 10737c478bd9Sstevel@tonic-gate qbuf->qb_buf.bi_length, DDI_DMA_SYNC_FORDEV); 10747c478bd9Sstevel@tonic-gate 10757c478bd9Sstevel@tonic-gate /* save away the status address for quick access in at_next() */ 10767c478bd9Sstevel@tonic-gate cmd->qc_status_addr = &desc->status; 10777c478bd9Sstevel@tonic-gate 10787c478bd9Sstevel@tonic-gate /* 10797c478bd9Sstevel@tonic-gate * Setup the command pointer. This tells the HW where to get the 10807c478bd9Sstevel@tonic-gate * descriptor we just setup. This includes the IO address along with 10817c478bd9Sstevel@tonic-gate * a 4 bit 16 byte block count 10827c478bd9Sstevel@tonic-gate */ 10837c478bd9Sstevel@tonic-gate command_ptr = (uint32_t)((qbuf->qb_cookie[qbuf->qb_ptrs.qp_current_buf 10847c478bd9Sstevel@tonic-gate ].dmac_address + qbuf->qb_ptrs.qp_offset) | (q_handle->q_block_cnt & 10857c478bd9Sstevel@tonic-gate DESC_Z_MASK)); 10867c478bd9Sstevel@tonic-gate 10877c478bd9Sstevel@tonic-gate /* 10887c478bd9Sstevel@tonic-gate * if we previously setup a descriptor, add this new descriptor into 10897c478bd9Sstevel@tonic-gate * the previous descriptor's "next" pointer. 10907c478bd9Sstevel@tonic-gate */ 10917c478bd9Sstevel@tonic-gate if (q_handle->q_previous != NULL) { 10927c478bd9Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle, &q_handle->q_previous->branch, 10937c478bd9Sstevel@tonic-gate command_ptr); 10947c478bd9Sstevel@tonic-gate /* Sync buffer again, this gets the command pointer */ 10957c478bd9Sstevel@tonic-gate (void) ddi_dma_sync(qbuf->qb_buf.bi_dma_handle, 0, 10967c478bd9Sstevel@tonic-gate qbuf->qb_buf.bi_length, DDI_DMA_SYNC_FORDEV); 10977c478bd9Sstevel@tonic-gate } 10987c478bd9Sstevel@tonic-gate 10997c478bd9Sstevel@tonic-gate /* 11007c478bd9Sstevel@tonic-gate * this is now the previous descriptor. Update the current pointer, 11017c478bd9Sstevel@tonic-gate * clear the block count and reserved size since this is the end of 11027c478bd9Sstevel@tonic-gate * this command. 11037c478bd9Sstevel@tonic-gate */ 11047c478bd9Sstevel@tonic-gate q_handle->q_previous = (hci1394_desc_t *)desc; 11057c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_current += sizeof (hci1394_desc_imm_t); 11067c478bd9Sstevel@tonic-gate q_handle->q_block_cnt = 0; 11077c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_resv_size = 0; 11087c478bd9Sstevel@tonic-gate 11097c478bd9Sstevel@tonic-gate /* save away cleanup info when we are done with the command */ 11107c478bd9Sstevel@tonic-gate cmd->qc_descriptor_buf = qbuf->qb_ptrs.qp_current_buf; 11117c478bd9Sstevel@tonic-gate cmd->qc_descriptor_end = qbuf->qb_ptrs.qp_current - 1; 11127c478bd9Sstevel@tonic-gate 11137c478bd9Sstevel@tonic-gate /* If the DMA is not running, start it */ 11147c478bd9Sstevel@tonic-gate if (q_handle->q_dma_running == B_FALSE) { 11157c478bd9Sstevel@tonic-gate q_handle->q_info.qi_start(q_handle->q_info.qi_callback_arg, 11167c478bd9Sstevel@tonic-gate command_ptr); 11177c478bd9Sstevel@tonic-gate q_handle->q_dma_running = B_TRUE; 11187c478bd9Sstevel@tonic-gate /* the DMA is running, wake it up */ 11197c478bd9Sstevel@tonic-gate } else { 11207c478bd9Sstevel@tonic-gate q_handle->q_info.qi_wake(q_handle->q_info.qi_callback_arg); 11217c478bd9Sstevel@tonic-gate } 11227c478bd9Sstevel@tonic-gate 11237c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_write_OLI_exit, HCI1394_TNF_HAL_STACK, 11247c478bd9Sstevel@tonic-gate ""); 11257c478bd9Sstevel@tonic-gate } 11267c478bd9Sstevel@tonic-gate 11277c478bd9Sstevel@tonic-gate 11287c478bd9Sstevel@tonic-gate /* 11297c478bd9Sstevel@tonic-gate * hci1394_q_at_write_OL() 11307c478bd9Sstevel@tonic-gate * Write an OL descriptor into the AT descriptor buffer passed in as qbuf. 11317c478bd9Sstevel@tonic-gate * Buffer state information is stored in cmd. The IO address of the data 11327c478bd9Sstevel@tonic-gate * buffer is passed in io_addr. Size is the size of the data to be 11337c478bd9Sstevel@tonic-gate * transferred. 11347c478bd9Sstevel@tonic-gate */ 11357c478bd9Sstevel@tonic-gate void 11367c478bd9Sstevel@tonic-gate hci1394_q_at_write_OL(hci1394_q_handle_t q_handle, hci1394_q_buf_t *qbuf, 11377c478bd9Sstevel@tonic-gate hci1394_q_cmd_t *cmd, uint32_t io_addr, uint_t size) 11387c478bd9Sstevel@tonic-gate { 11397c478bd9Sstevel@tonic-gate hci1394_desc_t *desc; 11407c478bd9Sstevel@tonic-gate uint32_t data; 11417c478bd9Sstevel@tonic-gate uint32_t command_ptr; 11427c478bd9Sstevel@tonic-gate 11437c478bd9Sstevel@tonic-gate 11447c478bd9Sstevel@tonic-gate ASSERT(q_handle != NULL); 11457c478bd9Sstevel@tonic-gate ASSERT(qbuf != NULL); 11467c478bd9Sstevel@tonic-gate ASSERT(cmd != NULL); 11477c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&q_handle->q_mutex)); 11487c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_write_OL_enter, HCI1394_TNF_HAL_STACK, 11497c478bd9Sstevel@tonic-gate ""); 11507c478bd9Sstevel@tonic-gate 11517c478bd9Sstevel@tonic-gate /* make sure enough room for OL */ 11527c478bd9Sstevel@tonic-gate ASSERT(qbuf->qb_ptrs.qp_resv_size >= sizeof (hci1394_desc_t)); 11537c478bd9Sstevel@tonic-gate 11547c478bd9Sstevel@tonic-gate /* Setup OpenHCI OL Header */ 11557c478bd9Sstevel@tonic-gate desc = (hci1394_desc_t *)qbuf->qb_ptrs.qp_current; 11567c478bd9Sstevel@tonic-gate data = DESC_AT_OL | (size & DESC_HDR_REQCOUNT_MASK); 11577c478bd9Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle, &desc->hdr, data); 11587c478bd9Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle, &desc->data_addr, io_addr); 11597c478bd9Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle, &desc->branch, 0); 11607c478bd9Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle, &desc->status, 0); 11617c478bd9Sstevel@tonic-gate 11627c478bd9Sstevel@tonic-gate /* 11637c478bd9Sstevel@tonic-gate * We wrote 1 16 byte block in the descriptor buffer, update the count 11647c478bd9Sstevel@tonic-gate * accordingly. 11657c478bd9Sstevel@tonic-gate */ 11667c478bd9Sstevel@tonic-gate q_handle->q_block_cnt++; 11677c478bd9Sstevel@tonic-gate 11687c478bd9Sstevel@tonic-gate /* 11697c478bd9Sstevel@tonic-gate * Sync buffer in case DMA engine currently running. This must be done 11707c478bd9Sstevel@tonic-gate * before writing the command pointer in the previous descriptor. 11717c478bd9Sstevel@tonic-gate */ 11727c478bd9Sstevel@tonic-gate (void) ddi_dma_sync(qbuf->qb_buf.bi_dma_handle, 0, 11737c478bd9Sstevel@tonic-gate qbuf->qb_buf.bi_length, DDI_DMA_SYNC_FORDEV); 11747c478bd9Sstevel@tonic-gate 11757c478bd9Sstevel@tonic-gate /* save away the status address for quick access in at_next() */ 11767c478bd9Sstevel@tonic-gate cmd->qc_status_addr = &desc->status; 11777c478bd9Sstevel@tonic-gate 11787c478bd9Sstevel@tonic-gate /* 11797c478bd9Sstevel@tonic-gate * Setup the command pointer. This tells the HW where to get the 11807c478bd9Sstevel@tonic-gate * descriptor we just setup. This includes the IO address along with 11817c478bd9Sstevel@tonic-gate * a 4 bit 16 byte block count 11827c478bd9Sstevel@tonic-gate */ 11837c478bd9Sstevel@tonic-gate command_ptr = (uint32_t)((qbuf->qb_cookie[qbuf->qb_ptrs.qp_current_buf 11847c478bd9Sstevel@tonic-gate ].dmac_address + qbuf->qb_ptrs.qp_offset) | (q_handle->q_block_cnt & 11857c478bd9Sstevel@tonic-gate DESC_Z_MASK)); 11867c478bd9Sstevel@tonic-gate 11877c478bd9Sstevel@tonic-gate /* 11887c478bd9Sstevel@tonic-gate * if we previously setup a descriptor, add this new descriptor into 11897c478bd9Sstevel@tonic-gate * the previous descriptor's "next" pointer. 11907c478bd9Sstevel@tonic-gate */ 11917c478bd9Sstevel@tonic-gate if (q_handle->q_previous != NULL) { 11927c478bd9Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle, &q_handle->q_previous->branch, 11937c478bd9Sstevel@tonic-gate command_ptr); 11947c478bd9Sstevel@tonic-gate /* Sync buffer again, this gets the command pointer */ 11957c478bd9Sstevel@tonic-gate (void) ddi_dma_sync(qbuf->qb_buf.bi_dma_handle, 0, 11967c478bd9Sstevel@tonic-gate qbuf->qb_buf.bi_length, DDI_DMA_SYNC_FORDEV); 11977c478bd9Sstevel@tonic-gate } 11987c478bd9Sstevel@tonic-gate 11997c478bd9Sstevel@tonic-gate /* 12007c478bd9Sstevel@tonic-gate * this is now the previous descriptor. Update the current pointer, 12017c478bd9Sstevel@tonic-gate * clear the block count and reserved size since this is the end of 12027c478bd9Sstevel@tonic-gate * this command. 12037c478bd9Sstevel@tonic-gate */ 12047c478bd9Sstevel@tonic-gate q_handle->q_previous = desc; 12057c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_current += sizeof (hci1394_desc_t); 12067c478bd9Sstevel@tonic-gate q_handle->q_block_cnt = 0; 12077c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_resv_size = 0; 12087c478bd9Sstevel@tonic-gate 12097c478bd9Sstevel@tonic-gate /* save away cleanup info when we are done with the command */ 12107c478bd9Sstevel@tonic-gate cmd->qc_descriptor_buf = qbuf->qb_ptrs.qp_current_buf; 12117c478bd9Sstevel@tonic-gate cmd->qc_descriptor_end = qbuf->qb_ptrs.qp_current - 1; 12127c478bd9Sstevel@tonic-gate 12137c478bd9Sstevel@tonic-gate /* If the DMA is not running, start it */ 12147c478bd9Sstevel@tonic-gate if (q_handle->q_dma_running == B_FALSE) { 12157c478bd9Sstevel@tonic-gate q_handle->q_info.qi_start(q_handle->q_info.qi_callback_arg, 12167c478bd9Sstevel@tonic-gate command_ptr); 12177c478bd9Sstevel@tonic-gate q_handle->q_dma_running = B_TRUE; 12187c478bd9Sstevel@tonic-gate /* the DMA is running, wake it up */ 12197c478bd9Sstevel@tonic-gate } else { 12207c478bd9Sstevel@tonic-gate q_handle->q_info.qi_wake(q_handle->q_info.qi_callback_arg); 12217c478bd9Sstevel@tonic-gate } 12227c478bd9Sstevel@tonic-gate 12237c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_write_OL_exit, HCI1394_TNF_HAL_STACK, 12247c478bd9Sstevel@tonic-gate ""); 12257c478bd9Sstevel@tonic-gate } 12267c478bd9Sstevel@tonic-gate 12277c478bd9Sstevel@tonic-gate 12287c478bd9Sstevel@tonic-gate /* 12297c478bd9Sstevel@tonic-gate * hci1394_q_at_rep_put8() 12307c478bd9Sstevel@tonic-gate * Copy a byte stream from a kernel virtual address (data) to a IO mapped 12317c478bd9Sstevel@tonic-gate * data buffer (qbuf). Copy datasize bytes. State information for the 12327c478bd9Sstevel@tonic-gate * data buffer is kept in cmd. 12337c478bd9Sstevel@tonic-gate */ 12347c478bd9Sstevel@tonic-gate void 12357c478bd9Sstevel@tonic-gate hci1394_q_at_rep_put8(hci1394_q_buf_t *qbuf, hci1394_q_cmd_t *cmd, 12367c478bd9Sstevel@tonic-gate uint8_t *data, uint_t datasize) 12377c478bd9Sstevel@tonic-gate { 12387c478bd9Sstevel@tonic-gate ASSERT(qbuf != NULL); 12397c478bd9Sstevel@tonic-gate ASSERT(cmd != NULL); 12407c478bd9Sstevel@tonic-gate ASSERT(data != NULL); 12417c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_rep_put8_enter, HCI1394_TNF_HAL_STACK, 12427c478bd9Sstevel@tonic-gate ""); 12437c478bd9Sstevel@tonic-gate 12447c478bd9Sstevel@tonic-gate /* Make sure enough room for data */ 12457c478bd9Sstevel@tonic-gate ASSERT(qbuf->qb_ptrs.qp_resv_size >= datasize); 12467c478bd9Sstevel@tonic-gate 12477c478bd9Sstevel@tonic-gate /* Copy in data into the data buffer */ 12487c478bd9Sstevel@tonic-gate ddi_rep_put8(qbuf->qb_buf.bi_handle, data, 12497c478bd9Sstevel@tonic-gate (uint8_t *)qbuf->qb_ptrs.qp_current, datasize, DDI_DEV_AUTOINCR); 12507c478bd9Sstevel@tonic-gate 12517c478bd9Sstevel@tonic-gate /* Update the current pointer, offset, and reserved size */ 12527c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_current += datasize; 12537c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_offset = (uint32_t)(qbuf->qb_ptrs.qp_current - 12547c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_begin); 12557c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_resv_size -= datasize; 12567c478bd9Sstevel@tonic-gate 12577c478bd9Sstevel@tonic-gate /* save away cleanup info when we are done with the command */ 12587c478bd9Sstevel@tonic-gate cmd->qc_data_used = B_TRUE; 12597c478bd9Sstevel@tonic-gate cmd->qc_data_buf = qbuf->qb_ptrs.qp_current_buf; 12607c478bd9Sstevel@tonic-gate cmd->qc_data_end = qbuf->qb_ptrs.qp_current - 1; 12617c478bd9Sstevel@tonic-gate 12627c478bd9Sstevel@tonic-gate /* Sync data buffer */ 12637c478bd9Sstevel@tonic-gate (void) ddi_dma_sync(qbuf->qb_buf.bi_dma_handle, 0, 12647c478bd9Sstevel@tonic-gate qbuf->qb_buf.bi_length, DDI_DMA_SYNC_FORDEV); 12657c478bd9Sstevel@tonic-gate 12667c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_rep_put8_exit, HCI1394_TNF_HAL_STACK, 12677c478bd9Sstevel@tonic-gate ""); 12687c478bd9Sstevel@tonic-gate } 12697c478bd9Sstevel@tonic-gate 12707c478bd9Sstevel@tonic-gate 12717c478bd9Sstevel@tonic-gate /* 12727c478bd9Sstevel@tonic-gate * hci1394_q_at_copy_from_mblk() 12737c478bd9Sstevel@tonic-gate * Copy a byte stream from a mblk(s) to a IO mapped data buffer (qbuf). 12747c478bd9Sstevel@tonic-gate * Copy mblk->length bytes. The services layer and the hal use a private 12757c478bd9Sstevel@tonic-gate * structure (h1394_mblk_t) to keep track of how much of the mblk to send 12767c478bd9Sstevel@tonic-gate * since we may have to break the transfer up into smaller blocks. (i.e. a 12777c478bd9Sstevel@tonic-gate * 1MByte block write would go out in 2KByte chunks. State information for 12787c478bd9Sstevel@tonic-gate * the data buffer is kept in cmd. 12797c478bd9Sstevel@tonic-gate */ 12807c478bd9Sstevel@tonic-gate static void 12817c478bd9Sstevel@tonic-gate hci1394_q_at_copy_from_mblk(hci1394_q_buf_t *qbuf, hci1394_q_cmd_t *cmd, 12827c478bd9Sstevel@tonic-gate h1394_mblk_t *mblk) 12837c478bd9Sstevel@tonic-gate { 12847c478bd9Sstevel@tonic-gate uint_t bytes_left; 12857c478bd9Sstevel@tonic-gate uint_t length; 12867c478bd9Sstevel@tonic-gate 12877c478bd9Sstevel@tonic-gate 12887c478bd9Sstevel@tonic-gate ASSERT(qbuf != NULL); 12897c478bd9Sstevel@tonic-gate ASSERT(cmd != NULL); 12907c478bd9Sstevel@tonic-gate ASSERT(mblk != NULL); 12917c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_copy_from_mblk_enter, 12927c478bd9Sstevel@tonic-gate HCI1394_TNF_HAL_STACK, ""); 12937c478bd9Sstevel@tonic-gate 12947c478bd9Sstevel@tonic-gate /* We return these variables to the Services Layer when we are done */ 12957c478bd9Sstevel@tonic-gate mblk->next_offset = mblk->curr_offset; 12967c478bd9Sstevel@tonic-gate mblk->next_mblk = mblk->curr_mblk; 12977c478bd9Sstevel@tonic-gate bytes_left = mblk->length; 12987c478bd9Sstevel@tonic-gate 12997c478bd9Sstevel@tonic-gate /* do while there are bytes left to copy */ 13007c478bd9Sstevel@tonic-gate do { 13017c478bd9Sstevel@tonic-gate /* 13027c478bd9Sstevel@tonic-gate * If the entire data portion of the current block transfer is 13037c478bd9Sstevel@tonic-gate * contained within a single mblk. 13047c478bd9Sstevel@tonic-gate */ 13057c478bd9Sstevel@tonic-gate if ((mblk->next_offset + bytes_left) <= 13067c478bd9Sstevel@tonic-gate (mblk->next_mblk->b_wptr)) { 13077c478bd9Sstevel@tonic-gate /* Copy the data into the data Q */ 13087c478bd9Sstevel@tonic-gate hci1394_q_at_rep_put8(qbuf, cmd, 13097c478bd9Sstevel@tonic-gate (uint8_t *)mblk->next_offset, bytes_left); 13107c478bd9Sstevel@tonic-gate 13117c478bd9Sstevel@tonic-gate /* increment the mblk offset */ 13127c478bd9Sstevel@tonic-gate mblk->next_offset += bytes_left; 13137c478bd9Sstevel@tonic-gate 13147c478bd9Sstevel@tonic-gate /* we have no more bytes to put into the buffer */ 13157c478bd9Sstevel@tonic-gate bytes_left = 0; 13167c478bd9Sstevel@tonic-gate 13177c478bd9Sstevel@tonic-gate /* 13187c478bd9Sstevel@tonic-gate * If our offset is at the end of data in this mblk, go 13197c478bd9Sstevel@tonic-gate * to the next mblk. 13207c478bd9Sstevel@tonic-gate */ 13217c478bd9Sstevel@tonic-gate if (mblk->next_offset >= mblk->next_mblk->b_wptr) { 13227c478bd9Sstevel@tonic-gate mblk->next_mblk = mblk->next_mblk->b_cont; 13237c478bd9Sstevel@tonic-gate if (mblk->next_mblk != NULL) { 13247c478bd9Sstevel@tonic-gate mblk->next_offset = 13257c478bd9Sstevel@tonic-gate mblk->next_mblk->b_rptr; 13267c478bd9Sstevel@tonic-gate } 13277c478bd9Sstevel@tonic-gate } 13287c478bd9Sstevel@tonic-gate 13297c478bd9Sstevel@tonic-gate /* 13307c478bd9Sstevel@tonic-gate * The data portion of the current block transfer is spread 13317c478bd9Sstevel@tonic-gate * across two or more mblk's 13327c478bd9Sstevel@tonic-gate */ 13337c478bd9Sstevel@tonic-gate } else { 13347c478bd9Sstevel@tonic-gate /* 13357c478bd9Sstevel@tonic-gate * Figure out how much data is in this mblk. 13367c478bd9Sstevel@tonic-gate */ 13377c478bd9Sstevel@tonic-gate length = mblk->next_mblk->b_wptr - mblk->next_offset; 13387c478bd9Sstevel@tonic-gate 13397c478bd9Sstevel@tonic-gate /* Copy the data into the atreq data Q */ 13407c478bd9Sstevel@tonic-gate hci1394_q_at_rep_put8(qbuf, cmd, 13417c478bd9Sstevel@tonic-gate (uint8_t *)mblk->next_offset, length); 13427c478bd9Sstevel@tonic-gate 13437c478bd9Sstevel@tonic-gate /* update the bytes left count, go to the next mblk */ 13447c478bd9Sstevel@tonic-gate bytes_left = bytes_left - length; 13457c478bd9Sstevel@tonic-gate mblk->next_mblk = mblk->next_mblk->b_cont; 13467c478bd9Sstevel@tonic-gate ASSERT(mblk->next_mblk != NULL); 13477c478bd9Sstevel@tonic-gate mblk->next_offset = mblk->next_mblk->b_rptr; 13487c478bd9Sstevel@tonic-gate } 13497c478bd9Sstevel@tonic-gate } while (bytes_left > 0); 13507c478bd9Sstevel@tonic-gate 13517c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_at_copy_from_mblk_exit, 13527c478bd9Sstevel@tonic-gate HCI1394_TNF_HAL_STACK, ""); 13537c478bd9Sstevel@tonic-gate } 13547c478bd9Sstevel@tonic-gate 13557c478bd9Sstevel@tonic-gate 13567c478bd9Sstevel@tonic-gate /* 13577c478bd9Sstevel@tonic-gate * hci1394_q_ar_next() 13587c478bd9Sstevel@tonic-gate * Return an address to the next received AR packet. If there are no more 13597c478bd9Sstevel@tonic-gate * AR packets in the buffer, q_addr will be set to NULL. 13607c478bd9Sstevel@tonic-gate */ 13617c478bd9Sstevel@tonic-gate void 13627c478bd9Sstevel@tonic-gate hci1394_q_ar_next(hci1394_q_handle_t q_handle, uint32_t **q_addr) 13637c478bd9Sstevel@tonic-gate { 13647c478bd9Sstevel@tonic-gate hci1394_desc_t *desc; 13657c478bd9Sstevel@tonic-gate hci1394_q_buf_t *descb; 13667c478bd9Sstevel@tonic-gate hci1394_q_buf_t *datab; 13677c478bd9Sstevel@tonic-gate uint32_t residual_count; 13687c478bd9Sstevel@tonic-gate 13697c478bd9Sstevel@tonic-gate 13707c478bd9Sstevel@tonic-gate ASSERT(q_handle != NULL); 13717c478bd9Sstevel@tonic-gate ASSERT(q_addr != NULL); 13727c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_ar_next_enter, HCI1394_TNF_HAL_STACK, ""); 13737c478bd9Sstevel@tonic-gate 13747c478bd9Sstevel@tonic-gate descb = &q_handle->q_desc; 13757c478bd9Sstevel@tonic-gate datab = &q_handle->q_data; 13767c478bd9Sstevel@tonic-gate 13777c478bd9Sstevel@tonic-gate /* Sync Descriptor buffer */ 13787c478bd9Sstevel@tonic-gate (void) ddi_dma_sync(descb->qb_buf.bi_dma_handle, 0, 13797c478bd9Sstevel@tonic-gate descb->qb_buf.bi_length, DDI_DMA_SYNC_FORKERNEL); 13807c478bd9Sstevel@tonic-gate 13817c478bd9Sstevel@tonic-gate /* 13827c478bd9Sstevel@tonic-gate * Check residual in current IM count vs q_space_left to see if we have 13837c478bd9Sstevel@tonic-gate * received any more responses 13847c478bd9Sstevel@tonic-gate */ 13857c478bd9Sstevel@tonic-gate desc = (hci1394_desc_t *)q_handle->q_head; 13867c478bd9Sstevel@tonic-gate residual_count = ddi_get32(descb->qb_buf.bi_handle, &desc->status); 13877c478bd9Sstevel@tonic-gate residual_count &= DESC_ST_RESCOUNT_MASK; 13887c478bd9Sstevel@tonic-gate if (residual_count >= q_handle->q_space_left) { 13897c478bd9Sstevel@tonic-gate /* No new packets received */ 13907c478bd9Sstevel@tonic-gate *q_addr = NULL; 13917c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_ar_next_exit, 13927c478bd9Sstevel@tonic-gate HCI1394_TNF_HAL_STACK, ""); 13937c478bd9Sstevel@tonic-gate return; 13947c478bd9Sstevel@tonic-gate } 13957c478bd9Sstevel@tonic-gate 13967c478bd9Sstevel@tonic-gate /* Sync Data Q */ 13977c478bd9Sstevel@tonic-gate (void) ddi_dma_sync(datab->qb_buf.bi_dma_handle, 0, 13987c478bd9Sstevel@tonic-gate datab->qb_buf.bi_length, DDI_DMA_SYNC_FORKERNEL); 13997c478bd9Sstevel@tonic-gate 14007c478bd9Sstevel@tonic-gate /* 14017c478bd9Sstevel@tonic-gate * We have a new packet, return the address of the start of the 14027c478bd9Sstevel@tonic-gate * packet. 14037c478bd9Sstevel@tonic-gate */ 14047c478bd9Sstevel@tonic-gate *q_addr = (uint32_t *)datab->qb_ptrs.qp_current; 14057c478bd9Sstevel@tonic-gate 14067c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_ar_next_exit, HCI1394_TNF_HAL_STACK, ""); 14077c478bd9Sstevel@tonic-gate } 14087c478bd9Sstevel@tonic-gate 14097c478bd9Sstevel@tonic-gate 14107c478bd9Sstevel@tonic-gate /* 14117c478bd9Sstevel@tonic-gate * hci1394_q_ar_free() 14127c478bd9Sstevel@tonic-gate * Free the space used by the AR packet at the top of the data buffer. AR 14137c478bd9Sstevel@tonic-gate * packets are processed in the order that they are received. This will 14147c478bd9Sstevel@tonic-gate * free the oldest received packet which has not yet been freed. size is 14157c478bd9Sstevel@tonic-gate * how much space the packet takes up. 14167c478bd9Sstevel@tonic-gate */ 14177c478bd9Sstevel@tonic-gate void 14187c478bd9Sstevel@tonic-gate hci1394_q_ar_free(hci1394_q_handle_t q_handle, uint_t size) 14197c478bd9Sstevel@tonic-gate { 14207c478bd9Sstevel@tonic-gate hci1394_q_buf_t *descb; 14217c478bd9Sstevel@tonic-gate hci1394_q_buf_t *datab; 14227c478bd9Sstevel@tonic-gate 14237c478bd9Sstevel@tonic-gate 14247c478bd9Sstevel@tonic-gate ASSERT(q_handle != NULL); 14257c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_ar_free_enter, HCI1394_TNF_HAL_STACK, ""); 14267c478bd9Sstevel@tonic-gate 14277c478bd9Sstevel@tonic-gate descb = &q_handle->q_desc; 14287c478bd9Sstevel@tonic-gate datab = &q_handle->q_data; 14297c478bd9Sstevel@tonic-gate 14307c478bd9Sstevel@tonic-gate /* 14317c478bd9Sstevel@tonic-gate * Packet is in multiple buffers. Theoretically a buffer could be broken 14327c478bd9Sstevel@tonic-gate * in more than two buffers for an ARRESP. Since the buffers should be 14337c478bd9Sstevel@tonic-gate * in at least 4K increments this will not happen since the max packet 14347c478bd9Sstevel@tonic-gate * size is 2KBytes. 14357c478bd9Sstevel@tonic-gate */ 14367c478bd9Sstevel@tonic-gate if ((datab->qb_ptrs.qp_current + size) > datab->qb_ptrs.qp_end) { 14377c478bd9Sstevel@tonic-gate /* Add IM descriptor for used buffer back into Q */ 14387c478bd9Sstevel@tonic-gate hci1394_q_ar_write_IM(q_handle, descb, 14397c478bd9Sstevel@tonic-gate datab->qb_cookie[datab->qb_ptrs.qp_current_buf 14407c478bd9Sstevel@tonic-gate ].dmac_address, 14417c478bd9Sstevel@tonic-gate datab->qb_cookie[datab->qb_ptrs.qp_current_buf].dmac_size); 14427c478bd9Sstevel@tonic-gate 14437c478bd9Sstevel@tonic-gate /* Go to the next buffer */ 14447c478bd9Sstevel@tonic-gate hci1394_q_next_buf(datab); 14457c478bd9Sstevel@tonic-gate 14467c478bd9Sstevel@tonic-gate /* Update next buffers pointers for partial packet */ 14477c478bd9Sstevel@tonic-gate size -= q_handle->q_space_left; 14487c478bd9Sstevel@tonic-gate datab->qb_ptrs.qp_current += size; 14497c478bd9Sstevel@tonic-gate q_handle->q_space_left = 14507c478bd9Sstevel@tonic-gate datab->qb_cookie[datab->qb_ptrs.qp_current_buf].dmac_size - 14517c478bd9Sstevel@tonic-gate size; 14527c478bd9Sstevel@tonic-gate 14537c478bd9Sstevel@tonic-gate /* Change the head pointer to the next IM descriptor */ 14547c478bd9Sstevel@tonic-gate q_handle->q_head += sizeof (hci1394_desc_t); 14557c478bd9Sstevel@tonic-gate if ((q_handle->q_head + sizeof (hci1394_desc_t)) > 14567c478bd9Sstevel@tonic-gate (descb->qb_ptrs.qp_bottom + 1)) { 14577c478bd9Sstevel@tonic-gate q_handle->q_head = descb->qb_ptrs.qp_top; 14587c478bd9Sstevel@tonic-gate } 14597c478bd9Sstevel@tonic-gate 14607c478bd9Sstevel@tonic-gate /* Packet is only in one buffer */ 14617c478bd9Sstevel@tonic-gate } else { 14627c478bd9Sstevel@tonic-gate q_handle->q_space_left -= size; 14637c478bd9Sstevel@tonic-gate datab->qb_ptrs.qp_current += size; 14647c478bd9Sstevel@tonic-gate } 14657c478bd9Sstevel@tonic-gate 14667c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_ar_free_exit, HCI1394_TNF_HAL_STACK, ""); 14677c478bd9Sstevel@tonic-gate } 14687c478bd9Sstevel@tonic-gate 14697c478bd9Sstevel@tonic-gate 14707c478bd9Sstevel@tonic-gate /* 14717c478bd9Sstevel@tonic-gate * hci1394_q_ar_get32() 14727c478bd9Sstevel@tonic-gate * Read a quadlet of data regardless if it is in the current buffer or has 14737c478bd9Sstevel@tonic-gate * wrapped to the top buffer. If the address passed to this routine is 14747c478bd9Sstevel@tonic-gate * passed the bottom of the data buffer, this routine will automatically 14757c478bd9Sstevel@tonic-gate * wrap back to the top of the Q and look in the correct offset from the 14767c478bd9Sstevel@tonic-gate * top. Copy the data into the kernel virtual address provided. 14777c478bd9Sstevel@tonic-gate */ 14787c478bd9Sstevel@tonic-gate uint32_t 14797c478bd9Sstevel@tonic-gate hci1394_q_ar_get32(hci1394_q_handle_t q_handle, uint32_t *addr) 14807c478bd9Sstevel@tonic-gate { 14817c478bd9Sstevel@tonic-gate hci1394_q_buf_t *data; 14827c478bd9Sstevel@tonic-gate uintptr_t new_addr; 14837c478bd9Sstevel@tonic-gate uint32_t data32; 14847c478bd9Sstevel@tonic-gate 14857c478bd9Sstevel@tonic-gate 14867c478bd9Sstevel@tonic-gate ASSERT(q_handle != NULL); 14877c478bd9Sstevel@tonic-gate ASSERT(addr != NULL); 14887c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_get32_enter, HCI1394_TNF_HAL_STACK, ""); 14897c478bd9Sstevel@tonic-gate 14907c478bd9Sstevel@tonic-gate data = &q_handle->q_data; 14917c478bd9Sstevel@tonic-gate 14927c478bd9Sstevel@tonic-gate /* 14937c478bd9Sstevel@tonic-gate * if the data has wrapped to the top of the buffer, adjust the address. 14947c478bd9Sstevel@tonic-gate */ 14957c478bd9Sstevel@tonic-gate if ((uintptr_t)addr > (uintptr_t)data->qb_ptrs.qp_bottom) { 14967c478bd9Sstevel@tonic-gate new_addr = (uintptr_t)data->qb_ptrs.qp_top + ((uintptr_t)addr - 14977c478bd9Sstevel@tonic-gate ((uintptr_t)data->qb_ptrs.qp_bottom + (uintptr_t)1)); 14987c478bd9Sstevel@tonic-gate data32 = ddi_get32(data->qb_buf.bi_handle, 14997c478bd9Sstevel@tonic-gate (uint32_t *)new_addr); 15007c478bd9Sstevel@tonic-gate 15017c478bd9Sstevel@tonic-gate /* data is before end of buffer */ 15027c478bd9Sstevel@tonic-gate } else { 15037c478bd9Sstevel@tonic-gate data32 = ddi_get32(data->qb_buf.bi_handle, addr); 15047c478bd9Sstevel@tonic-gate } 15057c478bd9Sstevel@tonic-gate 15067c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_get32_exit, HCI1394_TNF_HAL_STACK, ""); 15077c478bd9Sstevel@tonic-gate 15087c478bd9Sstevel@tonic-gate return (data32); 15097c478bd9Sstevel@tonic-gate } 15107c478bd9Sstevel@tonic-gate 15117c478bd9Sstevel@tonic-gate 15127c478bd9Sstevel@tonic-gate /* 15137c478bd9Sstevel@tonic-gate * hci1394_q_ar_rep_get8() 15147c478bd9Sstevel@tonic-gate * Read a byte stream of data regardless if it is contiguous or has partially 15157c478bd9Sstevel@tonic-gate * or fully wrapped to the top buffer. If the address passed to this routine 15167c478bd9Sstevel@tonic-gate * is passed the bottom of the data buffer, or address + size is past the 15177c478bd9Sstevel@tonic-gate * bottom of the data buffer. this routine will automatically wrap back to 15187c478bd9Sstevel@tonic-gate * the top of the Q and look in the correct offset from the top. Copy the 15197c478bd9Sstevel@tonic-gate * data into the kernel virtual address provided. 15207c478bd9Sstevel@tonic-gate */ 15217c478bd9Sstevel@tonic-gate void 15227c478bd9Sstevel@tonic-gate hci1394_q_ar_rep_get8(hci1394_q_handle_t q_handle, uint8_t *dest, 15237c478bd9Sstevel@tonic-gate uint8_t *q_addr, uint_t size) 15247c478bd9Sstevel@tonic-gate { 15257c478bd9Sstevel@tonic-gate hci1394_q_buf_t *data; 15267c478bd9Sstevel@tonic-gate uintptr_t new_addr; 15277c478bd9Sstevel@tonic-gate uint_t new_size; 15287c478bd9Sstevel@tonic-gate uintptr_t new_dest; 15297c478bd9Sstevel@tonic-gate 15307c478bd9Sstevel@tonic-gate 15317c478bd9Sstevel@tonic-gate ASSERT(q_handle != NULL); 15327c478bd9Sstevel@tonic-gate ASSERT(dest != NULL); 15337c478bd9Sstevel@tonic-gate ASSERT(q_addr != NULL); 15347c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_ar_rep_get8_enter, HCI1394_TNF_HAL_STACK, 15357c478bd9Sstevel@tonic-gate ""); 15367c478bd9Sstevel@tonic-gate 15377c478bd9Sstevel@tonic-gate data = &q_handle->q_data; 15387c478bd9Sstevel@tonic-gate 15397c478bd9Sstevel@tonic-gate /* 15407c478bd9Sstevel@tonic-gate * There are three cases: 15417c478bd9Sstevel@tonic-gate * 1) All of the data has wrapped. 15427c478bd9Sstevel@tonic-gate * 2) Some of the data has not wrapped and some has wrapped. 15437c478bd9Sstevel@tonic-gate * 3) None of the data has wrapped. 15447c478bd9Sstevel@tonic-gate */ 15457c478bd9Sstevel@tonic-gate 15467c478bd9Sstevel@tonic-gate /* All of the data has wrapped, just adjust the starting address */ 15477c478bd9Sstevel@tonic-gate if ((uintptr_t)q_addr > (uintptr_t)data->qb_ptrs.qp_bottom) { 15487c478bd9Sstevel@tonic-gate new_addr = (uintptr_t)data->qb_ptrs.qp_top + 15497c478bd9Sstevel@tonic-gate ((uintptr_t)q_addr - ((uintptr_t)data->qb_ptrs.qp_bottom + 15507c478bd9Sstevel@tonic-gate (uintptr_t)1)); 15517c478bd9Sstevel@tonic-gate ddi_rep_get8(data->qb_buf.bi_handle, dest, (uint8_t *)new_addr, 15527c478bd9Sstevel@tonic-gate size, DDI_DEV_AUTOINCR); 15537c478bd9Sstevel@tonic-gate 15547c478bd9Sstevel@tonic-gate /* 15557c478bd9Sstevel@tonic-gate * Some of the data has wrapped. Copy the data that hasn't wrapped, 15567c478bd9Sstevel@tonic-gate * adjust the address, then copy the rest. 15577c478bd9Sstevel@tonic-gate */ 15587c478bd9Sstevel@tonic-gate } else if (((uintptr_t)q_addr + (uintptr_t)size) > 15597c478bd9Sstevel@tonic-gate ((uintptr_t)data->qb_ptrs.qp_bottom + (uintptr_t)1)) { 15607c478bd9Sstevel@tonic-gate /* Copy first half */ 15617c478bd9Sstevel@tonic-gate new_size = (uint_t)(((uintptr_t)data->qb_ptrs.qp_bottom + 15627c478bd9Sstevel@tonic-gate (uintptr_t)1) - (uintptr_t)q_addr); 15637c478bd9Sstevel@tonic-gate ddi_rep_get8(data->qb_buf.bi_handle, dest, q_addr, new_size, 15647c478bd9Sstevel@tonic-gate DDI_DEV_AUTOINCR); 15657c478bd9Sstevel@tonic-gate 15667c478bd9Sstevel@tonic-gate /* copy second half */ 15677c478bd9Sstevel@tonic-gate new_dest = (uintptr_t)dest + (uintptr_t)new_size; 15687c478bd9Sstevel@tonic-gate new_size = size - new_size; 15697c478bd9Sstevel@tonic-gate new_addr = (uintptr_t)data->qb_ptrs.qp_top; 15707c478bd9Sstevel@tonic-gate ddi_rep_get8(data->qb_buf.bi_handle, (uint8_t *)new_dest, 15717c478bd9Sstevel@tonic-gate (uint8_t *)new_addr, new_size, DDI_DEV_AUTOINCR); 15727c478bd9Sstevel@tonic-gate 15737c478bd9Sstevel@tonic-gate /* None of the data has wrapped */ 15747c478bd9Sstevel@tonic-gate } else { 15757c478bd9Sstevel@tonic-gate ddi_rep_get8(data->qb_buf.bi_handle, dest, q_addr, size, 15767c478bd9Sstevel@tonic-gate DDI_DEV_AUTOINCR); 15777c478bd9Sstevel@tonic-gate } 15787c478bd9Sstevel@tonic-gate 15797c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_ar_rep_get8_exit, HCI1394_TNF_HAL_STACK, 15807c478bd9Sstevel@tonic-gate ""); 15817c478bd9Sstevel@tonic-gate } 15827c478bd9Sstevel@tonic-gate 15837c478bd9Sstevel@tonic-gate 15847c478bd9Sstevel@tonic-gate /* 15857c478bd9Sstevel@tonic-gate * hci1394_q_ar_copy_to_mblk() 15867c478bd9Sstevel@tonic-gate * Read a byte stream of data regardless if it is contiguous or has partially 15877c478bd9Sstevel@tonic-gate * or fully wrapped to the top buffer. If the address passed to this routine 15887c478bd9Sstevel@tonic-gate * is passed the bottom of the data buffer, or address + size is passed the 15897c478bd9Sstevel@tonic-gate * bottom of the data buffer. this routine will automatically wrap back to 15907c478bd9Sstevel@tonic-gate * the top of the Q and look in the correct offset from the top. Copy the 15917c478bd9Sstevel@tonic-gate * data into the mblk provided. The services layer and the hal use a private 15927c478bd9Sstevel@tonic-gate * structure (h1394_mblk_t) to keep track of how much of the mblk to receive 15937c478bd9Sstevel@tonic-gate * into since we may have to break the transfer up into smaller blocks. 15947c478bd9Sstevel@tonic-gate * (i.e. a 1MByte block read would go out in 2KByte requests. 15957c478bd9Sstevel@tonic-gate */ 15967c478bd9Sstevel@tonic-gate void 15977c478bd9Sstevel@tonic-gate hci1394_q_ar_copy_to_mblk(hci1394_q_handle_t q_handle, uint8_t *addr, 15987c478bd9Sstevel@tonic-gate h1394_mblk_t *mblk) 15997c478bd9Sstevel@tonic-gate { 16007c478bd9Sstevel@tonic-gate uint8_t *new_addr; 16017c478bd9Sstevel@tonic-gate uint_t bytes_left; 16027c478bd9Sstevel@tonic-gate uint_t length; 16037c478bd9Sstevel@tonic-gate 16047c478bd9Sstevel@tonic-gate 16057c478bd9Sstevel@tonic-gate ASSERT(q_handle != NULL); 16067c478bd9Sstevel@tonic-gate ASSERT(addr != NULL); 16077c478bd9Sstevel@tonic-gate ASSERT(mblk != NULL); 16087c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_copy_to_mblk_enter, 16097c478bd9Sstevel@tonic-gate HCI1394_TNF_HAL_STACK, ""); 16107c478bd9Sstevel@tonic-gate 16117c478bd9Sstevel@tonic-gate /* We return these variables to the Services Layer when we are done */ 16127c478bd9Sstevel@tonic-gate mblk->next_offset = mblk->curr_offset; 16137c478bd9Sstevel@tonic-gate mblk->next_mblk = mblk->curr_mblk; 16147c478bd9Sstevel@tonic-gate bytes_left = mblk->length; 16157c478bd9Sstevel@tonic-gate 16167c478bd9Sstevel@tonic-gate /* the address we copy from will change as we change mblks */ 16177c478bd9Sstevel@tonic-gate new_addr = addr; 16187c478bd9Sstevel@tonic-gate 16197c478bd9Sstevel@tonic-gate /* do while there are bytes left to copy */ 16207c478bd9Sstevel@tonic-gate do { 16217c478bd9Sstevel@tonic-gate /* 16227c478bd9Sstevel@tonic-gate * If the entire data portion of the current block transfer is 16237c478bd9Sstevel@tonic-gate * contained within a single mblk. 16247c478bd9Sstevel@tonic-gate */ 16257c478bd9Sstevel@tonic-gate if ((mblk->next_offset + bytes_left) <= 16267c478bd9Sstevel@tonic-gate (mblk->next_mblk->b_datap->db_lim)) { 16277c478bd9Sstevel@tonic-gate /* Copy the data into the mblk */ 16287c478bd9Sstevel@tonic-gate hci1394_q_ar_rep_get8(q_handle, 16297c478bd9Sstevel@tonic-gate (uint8_t *)mblk->next_offset, new_addr, bytes_left); 16307c478bd9Sstevel@tonic-gate 16317c478bd9Sstevel@tonic-gate /* increment the offset */ 16327c478bd9Sstevel@tonic-gate mblk->next_offset += bytes_left; 16337c478bd9Sstevel@tonic-gate mblk->next_mblk->b_wptr = mblk->next_offset; 16347c478bd9Sstevel@tonic-gate 16357c478bd9Sstevel@tonic-gate /* we have no more bytes to put into the buffer */ 16367c478bd9Sstevel@tonic-gate bytes_left = 0; 16377c478bd9Sstevel@tonic-gate 16387c478bd9Sstevel@tonic-gate /* 16397c478bd9Sstevel@tonic-gate * If our offset is at the end of data in this mblk, go 16407c478bd9Sstevel@tonic-gate * to the next mblk. 16417c478bd9Sstevel@tonic-gate */ 16427c478bd9Sstevel@tonic-gate if (mblk->next_offset >= 16437c478bd9Sstevel@tonic-gate mblk->next_mblk->b_datap->db_lim) { 16447c478bd9Sstevel@tonic-gate mblk->next_mblk = mblk->next_mblk->b_cont; 16457c478bd9Sstevel@tonic-gate if (mblk->next_mblk != NULL) { 16467c478bd9Sstevel@tonic-gate mblk->next_offset = 16477c478bd9Sstevel@tonic-gate mblk->next_mblk->b_wptr; 16487c478bd9Sstevel@tonic-gate } 16497c478bd9Sstevel@tonic-gate } 16507c478bd9Sstevel@tonic-gate 16517c478bd9Sstevel@tonic-gate /* 16527c478bd9Sstevel@tonic-gate * The data portion of the current block transfer is spread 16537c478bd9Sstevel@tonic-gate * across two or more mblk's 16547c478bd9Sstevel@tonic-gate */ 16557c478bd9Sstevel@tonic-gate } else { 16567c478bd9Sstevel@tonic-gate /* Figure out how much data is in this mblk */ 16577c478bd9Sstevel@tonic-gate length = mblk->next_mblk->b_datap->db_lim - 16587c478bd9Sstevel@tonic-gate mblk->next_offset; 16597c478bd9Sstevel@tonic-gate 16607c478bd9Sstevel@tonic-gate /* Copy the data into the mblk */ 16617c478bd9Sstevel@tonic-gate hci1394_q_ar_rep_get8(q_handle, 16627c478bd9Sstevel@tonic-gate (uint8_t *)mblk->next_offset, new_addr, length); 16637c478bd9Sstevel@tonic-gate mblk->next_mblk->b_wptr = 16647c478bd9Sstevel@tonic-gate mblk->next_mblk->b_datap->db_lim; 16657c478bd9Sstevel@tonic-gate 16667c478bd9Sstevel@tonic-gate /* 16677c478bd9Sstevel@tonic-gate * update the bytes left and address to copy from, go 16687c478bd9Sstevel@tonic-gate * to the next mblk. 16697c478bd9Sstevel@tonic-gate */ 16707c478bd9Sstevel@tonic-gate bytes_left = bytes_left - length; 16717c478bd9Sstevel@tonic-gate new_addr = (uint8_t *)((uintptr_t)new_addr + 16727c478bd9Sstevel@tonic-gate (uintptr_t)length); 16737c478bd9Sstevel@tonic-gate mblk->next_mblk = mblk->next_mblk->b_cont; 16747c478bd9Sstevel@tonic-gate ASSERT(mblk->next_mblk != NULL); 16757c478bd9Sstevel@tonic-gate mblk->next_offset = mblk->next_mblk->b_wptr; 16767c478bd9Sstevel@tonic-gate } 16777c478bd9Sstevel@tonic-gate } while (bytes_left > 0); 16787c478bd9Sstevel@tonic-gate 16797c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_copy_to_mblk_exit, 16807c478bd9Sstevel@tonic-gate HCI1394_TNF_HAL_STACK, ""); 16817c478bd9Sstevel@tonic-gate } 16827c478bd9Sstevel@tonic-gate 16837c478bd9Sstevel@tonic-gate 16847c478bd9Sstevel@tonic-gate /* 16857c478bd9Sstevel@tonic-gate * hci1394_q_ar_write_IM() 16867c478bd9Sstevel@tonic-gate * Write an IM descriptor into the AR descriptor buffer passed in as qbuf. 16877c478bd9Sstevel@tonic-gate * The IO address of the data buffer is passed in io_addr. datasize is the 16887c478bd9Sstevel@tonic-gate * size of the data data buffer to receive into. 16897c478bd9Sstevel@tonic-gate */ 16907c478bd9Sstevel@tonic-gate void 16917c478bd9Sstevel@tonic-gate hci1394_q_ar_write_IM(hci1394_q_handle_t q_handle, hci1394_q_buf_t *qbuf, 16927c478bd9Sstevel@tonic-gate uint32_t io_addr, uint_t datasize) 16937c478bd9Sstevel@tonic-gate { 16947c478bd9Sstevel@tonic-gate hci1394_desc_t *desc; 16957c478bd9Sstevel@tonic-gate uint32_t data; 16967c478bd9Sstevel@tonic-gate uint32_t command_ptr; 16977c478bd9Sstevel@tonic-gate 16987c478bd9Sstevel@tonic-gate 16997c478bd9Sstevel@tonic-gate ASSERT(q_handle != NULL); 17007c478bd9Sstevel@tonic-gate ASSERT(qbuf != NULL); 17017c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_ar_write_IM_enter, HCI1394_TNF_HAL_STACK, 17027c478bd9Sstevel@tonic-gate ""); 17037c478bd9Sstevel@tonic-gate 17047c478bd9Sstevel@tonic-gate /* Make sure enough room for IM */ 17057c478bd9Sstevel@tonic-gate if ((qbuf->qb_ptrs.qp_current + sizeof (hci1394_desc_t)) > 17067c478bd9Sstevel@tonic-gate (qbuf->qb_ptrs.qp_bottom + 1)) { 17077c478bd9Sstevel@tonic-gate hci1394_q_next_buf(qbuf); 17087c478bd9Sstevel@tonic-gate } else { 17097c478bd9Sstevel@tonic-gate /* Store the offset of the top of this descriptor block */ 17107c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_offset = (uint32_t)(qbuf->qb_ptrs.qp_current - 17117c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_begin); 17127c478bd9Sstevel@tonic-gate } 17137c478bd9Sstevel@tonic-gate 17147c478bd9Sstevel@tonic-gate /* Setup OpenHCI IM Header */ 17157c478bd9Sstevel@tonic-gate desc = (hci1394_desc_t *)qbuf->qb_ptrs.qp_current; 17167c478bd9Sstevel@tonic-gate data = DESC_AR_IM | (datasize & DESC_HDR_REQCOUNT_MASK); 17177c478bd9Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle, &desc->hdr, data); 17187c478bd9Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle, &desc->data_addr, io_addr); 17197c478bd9Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle, &desc->branch, 0); 17207c478bd9Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle, &desc->status, datasize & 17217c478bd9Sstevel@tonic-gate DESC_ST_RESCOUNT_MASK); 17227c478bd9Sstevel@tonic-gate 17237c478bd9Sstevel@tonic-gate /* 17247c478bd9Sstevel@tonic-gate * Sync buffer in case DMA engine currently running. This must be done 17257c478bd9Sstevel@tonic-gate * before writing the command pointer in the previous descriptor. 17267c478bd9Sstevel@tonic-gate */ 17277c478bd9Sstevel@tonic-gate (void) ddi_dma_sync(qbuf->qb_buf.bi_dma_handle, 0, 17287c478bd9Sstevel@tonic-gate qbuf->qb_buf.bi_length, DDI_DMA_SYNC_FORDEV); 17297c478bd9Sstevel@tonic-gate 17307c478bd9Sstevel@tonic-gate /* 17317c478bd9Sstevel@tonic-gate * Setup the command pointer. This tells the HW where to get the 17327c478bd9Sstevel@tonic-gate * descriptor we just setup. This includes the IO address along with 17337c478bd9Sstevel@tonic-gate * a 4 bit 16 byte block count. We only wrote 1 16 byte block. 17347c478bd9Sstevel@tonic-gate */ 17357c478bd9Sstevel@tonic-gate command_ptr = (uint32_t)((qbuf->qb_cookie[qbuf->qb_ptrs.qp_current_buf 17367c478bd9Sstevel@tonic-gate ].dmac_address + qbuf->qb_ptrs.qp_offset) | 1); 17377c478bd9Sstevel@tonic-gate 17387c478bd9Sstevel@tonic-gate /* 17397c478bd9Sstevel@tonic-gate * if we previously setup a descriptor, add this new descriptor into 17407c478bd9Sstevel@tonic-gate * the previous descriptor's "next" pointer. 17417c478bd9Sstevel@tonic-gate */ 17427c478bd9Sstevel@tonic-gate if (q_handle->q_previous != NULL) { 17437c478bd9Sstevel@tonic-gate ddi_put32(qbuf->qb_buf.bi_handle, 17447c478bd9Sstevel@tonic-gate &q_handle->q_previous->branch, command_ptr); 17457c478bd9Sstevel@tonic-gate /* Sync buffer again, this gets the command pointer */ 17467c478bd9Sstevel@tonic-gate (void) ddi_dma_sync(qbuf->qb_buf.bi_dma_handle, 0, 17477c478bd9Sstevel@tonic-gate qbuf->qb_buf.bi_length, DDI_DMA_SYNC_FORDEV); 17487c478bd9Sstevel@tonic-gate } 17497c478bd9Sstevel@tonic-gate 17507c478bd9Sstevel@tonic-gate /* this is the new previous descriptor. Update the current pointer */ 17517c478bd9Sstevel@tonic-gate q_handle->q_previous = desc; 17527c478bd9Sstevel@tonic-gate qbuf->qb_ptrs.qp_current += sizeof (hci1394_desc_t); 17537c478bd9Sstevel@tonic-gate 17547c478bd9Sstevel@tonic-gate /* If the DMA is not running, start it */ 17557c478bd9Sstevel@tonic-gate if (q_handle->q_dma_running == B_FALSE) { 17567c478bd9Sstevel@tonic-gate q_handle->q_info.qi_start(q_handle->q_info.qi_callback_arg, 17577c478bd9Sstevel@tonic-gate command_ptr); 17587c478bd9Sstevel@tonic-gate q_handle->q_dma_running = B_TRUE; 17597c478bd9Sstevel@tonic-gate /* the DMA is running, wake it up */ 17607c478bd9Sstevel@tonic-gate } else { 17617c478bd9Sstevel@tonic-gate q_handle->q_info.qi_wake(q_handle->q_info.qi_callback_arg); 17627c478bd9Sstevel@tonic-gate } 17637c478bd9Sstevel@tonic-gate 17647c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(hci1394_q_ar_write_IM_exit, HCI1394_TNF_HAL_STACK, 17657c478bd9Sstevel@tonic-gate ""); 17667c478bd9Sstevel@tonic-gate } 1767