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 /*
237c478bd9Sstevel@tonic-gate  * Copyright (c) 1999-2000 by Sun Microsystems, Inc.
247c478bd9Sstevel@tonic-gate  * All rights reserved.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*
287c478bd9Sstevel@tonic-gate  * hci1394_async.c
297c478bd9Sstevel@tonic-gate  *    These routines manipulate the 1394 asynchronous dma engines.  This
307c478bd9Sstevel@tonic-gate  *    includes incoming and outgoing reads, writes, and locks and their
317c478bd9Sstevel@tonic-gate  *    associated responses.
327c478bd9Sstevel@tonic-gate  */
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate #include <sys/conf.h>
357c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
367c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
377c478bd9Sstevel@tonic-gate #include <sys/stat.h>
387c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
397c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
407c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
417c478bd9Sstevel@tonic-gate #include <sys/types.h>
427c478bd9Sstevel@tonic-gate #include <sys/note.h>
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate #include <sys/1394/h1394.h>
457c478bd9Sstevel@tonic-gate #include <sys/1394/adapters/hci1394.h>
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate /*
497c478bd9Sstevel@tonic-gate  * ASYNC_ARRESP_ACK_ERROR is or'd into the error status when we get an ACK error
507c478bd9Sstevel@tonic-gate  * on an ARRESP.  Since the 1394 response code overlaps with the OpenHCI ACK/EVT
517c478bd9Sstevel@tonic-gate  * errors, we use this to distinguish between the errors in process_arresp().
527c478bd9Sstevel@tonic-gate  */
537c478bd9Sstevel@tonic-gate #define	ASYNC_ARRESP_ACK_ERROR		0x8000
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate /* Macro's to help extract 48-bit 1394 address into a uint64_t */
567c478bd9Sstevel@tonic-gate #define	HCI1394_TO_ADDR_HI(data) (((uint64_t)((data) & 0xFFFF)) << 32)
577c478bd9Sstevel@tonic-gate #define	HCI1394_TO_ADDR_LO(data) ((uint64_t)((data) & 0xFFFFFFFF))
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate /*
607c478bd9Sstevel@tonic-gate  * Macro to convert a byte stream into a big endian quadlet or octlet or back
617c478bd9Sstevel@tonic-gate  * the other way. 1394 arithmetic lock operations are done on big endian
627c478bd9Sstevel@tonic-gate  * quadlets or octlets. compare swaps and bit masks are done on a byte streams.
637c478bd9Sstevel@tonic-gate  * All data is treated as byte streams over the bus. These macros will convert
647c478bd9Sstevel@tonic-gate  * the data to a big endian "integer" on x86 plaforms if the operation is an
657c478bd9Sstevel@tonic-gate  * arithmetic lock operation.  It will do nothing if it is not on x86 or is not
667c478bd9Sstevel@tonic-gate  * an arithmetic lock operation.
677c478bd9Sstevel@tonic-gate  */
687c478bd9Sstevel@tonic-gate #ifdef _LITTLE_ENDIAN
697c478bd9Sstevel@tonic-gate #define	HCI1394_ARITH_LOCK_SWAP32(tcode, data) \
707c478bd9Sstevel@tonic-gate 	(((tcode) == CMD1394_LOCK_FETCH_ADD) || \
717c478bd9Sstevel@tonic-gate 	((tcode) == CMD1394_LOCK_BOUNDED_ADD) || \
727c478bd9Sstevel@tonic-gate 	((tcode) == CMD1394_LOCK_WRAP_ADD)) ? \
737c478bd9Sstevel@tonic-gate 	(ddi_swap32(data)) : (data)
747c478bd9Sstevel@tonic-gate #define	HCI1394_ARITH_LOCK_SWAP64(tcode, data) \
757c478bd9Sstevel@tonic-gate 	(((tcode) == CMD1394_LOCK_FETCH_ADD) || \
767c478bd9Sstevel@tonic-gate 	((tcode) == CMD1394_LOCK_BOUNDED_ADD) || \
777c478bd9Sstevel@tonic-gate 	((tcode) == CMD1394_LOCK_WRAP_ADD)) ? \
787c478bd9Sstevel@tonic-gate 	(ddi_swap64(data)) : (data)
797c478bd9Sstevel@tonic-gate #else
807c478bd9Sstevel@tonic-gate #define	HCI1394_ARITH_LOCK_SWAP32(tcode, data) (data)
817c478bd9Sstevel@tonic-gate #define	HCI1394_ARITH_LOCK_SWAP64(tcode, data) (data)
827c478bd9Sstevel@tonic-gate #endif
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate static int hci1394_async_arresp_read(hci1394_async_handle_t async_handle,
877c478bd9Sstevel@tonic-gate     hci1394_basic_pkt_t *pkt, uint_t *tcode, hci1394_async_cmd_t **hcicmd,
887c478bd9Sstevel@tonic-gate     uint_t *size);
897c478bd9Sstevel@tonic-gate static int hci1394_async_arresp_size_get(uint_t tcode, hci1394_q_handle_t q,
907c478bd9Sstevel@tonic-gate     uint32_t *addr, uint_t *size);
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate static int hci1394_async_arreq_read(hci1394_async_handle_t async_handle,
937c478bd9Sstevel@tonic-gate     hci1394_basic_pkt_t *pkt, uint_t *tcode, hci1394_async_cmd_t **hcicmd,
947c478bd9Sstevel@tonic-gate     uint_t *size);
957c478bd9Sstevel@tonic-gate static int hci1394_async_arreq_read_qrd(hci1394_async_handle_t async_handle,
967c478bd9Sstevel@tonic-gate     hci1394_basic_pkt_t *pkt, hci1394_async_cmd_t *hcicmd, uint_t *size);
977c478bd9Sstevel@tonic-gate static int hci1394_async_arreq_read_qwr(hci1394_async_handle_t async_handle,
987c478bd9Sstevel@tonic-gate     hci1394_basic_pkt_t *pkt, hci1394_async_cmd_t *hcicmd, uint_t *size);
997c478bd9Sstevel@tonic-gate static int hci1394_async_arreq_read_brd(hci1394_async_handle_t async_handle,
1007c478bd9Sstevel@tonic-gate     hci1394_basic_pkt_t *pkt, hci1394_async_cmd_t *hcicmd, uint_t *size);
1017c478bd9Sstevel@tonic-gate static int hci1394_async_arreq_read_bwr(hci1394_async_handle_t async_handle,
1027c478bd9Sstevel@tonic-gate     hci1394_basic_pkt_t *pkt, hci1394_async_cmd_t *hcicmd, uint_t *size);
1037c478bd9Sstevel@tonic-gate static int hci1394_async_arreq_read_lck(hci1394_async_handle_t async_handle,
1047c478bd9Sstevel@tonic-gate     hci1394_basic_pkt_t *pkt, hci1394_async_cmd_t *hcicmd, uint_t *size);
1057c478bd9Sstevel@tonic-gate static int hci1394_async_arreq_read_phy(hci1394_async_handle_t async_handle,
1067c478bd9Sstevel@tonic-gate     hci1394_basic_pkt_t *pkt, hci1394_async_cmd_t *hcicmd, uint_t *size,
1077c478bd9Sstevel@tonic-gate     boolean_t *bus_reset_token);
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate static void hci1394_async_hcicmd_init(hci1394_async_handle_t async_handle,
1107c478bd9Sstevel@tonic-gate     cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv,
1117c478bd9Sstevel@tonic-gate     hci1394_async_cmd_t **hcicmd);
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate static void hci1394_async_atreq_start(void *async, uint32_t command_ptr);
1147c478bd9Sstevel@tonic-gate static void hci1394_async_arresp_start(void *async, uint32_t command_ptr);
1157c478bd9Sstevel@tonic-gate static void hci1394_async_arreq_start(void *async, uint32_t command_ptr);
1167c478bd9Sstevel@tonic-gate static void hci1394_async_atresp_start(void *async, uint32_t command_ptr);
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate static void hci1394_async_atreq_wake(void *async);
1197c478bd9Sstevel@tonic-gate static void hci1394_async_arresp_wake(void *async);
1207c478bd9Sstevel@tonic-gate static void hci1394_async_arreq_wake(void *async);
1217c478bd9Sstevel@tonic-gate static void hci1394_async_atresp_wake(void *async);
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate static void hci1394_async_atreq_flush(hci1394_async_handle_t async_handle);
1247c478bd9Sstevel@tonic-gate static void hci1394_async_arresp_flush(hci1394_async_handle_t async_handle);
1257c478bd9Sstevel@tonic-gate static void hci1394_async_arreq_flush(hci1394_async_handle_t async_handle);
1267c478bd9Sstevel@tonic-gate static void hci1394_async_atresp_flush(hci1394_async_handle_t async_handle);
1277c478bd9Sstevel@tonic-gate static void hci1394_async_pending_list_flush(hci1394_async_handle_t
1287c478bd9Sstevel@tonic-gate     async_handle);
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate static void hci1394_async_pending_timeout(hci1394_tlist_node_t *node,
1317c478bd9Sstevel@tonic-gate     void *arg);
1327c478bd9Sstevel@tonic-gate static uint_t hci1394_async_timeout_calc(hci1394_async_handle_t async_handle,
1337c478bd9Sstevel@tonic-gate     uint_t current_time);
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate _NOTE(SCHEME_PROTECTS_DATA("unique", msgb))
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate /*
1387c478bd9Sstevel@tonic-gate  * hci1394_async_init()
1397c478bd9Sstevel@tonic-gate  *    Initialize the async DMA engines and state. We init the tlabels; ATREQ
1407c478bd9Sstevel@tonic-gate  *    pending Q; and ATREQ, ARRESP, ARREQ, and ATRESP Q's. init() returns a
1417c478bd9Sstevel@tonic-gate  *    handle to be used in rest of the functions.
1427c478bd9Sstevel@tonic-gate  */
1437c478bd9Sstevel@tonic-gate int
hci1394_async_init(hci1394_drvinfo_t * drvinfo,hci1394_ohci_handle_t ohci_handle,hci1394_csr_handle_t csr_handle,hci1394_async_handle_t * async_handle)1447c478bd9Sstevel@tonic-gate hci1394_async_init(hci1394_drvinfo_t *drvinfo,
1457c478bd9Sstevel@tonic-gate     hci1394_ohci_handle_t ohci_handle, hci1394_csr_handle_t csr_handle,
1467c478bd9Sstevel@tonic-gate     hci1394_async_handle_t *async_handle)
1477c478bd9Sstevel@tonic-gate {
1487c478bd9Sstevel@tonic-gate 	hci1394_tlist_timer_t timer_info;
1497c478bd9Sstevel@tonic-gate 	hci1394_q_info_t qinfo;
1507c478bd9Sstevel@tonic-gate 	hci1394_async_t *async;
1517c478bd9Sstevel@tonic-gate 	int status;
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 	ASSERT(drvinfo != NULL);
1557c478bd9Sstevel@tonic-gate 	ASSERT(ohci_handle != NULL);
1567c478bd9Sstevel@tonic-gate 	ASSERT(csr_handle != NULL);
1577c478bd9Sstevel@tonic-gate 	ASSERT(async_handle != NULL);
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate 	/* alloc the space to keep track of the list */
1607c478bd9Sstevel@tonic-gate 	async = kmem_alloc(sizeof (hci1394_async_t), KM_SLEEP);
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate 	/* copy in parms to our local state */
1637c478bd9Sstevel@tonic-gate 	async->as_drvinfo = drvinfo;
1647c478bd9Sstevel@tonic-gate 	async->as_ohci = ohci_handle;
1657c478bd9Sstevel@tonic-gate 	async->as_csr = csr_handle;
1667c478bd9Sstevel@tonic-gate 	async->as_flushing_arreq = B_FALSE;
1677c478bd9Sstevel@tonic-gate 	async->as_phy_reset = 0xFFFFFFFF;
1687c478bd9Sstevel@tonic-gate 	mutex_init(&async->as_atomic_lookup, NULL, MUTEX_DRIVER,
1697c478bd9Sstevel@tonic-gate 	    drvinfo->di_iblock_cookie);
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate 	/*
1727c478bd9Sstevel@tonic-gate 	 * Initialize the tlabels. Reclaim a bad tlabel after the split timeout
1737c478bd9Sstevel@tonic-gate 	 * has gone by. This time is in reference to the point the transaction
1747c478bd9Sstevel@tonic-gate 	 * has been marked as bad. Therefore the tlabel will be reclaimed at
1757c478bd9Sstevel@tonic-gate 	 * twice the split_timeout. (i.e. if the split timeout was set to 100mS
1767c478bd9Sstevel@tonic-gate 	 * and the transaction has timed out, 100mS has already gone by. We need
1777c478bd9Sstevel@tonic-gate 	 * to wait for 100mS more before we can reuse the tlabel. Therefore, the
1787c478bd9Sstevel@tonic-gate 	 * reclaim time is split_timeout and not split_timeout * 2. The split
1797c478bd9Sstevel@tonic-gate 	 * timeout is stored as the number of bus cycles.  We need to convert
1807c478bd9Sstevel@tonic-gate 	 * this to nS since the reclaim time is passed as nS.
1817c478bd9Sstevel@tonic-gate 	 */
1827c478bd9Sstevel@tonic-gate 	hci1394_tlabel_init(drvinfo, OHCI_BUS_CYCLE_TO_nS(
1837c478bd9Sstevel@tonic-gate 	    hci1394_csr_split_timeout_get(csr_handle)), &async->as_tlabel);
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate 	/*
1867c478bd9Sstevel@tonic-gate 	 * Initialize ATREQ pending list. A pended ATREQ will be timed out after
1877c478bd9Sstevel@tonic-gate 	 * "split_timeout" has gone by. split timeout is in bus cycles so we
1887c478bd9Sstevel@tonic-gate 	 * need to convert that to nS for the tlist timer info. We will set the
1897c478bd9Sstevel@tonic-gate 	 * timer resolution to 1/2 of the timeout so that we will have a worst
1907c478bd9Sstevel@tonic-gate 	 * case timeout of split timeout + (1/2 * split timeout).  See
1917c478bd9Sstevel@tonic-gate 	 * hci1394_tlist.h for more information about this.
1927c478bd9Sstevel@tonic-gate 	 */
1937c478bd9Sstevel@tonic-gate 	timer_info.tlt_timeout =
1947c478bd9Sstevel@tonic-gate 	    OHCI_BUS_CYCLE_TO_nS(hci1394_csr_split_timeout_get(csr_handle));
1957c478bd9Sstevel@tonic-gate 	timer_info.tlt_timer_resolution = timer_info.tlt_timeout / 2;
1967c478bd9Sstevel@tonic-gate 	timer_info.tlt_callback = hci1394_async_pending_timeout;
1977c478bd9Sstevel@tonic-gate 	timer_info.tlt_callback_arg = async;
1987c478bd9Sstevel@tonic-gate 	hci1394_tlist_init(drvinfo, &timer_info, &async->as_pending_list);
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 	/* Initialize ATREQ Q */
2017c478bd9Sstevel@tonic-gate 	qinfo.qi_desc_size = ASYNC_ATREQ_DESC_SIZE;
2027c478bd9Sstevel@tonic-gate 	qinfo.qi_data_size = ASYNC_ATREQ_DATA_SIZE;
2037c478bd9Sstevel@tonic-gate 	qinfo.qi_mode = HCI1394_ATQ;
2047c478bd9Sstevel@tonic-gate 	qinfo.qi_start = hci1394_async_atreq_start;
2057c478bd9Sstevel@tonic-gate 	qinfo.qi_wake = hci1394_async_atreq_wake;
2067c478bd9Sstevel@tonic-gate 	qinfo.qi_callback_arg = async;
2077c478bd9Sstevel@tonic-gate 	status = hci1394_q_init(drvinfo, async->as_ohci, &qinfo,
2087c478bd9Sstevel@tonic-gate 	    &async->as_atreq_q);
2097c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
2107c478bd9Sstevel@tonic-gate 		mutex_destroy(&async->as_atomic_lookup);
2117c478bd9Sstevel@tonic-gate 		hci1394_tlist_fini(&async->as_pending_list);
2127c478bd9Sstevel@tonic-gate 		hci1394_tlabel_fini(&async->as_tlabel);
2137c478bd9Sstevel@tonic-gate 		kmem_free(async, sizeof (hci1394_async_t));
2147c478bd9Sstevel@tonic-gate 		*async_handle = NULL;
2157c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
2167c478bd9Sstevel@tonic-gate 	}
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate 	/* Initialize ARRESP Q */
2197c478bd9Sstevel@tonic-gate 	qinfo.qi_desc_size = ASYNC_ARRESP_DESC_SIZE;
2207c478bd9Sstevel@tonic-gate 	qinfo.qi_data_size = ASYNC_ARRESP_DATA_SIZE;
2217c478bd9Sstevel@tonic-gate 	qinfo.qi_mode = HCI1394_ARQ;
2227c478bd9Sstevel@tonic-gate 	qinfo.qi_start = hci1394_async_arresp_start;
2237c478bd9Sstevel@tonic-gate 	qinfo.qi_wake = hci1394_async_arresp_wake;
2247c478bd9Sstevel@tonic-gate 	qinfo.qi_callback_arg = async;
2257c478bd9Sstevel@tonic-gate 	status = hci1394_q_init(drvinfo, async->as_ohci, &qinfo,
2267c478bd9Sstevel@tonic-gate 	    &async->as_arresp_q);
2277c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
2287c478bd9Sstevel@tonic-gate 		mutex_destroy(&async->as_atomic_lookup);
2297c478bd9Sstevel@tonic-gate 		hci1394_tlist_fini(&async->as_pending_list);
2307c478bd9Sstevel@tonic-gate 		hci1394_tlabel_fini(&async->as_tlabel);
2317c478bd9Sstevel@tonic-gate 		hci1394_q_fini(&async->as_atreq_q);
2327c478bd9Sstevel@tonic-gate 		kmem_free(async, sizeof (hci1394_async_t));
2337c478bd9Sstevel@tonic-gate 		*async_handle = NULL;
2347c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
2357c478bd9Sstevel@tonic-gate 	}
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate 	/* Initialize ARREQ Q */
2387c478bd9Sstevel@tonic-gate 	qinfo.qi_desc_size = ASYNC_ARREQ_DESC_SIZE;
2397c478bd9Sstevel@tonic-gate 	qinfo.qi_data_size = ASYNC_ARREQ_DATA_SIZE;
2407c478bd9Sstevel@tonic-gate 	qinfo.qi_mode = HCI1394_ARQ;
2417c478bd9Sstevel@tonic-gate 	qinfo.qi_start = hci1394_async_arreq_start;
2427c478bd9Sstevel@tonic-gate 	qinfo.qi_wake = hci1394_async_arreq_wake;
2437c478bd9Sstevel@tonic-gate 	qinfo.qi_callback_arg = async;
2447c478bd9Sstevel@tonic-gate 	status = hci1394_q_init(drvinfo, async->as_ohci, &qinfo,
2457c478bd9Sstevel@tonic-gate 	    &async->as_arreq_q);
2467c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
2477c478bd9Sstevel@tonic-gate 		mutex_destroy(&async->as_atomic_lookup);
2487c478bd9Sstevel@tonic-gate 		hci1394_tlist_fini(&async->as_pending_list);
2497c478bd9Sstevel@tonic-gate 		hci1394_tlabel_fini(&async->as_tlabel);
2507c478bd9Sstevel@tonic-gate 		hci1394_q_fini(&async->as_atreq_q);
2517c478bd9Sstevel@tonic-gate 		hci1394_q_fini(&async->as_arresp_q);
2527c478bd9Sstevel@tonic-gate 		kmem_free(async, sizeof (hci1394_async_t));
2537c478bd9Sstevel@tonic-gate 		*async_handle = NULL;
2547c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
2557c478bd9Sstevel@tonic-gate 	}
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate 	/* Initialize ATRESP Q */
2587c478bd9Sstevel@tonic-gate 	qinfo.qi_desc_size = ASYNC_ATRESP_DESC_SIZE;
2597c478bd9Sstevel@tonic-gate 	qinfo.qi_data_size = ASYNC_ATRESP_DATA_SIZE;
2607c478bd9Sstevel@tonic-gate 	qinfo.qi_mode = HCI1394_ATQ;
2617c478bd9Sstevel@tonic-gate 	qinfo.qi_start = hci1394_async_atresp_start;
2627c478bd9Sstevel@tonic-gate 	qinfo.qi_wake = hci1394_async_atresp_wake;
2637c478bd9Sstevel@tonic-gate 	qinfo.qi_callback_arg = async;
2647c478bd9Sstevel@tonic-gate 	status = hci1394_q_init(drvinfo, async->as_ohci, &qinfo,
2657c478bd9Sstevel@tonic-gate 	    &async->as_atresp_q);
2667c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
2677c478bd9Sstevel@tonic-gate 		mutex_destroy(&async->as_atomic_lookup);
2687c478bd9Sstevel@tonic-gate 		hci1394_tlist_fini(&async->as_pending_list);
2697c478bd9Sstevel@tonic-gate 		hci1394_tlabel_fini(&async->as_tlabel);
2707c478bd9Sstevel@tonic-gate 		hci1394_q_fini(&async->as_atreq_q);
2717c478bd9Sstevel@tonic-gate 		hci1394_q_fini(&async->as_arresp_q);
2727c478bd9Sstevel@tonic-gate 		hci1394_q_fini(&async->as_arreq_q);
2737c478bd9Sstevel@tonic-gate 		kmem_free(async, sizeof (hci1394_async_t));
2747c478bd9Sstevel@tonic-gate 		*async_handle = NULL;
2757c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
2767c478bd9Sstevel@tonic-gate 	}
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate 	*async_handle = async;
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
2817c478bd9Sstevel@tonic-gate }
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate 
2847c478bd9Sstevel@tonic-gate /*
2857c478bd9Sstevel@tonic-gate  * hci1394_async_fini()
2867c478bd9Sstevel@tonic-gate  *    Free's up the space allocated in init().  Notice that a pointer to the
2877c478bd9Sstevel@tonic-gate  *    handle is used for the parameter.  fini() will set your handle to NULL
2887c478bd9Sstevel@tonic-gate  *    before returning.
2897c478bd9Sstevel@tonic-gate  */
2907c478bd9Sstevel@tonic-gate void
hci1394_async_fini(hci1394_async_handle_t * async_handle)2917c478bd9Sstevel@tonic-gate hci1394_async_fini(hci1394_async_handle_t *async_handle)
2927c478bd9Sstevel@tonic-gate {
2937c478bd9Sstevel@tonic-gate 	hci1394_async_t *async;
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate 
2967c478bd9Sstevel@tonic-gate 	ASSERT(async_handle != NULL);
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate 	async = (hci1394_async_t *)*async_handle;
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate 	mutex_destroy(&async->as_atomic_lookup);
3017c478bd9Sstevel@tonic-gate 	hci1394_tlabel_fini(&async->as_tlabel);
3027c478bd9Sstevel@tonic-gate 	hci1394_tlist_fini(&async->as_pending_list);
3037c478bd9Sstevel@tonic-gate 	hci1394_q_fini(&async->as_atreq_q);
3047c478bd9Sstevel@tonic-gate 	hci1394_q_fini(&async->as_atresp_q);
3057c478bd9Sstevel@tonic-gate 	hci1394_q_fini(&async->as_arreq_q);
3067c478bd9Sstevel@tonic-gate 	hci1394_q_fini(&async->as_arresp_q);
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate 	kmem_free(async, sizeof (hci1394_async_t));
3097c478bd9Sstevel@tonic-gate 
3107c478bd9Sstevel@tonic-gate 	/* set handle to null.  This helps catch bugs. */
3117c478bd9Sstevel@tonic-gate 	*async_handle = NULL;
3127c478bd9Sstevel@tonic-gate }
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate /*
3167c478bd9Sstevel@tonic-gate  * hci1394_async_suspend()
3177c478bd9Sstevel@tonic-gate  *    The system is getting ready to be suspended.  Make sure that all of
3187c478bd9Sstevel@tonic-gate  *    the Q's are clean and that the there are no scheduled timeouts in the
3197c478bd9Sstevel@tonic-gate  *    pending Q.
3207c478bd9Sstevel@tonic-gate  */
3217c478bd9Sstevel@tonic-gate void
hci1394_async_suspend(hci1394_async_handle_t async_handle)3227c478bd9Sstevel@tonic-gate hci1394_async_suspend(hci1394_async_handle_t async_handle)
3237c478bd9Sstevel@tonic-gate {
3247c478bd9Sstevel@tonic-gate 	ASSERT(async_handle != NULL);
3257c478bd9Sstevel@tonic-gate 
3267c478bd9Sstevel@tonic-gate 	/* Flush out async DMA Q's */
3277c478bd9Sstevel@tonic-gate 	hci1394_async_flush(async_handle);
3287c478bd9Sstevel@tonic-gate 
3297c478bd9Sstevel@tonic-gate 	/* Cancel any scheduled pending timeouts */
3307c478bd9Sstevel@tonic-gate 	hci1394_tlist_timeout_cancel(async_handle->as_pending_list);
3317c478bd9Sstevel@tonic-gate }
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate /*
3357c478bd9Sstevel@tonic-gate  * hci1394_async_resume()
3367c478bd9Sstevel@tonic-gate  *    Re-setup the DMA Q's during a resume after a successful suspend. The
3377c478bd9Sstevel@tonic-gate  *    tlabels will be re-initialized during the bus reset and the pending Q will
3387c478bd9Sstevel@tonic-gate  *    be flushed during the suspend.
3397c478bd9Sstevel@tonic-gate  */
3407c478bd9Sstevel@tonic-gate int
hci1394_async_resume(hci1394_async_handle_t async_handle)3417c478bd9Sstevel@tonic-gate hci1394_async_resume(hci1394_async_handle_t async_handle)
3427c478bd9Sstevel@tonic-gate {
3437c478bd9Sstevel@tonic-gate 	ASSERT(async_handle != NULL);
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate 	hci1394_q_resume(async_handle->as_atreq_q);
3467c478bd9Sstevel@tonic-gate 	hci1394_q_resume(async_handle->as_atresp_q);
3477c478bd9Sstevel@tonic-gate 	hci1394_q_resume(async_handle->as_arreq_q);
3487c478bd9Sstevel@tonic-gate 	hci1394_q_resume(async_handle->as_arresp_q);
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
3517c478bd9Sstevel@tonic-gate }
3527c478bd9Sstevel@tonic-gate 
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate /*
3557c478bd9Sstevel@tonic-gate  * hci1394_async_cmd_overhead()
3567c478bd9Sstevel@tonic-gate  *    Return the size of the HAL private area to attach to every alloced 1394
3577c478bd9Sstevel@tonic-gate  *    framework command.  This allows us to track command state without having
3587c478bd9Sstevel@tonic-gate  *    to alloc memory every time a command comes down the pipe.
3597c478bd9Sstevel@tonic-gate  */
3607c478bd9Sstevel@tonic-gate uint_t
hci1394_async_cmd_overhead()3617c478bd9Sstevel@tonic-gate hci1394_async_cmd_overhead()
3627c478bd9Sstevel@tonic-gate {
3637c478bd9Sstevel@tonic-gate 	return (sizeof (hci1394_async_cmd_t));
3647c478bd9Sstevel@tonic-gate }
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate /*
3687c478bd9Sstevel@tonic-gate  * hci1394_async_flush()
3697c478bd9Sstevel@tonic-gate  *    Flush out the Async Q's and the ATREQ pending list.  This is called every
3707c478bd9Sstevel@tonic-gate  *    bus reset so that we're sync'd up with the HW and when shutting down or
3717c478bd9Sstevel@tonic-gate  *    suspending to make sure we cleanup after all commands.
3727c478bd9Sstevel@tonic-gate  */
3737c478bd9Sstevel@tonic-gate void
hci1394_async_flush(hci1394_async_handle_t async_handle)3747c478bd9Sstevel@tonic-gate hci1394_async_flush(hci1394_async_handle_t async_handle)
3757c478bd9Sstevel@tonic-gate {
3767c478bd9Sstevel@tonic-gate 	ASSERT(async_handle != NULL);
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate 	hci1394_async_atreq_flush(async_handle);
3797c478bd9Sstevel@tonic-gate 	hci1394_async_arresp_flush(async_handle);
3807c478bd9Sstevel@tonic-gate 	hci1394_async_pending_list_flush(async_handle);
3817c478bd9Sstevel@tonic-gate 	hci1394_async_arreq_flush(async_handle);
3827c478bd9Sstevel@tonic-gate 	hci1394_async_atresp_flush(async_handle);
3837c478bd9Sstevel@tonic-gate 	hci1394_tlabel_reset(async_handle->as_tlabel);
3847c478bd9Sstevel@tonic-gate }
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate /*
3887c478bd9Sstevel@tonic-gate  * hci1394_async_pending_timeout_update()
3897c478bd9Sstevel@tonic-gate  *    Update the timeout for the pending list. This updates both the pending
3907c478bd9Sstevel@tonic-gate  *    list timeout and time we wait to reclaim  bad tlabels.  timeout is the
3917c478bd9Sstevel@tonic-gate  *    time in nS so we do not have to do any conversions. This routine will be
3927c478bd9Sstevel@tonic-gate  *    called when the CSR split timeout registers are updated.
3937c478bd9Sstevel@tonic-gate  */
3947c478bd9Sstevel@tonic-gate void
hci1394_async_pending_timeout_update(hci1394_async_handle_t async_handle,hrtime_t timeout)3957c478bd9Sstevel@tonic-gate hci1394_async_pending_timeout_update(hci1394_async_handle_t async_handle,
3967c478bd9Sstevel@tonic-gate     hrtime_t timeout)
3977c478bd9Sstevel@tonic-gate {
3987c478bd9Sstevel@tonic-gate 	ASSERT(async_handle != NULL);
3997c478bd9Sstevel@tonic-gate 	hci1394_tlist_timeout_update(async_handle->as_pending_list, timeout);
4007c478bd9Sstevel@tonic-gate 	hci1394_tlabel_set_reclaim_time(async_handle->as_tlabel, timeout);
4017c478bd9Sstevel@tonic-gate }
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate /*
4057c478bd9Sstevel@tonic-gate  * hci1394_async_atreq_process()
4067c478bd9Sstevel@tonic-gate  *    Process an atreq, if one has completed. This is called during interrupt
4077c478bd9Sstevel@tonic-gate  *    processing and will process a completed atreq. It returns status if an
4087c478bd9Sstevel@tonic-gate  *    atreq was processed so that the ISR knows that it needs to be called
4097c478bd9Sstevel@tonic-gate  *    again to see if another ATREQ has completed. flush_q set to B_TRUE tells
4107c478bd9Sstevel@tonic-gate  *    this routine to process all commands regardless of their completion
4117c478bd9Sstevel@tonic-gate  *    status.  This is used during bus reset processing to remove all commands
4127c478bd9Sstevel@tonic-gate  *    from the Q.
4137c478bd9Sstevel@tonic-gate  *
4147c478bd9Sstevel@tonic-gate  *    There are a few race conditions that we have to watch for in atreq/arresp.
4157c478bd9Sstevel@tonic-gate  *    They all have to do with pended responses so they are not applicable in
4167c478bd9Sstevel@tonic-gate  *    the ARREQ/ATRESP engine (since ATRESP's can't be pended).
4177c478bd9Sstevel@tonic-gate  *
4187c478bd9Sstevel@tonic-gate  *    Since the race conditions only exist for pended responses, we will only
4197c478bd9Sstevel@tonic-gate  *    talk about that sequence here. We're also going to simplify the discussion
4207c478bd9Sstevel@tonic-gate  *    so what the code does, so it won't exactly match what we say (e.g. we
4217c478bd9Sstevel@tonic-gate  *    don't always setup a timeout for every single command, etc.)
4227c478bd9Sstevel@tonic-gate  *
4237c478bd9Sstevel@tonic-gate  *    After Q'ing up an ATREQ, we will process the result of that command in
4247c478bd9Sstevel@tonic-gate  *    one of a couple different paths. A normal condition would be that we Q up
4257c478bd9Sstevel@tonic-gate  *    a command, we get an ATREQ complete interrupt and look at the ATREQ
4267c478bd9Sstevel@tonic-gate  *    result. In the case it has been pended, we setup a timeout to wait for the
4277c478bd9Sstevel@tonic-gate  *    response. If we receive the response before the timeout, the command is
4287c478bd9Sstevel@tonic-gate  *    done and we send the response up the chain, if we do not, the command is
4297c478bd9Sstevel@tonic-gate  *    done and we send a timeout notification up the chain.
4307c478bd9Sstevel@tonic-gate  *
4317c478bd9Sstevel@tonic-gate  *    The first race condition is when we get the timeout at the same time as
4327c478bd9Sstevel@tonic-gate  *    the response. At first glance a mutex around the command state would
4337c478bd9Sstevel@tonic-gate  *    solve this problem. But on a multi-processor machine, we may have the
4347c478bd9Sstevel@tonic-gate  *    ARRESP interrupt handler(ISR) running on one processor and the timeout on
4357c478bd9Sstevel@tonic-gate  *    another. This means that the command state could change between two
4367c478bd9Sstevel@tonic-gate  *    reads while in the ISR. This means we need to have a little more complex
4377c478bd9Sstevel@tonic-gate  *    logic around changing the command state and have to be careful how and
4387c478bd9Sstevel@tonic-gate  *    when we do this.
4397c478bd9Sstevel@tonic-gate  *
4407c478bd9Sstevel@tonic-gate  *    The second race condition is that we could see the ARRESP before we
4417c478bd9Sstevel@tonic-gate  *    process the ATREQ. We could be processing a few ARRESP from previous
4427c478bd9Sstevel@tonic-gate  *    ATREQ's when the ATREQ completes and then the ARRESP comes in.  Since we
4437c478bd9Sstevel@tonic-gate  *    already are in the interrupt handler, the ATREQ complete will not preempt
4447c478bd9Sstevel@tonic-gate  *    us.
4457c478bd9Sstevel@tonic-gate  *
4467c478bd9Sstevel@tonic-gate  *    We will never see a race condition between the ATREQ interrupt for a
4477c478bd9Sstevel@tonic-gate  *    command and the pending timeout since the command is not being timed until
4487c478bd9Sstevel@tonic-gate  *    this routine is run for that command.
4497c478bd9Sstevel@tonic-gate  */
4507c478bd9Sstevel@tonic-gate int
hci1394_async_atreq_process(hci1394_async_handle_t async_handle,boolean_t flush_q,boolean_t * request_available)4517c478bd9Sstevel@tonic-gate hci1394_async_atreq_process(hci1394_async_handle_t async_handle,
4527c478bd9Sstevel@tonic-gate     boolean_t flush_q, boolean_t *request_available)
4537c478bd9Sstevel@tonic-gate {
4547c478bd9Sstevel@tonic-gate 	hci1394_async_cmd_t *hcicmd;
4557c478bd9Sstevel@tonic-gate 	hci1394_q_cmd_t *qcmd;
4567c478bd9Sstevel@tonic-gate 	int cmd_status;
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate 
4597c478bd9Sstevel@tonic-gate 	ASSERT(async_handle != NULL);
4607c478bd9Sstevel@tonic-gate 	ASSERT(request_available != NULL);
4617c478bd9Sstevel@tonic-gate 
4627c478bd9Sstevel@tonic-gate 	/*
4637c478bd9Sstevel@tonic-gate 	 * Get the next ATREQ that has completed (if one has). Space is free'd
4647c478bd9Sstevel@tonic-gate 	 * up in atreq_q and atreq_data_q as part of this function call.
4657c478bd9Sstevel@tonic-gate 	 */
4667c478bd9Sstevel@tonic-gate 	hci1394_q_at_next(async_handle->as_atreq_q, flush_q, &qcmd);
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate 	/*
4697c478bd9Sstevel@tonic-gate 	 * See if there were anymore requests on ATREQ Q. A NULL means there
4707c478bd9Sstevel@tonic-gate 	 * were no completed commands left on the Q
4717c478bd9Sstevel@tonic-gate 	 */
4727c478bd9Sstevel@tonic-gate 	if (qcmd == NULL) {
4737c478bd9Sstevel@tonic-gate 		*request_available = B_FALSE;
4747c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
4757c478bd9Sstevel@tonic-gate 	}
4767c478bd9Sstevel@tonic-gate 
4777c478bd9Sstevel@tonic-gate 	/* There is a completed ATREQ, setup the HAL command pointer */
4787c478bd9Sstevel@tonic-gate 	*request_available = B_TRUE;
4797c478bd9Sstevel@tonic-gate 	hcicmd = (hci1394_async_cmd_t *)qcmd->qc_arg;
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 	/* save away the command completed timestamp for the services layer */
4827c478bd9Sstevel@tonic-gate 	hcicmd->ac_priv->ack_tstamp = qcmd->qc_timestamp;
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate 	/*
4857c478bd9Sstevel@tonic-gate 	 * Make sure this command has not already been processed. This command
4867c478bd9Sstevel@tonic-gate 	 * may have already received a response.  If the ACK was not an ACK
4877c478bd9Sstevel@tonic-gate 	 * pending, we have a HW error (i.e. The target HW sent a response to a
4887c478bd9Sstevel@tonic-gate 	 * non-pended request). There is a race condition where the software
4897c478bd9Sstevel@tonic-gate 	 * will see and complete a response before processing it's ACK Pending.
4907c478bd9Sstevel@tonic-gate 	 * This can only happen for ACK pendings. We have seen this race
4917c478bd9Sstevel@tonic-gate 	 * condition and response to a non-pended request during real-world
4927c478bd9Sstevel@tonic-gate 	 * testing :-)
4937c478bd9Sstevel@tonic-gate 	 */
4947c478bd9Sstevel@tonic-gate 	if (hcicmd->ac_state != HCI1394_CMD_STATE_IN_PROGRESS) {
4957c478bd9Sstevel@tonic-gate 		/*
4967c478bd9Sstevel@tonic-gate 		 * we already processed the ARRESP in arresp_process(), it
4977c478bd9Sstevel@tonic-gate 		 * better have been ACK pended. Otherwise the target device
4987c478bd9Sstevel@tonic-gate 		 * performed an illegal action.
4997c478bd9Sstevel@tonic-gate 		 */
5007c478bd9Sstevel@tonic-gate 		if (qcmd->qc_status == OHCI_ACK_PENDING) {
5017c478bd9Sstevel@tonic-gate 			/*
5027c478bd9Sstevel@tonic-gate 			 * Tell source that their command has completed. We're
5037c478bd9Sstevel@tonic-gate 			 * done with this command.
5047c478bd9Sstevel@tonic-gate 			 * NOTE: We use ac_status which was set in
5057c478bd9Sstevel@tonic-gate 			 * process_arresp()
5067c478bd9Sstevel@tonic-gate 			 */
5077c478bd9Sstevel@tonic-gate 			h1394_cmd_is_complete(
5087c478bd9Sstevel@tonic-gate 			    async_handle->as_drvinfo->di_sl_private,
5097c478bd9Sstevel@tonic-gate 			    hcicmd->ac_cmd, H1394_AT_REQ,
5107c478bd9Sstevel@tonic-gate 			    hcicmd->ac_status);
5117c478bd9Sstevel@tonic-gate 			return (DDI_SUCCESS);
5127c478bd9Sstevel@tonic-gate 		/*
5137c478bd9Sstevel@tonic-gate 		 * This is a HW error.  Process the ACK like we never saw the
5147c478bd9Sstevel@tonic-gate 		 * response. We will do this below.
5157c478bd9Sstevel@tonic-gate 		 */
5167c478bd9Sstevel@tonic-gate 		}
5177c478bd9Sstevel@tonic-gate 	}
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate 	/*
5207c478bd9Sstevel@tonic-gate 	 * if we got an ack pending, add it to the pending list and leave. We
5217c478bd9Sstevel@tonic-gate 	 * will either get an ARRESP or the pending list will timeout the
5227c478bd9Sstevel@tonic-gate 	 * response.
5237c478bd9Sstevel@tonic-gate 	 */
5247c478bd9Sstevel@tonic-gate 	if (qcmd->qc_status == OHCI_ACK_PENDING) {
5257c478bd9Sstevel@tonic-gate 		hcicmd->ac_state = HCI1394_CMD_STATE_PENDING;
5267c478bd9Sstevel@tonic-gate 		/* Add this command to the pending list */
5277c478bd9Sstevel@tonic-gate 		hcicmd->ac_plist_node.tln_addr = hcicmd;
5287c478bd9Sstevel@tonic-gate 		hci1394_tlist_add(async_handle->as_pending_list,
5297c478bd9Sstevel@tonic-gate 		    &hcicmd->ac_plist_node);
5307c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
5317c478bd9Sstevel@tonic-gate 	}
5327c478bd9Sstevel@tonic-gate 
5337c478bd9Sstevel@tonic-gate 	/*
5347c478bd9Sstevel@tonic-gate 	 * setup our return command status based on the ACK from the HW. See the
5357c478bd9Sstevel@tonic-gate 	 * OpenHCI 1.0 spec (table 3.2 on pg. 18) for more information about
5367c478bd9Sstevel@tonic-gate 	 * these ACK/EVT's.
5377c478bd9Sstevel@tonic-gate 	 */
5387c478bd9Sstevel@tonic-gate 	switch (qcmd->qc_status) {
5397c478bd9Sstevel@tonic-gate 	case OHCI_ACK_COMPLETE:
5407c478bd9Sstevel@tonic-gate 		cmd_status = H1394_CMD_SUCCESS;
5417c478bd9Sstevel@tonic-gate 		break;
5427c478bd9Sstevel@tonic-gate 
5437c478bd9Sstevel@tonic-gate 	/*
5447c478bd9Sstevel@tonic-gate 	 * we can get a nostatus during a bus reset (i.e. we shutdown the AT
5457c478bd9Sstevel@tonic-gate 	 * engine before it flushed all the commands)
5467c478bd9Sstevel@tonic-gate 	 */
5477c478bd9Sstevel@tonic-gate 	case OHCI_EVT_FLUSHED:
5487c478bd9Sstevel@tonic-gate 	case OHCI_EVT_NO_STATUS:
5497c478bd9Sstevel@tonic-gate 		cmd_status = H1394_CMD_EBUSRESET;
5507c478bd9Sstevel@tonic-gate 		break;
5517c478bd9Sstevel@tonic-gate 
5527c478bd9Sstevel@tonic-gate 	case OHCI_EVT_MISSING_ACK:
5537c478bd9Sstevel@tonic-gate 	case OHCI_EVT_TIMEOUT:
5547c478bd9Sstevel@tonic-gate 		cmd_status = H1394_CMD_ETIMEOUT;
5557c478bd9Sstevel@tonic-gate 		break;
5567c478bd9Sstevel@tonic-gate 
5577c478bd9Sstevel@tonic-gate 	case OHCI_ACK_BUSY_X:
5587c478bd9Sstevel@tonic-gate 	case OHCI_ACK_BUSY_A:
5597c478bd9Sstevel@tonic-gate 	case OHCI_ACK_BUSY_B:
5607c478bd9Sstevel@tonic-gate 		cmd_status = H1394_CMD_EDEVICE_BUSY;
5617c478bd9Sstevel@tonic-gate 		break;
5627c478bd9Sstevel@tonic-gate 
5637c478bd9Sstevel@tonic-gate 	case OHCI_ACK_TARDY:
5647c478bd9Sstevel@tonic-gate 		cmd_status = H1394_CMD_EDEVICE_POWERUP;
5657c478bd9Sstevel@tonic-gate 		break;
5667c478bd9Sstevel@tonic-gate 
5677c478bd9Sstevel@tonic-gate 	case OHCI_ACK_DATA_ERROR:
5687c478bd9Sstevel@tonic-gate 		cmd_status = H1394_CMD_EDATA_ERROR;
5697c478bd9Sstevel@tonic-gate 		break;
5707c478bd9Sstevel@tonic-gate 
5717c478bd9Sstevel@tonic-gate 	case OHCI_ACK_TYPE_ERROR:
5727c478bd9Sstevel@tonic-gate 		cmd_status = H1394_CMD_ETYPE_ERROR;
5737c478bd9Sstevel@tonic-gate 		break;
5747c478bd9Sstevel@tonic-gate 
5757c478bd9Sstevel@tonic-gate 	case OHCI_ACK_CONFLICT_ERROR:
5767c478bd9Sstevel@tonic-gate 		cmd_status = H1394_CMD_ERSRC_CONFLICT;
5777c478bd9Sstevel@tonic-gate 		break;
5787c478bd9Sstevel@tonic-gate 
5797c478bd9Sstevel@tonic-gate 	case OHCI_ACK_ADDRESS_ERROR:
5807c478bd9Sstevel@tonic-gate 		cmd_status = H1394_CMD_EADDR_ERROR;
5817c478bd9Sstevel@tonic-gate 		break;
5827c478bd9Sstevel@tonic-gate 
5837c478bd9Sstevel@tonic-gate 	case OHCI_EVT_UNDERRUN:
5847c478bd9Sstevel@tonic-gate 	case OHCI_EVT_DATA_READ:
5857c478bd9Sstevel@tonic-gate 	case OHCI_EVT_TCODE_ERR:
5867c478bd9Sstevel@tonic-gate 	case OHCI_EVT_DESCRIPTOR_READ:
5877c478bd9Sstevel@tonic-gate 	case OHCI_EVT_UNKNOWN:
5887c478bd9Sstevel@tonic-gate 	default:
5897c478bd9Sstevel@tonic-gate 		cmd_status = H1394_CMD_EUNKNOWN_ERROR;
5907c478bd9Sstevel@tonic-gate 		break;
5917c478bd9Sstevel@tonic-gate 	}
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate 	/*
5947c478bd9Sstevel@tonic-gate 	 * Free the tlabel that was used for this transfer. We will not try and
5957c478bd9Sstevel@tonic-gate 	 * free the tlabel in the case that we already received a response or if
5967c478bd9Sstevel@tonic-gate 	 * we did not allocate one (PHY packet). If we already received a
5977c478bd9Sstevel@tonic-gate 	 * response, the tlabel would have been free'd in
5987c478bd9Sstevel@tonic-gate 	 * hci1394_async_arresp_process().
5997c478bd9Sstevel@tonic-gate 	 */
6007c478bd9Sstevel@tonic-gate 	if ((hcicmd->ac_state == HCI1394_CMD_STATE_IN_PROGRESS) &&
6017c478bd9Sstevel@tonic-gate 	    (hcicmd->ac_tlabel_alloc == B_TRUE)) {
6027c478bd9Sstevel@tonic-gate 		hci1394_tlabel_free(async_handle->as_tlabel,
6037c478bd9Sstevel@tonic-gate 		    &hcicmd->ac_tlabel);
6047c478bd9Sstevel@tonic-gate 	}
6057c478bd9Sstevel@tonic-gate 
6067c478bd9Sstevel@tonic-gate 	/*
6077c478bd9Sstevel@tonic-gate 	 * if we got anything other than and ACK pending, we are done w/ this
6087c478bd9Sstevel@tonic-gate 	 * transaction.
6097c478bd9Sstevel@tonic-gate 	 */
6107c478bd9Sstevel@tonic-gate 	hcicmd->ac_state = HCI1394_CMD_STATE_COMPLETED;
6117c478bd9Sstevel@tonic-gate 
6127c478bd9Sstevel@tonic-gate 	/* tell the services layer that the command has completed */
6137c478bd9Sstevel@tonic-gate 	h1394_cmd_is_complete(async_handle->as_drvinfo->di_sl_private,
6147c478bd9Sstevel@tonic-gate 	    hcicmd->ac_cmd, H1394_AT_REQ, cmd_status);
6157c478bd9Sstevel@tonic-gate 
6167c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
6177c478bd9Sstevel@tonic-gate }
6187c478bd9Sstevel@tonic-gate 
6197c478bd9Sstevel@tonic-gate 
6207c478bd9Sstevel@tonic-gate /*
6217c478bd9Sstevel@tonic-gate  * hci1394_async_arresp_process()
6227c478bd9Sstevel@tonic-gate  *    Process an arresp, if one has completed. This is called during interrupt
6237c478bd9Sstevel@tonic-gate  *    processing and will process a completed arresp. It returns status if an
6247c478bd9Sstevel@tonic-gate  *    arresp was processed so that the ISR knows that it needs to be called
6257c478bd9Sstevel@tonic-gate  *    again to see if another ARRESP has completed.
6267c478bd9Sstevel@tonic-gate  */
6277c478bd9Sstevel@tonic-gate int
hci1394_async_arresp_process(hci1394_async_handle_t async_handle,boolean_t * response_available)6287c478bd9Sstevel@tonic-gate hci1394_async_arresp_process(hci1394_async_handle_t async_handle,
6297c478bd9Sstevel@tonic-gate     boolean_t *response_available)
6307c478bd9Sstevel@tonic-gate {
6317c478bd9Sstevel@tonic-gate 	hci1394_async_cmd_t *hcicmd;
6327c478bd9Sstevel@tonic-gate 	uint32_t *addr;
6337c478bd9Sstevel@tonic-gate 	int cmd_status;
6347c478bd9Sstevel@tonic-gate 	uint_t tcode;
6357c478bd9Sstevel@tonic-gate 	uint_t size;
6367c478bd9Sstevel@tonic-gate 	int status;
6377c478bd9Sstevel@tonic-gate 
6387c478bd9Sstevel@tonic-gate 
6397c478bd9Sstevel@tonic-gate 	ASSERT(async_handle != NULL);
6407c478bd9Sstevel@tonic-gate 	ASSERT(response_available != NULL);
6417c478bd9Sstevel@tonic-gate 
6427c478bd9Sstevel@tonic-gate 	/*
6437c478bd9Sstevel@tonic-gate 	 * See if there were any responses on ARRESP Q. A NULL means there
6447c478bd9Sstevel@tonic-gate 	 * were no responses on the Q. This call does NOT free up space. We
6457c478bd9Sstevel@tonic-gate 	 * need to do that later after we figure out how much space the
6467c478bd9Sstevel@tonic-gate 	 * response takes up.
6477c478bd9Sstevel@tonic-gate 	 */
6487c478bd9Sstevel@tonic-gate 	hci1394_q_ar_next(async_handle->as_arresp_q, &addr);
6497c478bd9Sstevel@tonic-gate 	if (addr == NULL) {
6507c478bd9Sstevel@tonic-gate 		*response_available = B_FALSE;
6517c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
6527c478bd9Sstevel@tonic-gate 	}
6537c478bd9Sstevel@tonic-gate 
6547c478bd9Sstevel@tonic-gate 	/*
6557c478bd9Sstevel@tonic-gate 	 * We got a response. Lock out pending timeout callback from marking
6567c478bd9Sstevel@tonic-gate 	 * tlabel bad.
6577c478bd9Sstevel@tonic-gate 	 */
6587c478bd9Sstevel@tonic-gate 	*response_available = B_TRUE;
6597c478bd9Sstevel@tonic-gate 	mutex_enter(&async_handle->as_atomic_lookup);
6607c478bd9Sstevel@tonic-gate 
6617c478bd9Sstevel@tonic-gate 	/*
6627c478bd9Sstevel@tonic-gate 	 * Read in the response into the 1394 framework command. We could get a
6637c478bd9Sstevel@tonic-gate 	 * NULL for a command if we got a response with an error (i.e. tlabel
6647c478bd9Sstevel@tonic-gate 	 * that didn't match a request) This would be a successful read but with
6657c478bd9Sstevel@tonic-gate 	 * a NULL hcicmd returned. If we ever get a DDI_FAILURE, we will
6667c478bd9Sstevel@tonic-gate 	 * shutdown.
6677c478bd9Sstevel@tonic-gate 	 */
6687c478bd9Sstevel@tonic-gate 	status = hci1394_async_arresp_read(async_handle,
6697c478bd9Sstevel@tonic-gate 	    (hci1394_basic_pkt_t *)addr, &tcode, &hcicmd, &size);
6707c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
6717c478bd9Sstevel@tonic-gate 		mutex_exit(&async_handle->as_atomic_lookup);
6727c478bd9Sstevel@tonic-gate 		h1394_error_detected(async_handle->as_drvinfo->di_sl_private,
6737c478bd9Sstevel@tonic-gate 		    H1394_SELF_INITIATED_SHUTDOWN, NULL);
6747c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "hci1394(%d): driver shutdown: "
6757c478bd9Sstevel@tonic-gate 		    "unrecoverable error interrupt detected",
6767c478bd9Sstevel@tonic-gate 		    async_handle->as_drvinfo->di_instance);
6777c478bd9Sstevel@tonic-gate 		hci1394_shutdown(async_handle->as_drvinfo->di_dip);
6787c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
6797c478bd9Sstevel@tonic-gate 	}
6807c478bd9Sstevel@tonic-gate 
6817c478bd9Sstevel@tonic-gate 	/* Free up the arresp Q space, we are done with the data */
6827c478bd9Sstevel@tonic-gate 	hci1394_q_ar_free(async_handle->as_arresp_q, size);
6837c478bd9Sstevel@tonic-gate 
6847c478bd9Sstevel@tonic-gate 	/*
6857c478bd9Sstevel@tonic-gate 	 * if we did not get a valid command response (i.e. we got a bad tlabel
6867c478bd9Sstevel@tonic-gate 	 * or something like that) we don't have anything else to do.  We will
6877c478bd9Sstevel@tonic-gate 	 * say that we processed a response and will return successfully. We
6887c478bd9Sstevel@tonic-gate 	 * still may have other responses on the Q.
6897c478bd9Sstevel@tonic-gate 	 */
6907c478bd9Sstevel@tonic-gate 	if (hcicmd == NULL) {
6917c478bd9Sstevel@tonic-gate 		mutex_exit(&async_handle->as_atomic_lookup);
6927c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
6937c478bd9Sstevel@tonic-gate 	}
6947c478bd9Sstevel@tonic-gate 
6957c478bd9Sstevel@tonic-gate 	/*
6967c478bd9Sstevel@tonic-gate 	 * Make sure this is in the pending list. There is a small chance that
6977c478bd9Sstevel@tonic-gate 	 * we will see the response before we see the ACK PENDING. If it is the
6987c478bd9Sstevel@tonic-gate 	 * expected case, it is in the pending list.  We will remove it since
6997c478bd9Sstevel@tonic-gate 	 * we are done with the command.
7007c478bd9Sstevel@tonic-gate 	 *
7017c478bd9Sstevel@tonic-gate 	 * NOTE: there is a race condition here with the pending timeout.  Look
7027c478bd9Sstevel@tonic-gate 	 * at the comments before hci1394_async_atreq_process() for more info.
7037c478bd9Sstevel@tonic-gate 	 */
7047c478bd9Sstevel@tonic-gate 	if (hcicmd->ac_state == HCI1394_CMD_STATE_PENDING) {
7057c478bd9Sstevel@tonic-gate 		/* remove this transfer from our the pending list */
7067c478bd9Sstevel@tonic-gate 		status = hci1394_tlist_delete(async_handle->as_pending_list,
7077c478bd9Sstevel@tonic-gate 		    &hcicmd->ac_plist_node);
7087c478bd9Sstevel@tonic-gate 		if (status != DDI_SUCCESS) {
7097c478bd9Sstevel@tonic-gate 			mutex_exit(&async_handle->as_atomic_lookup);
7107c478bd9Sstevel@tonic-gate 			return (DDI_SUCCESS);
7117c478bd9Sstevel@tonic-gate 		}
7127c478bd9Sstevel@tonic-gate 	}
7137c478bd9Sstevel@tonic-gate 
7147c478bd9Sstevel@tonic-gate 	/* allow pending timeout callback to mark tlabel as bad */
7157c478bd9Sstevel@tonic-gate 	mutex_exit(&async_handle->as_atomic_lookup);
7167c478bd9Sstevel@tonic-gate 
7177c478bd9Sstevel@tonic-gate 	/*
7187c478bd9Sstevel@tonic-gate 	 * We got a valid response that we were able to read in. Free the tlabel
7197c478bd9Sstevel@tonic-gate 	 * that was used for this transfer.
7207c478bd9Sstevel@tonic-gate 	 */
7217c478bd9Sstevel@tonic-gate 	hci1394_tlabel_free(async_handle->as_tlabel, &hcicmd->ac_tlabel);
7227c478bd9Sstevel@tonic-gate 
7237c478bd9Sstevel@tonic-gate 	/*
7247c478bd9Sstevel@tonic-gate 	 * Setup our return command status based on the RESP or ACK or SW error.
7257c478bd9Sstevel@tonic-gate 	 * See the IEEE1394-1995 spec (6.2.4.10 on pg. 159) for more information
7267c478bd9Sstevel@tonic-gate 	 * on response codes. See the OpenHCI 1.0 spec (table 3.2 on pg. 18) for
7277c478bd9Sstevel@tonic-gate 	 * more information about ACK/EVT's. ac_status could have an IEEE1394
7287c478bd9Sstevel@tonic-gate 	 * response in it, a 1394 EVT/ACK, or a special cmd1394 error for a
7297c478bd9Sstevel@tonic-gate 	 * device error caught in SW (e.g. for a block read request that got a
7307c478bd9Sstevel@tonic-gate 	 * quadlet read response). We use a special mask to separate the
7317c478bd9Sstevel@tonic-gate 	 * ACK/EVT's from the responses (ASYNC_ARRESP_ACK_ERROR).
7327c478bd9Sstevel@tonic-gate 	 */
7337c478bd9Sstevel@tonic-gate 	switch (hcicmd->ac_status) {
7347c478bd9Sstevel@tonic-gate 	case IEEE1394_RESP_COMPLETE:
7357c478bd9Sstevel@tonic-gate 		cmd_status = H1394_CMD_SUCCESS;
7367c478bd9Sstevel@tonic-gate 		break;
7377c478bd9Sstevel@tonic-gate 	case IEEE1394_RESP_DATA_ERROR:
7387c478bd9Sstevel@tonic-gate 		cmd_status = H1394_CMD_EDATA_ERROR;
7397c478bd9Sstevel@tonic-gate 		break;
7407c478bd9Sstevel@tonic-gate 	case IEEE1394_RESP_TYPE_ERROR:
7417c478bd9Sstevel@tonic-gate 		cmd_status = H1394_CMD_ETYPE_ERROR;
7427c478bd9Sstevel@tonic-gate 		break;
7437c478bd9Sstevel@tonic-gate 	case IEEE1394_RESP_CONFLICT_ERROR:
7447c478bd9Sstevel@tonic-gate 		cmd_status = H1394_CMD_ERSRC_CONFLICT;
7457c478bd9Sstevel@tonic-gate 		break;
7467c478bd9Sstevel@tonic-gate 	case IEEE1394_RESP_ADDRESS_ERROR:
7477c478bd9Sstevel@tonic-gate 		cmd_status = H1394_CMD_EADDR_ERROR;
7487c478bd9Sstevel@tonic-gate 		break;
7497c478bd9Sstevel@tonic-gate 	case H1394_CMD_EDEVICE_ERROR:
7507c478bd9Sstevel@tonic-gate 		cmd_status = H1394_CMD_EDEVICE_ERROR;
7517c478bd9Sstevel@tonic-gate 		break;
7527c478bd9Sstevel@tonic-gate 	case OHCI_ACK_DATA_ERROR | ASYNC_ARRESP_ACK_ERROR:
7537c478bd9Sstevel@tonic-gate 		cmd_status = H1394_CMD_EDATA_ERROR;
7547c478bd9Sstevel@tonic-gate 		break;
7557c478bd9Sstevel@tonic-gate 	case OHCI_ACK_TYPE_ERROR | ASYNC_ARRESP_ACK_ERROR:
7567c478bd9Sstevel@tonic-gate 		cmd_status = H1394_CMD_ETYPE_ERROR;
7577c478bd9Sstevel@tonic-gate 		break;
7587c478bd9Sstevel@tonic-gate 	case OHCI_EVT_UNDERRUN | ASYNC_ARRESP_ACK_ERROR:
7597c478bd9Sstevel@tonic-gate 	case OHCI_EVT_DATA_READ | ASYNC_ARRESP_ACK_ERROR:
7607c478bd9Sstevel@tonic-gate 	case OHCI_EVT_TCODE_ERR | ASYNC_ARRESP_ACK_ERROR:
7617c478bd9Sstevel@tonic-gate 		cmd_status = H1394_CMD_EUNKNOWN_ERROR;
7627c478bd9Sstevel@tonic-gate 		break;
7637c478bd9Sstevel@tonic-gate 	default:
7647c478bd9Sstevel@tonic-gate 		cmd_status = H1394_CMD_EUNKNOWN_ERROR;
7657c478bd9Sstevel@tonic-gate 		break;
7667c478bd9Sstevel@tonic-gate 	}
7677c478bd9Sstevel@tonic-gate 
7687c478bd9Sstevel@tonic-gate 	/*
7697c478bd9Sstevel@tonic-gate 	 * if we have already processed the atreq and put it on the pending Q
7707c478bd9Sstevel@tonic-gate 	 * (normal case), tell the services layer it completed.
7717c478bd9Sstevel@tonic-gate 	 */
7727c478bd9Sstevel@tonic-gate 	if (hcicmd->ac_state == HCI1394_CMD_STATE_PENDING) {
7737c478bd9Sstevel@tonic-gate 		/* Set state indicating that we are done with this cmd */
7747c478bd9Sstevel@tonic-gate 		hcicmd->ac_state = HCI1394_CMD_STATE_COMPLETED;
7757c478bd9Sstevel@tonic-gate 
7767c478bd9Sstevel@tonic-gate 		/* tell the services lyaer the command has completed */
7777c478bd9Sstevel@tonic-gate 		h1394_cmd_is_complete(async_handle->as_drvinfo->di_sl_private,
7787c478bd9Sstevel@tonic-gate 		    hcicmd->ac_cmd, H1394_AT_REQ, cmd_status);
7797c478bd9Sstevel@tonic-gate 
7807c478bd9Sstevel@tonic-gate 	/*
7817c478bd9Sstevel@tonic-gate 	 * We have not seen the atreq status yet.  We will call
7827c478bd9Sstevel@tonic-gate 	 * h1394_command_is_complete() in atreq_process() in case we did not get
7837c478bd9Sstevel@tonic-gate 	 * an ack pending (target HW error -> this is based on real world
7847c478bd9Sstevel@tonic-gate 	 * experience :-))
7857c478bd9Sstevel@tonic-gate 	 */
7867c478bd9Sstevel@tonic-gate 	} else {
7877c478bd9Sstevel@tonic-gate 		/* Set state indicating that we are done with this cmd */
7887c478bd9Sstevel@tonic-gate 		hcicmd->ac_state = HCI1394_CMD_STATE_COMPLETED;
7897c478bd9Sstevel@tonic-gate 
7907c478bd9Sstevel@tonic-gate 		/* save away the status for atreq_process() */
7917c478bd9Sstevel@tonic-gate 		hcicmd->ac_status = cmd_status;
7927c478bd9Sstevel@tonic-gate 	}
7937c478bd9Sstevel@tonic-gate 
7947c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
7957c478bd9Sstevel@tonic-gate }
7967c478bd9Sstevel@tonic-gate 
7977c478bd9Sstevel@tonic-gate 
7987c478bd9Sstevel@tonic-gate /*
7997c478bd9Sstevel@tonic-gate  * hci1394_async_arreq_process()
8007c478bd9Sstevel@tonic-gate  *    Process an arreq, if one has arrived. This is called during interrupt
8017c478bd9Sstevel@tonic-gate  *    processing and will process an arreq that has arrived. It returns status
8027c478bd9Sstevel@tonic-gate  *    if an arreq was processed so that the ISR knows that it needs to be
8037c478bd9Sstevel@tonic-gate  *    called again to see if another ARREQ has arrived.
8047c478bd9Sstevel@tonic-gate  */
8057c478bd9Sstevel@tonic-gate int
hci1394_async_arreq_process(hci1394_async_handle_t async_handle,boolean_t * request_available)8067c478bd9Sstevel@tonic-gate hci1394_async_arreq_process(hci1394_async_handle_t async_handle,
8077c478bd9Sstevel@tonic-gate     boolean_t *request_available)
8087c478bd9Sstevel@tonic-gate {
8097c478bd9Sstevel@tonic-gate 	hci1394_async_cmd_t *hcicmd;
8107c478bd9Sstevel@tonic-gate 	uint32_t *addr;
8117c478bd9Sstevel@tonic-gate 	uint_t tcode;
8127c478bd9Sstevel@tonic-gate 	uint_t size;
8137c478bd9Sstevel@tonic-gate 	int status;
8147c478bd9Sstevel@tonic-gate 
8157c478bd9Sstevel@tonic-gate 
8167c478bd9Sstevel@tonic-gate 	ASSERT(async_handle != NULL);
8177c478bd9Sstevel@tonic-gate 	ASSERT(request_available != NULL);
8187c478bd9Sstevel@tonic-gate 
8197c478bd9Sstevel@tonic-gate 	/*
8207c478bd9Sstevel@tonic-gate 	 * See if there were any requests on ARREQ Q. A NULL means there
8217c478bd9Sstevel@tonic-gate 	 * were no requests on the Q. This call does NOT free up space. We
8227c478bd9Sstevel@tonic-gate 	 * need to do that later after we figure out how much space the
8237c478bd9Sstevel@tonic-gate 	 * request takes up.
8247c478bd9Sstevel@tonic-gate 	 */
8257c478bd9Sstevel@tonic-gate 	hci1394_q_ar_next(async_handle->as_arreq_q, &addr);
8267c478bd9Sstevel@tonic-gate 	if (addr == NULL) {
8277c478bd9Sstevel@tonic-gate 		*request_available = B_FALSE;
8287c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
8297c478bd9Sstevel@tonic-gate 	}
8307c478bd9Sstevel@tonic-gate 
8317c478bd9Sstevel@tonic-gate 	/*
8327c478bd9Sstevel@tonic-gate 	 * We got a request. Read the request into a 1394 framework command.
8337c478bd9Sstevel@tonic-gate 	 * We could get a NULL for a command if we got a request with an error
8347c478bd9Sstevel@tonic-gate 	 * (i.e. ARREQ ACK was not ack pending or ack complete). This would be a
8357c478bd9Sstevel@tonic-gate 	 * successful read but with a NULL hcicmd returned. If we ever get a
8367c478bd9Sstevel@tonic-gate 	 * DDI_FAILURE, we will shutdown.
8377c478bd9Sstevel@tonic-gate 	 */
8387c478bd9Sstevel@tonic-gate 	*request_available = B_TRUE;
8397c478bd9Sstevel@tonic-gate 	status = hci1394_async_arreq_read(async_handle,
8407c478bd9Sstevel@tonic-gate 	    (hci1394_basic_pkt_t *)addr, &tcode, &hcicmd, &size);
8417c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
8427c478bd9Sstevel@tonic-gate 		h1394_error_detected(async_handle->as_drvinfo->di_sl_private,
8437c478bd9Sstevel@tonic-gate 		    H1394_SELF_INITIATED_SHUTDOWN, NULL);
8447c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "hci1394(%d): driver shutdown: "
8457c478bd9Sstevel@tonic-gate 		    "unrecoverable error interrupt detected",
8467c478bd9Sstevel@tonic-gate 		    async_handle->as_drvinfo->di_instance);
8477c478bd9Sstevel@tonic-gate 		hci1394_shutdown(async_handle->as_drvinfo->di_dip);
8487c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
8497c478bd9Sstevel@tonic-gate 	}
8507c478bd9Sstevel@tonic-gate 
8517c478bd9Sstevel@tonic-gate 	/* Free up the arreq Q space, we are done with the data */
8527c478bd9Sstevel@tonic-gate 	hci1394_q_ar_free(async_handle->as_arreq_q, size);
8537c478bd9Sstevel@tonic-gate 
8547c478bd9Sstevel@tonic-gate 	/*
8557c478bd9Sstevel@tonic-gate 	 * if we did not get a valid request (i.e. The ARREQ had a bad ACK
8567c478bd9Sstevel@tonic-gate 	 * or something like that) we don't have anything else to do.  We will
8577c478bd9Sstevel@tonic-gate 	 * say that we processed a request and will return successfully. We
8587c478bd9Sstevel@tonic-gate 	 * still may have other requests on the Q.
8597c478bd9Sstevel@tonic-gate 	 */
8607c478bd9Sstevel@tonic-gate 	if (hcicmd == NULL) {
8617c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
8627c478bd9Sstevel@tonic-gate 	}
8637c478bd9Sstevel@tonic-gate 
8647c478bd9Sstevel@tonic-gate 	/*
8657c478bd9Sstevel@tonic-gate 	 * If as_flushing_arreq is set, we do not want to send any requests up
8667c478bd9Sstevel@tonic-gate 	 * to the Services Layer. We are flushing the ARREQ until we see a bus
8677c478bd9Sstevel@tonic-gate 	 * reset token that matches the current bus generation. Free up the
8687c478bd9Sstevel@tonic-gate 	 * alloc'd command and return success.
8697c478bd9Sstevel@tonic-gate 	 */
8707c478bd9Sstevel@tonic-gate 	if (async_handle->as_flushing_arreq == B_TRUE) {
8717c478bd9Sstevel@tonic-gate 		hci1394_async_response_complete(async_handle, hcicmd->ac_cmd,
8727c478bd9Sstevel@tonic-gate 		    hcicmd->ac_priv);
8737c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
8747c478bd9Sstevel@tonic-gate 	}
8757c478bd9Sstevel@tonic-gate 
8767c478bd9Sstevel@tonic-gate 	/*
8777c478bd9Sstevel@tonic-gate 	 * We got a valid request that we were able to read in. Call into the
8787c478bd9Sstevel@tonic-gate 	 * services layer based on the type of request.
8797c478bd9Sstevel@tonic-gate 	 */
8807c478bd9Sstevel@tonic-gate 	switch (tcode) {
8817c478bd9Sstevel@tonic-gate 	case IEEE1394_TCODE_READ_QUADLET:
8827c478bd9Sstevel@tonic-gate 	case IEEE1394_TCODE_READ_BLOCK:
8837c478bd9Sstevel@tonic-gate 		h1394_read_request(async_handle->as_drvinfo->di_sl_private,
8847c478bd9Sstevel@tonic-gate 		    hcicmd->ac_cmd);
8857c478bd9Sstevel@tonic-gate 		break;
8867c478bd9Sstevel@tonic-gate 	case IEEE1394_TCODE_WRITE_QUADLET:
8877c478bd9Sstevel@tonic-gate 	case IEEE1394_TCODE_WRITE_BLOCK:
8887c478bd9Sstevel@tonic-gate 		h1394_write_request(async_handle->as_drvinfo->di_sl_private,
8897c478bd9Sstevel@tonic-gate 		    hcicmd->ac_cmd);
8907c478bd9Sstevel@tonic-gate 		break;
8917c478bd9Sstevel@tonic-gate 	case IEEE1394_TCODE_LOCK:
8927c478bd9Sstevel@tonic-gate 		h1394_lock_request(async_handle->as_drvinfo->di_sl_private,
8937c478bd9Sstevel@tonic-gate 		    hcicmd->ac_cmd);
8947c478bd9Sstevel@tonic-gate 		break;
8957c478bd9Sstevel@tonic-gate 	case IEEE1394_TCODE_PHY:
8967c478bd9Sstevel@tonic-gate 		/*
8977c478bd9Sstevel@tonic-gate 		 * OpenHCI only handles 1 PHY quadlet at a time. If a selfid
8987c478bd9Sstevel@tonic-gate 		 * packet was received with multiple quadlets, we will treat
8997c478bd9Sstevel@tonic-gate 		 * each quadlet as a separate call.  We do not notify the
9007c478bd9Sstevel@tonic-gate 		 * services layer through the normal command interface, we will
9017c478bd9Sstevel@tonic-gate 		 * treat it like a command internally and then free up the
9027c478bd9Sstevel@tonic-gate 		 * command ourselves when we are done with it.
9037c478bd9Sstevel@tonic-gate 		 */
9047c478bd9Sstevel@tonic-gate 		h1394_phy_packet(async_handle->as_drvinfo->di_sl_private,
9057c478bd9Sstevel@tonic-gate 		    &hcicmd->ac_cmd->cmd_u.q.quadlet_data, 1,
9067c478bd9Sstevel@tonic-gate 		    hcicmd->ac_priv->recv_tstamp);
9077c478bd9Sstevel@tonic-gate 		/* free alloc'd command */
9087c478bd9Sstevel@tonic-gate 		hci1394_async_response_complete(async_handle, hcicmd->ac_cmd,
9097c478bd9Sstevel@tonic-gate 		    hcicmd->ac_priv);
9107c478bd9Sstevel@tonic-gate 		break;
9117c478bd9Sstevel@tonic-gate 	default:
9127c478bd9Sstevel@tonic-gate 		/* free alloc'd command */
9137c478bd9Sstevel@tonic-gate 		hci1394_async_response_complete(async_handle, hcicmd->ac_cmd,
9147c478bd9Sstevel@tonic-gate 		    hcicmd->ac_priv);
9157c478bd9Sstevel@tonic-gate 		break;
9167c478bd9Sstevel@tonic-gate 	}
9177c478bd9Sstevel@tonic-gate 
9187c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
9197c478bd9Sstevel@tonic-gate }
9207c478bd9Sstevel@tonic-gate 
9217c478bd9Sstevel@tonic-gate 
9227c478bd9Sstevel@tonic-gate /*
9237c478bd9Sstevel@tonic-gate  * hci1394_async_atresp_process()
9247c478bd9Sstevel@tonic-gate  *    Process an atresp, if one has completed. This is called during interrupt
9257c478bd9Sstevel@tonic-gate  *    processing and will process a completed atresp. It returns status if an
9267c478bd9Sstevel@tonic-gate  *    atresp was processed so that the ISR knows that it needs to be called
9277c478bd9Sstevel@tonic-gate  *    again to see if another ATRESP has completed. flush_q set to B_TRUE tells
9287c478bd9Sstevel@tonic-gate  *    this routine to process all commands regardless of their completion
9297c478bd9Sstevel@tonic-gate  *    status.  This is used during bus reset processing to remove all commands
9307c478bd9Sstevel@tonic-gate  *    from the Q.
9317c478bd9Sstevel@tonic-gate  */
9327c478bd9Sstevel@tonic-gate int
hci1394_async_atresp_process(hci1394_async_handle_t async_handle,boolean_t flush_q,boolean_t * response_available)9337c478bd9Sstevel@tonic-gate hci1394_async_atresp_process(hci1394_async_handle_t async_handle,
9347c478bd9Sstevel@tonic-gate     boolean_t flush_q, boolean_t *response_available)
9357c478bd9Sstevel@tonic-gate {
9367c478bd9Sstevel@tonic-gate 	hci1394_async_cmd_t *hcicmd;
9377c478bd9Sstevel@tonic-gate 	hci1394_q_cmd_t *qcmd;
9387c478bd9Sstevel@tonic-gate 	int cmd_status;
9397c478bd9Sstevel@tonic-gate 
9407c478bd9Sstevel@tonic-gate 
9417c478bd9Sstevel@tonic-gate 	ASSERT(async_handle != NULL);
9427c478bd9Sstevel@tonic-gate 	ASSERT(response_available != NULL);
9437c478bd9Sstevel@tonic-gate 
9447c478bd9Sstevel@tonic-gate 	/*
9457c478bd9Sstevel@tonic-gate 	 * Get the next ATRESP that has completed (if one has). Space is free'd
9467c478bd9Sstevel@tonic-gate 	 * up in atresp_q and atresp_data_q as part of this function call.
9477c478bd9Sstevel@tonic-gate 	 */
9487c478bd9Sstevel@tonic-gate 	hci1394_q_at_next(async_handle->as_atresp_q, flush_q, &qcmd);
9497c478bd9Sstevel@tonic-gate 
9507c478bd9Sstevel@tonic-gate 	/*
9517c478bd9Sstevel@tonic-gate 	 * See if there were anymore requests on ATRESP Q. A NULL means there
9527c478bd9Sstevel@tonic-gate 	 * were no completed commands left on the Q.
9537c478bd9Sstevel@tonic-gate 	 */
9547c478bd9Sstevel@tonic-gate 	if (qcmd == NULL) {
9557c478bd9Sstevel@tonic-gate 		*response_available = B_FALSE;
9567c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
9577c478bd9Sstevel@tonic-gate 	}
9587c478bd9Sstevel@tonic-gate 
9597c478bd9Sstevel@tonic-gate 	/* There is a completed ATRESP, setup the HAL command pointer */
9607c478bd9Sstevel@tonic-gate 	*response_available = B_TRUE;
9617c478bd9Sstevel@tonic-gate 	hcicmd = (hci1394_async_cmd_t *)qcmd->qc_arg;
9627c478bd9Sstevel@tonic-gate 
9637c478bd9Sstevel@tonic-gate 	/* save away the command completed timestamp for the services layer */
9647c478bd9Sstevel@tonic-gate 	hcicmd->ac_priv->ack_tstamp = qcmd->qc_timestamp;
9657c478bd9Sstevel@tonic-gate 
9667c478bd9Sstevel@tonic-gate 	/*
9677c478bd9Sstevel@tonic-gate 	 * setup our return command status based on the ACK from the HW. See the
9687c478bd9Sstevel@tonic-gate 	 * OpenHCI 1.0 spec (table 3.2 on pg. 18) for more information about
9697c478bd9Sstevel@tonic-gate 	 * these ACK/EVT's.
9707c478bd9Sstevel@tonic-gate 	 */
9717c478bd9Sstevel@tonic-gate 	switch (qcmd->qc_status) {
9727c478bd9Sstevel@tonic-gate 	case OHCI_ACK_COMPLETE:
9737c478bd9Sstevel@tonic-gate 		cmd_status = H1394_CMD_SUCCESS;
9747c478bd9Sstevel@tonic-gate 		break;
9757c478bd9Sstevel@tonic-gate 
9767c478bd9Sstevel@tonic-gate 	/*
9777c478bd9Sstevel@tonic-gate 	 * we can get a nostatus during a bus reset (i.e. we shutdown the AT
9787c478bd9Sstevel@tonic-gate 	 * engine before it flushed all the commands)
9797c478bd9Sstevel@tonic-gate 	 */
9807c478bd9Sstevel@tonic-gate 	case OHCI_EVT_FLUSHED:
9817c478bd9Sstevel@tonic-gate 	case OHCI_EVT_NO_STATUS:
9827c478bd9Sstevel@tonic-gate 		cmd_status = H1394_CMD_EBUSRESET;
9837c478bd9Sstevel@tonic-gate 		break;
9847c478bd9Sstevel@tonic-gate 
9857c478bd9Sstevel@tonic-gate 	case OHCI_EVT_MISSING_ACK:
9867c478bd9Sstevel@tonic-gate 	case OHCI_EVT_TIMEOUT:
9877c478bd9Sstevel@tonic-gate 		cmd_status = H1394_CMD_ETIMEOUT;
9887c478bd9Sstevel@tonic-gate 		break;
9897c478bd9Sstevel@tonic-gate 
9907c478bd9Sstevel@tonic-gate 	case OHCI_ACK_BUSY_X:
9917c478bd9Sstevel@tonic-gate 	case OHCI_ACK_BUSY_A:
9927c478bd9Sstevel@tonic-gate 	case OHCI_ACK_BUSY_B:
9937c478bd9Sstevel@tonic-gate 		cmd_status = H1394_CMD_EDEVICE_BUSY;
9947c478bd9Sstevel@tonic-gate 		break;
9957c478bd9Sstevel@tonic-gate 
9967c478bd9Sstevel@tonic-gate 	case OHCI_ACK_TARDY:
9977c478bd9Sstevel@tonic-gate 		cmd_status = H1394_CMD_EDEVICE_POWERUP;
9987c478bd9Sstevel@tonic-gate 		break;
9997c478bd9Sstevel@tonic-gate 
10007c478bd9Sstevel@tonic-gate 	case OHCI_ACK_DATA_ERROR:
10017c478bd9Sstevel@tonic-gate 		cmd_status = H1394_CMD_EDATA_ERROR;
10027c478bd9Sstevel@tonic-gate 		break;
10037c478bd9Sstevel@tonic-gate 
10047c478bd9Sstevel@tonic-gate 	case OHCI_ACK_TYPE_ERROR:
10057c478bd9Sstevel@tonic-gate 		cmd_status = H1394_CMD_ETYPE_ERROR;
10067c478bd9Sstevel@tonic-gate 		break;
10077c478bd9Sstevel@tonic-gate 
10087c478bd9Sstevel@tonic-gate 	case OHCI_ACK_CONFLICT_ERROR:
10097c478bd9Sstevel@tonic-gate 		cmd_status = H1394_CMD_ERSRC_CONFLICT;
10107c478bd9Sstevel@tonic-gate 		break;
10117c478bd9Sstevel@tonic-gate 
10127c478bd9Sstevel@tonic-gate 	case OHCI_ACK_ADDRESS_ERROR:
10137c478bd9Sstevel@tonic-gate 		cmd_status = H1394_CMD_EADDR_ERROR;
10147c478bd9Sstevel@tonic-gate 		break;
10157c478bd9Sstevel@tonic-gate 
10167c478bd9Sstevel@tonic-gate 	case OHCI_EVT_UNKNOWN:
10177c478bd9Sstevel@tonic-gate 		cmd_status = H1394_CMD_EUNKNOWN_ERROR;
10187c478bd9Sstevel@tonic-gate 		break;
10197c478bd9Sstevel@tonic-gate 
10207c478bd9Sstevel@tonic-gate 	case OHCI_EVT_UNDERRUN:
10217c478bd9Sstevel@tonic-gate 	case OHCI_EVT_DATA_READ:
10227c478bd9Sstevel@tonic-gate 	case OHCI_EVT_TCODE_ERR:
10237c478bd9Sstevel@tonic-gate 	case OHCI_EVT_DESCRIPTOR_READ:
10247c478bd9Sstevel@tonic-gate 	default:
10257c478bd9Sstevel@tonic-gate 		cmd_status = H1394_CMD_EUNKNOWN_ERROR;
10267c478bd9Sstevel@tonic-gate 		break;
10277c478bd9Sstevel@tonic-gate 	}
10287c478bd9Sstevel@tonic-gate 
10297c478bd9Sstevel@tonic-gate 	/* tell the services layer that the command has completed */
10307c478bd9Sstevel@tonic-gate 	h1394_cmd_is_complete(async_handle->as_drvinfo->di_sl_private,
10317c478bd9Sstevel@tonic-gate 	    hcicmd->ac_cmd, H1394_AT_RESP, cmd_status);
10327c478bd9Sstevel@tonic-gate 
10337c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
10347c478bd9Sstevel@tonic-gate }
10357c478bd9Sstevel@tonic-gate 
10367c478bd9Sstevel@tonic-gate 
10377c478bd9Sstevel@tonic-gate /*
10387c478bd9Sstevel@tonic-gate  * hci1394_async_arresp_read()
10397c478bd9Sstevel@tonic-gate  *    Read ARRESP in from memory into 1394 Framework command. We read the tcode
10407c478bd9Sstevel@tonic-gate  *    which tells us which kind of arresp the packet is, get the size of the
10417c478bd9Sstevel@tonic-gate  *    response, read in the sender, tlabel, and response code, and then
10427c478bd9Sstevel@tonic-gate  *    lookup the command based on the sender and tlabel. Once we get the command
10437c478bd9Sstevel@tonic-gate  *    (corresponding to the ATREQ), we will copy the rest of the response into
10447c478bd9Sstevel@tonic-gate  *    that command.
10457c478bd9Sstevel@tonic-gate  *
10467c478bd9Sstevel@tonic-gate  *    The only time this routine should return DDI_FAILURE is if it was unable
10477c478bd9Sstevel@tonic-gate  *    to maintain a good state in the ARRESP Q (i.e. an unknown response was
10487c478bd9Sstevel@tonic-gate  *    received and we can not cleanup after it.)  If we detect a recoverable
10497c478bd9Sstevel@tonic-gate  *    error, and it doesn't make sense to pass the response up to the Services
10507c478bd9Sstevel@tonic-gate  *    Layer, we should return DDI_SUCCESS with hcicmd = NULL.
10517c478bd9Sstevel@tonic-gate  */
10527c478bd9Sstevel@tonic-gate static int
hci1394_async_arresp_read(hci1394_async_handle_t async_handle,hci1394_basic_pkt_t * pkt,uint_t * tcode,hci1394_async_cmd_t ** hcicmd,uint_t * size)10537c478bd9Sstevel@tonic-gate hci1394_async_arresp_read(hci1394_async_handle_t async_handle,
10547c478bd9Sstevel@tonic-gate     hci1394_basic_pkt_t *pkt,  uint_t *tcode, hci1394_async_cmd_t **hcicmd,
10557c478bd9Sstevel@tonic-gate     uint_t *size)
10567c478bd9Sstevel@tonic-gate {
10577c478bd9Sstevel@tonic-gate 	hci1394_tlabel_info_t ac_tlabel;
10587c478bd9Sstevel@tonic-gate 	h1394_cmd_priv_t *cmd_priv;
10597c478bd9Sstevel@tonic-gate 	cmd1394_cmd_t *cmd;
10607c478bd9Sstevel@tonic-gate 	uint32_t *status_addr;
10617c478bd9Sstevel@tonic-gate 	uint_t data_length;
10627c478bd9Sstevel@tonic-gate 	uint32_t quadlet;
10637c478bd9Sstevel@tonic-gate 	void *command;
10647c478bd9Sstevel@tonic-gate 	uint_t rcode;
10657c478bd9Sstevel@tonic-gate 	uint_t ack;
10667c478bd9Sstevel@tonic-gate 	int status;
10677c478bd9Sstevel@tonic-gate 
10687c478bd9Sstevel@tonic-gate 
10697c478bd9Sstevel@tonic-gate 	ASSERT(async_handle != NULL);
10707c478bd9Sstevel@tonic-gate 	ASSERT(pkt != NULL);
10717c478bd9Sstevel@tonic-gate 	ASSERT(tcode != NULL);
10727c478bd9Sstevel@tonic-gate 	ASSERT(hcicmd != NULL);
10737c478bd9Sstevel@tonic-gate 	ASSERT(size != NULL);
10747c478bd9Sstevel@tonic-gate 
10757c478bd9Sstevel@tonic-gate 	/* read in the arresp tcode */
10767c478bd9Sstevel@tonic-gate 	quadlet = hci1394_q_ar_get32(async_handle->as_arresp_q, &pkt->q1);
10777c478bd9Sstevel@tonic-gate 	*tcode = HCI1394_DESC_TCODE_GET(quadlet);
10787c478bd9Sstevel@tonic-gate 
10797c478bd9Sstevel@tonic-gate 	/* Get the size of the arresp */
10807c478bd9Sstevel@tonic-gate 	status = hci1394_async_arresp_size_get(*tcode,
10817c478bd9Sstevel@tonic-gate 	    async_handle->as_arresp_q, &pkt->q1, size);
10827c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
10837c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
10847c478bd9Sstevel@tonic-gate 	}
10857c478bd9Sstevel@tonic-gate 
10867c478bd9Sstevel@tonic-gate 	/* Read in the tlabel, destination, and rcode (response code) */
10877c478bd9Sstevel@tonic-gate 	quadlet = hci1394_q_ar_get32(async_handle->as_arresp_q, &pkt->q1);
10887c478bd9Sstevel@tonic-gate 	ac_tlabel.tbi_tlabel = HCI1394_DESC_TLABEL_GET(quadlet);
10897c478bd9Sstevel@tonic-gate 	quadlet = hci1394_q_ar_get32(async_handle->as_arresp_q, &pkt->q2);
10907c478bd9Sstevel@tonic-gate 	ac_tlabel.tbi_destination = HCI1394_DESC_DESTID_GET(quadlet);
10917c478bd9Sstevel@tonic-gate 	rcode = HCI1394_DESC_RCODE_GET(quadlet);
10927c478bd9Sstevel@tonic-gate 
10937c478bd9Sstevel@tonic-gate 	/* Lookup the ATREQ framework command this response goes with */
10947c478bd9Sstevel@tonic-gate 	hci1394_tlabel_lookup(async_handle->as_tlabel, &ac_tlabel, &command);
10957c478bd9Sstevel@tonic-gate 
10967c478bd9Sstevel@tonic-gate 	/*
10977c478bd9Sstevel@tonic-gate 	 * If there is not a cooresponding ATREQ command, this is an error. We
10987c478bd9Sstevel@tonic-gate 	 * will ignore this response but still return success so we cleanup
10997c478bd9Sstevel@tonic-gate 	 * after it and go on with other arresp's. This could happend if a
11007c478bd9Sstevel@tonic-gate 	 * response was sent after the command has timed out or if the target
11017c478bd9Sstevel@tonic-gate 	 * device is misbehaving. (we have seen both cases)
11027c478bd9Sstevel@tonic-gate 	 */
11037c478bd9Sstevel@tonic-gate 	*hcicmd = (hci1394_async_cmd_t *)command;
11047c478bd9Sstevel@tonic-gate 	if ((*hcicmd) == NULL) {
11057c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
11067c478bd9Sstevel@tonic-gate 	}
11077c478bd9Sstevel@tonic-gate 
11087c478bd9Sstevel@tonic-gate 	/*
11097c478bd9Sstevel@tonic-gate 	 * copy the response code into the hal private command space. Setup
11107c478bd9Sstevel@tonic-gate 	 * shortcuts to the 1394 framework command (cmd) and the HAL/SL private
11117c478bd9Sstevel@tonic-gate 	 * area (cmd_priv). A command is made up of 4 parts. There is the public
11127c478bd9Sstevel@tonic-gate 	 * part which is accessable to the target driver, there is the Services
11137c478bd9Sstevel@tonic-gate 	 * Layer private part which is only accessible to the services layer,
11147c478bd9Sstevel@tonic-gate 	 * there is the SL/HAL private area which is where the SL and HAL share
11157c478bd9Sstevel@tonic-gate 	 * information about a particular command, and there is the HAL private
11167c478bd9Sstevel@tonic-gate 	 * area where we keep track of our command specific state information.
11177c478bd9Sstevel@tonic-gate 	 */
11187c478bd9Sstevel@tonic-gate 	(*hcicmd)->ac_status = rcode;
11197c478bd9Sstevel@tonic-gate 	cmd = (*hcicmd)->ac_cmd;
11207c478bd9Sstevel@tonic-gate 	cmd_priv = (*hcicmd)->ac_priv;
11217c478bd9Sstevel@tonic-gate 
11227c478bd9Sstevel@tonic-gate 	/*
11237c478bd9Sstevel@tonic-gate 	 * Calculate the address where the status of the ARRESP and timestamp is
11247c478bd9Sstevel@tonic-gate 	 * kept at.  It is the last quadlet in the response. Save away the
11257c478bd9Sstevel@tonic-gate 	 * timestamp.
11267c478bd9Sstevel@tonic-gate 	 */
11277c478bd9Sstevel@tonic-gate 	status_addr = (uint32_t *)((uintptr_t)pkt + (uintptr_t)*size -
11287c478bd9Sstevel@tonic-gate 	    (uintptr_t)IEEE1394_QUADLET);
11297c478bd9Sstevel@tonic-gate 	quadlet = hci1394_q_ar_get32(async_handle->as_arresp_q, status_addr);
11307c478bd9Sstevel@tonic-gate 	cmd_priv->recv_tstamp = HCI1394_DESC_TIMESTAMP_GET(quadlet);
11317c478bd9Sstevel@tonic-gate 
11327c478bd9Sstevel@tonic-gate 	/*
11337c478bd9Sstevel@tonic-gate 	 * if we did not get an ACK_COMPLETE, we will use the ack error instead
11347c478bd9Sstevel@tonic-gate 	 * of the response in the packet for our status. We use special mask to
11357c478bd9Sstevel@tonic-gate 	 * separate the reponses from the ACKs (ASYNC_ARRESP_ACK_ERROR). We will
11367c478bd9Sstevel@tonic-gate 	 * return success with hcicmd set to the command so that this error gets
11377c478bd9Sstevel@tonic-gate 	 * sent up to the Services Layer.
11387c478bd9Sstevel@tonic-gate 	 */
11397c478bd9Sstevel@tonic-gate 	ack = HCI1394_DESC_EVT_GET(quadlet);
11407c478bd9Sstevel@tonic-gate 	if (ack != OHCI_ACK_COMPLETE) {
11417c478bd9Sstevel@tonic-gate 		/* use the ack error instead of rcode for the command status */
11427c478bd9Sstevel@tonic-gate 		(*hcicmd)->ac_status = ack | ASYNC_ARRESP_ACK_ERROR;
11437c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
11447c478bd9Sstevel@tonic-gate 	}
11457c478bd9Sstevel@tonic-gate 
11467c478bd9Sstevel@tonic-gate 	/*
11477c478bd9Sstevel@tonic-gate 	 * If we get to this point we have gotten a valid ACK on the response
11487c478bd9Sstevel@tonic-gate 	 * and have matched up the response with an ATREQ. Now we check the
11497c478bd9Sstevel@tonic-gate 	 * response code. If it is not resp_complete, we do not have anything
11507c478bd9Sstevel@tonic-gate 	 * left to look at in the response. Return successfully.
11517c478bd9Sstevel@tonic-gate 	 */
11527c478bd9Sstevel@tonic-gate 	if (rcode != IEEE1394_RESP_COMPLETE) {
11537c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
11547c478bd9Sstevel@tonic-gate 	}
11557c478bd9Sstevel@tonic-gate 
11567c478bd9Sstevel@tonic-gate 	/*
11577c478bd9Sstevel@tonic-gate 	 * Read the rest of the response (based on which kind of response it is)
11587c478bd9Sstevel@tonic-gate 	 * into the 1394 framework command. In all of the different responses,
11597c478bd9Sstevel@tonic-gate 	 * we check to make sure the response matches the original request. We
11607c478bd9Sstevel@tonic-gate 	 * originally did not have this check but found a device or two which
11617c478bd9Sstevel@tonic-gate 	 * did not behave very well and would cause us to corrupt our commands.
11627c478bd9Sstevel@tonic-gate 	 * Now we check :-) We will return success when we get this error since
11637c478bd9Sstevel@tonic-gate 	 * we can recover from it.
11647c478bd9Sstevel@tonic-gate 	 */
11657c478bd9Sstevel@tonic-gate 	switch (*tcode) {
11667c478bd9Sstevel@tonic-gate 	case IEEE1394_TCODE_WRITE_RESP:
11677c478bd9Sstevel@tonic-gate 		/*
11687c478bd9Sstevel@tonic-gate 		 * make sure the ATREQ was a quadlet/block write. The same
11697c478bd9Sstevel@tonic-gate 		 * response is sent back for those two type of ATREQs.
11707c478bd9Sstevel@tonic-gate 		 */
11717c478bd9Sstevel@tonic-gate 		if ((cmd->cmd_type != CMD1394_ASYNCH_WR_QUAD) &&
11727c478bd9Sstevel@tonic-gate 		    (cmd->cmd_type != CMD1394_ASYNCH_WR_BLOCK)) {
11737c478bd9Sstevel@tonic-gate 			(*hcicmd)->ac_status = H1394_CMD_EDEVICE_ERROR;
11747c478bd9Sstevel@tonic-gate 			return (DDI_SUCCESS);
11757c478bd9Sstevel@tonic-gate 		}
11767c478bd9Sstevel@tonic-gate 		break;
11777c478bd9Sstevel@tonic-gate 
11787c478bd9Sstevel@tonic-gate 	case IEEE1394_TCODE_READ_QUADLET_RESP:
11797c478bd9Sstevel@tonic-gate 		/* make sure the ATREQ was a quadlet read */
11807c478bd9Sstevel@tonic-gate 		if (cmd->cmd_type != CMD1394_ASYNCH_RD_QUAD) {
11817c478bd9Sstevel@tonic-gate 			(*hcicmd)->ac_status = H1394_CMD_EDEVICE_ERROR;
11827c478bd9Sstevel@tonic-gate 			return (DDI_SUCCESS);
11837c478bd9Sstevel@tonic-gate 		}
11847c478bd9Sstevel@tonic-gate 
11857c478bd9Sstevel@tonic-gate 		/*
11867c478bd9Sstevel@tonic-gate 		 * read the quadlet read response in.  Data is treated as a byte
11877c478bd9Sstevel@tonic-gate 		 * stream.
11887c478bd9Sstevel@tonic-gate 		 */
11897c478bd9Sstevel@tonic-gate 		hci1394_q_ar_rep_get8(async_handle->as_arresp_q,
11907c478bd9Sstevel@tonic-gate 		    (uint8_t *)&cmd->cmd_u.q.quadlet_data,
11917c478bd9Sstevel@tonic-gate 		    (uint8_t *)&pkt->q4, IEEE1394_QUADLET);
11927c478bd9Sstevel@tonic-gate 		break;
11937c478bd9Sstevel@tonic-gate 
11947c478bd9Sstevel@tonic-gate 	case IEEE1394_TCODE_READ_BLOCK_RESP:
11957c478bd9Sstevel@tonic-gate 		/* make sure the ATREQ was a block read */
11967c478bd9Sstevel@tonic-gate 		if (cmd->cmd_type != CMD1394_ASYNCH_RD_BLOCK) {
11977c478bd9Sstevel@tonic-gate 			(*hcicmd)->ac_status = H1394_CMD_EDEVICE_ERROR;
11987c478bd9Sstevel@tonic-gate 			return (DDI_SUCCESS);
11997c478bd9Sstevel@tonic-gate 		}
12007c478bd9Sstevel@tonic-gate 
12017c478bd9Sstevel@tonic-gate 		/*
12027c478bd9Sstevel@tonic-gate 		 * read in the data length.  Make sure the data length is the
12037c478bd9Sstevel@tonic-gate 		 * same size as the read block request size that went out.
12047c478bd9Sstevel@tonic-gate 		 */
12057c478bd9Sstevel@tonic-gate 		quadlet = hci1394_q_ar_get32(async_handle->as_arresp_q,
12067c478bd9Sstevel@tonic-gate 		    &pkt->q4);
12077c478bd9Sstevel@tonic-gate 		data_length = HCI1394_DESC_DATALEN_GET(quadlet);
12087c478bd9Sstevel@tonic-gate 		if (data_length != cmd_priv->mblk.length) {
12097c478bd9Sstevel@tonic-gate 			(*hcicmd)->ac_status = H1394_CMD_EDEVICE_ERROR;
12107c478bd9Sstevel@tonic-gate 			return (DDI_SUCCESS);
12117c478bd9Sstevel@tonic-gate 		}
12127c478bd9Sstevel@tonic-gate 
12137c478bd9Sstevel@tonic-gate 		/* Copy the read block data into the command mblk */
12147c478bd9Sstevel@tonic-gate 		hci1394_q_ar_copy_to_mblk(async_handle->as_arresp_q,
12157c478bd9Sstevel@tonic-gate 		    (uint8_t *)&pkt->q5, &cmd_priv->mblk);
12167c478bd9Sstevel@tonic-gate 		break;
12177c478bd9Sstevel@tonic-gate 
12187c478bd9Sstevel@tonic-gate 	case IEEE1394_TCODE_LOCK_RESP:
12197c478bd9Sstevel@tonic-gate 		/* read in the data length */
12207c478bd9Sstevel@tonic-gate 		quadlet = hci1394_q_ar_get32(async_handle->as_arresp_q,
12217c478bd9Sstevel@tonic-gate 		    &pkt->q4);
12227c478bd9Sstevel@tonic-gate 		data_length = HCI1394_DESC_DATALEN_GET(quadlet);
12237c478bd9Sstevel@tonic-gate 
12247c478bd9Sstevel@tonic-gate 		if (cmd->cmd_type == CMD1394_ASYNCH_LOCK_32) {
12257c478bd9Sstevel@tonic-gate 			/*
12267c478bd9Sstevel@tonic-gate 			 * read in the data length.  Make sure the data length
12277c478bd9Sstevel@tonic-gate 			 * is the valid for a lock32 response (1 quadlet)
12287c478bd9Sstevel@tonic-gate 			 */
12297c478bd9Sstevel@tonic-gate 			if (data_length != IEEE1394_QUADLET) {
12307c478bd9Sstevel@tonic-gate 				(*hcicmd)->ac_status = H1394_CMD_EDEVICE_ERROR;
12317c478bd9Sstevel@tonic-gate 				return (DDI_SUCCESS);
12327c478bd9Sstevel@tonic-gate 			}
12337c478bd9Sstevel@tonic-gate 
12347c478bd9Sstevel@tonic-gate 			/*
12357c478bd9Sstevel@tonic-gate 			 * read the lock32 response in. Data is treated as a
12367c478bd9Sstevel@tonic-gate 			 * byte stream unless it is an arithmetic lock
12377c478bd9Sstevel@tonic-gate 			 * operation. In that case we treat data like a 32-bit
12387c478bd9Sstevel@tonic-gate 			 * word.
12397c478bd9Sstevel@tonic-gate 			 */
12407c478bd9Sstevel@tonic-gate 			hci1394_q_ar_rep_get8(async_handle->as_arresp_q,
12417c478bd9Sstevel@tonic-gate 			    (uint8_t *)&cmd->cmd_u.l32.old_value,
12427c478bd9Sstevel@tonic-gate 			    (uint8_t *)&pkt->q5, IEEE1394_QUADLET);
12437c478bd9Sstevel@tonic-gate 			cmd->cmd_u.l32.old_value = HCI1394_ARITH_LOCK_SWAP32(
12447c478bd9Sstevel@tonic-gate 			    cmd->cmd_u.l32.lock_type, cmd->cmd_u.l32.old_value);
12457c478bd9Sstevel@tonic-gate 
12467c478bd9Sstevel@tonic-gate 		} else if (cmd->cmd_type == CMD1394_ASYNCH_LOCK_64) {
12477c478bd9Sstevel@tonic-gate 			/*
12487c478bd9Sstevel@tonic-gate 			 * read in the data length.  Make sure the data length
12497c478bd9Sstevel@tonic-gate 			 * is the valid for a lock64 response (1 octlet)
12507c478bd9Sstevel@tonic-gate 			 */
12517c478bd9Sstevel@tonic-gate 			if (data_length != IEEE1394_OCTLET) {
12527c478bd9Sstevel@tonic-gate 				(*hcicmd)->ac_status = H1394_CMD_EDEVICE_ERROR;
12537c478bd9Sstevel@tonic-gate 				return (DDI_SUCCESS);
12547c478bd9Sstevel@tonic-gate 			}
12557c478bd9Sstevel@tonic-gate 
12567c478bd9Sstevel@tonic-gate 			/*
12577c478bd9Sstevel@tonic-gate 			 * read the lock64 response in. Data is treated as a
12587c478bd9Sstevel@tonic-gate 			 * byte stream unless it is an arithmetic lock
12597c478bd9Sstevel@tonic-gate 			 * operation. In that case we treat data like a 64-bit
12607c478bd9Sstevel@tonic-gate 			 * word.
12617c478bd9Sstevel@tonic-gate 			 */
12627c478bd9Sstevel@tonic-gate 			hci1394_q_ar_rep_get8(async_handle->as_arresp_q,
12637c478bd9Sstevel@tonic-gate 			    (uint8_t *)&cmd->cmd_u.l64.old_value,
12647c478bd9Sstevel@tonic-gate 			    (uint8_t *)&pkt->q5, IEEE1394_OCTLET);
12657c478bd9Sstevel@tonic-gate 			cmd->cmd_u.l64.old_value = HCI1394_ARITH_LOCK_SWAP64(
12667c478bd9Sstevel@tonic-gate 			    cmd->cmd_u.l64.lock_type, cmd->cmd_u.l64.old_value);
12677c478bd9Sstevel@tonic-gate 
12687c478bd9Sstevel@tonic-gate 		/*
12697c478bd9Sstevel@tonic-gate 		 * we sent out a request that was NOT a lock request and got
12707c478bd9Sstevel@tonic-gate 		 * back a lock response.
12717c478bd9Sstevel@tonic-gate 		 */
12727c478bd9Sstevel@tonic-gate 		} else {
12737c478bd9Sstevel@tonic-gate 			(*hcicmd)->ac_status = H1394_CMD_EDEVICE_ERROR;
12747c478bd9Sstevel@tonic-gate 			return (DDI_SUCCESS);
12757c478bd9Sstevel@tonic-gate 		}
12767c478bd9Sstevel@tonic-gate 		break;
12777c478bd9Sstevel@tonic-gate 
12787c478bd9Sstevel@tonic-gate 	default:
12797c478bd9Sstevel@tonic-gate 		/* we got a tcode that we don't know about. Return error */
12807c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
12817c478bd9Sstevel@tonic-gate 	}
12827c478bd9Sstevel@tonic-gate 
12837c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
12847c478bd9Sstevel@tonic-gate }
12857c478bd9Sstevel@tonic-gate 
12867c478bd9Sstevel@tonic-gate 
12877c478bd9Sstevel@tonic-gate /*
12887c478bd9Sstevel@tonic-gate  * hci1394_async_arreq_read()
12897c478bd9Sstevel@tonic-gate  *    Read ARREQ in from memory into a 1394 Framework command. Allocate a 1394
12907c478bd9Sstevel@tonic-gate  *    framework command, read in the ARREQ, and before passing it up to the
12917c478bd9Sstevel@tonic-gate  *    services layer, see if it was a valid broadcast request.
12927c478bd9Sstevel@tonic-gate  *
12937c478bd9Sstevel@tonic-gate  *    The only time this routine should return DDI_FAILURE is if it was unable
12947c478bd9Sstevel@tonic-gate  *    to maintain a good state in the ARREQ Q (i.e. an unknown request was
12957c478bd9Sstevel@tonic-gate  *    received and we can not cleanup after it.)  If we detect a recoverable
12967c478bd9Sstevel@tonic-gate  *    error we should return DDI_SUCCESS with hcicmd = NULL.
12977c478bd9Sstevel@tonic-gate  */
12987c478bd9Sstevel@tonic-gate static int
hci1394_async_arreq_read(hci1394_async_handle_t async_handle,hci1394_basic_pkt_t * pkt,uint_t * tcode,hci1394_async_cmd_t ** hcicmd,uint_t * size)12997c478bd9Sstevel@tonic-gate hci1394_async_arreq_read(hci1394_async_handle_t async_handle,
13007c478bd9Sstevel@tonic-gate     hci1394_basic_pkt_t *pkt, uint_t *tcode, hci1394_async_cmd_t **hcicmd,
13017c478bd9Sstevel@tonic-gate     uint_t *size)
13027c478bd9Sstevel@tonic-gate {
13037c478bd9Sstevel@tonic-gate 	h1394_cmd_priv_t *cmd_priv;
13047c478bd9Sstevel@tonic-gate 	boolean_t is_reset_token;
13057c478bd9Sstevel@tonic-gate 	cmd1394_cmd_t *cmd;
13067c478bd9Sstevel@tonic-gate 	uint32_t quadlet;
13077c478bd9Sstevel@tonic-gate 	int status;
13087c478bd9Sstevel@tonic-gate 
13097c478bd9Sstevel@tonic-gate 
13107c478bd9Sstevel@tonic-gate 	ASSERT(async_handle != NULL);
13117c478bd9Sstevel@tonic-gate 	ASSERT(pkt != NULL);
13127c478bd9Sstevel@tonic-gate 	ASSERT(tcode != NULL);
13137c478bd9Sstevel@tonic-gate 	ASSERT(hcicmd != NULL);
13147c478bd9Sstevel@tonic-gate 	ASSERT(size != NULL);
13157c478bd9Sstevel@tonic-gate 
13167c478bd9Sstevel@tonic-gate 	/* read in the arresp tcode */
13177c478bd9Sstevel@tonic-gate 	quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q1);
13187c478bd9Sstevel@tonic-gate 	*tcode = HCI1394_DESC_TCODE_GET(quadlet);
13197c478bd9Sstevel@tonic-gate 
13207c478bd9Sstevel@tonic-gate 	/*
13217c478bd9Sstevel@tonic-gate 	 * Allocated 1394 framework command.  The Services layer takes care of
13227c478bd9Sstevel@tonic-gate 	 * cacheing commands. This is called during interrupt processing so we
13237c478bd9Sstevel@tonic-gate 	 * do not want to sleep.
13247c478bd9Sstevel@tonic-gate 	 */
13257c478bd9Sstevel@tonic-gate 	status = h1394_alloc_cmd(async_handle->as_drvinfo->di_sl_private,
13267c478bd9Sstevel@tonic-gate 	    H1394_ALLOC_CMD_NOSLEEP, &cmd, &cmd_priv);
13277c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
13287c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
13297c478bd9Sstevel@tonic-gate 	}
13307c478bd9Sstevel@tonic-gate 
13317c478bd9Sstevel@tonic-gate 	/* Initialize the HAL private command info */
13327c478bd9Sstevel@tonic-gate 	hci1394_async_hcicmd_init(async_handle, cmd, cmd_priv, hcicmd);
13337c478bd9Sstevel@tonic-gate 
13347c478bd9Sstevel@tonic-gate 	/*
13357c478bd9Sstevel@tonic-gate 	 * There are two generations in the command structure, one in the public
13367c478bd9Sstevel@tonic-gate 	 * space and one in the HAL/SL private shared space. We need to fill in
13377c478bd9Sstevel@tonic-gate 	 * both.  We only use the private one internally.
13387c478bd9Sstevel@tonic-gate 	 */
13397c478bd9Sstevel@tonic-gate 	cmd_priv->bus_generation = async_handle->as_drvinfo->di_gencnt;
13407c478bd9Sstevel@tonic-gate 	cmd->bus_generation = async_handle->as_drvinfo->di_gencnt;
13417c478bd9Sstevel@tonic-gate 
13427c478bd9Sstevel@tonic-gate 	/*
13437c478bd9Sstevel@tonic-gate 	 * Read the request (based on which kind of request it is) into the 1394
13447c478bd9Sstevel@tonic-gate 	 * framework command.
13457c478bd9Sstevel@tonic-gate 	 */
13467c478bd9Sstevel@tonic-gate 	switch (*tcode) {
13477c478bd9Sstevel@tonic-gate 	case IEEE1394_TCODE_READ_QUADLET:
13487c478bd9Sstevel@tonic-gate 		/*
13497c478bd9Sstevel@tonic-gate 		 * We got a ARREQ quadlet read request. Read in the packet.
13507c478bd9Sstevel@tonic-gate 		 * If there is a problem with the packet (i.e. we don't get
13517c478bd9Sstevel@tonic-gate 		 * DDI_SUCCESS), we will free up the command and return NULL in
13527c478bd9Sstevel@tonic-gate 		 * hcicmd to indicate that we did not get a valid ARREQ to
13537c478bd9Sstevel@tonic-gate 		 * process.
13547c478bd9Sstevel@tonic-gate 		 */
13557c478bd9Sstevel@tonic-gate 		status = hci1394_async_arreq_read_qrd(async_handle, pkt,
13567c478bd9Sstevel@tonic-gate 		    *hcicmd, size);
13577c478bd9Sstevel@tonic-gate 		if (status != DDI_SUCCESS) {
13587c478bd9Sstevel@tonic-gate 			hci1394_async_response_complete(async_handle, cmd,
13597c478bd9Sstevel@tonic-gate 			    cmd_priv);
13607c478bd9Sstevel@tonic-gate 			*hcicmd = NULL;
13617c478bd9Sstevel@tonic-gate 			return (DDI_SUCCESS);
13627c478bd9Sstevel@tonic-gate 		}
13637c478bd9Sstevel@tonic-gate 		break;
13647c478bd9Sstevel@tonic-gate 
13657c478bd9Sstevel@tonic-gate 	case IEEE1394_TCODE_WRITE_QUADLET:
13667c478bd9Sstevel@tonic-gate 		/*
13677c478bd9Sstevel@tonic-gate 		 * We got a ARREQ quadlet write request. Read in the packet.
13687c478bd9Sstevel@tonic-gate 		 * If there is a problem with the packet (i.e. we don't get
13697c478bd9Sstevel@tonic-gate 		 * DDI_SUCCESS), we will free up the command and return NULL in
13707c478bd9Sstevel@tonic-gate 		 * hcicmd to indicate that we did not get a valid ARREQ to
13717c478bd9Sstevel@tonic-gate 		 * process.
13727c478bd9Sstevel@tonic-gate 		 */
13737c478bd9Sstevel@tonic-gate 		status = hci1394_async_arreq_read_qwr(async_handle, pkt,
13747c478bd9Sstevel@tonic-gate 		    *hcicmd, size);
13757c478bd9Sstevel@tonic-gate 		if (status != DDI_SUCCESS) {
13767c478bd9Sstevel@tonic-gate 			hci1394_async_response_complete(async_handle, cmd,
13777c478bd9Sstevel@tonic-gate 			    cmd_priv);
13787c478bd9Sstevel@tonic-gate 			*hcicmd = NULL;
13797c478bd9Sstevel@tonic-gate 			return (DDI_SUCCESS);
13807c478bd9Sstevel@tonic-gate 		}
13817c478bd9Sstevel@tonic-gate 		break;
13827c478bd9Sstevel@tonic-gate 
13837c478bd9Sstevel@tonic-gate 	case IEEE1394_TCODE_READ_BLOCK:
13847c478bd9Sstevel@tonic-gate 		/*
13857c478bd9Sstevel@tonic-gate 		 * We got a ARREQ block read request. Read in the packet.
13867c478bd9Sstevel@tonic-gate 		 * If there is a problem with the packet (i.e. we don't get
13877c478bd9Sstevel@tonic-gate 		 * DDI_SUCCESS), we will free up the command and return NULL in
13887c478bd9Sstevel@tonic-gate 		 * hcicmd to indicate that we did not get a valid ARREQ to
13897c478bd9Sstevel@tonic-gate 		 * process.
13907c478bd9Sstevel@tonic-gate 		 */
13917c478bd9Sstevel@tonic-gate 		status = hci1394_async_arreq_read_brd(async_handle, pkt,
13927c478bd9Sstevel@tonic-gate 		    *hcicmd, size);
13937c478bd9Sstevel@tonic-gate 		if (status != DDI_SUCCESS) {
13947c478bd9Sstevel@tonic-gate 			hci1394_async_response_complete(async_handle, cmd,
13957c478bd9Sstevel@tonic-gate 			    cmd_priv);
13967c478bd9Sstevel@tonic-gate 			*hcicmd = NULL;
13977c478bd9Sstevel@tonic-gate 			return (DDI_SUCCESS);
13987c478bd9Sstevel@tonic-gate 		}
13997c478bd9Sstevel@tonic-gate 		break;
14007c478bd9Sstevel@tonic-gate 
14017c478bd9Sstevel@tonic-gate 	case IEEE1394_TCODE_WRITE_BLOCK:
14027c478bd9Sstevel@tonic-gate 		/*
14037c478bd9Sstevel@tonic-gate 		 * We got a ARREQ block write request. Read in the packet.
14047c478bd9Sstevel@tonic-gate 		 * If there is a problem with the packet (i.e. we don't get
14057c478bd9Sstevel@tonic-gate 		 * DDI_SUCCESS), we will free up the command and return NULL in
14067c478bd9Sstevel@tonic-gate 		 * hcicmd to indicate that we did not get a valid ARREQ to
14077c478bd9Sstevel@tonic-gate 		 * process.
14087c478bd9Sstevel@tonic-gate 		 */
14097c478bd9Sstevel@tonic-gate 		status = hci1394_async_arreq_read_bwr(async_handle, pkt,
14107c478bd9Sstevel@tonic-gate 		    *hcicmd, size);
14117c478bd9Sstevel@tonic-gate 		if (status != DDI_SUCCESS) {
14127c478bd9Sstevel@tonic-gate 			hci1394_async_response_complete(async_handle, cmd,
14137c478bd9Sstevel@tonic-gate 			    cmd_priv);
14147c478bd9Sstevel@tonic-gate 			*hcicmd = NULL;
14157c478bd9Sstevel@tonic-gate 			return (DDI_SUCCESS);
14167c478bd9Sstevel@tonic-gate 		}
14177c478bd9Sstevel@tonic-gate 		break;
14187c478bd9Sstevel@tonic-gate 
14197c478bd9Sstevel@tonic-gate 	case IEEE1394_TCODE_LOCK:
14207c478bd9Sstevel@tonic-gate 		/*
14217c478bd9Sstevel@tonic-gate 		 * We got a ARREQ lock request. Read in the packet.
14227c478bd9Sstevel@tonic-gate 		 * If there is a problem with the packet (i.e. we don't get
14237c478bd9Sstevel@tonic-gate 		 * DDI_SUCCESS), we will free up the command and return NULL in
14247c478bd9Sstevel@tonic-gate 		 * hcicmd to indicate that we did not get a valid ARREQ to
14257c478bd9Sstevel@tonic-gate 		 * process.
14267c478bd9Sstevel@tonic-gate 		 */
14277c478bd9Sstevel@tonic-gate 		status = hci1394_async_arreq_read_lck(async_handle, pkt,
14287c478bd9Sstevel@tonic-gate 		    *hcicmd, size);
14297c478bd9Sstevel@tonic-gate 		if (status != DDI_SUCCESS) {
14307c478bd9Sstevel@tonic-gate 			hci1394_async_response_complete(async_handle, cmd,
14317c478bd9Sstevel@tonic-gate 			    cmd_priv);
14327c478bd9Sstevel@tonic-gate 			*hcicmd = NULL;
14337c478bd9Sstevel@tonic-gate 			return (DDI_SUCCESS);
14347c478bd9Sstevel@tonic-gate 		}
14357c478bd9Sstevel@tonic-gate 		break;
14367c478bd9Sstevel@tonic-gate 
14377c478bd9Sstevel@tonic-gate 	case IEEE1394_TCODE_PHY:
14387c478bd9Sstevel@tonic-gate 		/*
14397c478bd9Sstevel@tonic-gate 		 * We got a PHY packet in the ARREQ buffer. Read in the packet.
14407c478bd9Sstevel@tonic-gate 		 * If there is a problem with the packet (i.e. we don't get
14417c478bd9Sstevel@tonic-gate 		 * DDI_SUCCESS), we will free up the command and return NULL in
14427c478bd9Sstevel@tonic-gate 		 * hcicmd to indicate that we did not get a valid ARREQ to
14437c478bd9Sstevel@tonic-gate 		 * process.
14447c478bd9Sstevel@tonic-gate 		 */
14457c478bd9Sstevel@tonic-gate 		status = hci1394_async_arreq_read_phy(async_handle, pkt,
14467c478bd9Sstevel@tonic-gate 		    *hcicmd, size, &is_reset_token);
14477c478bd9Sstevel@tonic-gate 		if (status != DDI_SUCCESS) {
14487c478bd9Sstevel@tonic-gate 			hci1394_async_response_complete(async_handle, cmd,
14497c478bd9Sstevel@tonic-gate 			    cmd_priv);
14507c478bd9Sstevel@tonic-gate 			*hcicmd = NULL;
14517c478bd9Sstevel@tonic-gate 			return (DDI_SUCCESS);
14527c478bd9Sstevel@tonic-gate 		}
14537c478bd9Sstevel@tonic-gate 
14547c478bd9Sstevel@tonic-gate 		/*
14557c478bd9Sstevel@tonic-gate 		 * If we got a bus reset token, free up the command and return
14567c478bd9Sstevel@tonic-gate 		 * NULL in hcicmd to indicate that we did not get a valid ARREQ
14577c478bd9Sstevel@tonic-gate 		 * to process.
14587c478bd9Sstevel@tonic-gate 		 */
14597c478bd9Sstevel@tonic-gate 		if (is_reset_token == B_TRUE) {
14607c478bd9Sstevel@tonic-gate 			hci1394_async_response_complete(async_handle, cmd,
14617c478bd9Sstevel@tonic-gate 			    cmd_priv);
14627c478bd9Sstevel@tonic-gate 			*hcicmd = NULL;
14637c478bd9Sstevel@tonic-gate 			return (DDI_SUCCESS);
14647c478bd9Sstevel@tonic-gate 		}
14657c478bd9Sstevel@tonic-gate 		break;
14667c478bd9Sstevel@tonic-gate 
14677c478bd9Sstevel@tonic-gate 	default:
14687c478bd9Sstevel@tonic-gate 		/* we got a tcode that we don't know about. Return error */
14697c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
14707c478bd9Sstevel@tonic-gate 	}
14717c478bd9Sstevel@tonic-gate 
14727c478bd9Sstevel@tonic-gate 	/*
14737c478bd9Sstevel@tonic-gate 	 * If this command was broadcast and it was not a write, drop the
14747c478bd9Sstevel@tonic-gate 	 * command since it's an invalid request. We will free up the command
14757c478bd9Sstevel@tonic-gate 	 * and return NULL in hcicmd to indicate that we did not get a valid
14767c478bd9Sstevel@tonic-gate 	 * ARREQ to process.
14777c478bd9Sstevel@tonic-gate 	 */
14787c478bd9Sstevel@tonic-gate 	if ((((*hcicmd)->ac_dest & IEEE1394_NODE_NUM_MASK) ==
14797c478bd9Sstevel@tonic-gate 	    IEEE1394_BROADCAST_NODEID) && ((*tcode !=
14807c478bd9Sstevel@tonic-gate 	    IEEE1394_TCODE_WRITE_QUADLET) && (*tcode !=
14817c478bd9Sstevel@tonic-gate 	    IEEE1394_TCODE_WRITE_BLOCK))) {
14827c478bd9Sstevel@tonic-gate 		hci1394_async_response_complete(async_handle, cmd, cmd_priv);
14837c478bd9Sstevel@tonic-gate 		*hcicmd = NULL;
14847c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
14857c478bd9Sstevel@tonic-gate 
14867c478bd9Sstevel@tonic-gate 	/*
14877c478bd9Sstevel@tonic-gate 	 * It is a valid broadcast command, set that field in the public
14887c478bd9Sstevel@tonic-gate 	 * command structure.
14897c478bd9Sstevel@tonic-gate 	 */
14907c478bd9Sstevel@tonic-gate 	} else if ((((*hcicmd)->ac_dest & IEEE1394_NODE_NUM_MASK) ==
14917c478bd9Sstevel@tonic-gate 	    IEEE1394_BROADCAST_NODEID)) {
14927c478bd9Sstevel@tonic-gate 		cmd->broadcast = 1;
14937c478bd9Sstevel@tonic-gate 	}
14947c478bd9Sstevel@tonic-gate 
14957c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
14967c478bd9Sstevel@tonic-gate }
14977c478bd9Sstevel@tonic-gate 
14987c478bd9Sstevel@tonic-gate 
14997c478bd9Sstevel@tonic-gate /*
15007c478bd9Sstevel@tonic-gate  * hci1394_async_arreq_read_qrd()
15017c478bd9Sstevel@tonic-gate  *    Read ARREQ quadlet read into the 1394 Framework command. This routine will
15027c478bd9Sstevel@tonic-gate  *    return DDI_FAILURE if it was not able to read the request succesfully.
15037c478bd9Sstevel@tonic-gate  */
15047c478bd9Sstevel@tonic-gate static int
hci1394_async_arreq_read_qrd(hci1394_async_handle_t async_handle,hci1394_basic_pkt_t * pkt,hci1394_async_cmd_t * hcicmd,uint_t * size)15057c478bd9Sstevel@tonic-gate hci1394_async_arreq_read_qrd(hci1394_async_handle_t async_handle,
15067c478bd9Sstevel@tonic-gate     hci1394_basic_pkt_t *pkt, hci1394_async_cmd_t *hcicmd, uint_t *size)
15077c478bd9Sstevel@tonic-gate {
15087c478bd9Sstevel@tonic-gate 	h1394_cmd_priv_t *cmd_priv;
15097c478bd9Sstevel@tonic-gate 	cmd1394_cmd_t *cmd;
15107c478bd9Sstevel@tonic-gate 	uint32_t quadlet;
15117c478bd9Sstevel@tonic-gate 
15127c478bd9Sstevel@tonic-gate 
15137c478bd9Sstevel@tonic-gate 	ASSERT(async_handle != NULL);
15147c478bd9Sstevel@tonic-gate 	ASSERT(pkt != NULL);
15157c478bd9Sstevel@tonic-gate 	ASSERT(hcicmd != NULL);
15167c478bd9Sstevel@tonic-gate 	ASSERT(size != NULL);
15177c478bd9Sstevel@tonic-gate 
15187c478bd9Sstevel@tonic-gate 	/* Setup shortcuts, command type, and size of request */
15197c478bd9Sstevel@tonic-gate 	cmd = hcicmd->ac_cmd;
15207c478bd9Sstevel@tonic-gate 	cmd_priv = hcicmd->ac_priv;
15217c478bd9Sstevel@tonic-gate 	cmd->cmd_type = CMD1394_ASYNCH_RD_QUAD;
15227c478bd9Sstevel@tonic-gate 	*size = DESC_SZ_AR_READQUAD_REQ;
15237c478bd9Sstevel@tonic-gate 
15247c478bd9Sstevel@tonic-gate 	/*
15257c478bd9Sstevel@tonic-gate 	 * read in the ARREQ ACK/EVT, the speed, the time we received it, and
15267c478bd9Sstevel@tonic-gate 	 * calculate the ATRESP timeout for when we send it.
15277c478bd9Sstevel@tonic-gate 	 */
15287c478bd9Sstevel@tonic-gate 	quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q4);
15297c478bd9Sstevel@tonic-gate 	hcicmd->ac_status = HCI1394_DESC_EVT_GET(quadlet);
15307c478bd9Sstevel@tonic-gate 	cmd_priv->speed = HCI1394_DESC_AR_SPD_GET(quadlet);
15317c478bd9Sstevel@tonic-gate 	cmd_priv->recv_tstamp = HCI1394_DESC_TIMESTAMP_GET(quadlet);
15327c478bd9Sstevel@tonic-gate 	hcicmd->ac_qcmd.qc_timestamp = hci1394_async_timeout_calc(async_handle,
15337c478bd9Sstevel@tonic-gate 	    cmd_priv->recv_tstamp);
15347c478bd9Sstevel@tonic-gate 
15357c478bd9Sstevel@tonic-gate 	/*
15367c478bd9Sstevel@tonic-gate 	 * if the ARREQ ACK was bad, we were unable to successfully read in this
15377c478bd9Sstevel@tonic-gate 	 * request.  Return failure.
15387c478bd9Sstevel@tonic-gate 	 */
15397c478bd9Sstevel@tonic-gate 	if ((hcicmd->ac_status != OHCI_ACK_COMPLETE) &&
15407c478bd9Sstevel@tonic-gate 	    (hcicmd->ac_status != OHCI_ACK_PENDING)) {
15417c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
15427c478bd9Sstevel@tonic-gate 	}
15437c478bd9Sstevel@tonic-gate 
15447c478bd9Sstevel@tonic-gate 	/*
15457c478bd9Sstevel@tonic-gate 	 * Read in the tlabel and destination. We don't use an mblk for this
15467c478bd9Sstevel@tonic-gate 	 * request.
15477c478bd9Sstevel@tonic-gate 	 */
15487c478bd9Sstevel@tonic-gate 	quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q1);
15497c478bd9Sstevel@tonic-gate 	hcicmd->ac_dest = HCI1394_DESC_DESTID_GET(quadlet);
15507c478bd9Sstevel@tonic-gate 	hcicmd->ac_tlabel.tbi_tlabel = HCI1394_DESC_TLABEL_GET(quadlet);
15517c478bd9Sstevel@tonic-gate 	hcicmd->ac_mblk_alloc = B_FALSE;
15527c478bd9Sstevel@tonic-gate 
15537c478bd9Sstevel@tonic-gate 	/*
15547c478bd9Sstevel@tonic-gate 	 * Read in the sender so we know who to send the ATRESP to and read in
15557c478bd9Sstevel@tonic-gate 	 * the 1394 48-bit address for this request.
15567c478bd9Sstevel@tonic-gate 	 */
15577c478bd9Sstevel@tonic-gate 	quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q2);
15587c478bd9Sstevel@tonic-gate 	cmd->nodeID = HCI1394_DESC_SRCID_GET(quadlet);
15597c478bd9Sstevel@tonic-gate 	cmd->cmd_addr = HCI1394_TO_ADDR_HI(quadlet);
15607c478bd9Sstevel@tonic-gate 	quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q3);
15617c478bd9Sstevel@tonic-gate 	cmd->cmd_addr |= HCI1394_TO_ADDR_LO(quadlet);
15627c478bd9Sstevel@tonic-gate 
15637c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
15647c478bd9Sstevel@tonic-gate }
15657c478bd9Sstevel@tonic-gate 
15667c478bd9Sstevel@tonic-gate 
15677c478bd9Sstevel@tonic-gate /*
15687c478bd9Sstevel@tonic-gate  * hci1394_async_arreq_read_qwr()
15697c478bd9Sstevel@tonic-gate  *    Read ARREQ quadlet write into the 1394 Framework command. This routine
15707c478bd9Sstevel@tonic-gate  *    will return DDI_FAILURE if it was not able to read the request
15717c478bd9Sstevel@tonic-gate  *    succesfully.
15727c478bd9Sstevel@tonic-gate  */
15737c478bd9Sstevel@tonic-gate static int
hci1394_async_arreq_read_qwr(hci1394_async_handle_t async_handle,hci1394_basic_pkt_t * pkt,hci1394_async_cmd_t * hcicmd,uint_t * size)15747c478bd9Sstevel@tonic-gate hci1394_async_arreq_read_qwr(hci1394_async_handle_t async_handle,
15757c478bd9Sstevel@tonic-gate     hci1394_basic_pkt_t *pkt, hci1394_async_cmd_t *hcicmd, uint_t *size)
15767c478bd9Sstevel@tonic-gate {
15777c478bd9Sstevel@tonic-gate 	h1394_cmd_priv_t *cmd_priv;
15787c478bd9Sstevel@tonic-gate 	cmd1394_cmd_t *cmd;
15797c478bd9Sstevel@tonic-gate 	uint32_t quadlet;
15807c478bd9Sstevel@tonic-gate 
15817c478bd9Sstevel@tonic-gate 
15827c478bd9Sstevel@tonic-gate 	ASSERT(async_handle != NULL);
15837c478bd9Sstevel@tonic-gate 	ASSERT(pkt != NULL);
15847c478bd9Sstevel@tonic-gate 	ASSERT(hcicmd != NULL);
15857c478bd9Sstevel@tonic-gate 	ASSERT(size != NULL);
15867c478bd9Sstevel@tonic-gate 
15877c478bd9Sstevel@tonic-gate 	/* Setup shortcuts, command type, and size of request */
15887c478bd9Sstevel@tonic-gate 	cmd = hcicmd->ac_cmd;
15897c478bd9Sstevel@tonic-gate 	cmd_priv = hcicmd->ac_priv;
15907c478bd9Sstevel@tonic-gate 	cmd->cmd_type = CMD1394_ASYNCH_WR_QUAD;
15917c478bd9Sstevel@tonic-gate 	*size = DESC_SZ_AR_WRITEQUAD_REQ;
15927c478bd9Sstevel@tonic-gate 
15937c478bd9Sstevel@tonic-gate 	/*
15947c478bd9Sstevel@tonic-gate 	 * read in the ARREQ ACK/EVT, the speed, the time we received it, and
15957c478bd9Sstevel@tonic-gate 	 * calculate the ATRESP timeout for when we send it.
15967c478bd9Sstevel@tonic-gate 	 */
15977c478bd9Sstevel@tonic-gate 	quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q5);
15987c478bd9Sstevel@tonic-gate 	hcicmd->ac_status = HCI1394_DESC_EVT_GET(quadlet);
15997c478bd9Sstevel@tonic-gate 	cmd_priv->speed = HCI1394_DESC_AR_SPD_GET(quadlet);
16007c478bd9Sstevel@tonic-gate 	cmd_priv->recv_tstamp = HCI1394_DESC_TIMESTAMP_GET(quadlet);
16017c478bd9Sstevel@tonic-gate 	hcicmd->ac_qcmd.qc_timestamp = hci1394_async_timeout_calc(async_handle,
16027c478bd9Sstevel@tonic-gate 	    cmd_priv->recv_tstamp);
16037c478bd9Sstevel@tonic-gate 
16047c478bd9Sstevel@tonic-gate 	/*
16057c478bd9Sstevel@tonic-gate 	 * if the ARREQ ACK was bad, we were unable to successfully read in this
16067c478bd9Sstevel@tonic-gate 	 * request.  Return failure.
16077c478bd9Sstevel@tonic-gate 	 */
16087c478bd9Sstevel@tonic-gate 	if ((hcicmd->ac_status != OHCI_ACK_COMPLETE) &&
16097c478bd9Sstevel@tonic-gate 	    (hcicmd->ac_status != OHCI_ACK_PENDING)) {
16107c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
16117c478bd9Sstevel@tonic-gate 	}
16127c478bd9Sstevel@tonic-gate 
16137c478bd9Sstevel@tonic-gate 	/*
16147c478bd9Sstevel@tonic-gate 	 * Read in the tlabel and destination. We don't use an mblk for this
16157c478bd9Sstevel@tonic-gate 	 * request.
16167c478bd9Sstevel@tonic-gate 	 */
16177c478bd9Sstevel@tonic-gate 	quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q1);
16187c478bd9Sstevel@tonic-gate 	hcicmd->ac_dest = HCI1394_DESC_DESTID_GET(quadlet);
16197c478bd9Sstevel@tonic-gate 	hcicmd->ac_tlabel.tbi_tlabel = HCI1394_DESC_TLABEL_GET(quadlet);
16207c478bd9Sstevel@tonic-gate 	hcicmd->ac_mblk_alloc = B_FALSE;
16217c478bd9Sstevel@tonic-gate 
16227c478bd9Sstevel@tonic-gate 	/*
16237c478bd9Sstevel@tonic-gate 	 * Read in the sender so we know who to send the ATRESP to. Read in
16247c478bd9Sstevel@tonic-gate 	 * the 1394 48-bit address for this request. Copy the data quadlet into
16257c478bd9Sstevel@tonic-gate 	 * the command.  The data quadlet is treated like a byte stream.
16267c478bd9Sstevel@tonic-gate 	 */
16277c478bd9Sstevel@tonic-gate 	quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q2);
16287c478bd9Sstevel@tonic-gate 	cmd->nodeID = HCI1394_DESC_SRCID_GET(quadlet);
16297c478bd9Sstevel@tonic-gate 	cmd->cmd_addr = HCI1394_TO_ADDR_HI(quadlet);
16307c478bd9Sstevel@tonic-gate 	quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q3);
16317c478bd9Sstevel@tonic-gate 	cmd->cmd_addr |= HCI1394_TO_ADDR_LO(quadlet);
16327c478bd9Sstevel@tonic-gate 	hci1394_q_ar_rep_get8(async_handle->as_arreq_q,
16337c478bd9Sstevel@tonic-gate 	    (uint8_t *)&cmd->cmd_u.q.quadlet_data, (uint8_t *)&pkt->q4,
16347c478bd9Sstevel@tonic-gate 	    IEEE1394_QUADLET);
16357c478bd9Sstevel@tonic-gate 
16367c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
16377c478bd9Sstevel@tonic-gate }
16387c478bd9Sstevel@tonic-gate 
16397c478bd9Sstevel@tonic-gate 
16407c478bd9Sstevel@tonic-gate /*
16417c478bd9Sstevel@tonic-gate  * hci1394_async_arreq_read_brd()
16427c478bd9Sstevel@tonic-gate  *    Read ARREQ block read into the 1394 Framework command. This routine will
16437c478bd9Sstevel@tonic-gate  *    return DDI_FAILURE if it was not able to read the request succesfully.
16447c478bd9Sstevel@tonic-gate  */
16457c478bd9Sstevel@tonic-gate static int
hci1394_async_arreq_read_brd(hci1394_async_handle_t async_handle,hci1394_basic_pkt_t * pkt,hci1394_async_cmd_t * hcicmd,uint_t * size)16467c478bd9Sstevel@tonic-gate hci1394_async_arreq_read_brd(hci1394_async_handle_t async_handle,
16477c478bd9Sstevel@tonic-gate     hci1394_basic_pkt_t *pkt, hci1394_async_cmd_t *hcicmd, uint_t *size)
16487c478bd9Sstevel@tonic-gate {
16497c478bd9Sstevel@tonic-gate 	h1394_cmd_priv_t *cmd_priv;
16507c478bd9Sstevel@tonic-gate 	cmd1394_cmd_t *cmd;
16517c478bd9Sstevel@tonic-gate 	uint32_t quadlet;
16527c478bd9Sstevel@tonic-gate 
16537c478bd9Sstevel@tonic-gate 
16547c478bd9Sstevel@tonic-gate 	ASSERT(async_handle != NULL);
16557c478bd9Sstevel@tonic-gate 	ASSERT(pkt != NULL);
16567c478bd9Sstevel@tonic-gate 	ASSERT(hcicmd != NULL);
16577c478bd9Sstevel@tonic-gate 	ASSERT(size != NULL);
16587c478bd9Sstevel@tonic-gate 
16597c478bd9Sstevel@tonic-gate 	/* Setup shortcuts, command type, and size of request */
16607c478bd9Sstevel@tonic-gate 	cmd = hcicmd->ac_cmd;
16617c478bd9Sstevel@tonic-gate 	cmd_priv = hcicmd->ac_priv;
16627c478bd9Sstevel@tonic-gate 	cmd->cmd_type = CMD1394_ASYNCH_RD_BLOCK;
16637c478bd9Sstevel@tonic-gate 	*size = DESC_SZ_AR_READBLOCK_REQ;
16647c478bd9Sstevel@tonic-gate 
16657c478bd9Sstevel@tonic-gate 	/*
16667c478bd9Sstevel@tonic-gate 	 * read in the ARREQ ACK/EVT, the speed, the time we received it, and
16677c478bd9Sstevel@tonic-gate 	 * calculate the ATRESP timeout for when we send it.
16687c478bd9Sstevel@tonic-gate 	 */
16697c478bd9Sstevel@tonic-gate 	quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q5);
16707c478bd9Sstevel@tonic-gate 	hcicmd->ac_status = HCI1394_DESC_EVT_GET(quadlet);
16717c478bd9Sstevel@tonic-gate 	cmd_priv->speed = HCI1394_DESC_AR_SPD_GET(quadlet);
16727c478bd9Sstevel@tonic-gate 	cmd_priv->recv_tstamp = HCI1394_DESC_TIMESTAMP_GET(quadlet);
16737c478bd9Sstevel@tonic-gate 	hcicmd->ac_qcmd.qc_timestamp = hci1394_async_timeout_calc(async_handle,
16747c478bd9Sstevel@tonic-gate 	    cmd_priv->recv_tstamp);
16757c478bd9Sstevel@tonic-gate 
16767c478bd9Sstevel@tonic-gate 	/*
16777c478bd9Sstevel@tonic-gate 	 * if the ARREQ ACK was bad, we were unable to successfully read in this
16787c478bd9Sstevel@tonic-gate 	 * request.  Return failure.
16797c478bd9Sstevel@tonic-gate 	 */
16807c478bd9Sstevel@tonic-gate 	if ((hcicmd->ac_status != OHCI_ACK_COMPLETE) &&
16817c478bd9Sstevel@tonic-gate 	    (hcicmd->ac_status != OHCI_ACK_PENDING)) {
16827c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
16837c478bd9Sstevel@tonic-gate 	}
16847c478bd9Sstevel@tonic-gate 
16857c478bd9Sstevel@tonic-gate 	/* Read in the tlabel and destination */
16867c478bd9Sstevel@tonic-gate 	quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q1);
16877c478bd9Sstevel@tonic-gate 	hcicmd->ac_dest = HCI1394_DESC_DESTID_GET(quadlet);
16887c478bd9Sstevel@tonic-gate 	hcicmd->ac_tlabel.tbi_tlabel = HCI1394_DESC_TLABEL_GET(quadlet);
16897c478bd9Sstevel@tonic-gate 
16907c478bd9Sstevel@tonic-gate 	/*
16917c478bd9Sstevel@tonic-gate 	 * Read in the sender so we know who to send the ATRESP to. Read in
16927c478bd9Sstevel@tonic-gate 	 * the 1394 48-bit address for this request. Read in the block data size
16937c478bd9Sstevel@tonic-gate 	 * and allocate an mblk of that size.
16947c478bd9Sstevel@tonic-gate 	 */
16957c478bd9Sstevel@tonic-gate 	quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q2);
16967c478bd9Sstevel@tonic-gate 	cmd->nodeID = HCI1394_DESC_SRCID_GET(quadlet);
16977c478bd9Sstevel@tonic-gate 	cmd->cmd_addr = HCI1394_TO_ADDR_HI(quadlet);
16987c478bd9Sstevel@tonic-gate 	quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q3);
16997c478bd9Sstevel@tonic-gate 	cmd->cmd_addr |= HCI1394_TO_ADDR_LO(quadlet);
17007c478bd9Sstevel@tonic-gate 	quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q4);
17017c478bd9Sstevel@tonic-gate 	cmd->cmd_u.b.blk_length = HCI1394_DESC_DATALEN_GET(quadlet);
17027c478bd9Sstevel@tonic-gate 	cmd->cmd_u.b.data_block = allocb(cmd->cmd_u.b.blk_length, 0);
17037c478bd9Sstevel@tonic-gate 	if (cmd->cmd_u.b.data_block == NULL) {
17047c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
17057c478bd9Sstevel@tonic-gate 	}
17067c478bd9Sstevel@tonic-gate 	hcicmd->ac_mblk_alloc = B_TRUE;
17077c478bd9Sstevel@tonic-gate 
17087c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
17097c478bd9Sstevel@tonic-gate }
17107c478bd9Sstevel@tonic-gate 
17117c478bd9Sstevel@tonic-gate 
17127c478bd9Sstevel@tonic-gate /*
17137c478bd9Sstevel@tonic-gate  * hci1394_async_arreq_read_bwr()
17147c478bd9Sstevel@tonic-gate  *    Read ARREQ block write into the 1394 Framework command. This routine will
17157c478bd9Sstevel@tonic-gate  *    return DDI_FAILURE if it was not able to read the request succesfully.
17167c478bd9Sstevel@tonic-gate  */
17177c478bd9Sstevel@tonic-gate static int
hci1394_async_arreq_read_bwr(hci1394_async_handle_t async_handle,hci1394_basic_pkt_t * pkt,hci1394_async_cmd_t * hcicmd,uint_t * size)17187c478bd9Sstevel@tonic-gate hci1394_async_arreq_read_bwr(hci1394_async_handle_t async_handle,
17197c478bd9Sstevel@tonic-gate     hci1394_basic_pkt_t *pkt, hci1394_async_cmd_t *hcicmd, uint_t *size)
17207c478bd9Sstevel@tonic-gate {
17217c478bd9Sstevel@tonic-gate 	h1394_cmd_priv_t *cmd_priv;
17227c478bd9Sstevel@tonic-gate 	uint32_t *local_addr;
17237c478bd9Sstevel@tonic-gate 	cmd1394_cmd_t *cmd;
17247c478bd9Sstevel@tonic-gate 	uint32_t quadlet;
17257c478bd9Sstevel@tonic-gate 
17267c478bd9Sstevel@tonic-gate 
17277c478bd9Sstevel@tonic-gate 	ASSERT(async_handle != NULL);
17287c478bd9Sstevel@tonic-gate 	ASSERT(pkt != NULL);
17297c478bd9Sstevel@tonic-gate 	ASSERT(hcicmd != NULL);
17307c478bd9Sstevel@tonic-gate 	ASSERT(size != NULL);
17317c478bd9Sstevel@tonic-gate 
17327c478bd9Sstevel@tonic-gate 	/*
17337c478bd9Sstevel@tonic-gate 	 * Setup shortcuts, command type, and size of request. The size of the
17347c478bd9Sstevel@tonic-gate 	 * request is in quadlets, therefore we need to make sure we count in
17357c478bd9Sstevel@tonic-gate 	 * the padding when figureing out the size (i.e. data may be in bytes
17367c478bd9Sstevel@tonic-gate 	 * but the HW always pads to quadlets)
17377c478bd9Sstevel@tonic-gate 	 */
17387c478bd9Sstevel@tonic-gate 	cmd = hcicmd->ac_cmd;
17397c478bd9Sstevel@tonic-gate 	cmd_priv = hcicmd->ac_priv;
17407c478bd9Sstevel@tonic-gate 	cmd->cmd_type = CMD1394_ASYNCH_WR_BLOCK;
17417c478bd9Sstevel@tonic-gate 	quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q4);
17427c478bd9Sstevel@tonic-gate 	cmd->cmd_u.b.blk_length = HCI1394_DESC_DATALEN_GET(quadlet);
17437c478bd9Sstevel@tonic-gate 	*size = DESC_SZ_AR_WRITEBLOCK_REQ +
17447c478bd9Sstevel@tonic-gate 	    HCI1394_ALIGN_QUAD(cmd->cmd_u.b.blk_length);
17457c478bd9Sstevel@tonic-gate 
17467c478bd9Sstevel@tonic-gate 	/*
17477c478bd9Sstevel@tonic-gate 	 * read in the ARREQ ACK/EVT, the speed, the time we received it, and
17487c478bd9Sstevel@tonic-gate 	 * calculate the ATRESP timeout for when we send it. The status word is
17497c478bd9Sstevel@tonic-gate 	 * the last quadlet in the packet.
17507c478bd9Sstevel@tonic-gate 	 */
17517c478bd9Sstevel@tonic-gate 	local_addr = (uint32_t *)(((uintptr_t)(&pkt->q5)) +
17527c478bd9Sstevel@tonic-gate 	    ((uintptr_t)HCI1394_ALIGN_QUAD(cmd->cmd_u.b.blk_length)));
17537c478bd9Sstevel@tonic-gate 	quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, local_addr);
17547c478bd9Sstevel@tonic-gate 	hcicmd->ac_status = HCI1394_DESC_EVT_GET(quadlet);
17557c478bd9Sstevel@tonic-gate 	cmd_priv->speed = HCI1394_DESC_AR_SPD_GET(quadlet);
17567c478bd9Sstevel@tonic-gate 	cmd_priv->recv_tstamp = HCI1394_DESC_TIMESTAMP_GET(quadlet);
17577c478bd9Sstevel@tonic-gate 	hcicmd->ac_qcmd.qc_timestamp = hci1394_async_timeout_calc(async_handle,
17587c478bd9Sstevel@tonic-gate 	    cmd_priv->recv_tstamp);
17597c478bd9Sstevel@tonic-gate 
17607c478bd9Sstevel@tonic-gate 	/*
17617c478bd9Sstevel@tonic-gate 	 * if the ARREQ ACK was bad, we were unable to successfully read in this
17627c478bd9Sstevel@tonic-gate 	 * request.  Return failure.
17637c478bd9Sstevel@tonic-gate 	 */
17647c478bd9Sstevel@tonic-gate 	if ((hcicmd->ac_status != OHCI_ACK_COMPLETE) &&
17657c478bd9Sstevel@tonic-gate 	    (hcicmd->ac_status != OHCI_ACK_PENDING)) {
17667c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
17677c478bd9Sstevel@tonic-gate 	}
17687c478bd9Sstevel@tonic-gate 
17697c478bd9Sstevel@tonic-gate 	/* Read in the tlabel and destination */
17707c478bd9Sstevel@tonic-gate 	quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q1);
17717c478bd9Sstevel@tonic-gate 	hcicmd->ac_dest = HCI1394_DESC_DESTID_GET(quadlet);
17727c478bd9Sstevel@tonic-gate 	hcicmd->ac_tlabel.tbi_tlabel = HCI1394_DESC_TLABEL_GET(quadlet);
17737c478bd9Sstevel@tonic-gate 
17747c478bd9Sstevel@tonic-gate 	/*
17757c478bd9Sstevel@tonic-gate 	 * Read in the sender so we know who to send the ATRESP to. Read in
17767c478bd9Sstevel@tonic-gate 	 * the 1394 48-bit address for this request. Read in the block data size
17777c478bd9Sstevel@tonic-gate 	 * and allocate an mblk of that size.
17787c478bd9Sstevel@tonic-gate 	 */
17797c478bd9Sstevel@tonic-gate 	quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q2);
17807c478bd9Sstevel@tonic-gate 	cmd->nodeID = HCI1394_DESC_SRCID_GET(quadlet);
17817c478bd9Sstevel@tonic-gate 	cmd->cmd_addr = HCI1394_TO_ADDR_HI(quadlet);
17827c478bd9Sstevel@tonic-gate 	quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q3);
17837c478bd9Sstevel@tonic-gate 	cmd->cmd_addr |= HCI1394_TO_ADDR_LO(quadlet);
17847c478bd9Sstevel@tonic-gate 	cmd->cmd_u.b.data_block = allocb(cmd->cmd_u.b.blk_length, 0);
17857c478bd9Sstevel@tonic-gate 	if (cmd->cmd_u.b.data_block == NULL) {
17867c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
17877c478bd9Sstevel@tonic-gate 	}
17887c478bd9Sstevel@tonic-gate 	hcicmd->ac_mblk_alloc = B_TRUE;
17897c478bd9Sstevel@tonic-gate 
17907c478bd9Sstevel@tonic-gate 	/* Copy ARREQ write data into mblk_t */
17917c478bd9Sstevel@tonic-gate 	hci1394_q_ar_rep_get8(async_handle->as_arreq_q,
17927c478bd9Sstevel@tonic-gate 	    (uint8_t *)cmd->cmd_u.b.data_block->b_wptr,
17937c478bd9Sstevel@tonic-gate 	    (uint8_t *)&pkt->q5, cmd->cmd_u.b.blk_length);
17947c478bd9Sstevel@tonic-gate 
17957c478bd9Sstevel@tonic-gate 	/* Update mblk_t wptr */
17967c478bd9Sstevel@tonic-gate 	cmd->cmd_u.b.data_block->b_wptr += cmd->cmd_u.b.blk_length;
17977c478bd9Sstevel@tonic-gate 
17987c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
17997c478bd9Sstevel@tonic-gate }
18007c478bd9Sstevel@tonic-gate 
18017c478bd9Sstevel@tonic-gate 
18027c478bd9Sstevel@tonic-gate /*
18037c478bd9Sstevel@tonic-gate  * hci1394_async_arreq_read_lck()
18047c478bd9Sstevel@tonic-gate  *    Read ARREQ lock request into the 1394 Framework command. This routine will
18057c478bd9Sstevel@tonic-gate  *    return DDI_FAILURE if it was not able to read the request succesfully.
18067c478bd9Sstevel@tonic-gate  */
18077c478bd9Sstevel@tonic-gate static int
hci1394_async_arreq_read_lck(hci1394_async_handle_t async_handle,hci1394_basic_pkt_t * pkt,hci1394_async_cmd_t * hcicmd,uint_t * size)18087c478bd9Sstevel@tonic-gate hci1394_async_arreq_read_lck(hci1394_async_handle_t async_handle,
18097c478bd9Sstevel@tonic-gate     hci1394_basic_pkt_t *pkt, hci1394_async_cmd_t *hcicmd, uint_t *size)
18107c478bd9Sstevel@tonic-gate {
18117c478bd9Sstevel@tonic-gate 	h1394_cmd_priv_t *cmd_priv;
18127c478bd9Sstevel@tonic-gate 	uint32_t *local_addr;
18137c478bd9Sstevel@tonic-gate 	cmd1394_cmd_t *cmd;
18147c478bd9Sstevel@tonic-gate 	uint8_t *data_addr;
18157c478bd9Sstevel@tonic-gate 	uint32_t quadlet;
18167c478bd9Sstevel@tonic-gate 	uint32_t length;
18177c478bd9Sstevel@tonic-gate 
18187c478bd9Sstevel@tonic-gate 
18197c478bd9Sstevel@tonic-gate 	ASSERT(async_handle != NULL);
18207c478bd9Sstevel@tonic-gate 	ASSERT(pkt != NULL);
18217c478bd9Sstevel@tonic-gate 	ASSERT(hcicmd != NULL);
18227c478bd9Sstevel@tonic-gate 	ASSERT(size != NULL);
18237c478bd9Sstevel@tonic-gate 
18247c478bd9Sstevel@tonic-gate 	/*
18257c478bd9Sstevel@tonic-gate 	 * Setup shortcuts, command type, and size of request. The size of the
18267c478bd9Sstevel@tonic-gate 	 * request is in quadlets, therefore we need to make sure we count in
18277c478bd9Sstevel@tonic-gate 	 * the padding when figuring out the size (i.e. data may be in bytes
18287c478bd9Sstevel@tonic-gate 	 * but the HW always pads to quadlets)
18297c478bd9Sstevel@tonic-gate 	 */
18307c478bd9Sstevel@tonic-gate 	cmd = hcicmd->ac_cmd;
18317c478bd9Sstevel@tonic-gate 	cmd_priv = hcicmd->ac_priv;
18327c478bd9Sstevel@tonic-gate 	quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q4);
18337c478bd9Sstevel@tonic-gate 	length = HCI1394_DESC_DATALEN_GET(quadlet);
18347c478bd9Sstevel@tonic-gate 	*size = DESC_SZ_AR_LOCK_REQ + HCI1394_ALIGN_QUAD(length);
18357c478bd9Sstevel@tonic-gate 
18367c478bd9Sstevel@tonic-gate 	/* make sure the length is a valid lock request length */
18377c478bd9Sstevel@tonic-gate 	if (length == DESC_TWO_QUADS) {
18387c478bd9Sstevel@tonic-gate 		cmd->cmd_type = CMD1394_ASYNCH_LOCK_32;
18397c478bd9Sstevel@tonic-gate 		cmd->cmd_u.l32.lock_type = HCI1394_DESC_EXTTCODE_GET(quadlet);
18407c478bd9Sstevel@tonic-gate 	} else if (length == DESC_TWO_OCTLETS) {
18417c478bd9Sstevel@tonic-gate 		cmd->cmd_type = CMD1394_ASYNCH_LOCK_64;
18427c478bd9Sstevel@tonic-gate 		cmd->cmd_u.l64.lock_type = HCI1394_DESC_EXTTCODE_GET(quadlet);
18437c478bd9Sstevel@tonic-gate 	} else {
18447c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
18457c478bd9Sstevel@tonic-gate 	}
18467c478bd9Sstevel@tonic-gate 
18477c478bd9Sstevel@tonic-gate 	/*
18487c478bd9Sstevel@tonic-gate 	 * read in the ARREQ ACK/EVT, the speed, the time we received it, and
18497c478bd9Sstevel@tonic-gate 	 * calculate the ATRESP timeout for when we send it. The status word is
18507c478bd9Sstevel@tonic-gate 	 * the last quadlet in the packet.
18517c478bd9Sstevel@tonic-gate 	 */
18527c478bd9Sstevel@tonic-gate 	local_addr = (uint32_t *)(((uintptr_t)(&pkt->q5)) +
18537c478bd9Sstevel@tonic-gate 	    ((uintptr_t)HCI1394_ALIGN_QUAD(length)));
18547c478bd9Sstevel@tonic-gate 	quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, local_addr);
18557c478bd9Sstevel@tonic-gate 	hcicmd->ac_status = HCI1394_DESC_EVT_GET(quadlet);
18567c478bd9Sstevel@tonic-gate 	cmd_priv->speed = HCI1394_DESC_AR_SPD_GET(quadlet);
18577c478bd9Sstevel@tonic-gate 	cmd_priv->recv_tstamp = HCI1394_DESC_TIMESTAMP_GET(quadlet);
18587c478bd9Sstevel@tonic-gate 	hcicmd->ac_qcmd.qc_timestamp = hci1394_async_timeout_calc(async_handle,
18597c478bd9Sstevel@tonic-gate 	    cmd_priv->recv_tstamp);
18607c478bd9Sstevel@tonic-gate 
18617c478bd9Sstevel@tonic-gate 	/*
18627c478bd9Sstevel@tonic-gate 	 * if the ARREQ ACK was bad, we were unable to successfully read in this
18637c478bd9Sstevel@tonic-gate 	 * request.  Return failure.
18647c478bd9Sstevel@tonic-gate 	 */
18657c478bd9Sstevel@tonic-gate 	if ((hcicmd->ac_status != OHCI_ACK_COMPLETE) &&
18667c478bd9Sstevel@tonic-gate 	    (hcicmd->ac_status != OHCI_ACK_PENDING)) {
18677c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
18687c478bd9Sstevel@tonic-gate 	}
18697c478bd9Sstevel@tonic-gate 
18707c478bd9Sstevel@tonic-gate 	/* Read in the tlabel and destination */
18717c478bd9Sstevel@tonic-gate 	quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q1);
18727c478bd9Sstevel@tonic-gate 	hcicmd->ac_dest = HCI1394_DESC_DESTID_GET(quadlet);
18737c478bd9Sstevel@tonic-gate 	hcicmd->ac_tlabel.tbi_tlabel = HCI1394_DESC_TLABEL_GET(quadlet);
18747c478bd9Sstevel@tonic-gate 	hcicmd->ac_mblk_alloc = B_FALSE;
18757c478bd9Sstevel@tonic-gate 
18767c478bd9Sstevel@tonic-gate 	/*
18777c478bd9Sstevel@tonic-gate 	 * Read in the sender so we know who to send the ATRESP to. Read in
18787c478bd9Sstevel@tonic-gate 	 * the 1394 48-bit address for this request.
18797c478bd9Sstevel@tonic-gate 	 */
18807c478bd9Sstevel@tonic-gate 	quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q2);
18817c478bd9Sstevel@tonic-gate 	cmd->nodeID = HCI1394_DESC_SRCID_GET(quadlet);
18827c478bd9Sstevel@tonic-gate 	cmd->cmd_addr = HCI1394_TO_ADDR_HI(quadlet);
18837c478bd9Sstevel@tonic-gate 	quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q3);
18847c478bd9Sstevel@tonic-gate 	cmd->cmd_addr |= HCI1394_TO_ADDR_LO(quadlet);
18857c478bd9Sstevel@tonic-gate 
18867c478bd9Sstevel@tonic-gate 	/* Copy ARREQ lock data into 1394 framework command */
18877c478bd9Sstevel@tonic-gate 	if (cmd->cmd_type == CMD1394_ASYNCH_LOCK_32) {
18887c478bd9Sstevel@tonic-gate 		data_addr = (uint8_t *)&pkt->q5;
18897c478bd9Sstevel@tonic-gate 		hci1394_q_ar_rep_get8(async_handle->as_arreq_q,
18907c478bd9Sstevel@tonic-gate 		    (uint8_t *)&cmd->cmd_u.l32.arg_value, data_addr,
18917c478bd9Sstevel@tonic-gate 		    IEEE1394_QUADLET);
18927c478bd9Sstevel@tonic-gate 		data_addr = (uint8_t *)((uintptr_t)data_addr +
18937c478bd9Sstevel@tonic-gate 		    (uintptr_t)IEEE1394_QUADLET);
18947c478bd9Sstevel@tonic-gate 		hci1394_q_ar_rep_get8(async_handle->as_arreq_q,
18957c478bd9Sstevel@tonic-gate 		    (uint8_t *)&cmd->cmd_u.l32.data_value, data_addr,
18967c478bd9Sstevel@tonic-gate 		    IEEE1394_QUADLET);
18977c478bd9Sstevel@tonic-gate 		/*
18987c478bd9Sstevel@tonic-gate 		 * swap these for our correct architecture if we are doing
18997c478bd9Sstevel@tonic-gate 		 * arithmetic lock operations
19007c478bd9Sstevel@tonic-gate 		 */
19017c478bd9Sstevel@tonic-gate 		cmd->cmd_u.l32.arg_value = HCI1394_ARITH_LOCK_SWAP32(
19027c478bd9Sstevel@tonic-gate 		    cmd->cmd_u.l32.lock_type, cmd->cmd_u.l32.arg_value);
19037c478bd9Sstevel@tonic-gate 		cmd->cmd_u.l32.data_value = HCI1394_ARITH_LOCK_SWAP32(
19047c478bd9Sstevel@tonic-gate 		    cmd->cmd_u.l32.lock_type, cmd->cmd_u.l32.data_value);
19057c478bd9Sstevel@tonic-gate 	} else if (cmd->cmd_type == CMD1394_ASYNCH_LOCK_64) {
19067c478bd9Sstevel@tonic-gate 		data_addr = (uint8_t *)&pkt->q5;
19077c478bd9Sstevel@tonic-gate 		hci1394_q_ar_rep_get8(async_handle->as_arreq_q,
19087c478bd9Sstevel@tonic-gate 		    (uint8_t *)&cmd->cmd_u.l64.arg_value, data_addr,
19097c478bd9Sstevel@tonic-gate 		    IEEE1394_OCTLET);
19107c478bd9Sstevel@tonic-gate 		data_addr = (uint8_t *)((uintptr_t)data_addr +
19117c478bd9Sstevel@tonic-gate 		    (uintptr_t)IEEE1394_OCTLET);
19127c478bd9Sstevel@tonic-gate 		hci1394_q_ar_rep_get8(async_handle->as_arreq_q,
19137c478bd9Sstevel@tonic-gate 		    (uint8_t *)&cmd->cmd_u.l64.data_value, data_addr,
19147c478bd9Sstevel@tonic-gate 		    IEEE1394_OCTLET);
19157c478bd9Sstevel@tonic-gate 
19167c478bd9Sstevel@tonic-gate 		/*
19177c478bd9Sstevel@tonic-gate 		 * swap these for our correct architecture if we are doing
19187c478bd9Sstevel@tonic-gate 		 * arithmetic lock operations
19197c478bd9Sstevel@tonic-gate 		 */
19207c478bd9Sstevel@tonic-gate 		cmd->cmd_u.l64.arg_value = HCI1394_ARITH_LOCK_SWAP64(
19217c478bd9Sstevel@tonic-gate 		    cmd->cmd_u.l64.lock_type, cmd->cmd_u.l64.arg_value);
19227c478bd9Sstevel@tonic-gate 		cmd->cmd_u.l64.data_value = HCI1394_ARITH_LOCK_SWAP64(
19237c478bd9Sstevel@tonic-gate 		    cmd->cmd_u.l64.lock_type, cmd->cmd_u.l64.data_value);
19247c478bd9Sstevel@tonic-gate 	}
19257c478bd9Sstevel@tonic-gate 
19267c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
19277c478bd9Sstevel@tonic-gate }
19287c478bd9Sstevel@tonic-gate 
19297c478bd9Sstevel@tonic-gate 
19307c478bd9Sstevel@tonic-gate /*
19317c478bd9Sstevel@tonic-gate  * hci1394_async_arreq_read_phy()
19327c478bd9Sstevel@tonic-gate  *    Read ARREQ PHY quadlet into the 1394 Framework command. This routine will
19337c478bd9Sstevel@tonic-gate  *    return DDI_FAILURE if it was not able to read the request succesfully.
19347c478bd9Sstevel@tonic-gate  */
19357c478bd9Sstevel@tonic-gate static int
hci1394_async_arreq_read_phy(hci1394_async_handle_t async_handle,hci1394_basic_pkt_t * pkt,hci1394_async_cmd_t * hcicmd,uint_t * size,boolean_t * bus_reset_token)19367c478bd9Sstevel@tonic-gate hci1394_async_arreq_read_phy(hci1394_async_handle_t async_handle,
19377c478bd9Sstevel@tonic-gate     hci1394_basic_pkt_t *pkt, hci1394_async_cmd_t *hcicmd, uint_t *size,
19387c478bd9Sstevel@tonic-gate     boolean_t *bus_reset_token)
19397c478bd9Sstevel@tonic-gate {
19407c478bd9Sstevel@tonic-gate 	cmd1394_cmd_t *cmd;
19417c478bd9Sstevel@tonic-gate 	uint32_t quadlet;
19427c478bd9Sstevel@tonic-gate 	uint32_t data1;
19437c478bd9Sstevel@tonic-gate 	uint32_t data2;
19447c478bd9Sstevel@tonic-gate 
19457c478bd9Sstevel@tonic-gate 
19467c478bd9Sstevel@tonic-gate 	ASSERT(async_handle != NULL);
19477c478bd9Sstevel@tonic-gate 	ASSERT(pkt != NULL);
19487c478bd9Sstevel@tonic-gate 	ASSERT(hcicmd != NULL);
19497c478bd9Sstevel@tonic-gate 	ASSERT(size != NULL);
19507c478bd9Sstevel@tonic-gate 
19517c478bd9Sstevel@tonic-gate 	/* Setup shortcuts, command type, and size of request */
19527c478bd9Sstevel@tonic-gate 	cmd = hcicmd->ac_cmd;
19537c478bd9Sstevel@tonic-gate 	cmd->cmd_type = CMD1394_ASYNCH_WR_QUAD;
19547c478bd9Sstevel@tonic-gate 	*size = DESC_SZ_AR_PHY;
19557c478bd9Sstevel@tonic-gate 
19567c478bd9Sstevel@tonic-gate 	/*
19577c478bd9Sstevel@tonic-gate 	 * read in the ARREQ ACK/EVT, the speed, the time we received it, and
19587c478bd9Sstevel@tonic-gate 	 * set state that we do not use an mblk for this request.
19597c478bd9Sstevel@tonic-gate 	 */
19607c478bd9Sstevel@tonic-gate 	quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q4);
19617c478bd9Sstevel@tonic-gate 	hcicmd->ac_status = HCI1394_DESC_EVT_GET(quadlet);
19627c478bd9Sstevel@tonic-gate 	hcicmd->ac_priv->speed = HCI1394_DESC_AR_SPD_GET(quadlet);
19637c478bd9Sstevel@tonic-gate 	hcicmd->ac_priv->recv_tstamp = HCI1394_DESC_TIMESTAMP_GET(quadlet);
19647c478bd9Sstevel@tonic-gate 	hcicmd->ac_mblk_alloc = B_FALSE;
19657c478bd9Sstevel@tonic-gate 
19667c478bd9Sstevel@tonic-gate 	/* Read in the PHY packet quadlet and its check quadlet */
19677c478bd9Sstevel@tonic-gate 	data1 = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q2);
19687c478bd9Sstevel@tonic-gate 	data2 = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q3);
19697c478bd9Sstevel@tonic-gate 
19707c478bd9Sstevel@tonic-gate 	/*
19717c478bd9Sstevel@tonic-gate 	 * if this is a bus reset token, save away the generation. If the bus
19727c478bd9Sstevel@tonic-gate 	 * reset token is for the current generation, we do not need to flush
19737c478bd9Sstevel@tonic-gate 	 * the ARREQ Q anymore.
19747c478bd9Sstevel@tonic-gate 	 */
19757c478bd9Sstevel@tonic-gate 	if (hcicmd->ac_status == OHCI_EVT_BUS_RESET) {
19767c478bd9Sstevel@tonic-gate 		*bus_reset_token = B_TRUE;
19777c478bd9Sstevel@tonic-gate 		async_handle->as_phy_reset = HCI1394_DESC_PHYGEN_GET(data2);
19787c478bd9Sstevel@tonic-gate 		if (async_handle->as_phy_reset == hci1394_ohci_current_busgen(
19797c478bd9Sstevel@tonic-gate 		    async_handle->as_ohci)) {
19807c478bd9Sstevel@tonic-gate 			async_handle->as_flushing_arreq = B_FALSE;
19817c478bd9Sstevel@tonic-gate 		}
19827c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
19837c478bd9Sstevel@tonic-gate 	}
19847c478bd9Sstevel@tonic-gate 
19857c478bd9Sstevel@tonic-gate 	*bus_reset_token = B_FALSE;
19867c478bd9Sstevel@tonic-gate 
19877c478bd9Sstevel@tonic-gate 	/* if there is a data error in the PHY packet, return failure */
19887c478bd9Sstevel@tonic-gate 	if (data1 != ~data2) {
19897c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
19907c478bd9Sstevel@tonic-gate 	}
19917c478bd9Sstevel@tonic-gate 
19927c478bd9Sstevel@tonic-gate 	/* Copy the PHY quadlet to the command */
19937c478bd9Sstevel@tonic-gate 	cmd->cmd_u.q.quadlet_data = data1;
19947c478bd9Sstevel@tonic-gate 
19957c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
19967c478bd9Sstevel@tonic-gate }
19977c478bd9Sstevel@tonic-gate 
19987c478bd9Sstevel@tonic-gate 
19997c478bd9Sstevel@tonic-gate /*
20007c478bd9Sstevel@tonic-gate  * hci1394_async_phy()
20017c478bd9Sstevel@tonic-gate  *    Queue up ATREQ phy packet.
20027c478bd9Sstevel@tonic-gate  */
20037c478bd9Sstevel@tonic-gate int
hci1394_async_phy(hci1394_async_handle_t async_handle,cmd1394_cmd_t * cmd,h1394_cmd_priv_t * cmd_priv,int * result)20047c478bd9Sstevel@tonic-gate hci1394_async_phy(hci1394_async_handle_t async_handle, cmd1394_cmd_t *cmd,
20057c478bd9Sstevel@tonic-gate     h1394_cmd_priv_t *cmd_priv, int *result)
20067c478bd9Sstevel@tonic-gate {
20077c478bd9Sstevel@tonic-gate 	hci1394_basic_pkt_t header;
20087c478bd9Sstevel@tonic-gate 	hci1394_async_cmd_t *hcicmd;
20097c478bd9Sstevel@tonic-gate 	int status;
20107c478bd9Sstevel@tonic-gate 
20117c478bd9Sstevel@tonic-gate 
20127c478bd9Sstevel@tonic-gate 	ASSERT(async_handle != NULL);
20137c478bd9Sstevel@tonic-gate 	ASSERT(cmd != NULL);
20147c478bd9Sstevel@tonic-gate 	ASSERT(cmd_priv != NULL);
20157c478bd9Sstevel@tonic-gate 	ASSERT(result != NULL);
20167c478bd9Sstevel@tonic-gate 
20177c478bd9Sstevel@tonic-gate 	/*
20187c478bd9Sstevel@tonic-gate 	 * make sure this call is during the current bus generation (i.e. no
20197c478bd9Sstevel@tonic-gate 	 * bus resets have occured since this request was made.
20207c478bd9Sstevel@tonic-gate 	 */
20217c478bd9Sstevel@tonic-gate 	if (cmd_priv->bus_generation != hci1394_ohci_current_busgen(
20227c478bd9Sstevel@tonic-gate 	    async_handle->as_ohci)) {
20237c478bd9Sstevel@tonic-gate 		*result = H1394_STATUS_INVALID_BUSGEN;
20247c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
20257c478bd9Sstevel@tonic-gate 	}
20267c478bd9Sstevel@tonic-gate 
20277c478bd9Sstevel@tonic-gate 	/* Initialize the private HAL command structure */
20287c478bd9Sstevel@tonic-gate 	hci1394_async_hcicmd_init(async_handle, cmd, cmd_priv, &hcicmd);
20297c478bd9Sstevel@tonic-gate 
20307c478bd9Sstevel@tonic-gate 	/* We do not allocate a tlabel for a PHY packet */
20317c478bd9Sstevel@tonic-gate 	hcicmd->ac_tlabel_alloc = B_FALSE;
20327c478bd9Sstevel@tonic-gate 
20337c478bd9Sstevel@tonic-gate 	/*
20347c478bd9Sstevel@tonic-gate 	 * Setup the packet header information for a ATREQ PHY packet Add in
20357c478bd9Sstevel@tonic-gate 	 * the tcode, phy quadlet, and it's 1's complement.
20367c478bd9Sstevel@tonic-gate 	 */
20377c478bd9Sstevel@tonic-gate 	header.q1 = DESC_ATREQ_Q1_PHY;
20387c478bd9Sstevel@tonic-gate 	header.q2 = cmd->cmd_u.q.quadlet_data;
20397c478bd9Sstevel@tonic-gate 	header.q3 = ~header.q2;
20407c478bd9Sstevel@tonic-gate 
20417c478bd9Sstevel@tonic-gate 	/* Write request into the ATREQ Q. If we fail, we're out of space */
20427c478bd9Sstevel@tonic-gate 	status = hci1394_q_at(async_handle->as_atreq_q, &hcicmd->ac_qcmd,
20437c478bd9Sstevel@tonic-gate 	    &header, DESC_PKT_HDRLEN_AT_PHY, result);
20447c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
20457c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
20467c478bd9Sstevel@tonic-gate 	}
20477c478bd9Sstevel@tonic-gate 
20487c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
20497c478bd9Sstevel@tonic-gate }
20507c478bd9Sstevel@tonic-gate 
20517c478bd9Sstevel@tonic-gate 
20527c478bd9Sstevel@tonic-gate /*
20537c478bd9Sstevel@tonic-gate  * hci1394_async_write()
20547c478bd9Sstevel@tonic-gate  *    Queue up ATREQ write. This could be either a block write or a quadlet
20557c478bd9Sstevel@tonic-gate  *    write.
20567c478bd9Sstevel@tonic-gate  */
20577c478bd9Sstevel@tonic-gate int
hci1394_async_write(hci1394_async_handle_t async_handle,cmd1394_cmd_t * cmd,h1394_cmd_priv_t * cmd_priv,int * result)20587c478bd9Sstevel@tonic-gate hci1394_async_write(hci1394_async_handle_t async_handle, cmd1394_cmd_t *cmd,
20597c478bd9Sstevel@tonic-gate     h1394_cmd_priv_t *cmd_priv, int *result)
20607c478bd9Sstevel@tonic-gate {
20617c478bd9Sstevel@tonic-gate 	hci1394_async_cmd_t *hcicmd;
20627c478bd9Sstevel@tonic-gate 	hci1394_basic_pkt_t header;
20637c478bd9Sstevel@tonic-gate 	int status;
20647c478bd9Sstevel@tonic-gate 
20657c478bd9Sstevel@tonic-gate 
20667c478bd9Sstevel@tonic-gate 	ASSERT(async_handle != NULL);
20677c478bd9Sstevel@tonic-gate 	ASSERT(cmd != NULL);
20687c478bd9Sstevel@tonic-gate 	ASSERT(cmd_priv != NULL);
20697c478bd9Sstevel@tonic-gate 	ASSERT(result != NULL);
20707c478bd9Sstevel@tonic-gate 
20717c478bd9Sstevel@tonic-gate 	/*
20727c478bd9Sstevel@tonic-gate 	 * make sure this call is during the current bus generation (i.e. no
20737c478bd9Sstevel@tonic-gate 	 * bus resets have occured since this request was made.
20747c478bd9Sstevel@tonic-gate 	 */
20757c478bd9Sstevel@tonic-gate 	if (cmd_priv->bus_generation != hci1394_ohci_current_busgen(
20767c478bd9Sstevel@tonic-gate 	    async_handle->as_ohci)) {
20777c478bd9Sstevel@tonic-gate 		*result = H1394_STATUS_INVALID_BUSGEN;
20787c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
20797c478bd9Sstevel@tonic-gate 	}
20807c478bd9Sstevel@tonic-gate 
20817c478bd9Sstevel@tonic-gate 	/* Initialize the private HAL command structure */
20827c478bd9Sstevel@tonic-gate 	hci1394_async_hcicmd_init(async_handle, cmd, cmd_priv, &hcicmd);
20837c478bd9Sstevel@tonic-gate 	hcicmd->ac_dest = (uint_t)(cmd->cmd_addr >> IEEE1394_ADDR_PHY_ID_SHIFT);
20847c478bd9Sstevel@tonic-gate 
20857c478bd9Sstevel@tonic-gate 	/* allocate a tlabel for this request */
20867c478bd9Sstevel@tonic-gate 	status = hci1394_tlabel_alloc(async_handle->as_tlabel, hcicmd->ac_dest,
20877c478bd9Sstevel@tonic-gate 	    &hcicmd->ac_tlabel);
20887c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
20897c478bd9Sstevel@tonic-gate 		*result = H1394_STATUS_EMPTY_TLABEL;
20907c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
20917c478bd9Sstevel@tonic-gate 	}
20927c478bd9Sstevel@tonic-gate 
20937c478bd9Sstevel@tonic-gate 	/*
20947c478bd9Sstevel@tonic-gate 	 * Setup the packet header information for a ATREQ write packet. We
20957c478bd9Sstevel@tonic-gate 	 * will set the tcode later on since this could be a block write or
20967c478bd9Sstevel@tonic-gate 	 * a quadlet write. Set SRCBusId if this write is not a local bus
20977c478bd9Sstevel@tonic-gate 	 * access. Copy in the speed, tlabel, and destination address.
20987c478bd9Sstevel@tonic-gate 	 */
20997c478bd9Sstevel@tonic-gate 	header.q1 = 0;
21007c478bd9Sstevel@tonic-gate 	if ((hcicmd->ac_dest & IEEE1394_BUS_NUM_MASK) !=
21017c478bd9Sstevel@tonic-gate 	    IEEE1394_BUS_NUM_MASK) {
21027c478bd9Sstevel@tonic-gate 		header.q1 |= DESC_AT_SRCBUSID;
21037c478bd9Sstevel@tonic-gate 	}
21047c478bd9Sstevel@tonic-gate 	header.q1 |= HCI1394_DESC_AT_SPD_SET(cmd_priv->speed) |
21057c478bd9Sstevel@tonic-gate 	    HCI1394_DESC_TLABEL_SET(hcicmd->ac_tlabel.tbi_tlabel);
21067c478bd9Sstevel@tonic-gate 	header.q2 = (uint32_t)(cmd->cmd_addr >> 32);
21077c478bd9Sstevel@tonic-gate 	header.q3 = (uint32_t)(cmd->cmd_addr & DESC_PKT_DESTOFFLO_MASK);
21087c478bd9Sstevel@tonic-gate 
21097c478bd9Sstevel@tonic-gate 	/* Register this command w/ its tlabel */
21107c478bd9Sstevel@tonic-gate 	hci1394_tlabel_register(async_handle->as_tlabel, &hcicmd->ac_tlabel,
21117c478bd9Sstevel@tonic-gate 	    hcicmd);
21127c478bd9Sstevel@tonic-gate 
21137c478bd9Sstevel@tonic-gate 	/* If this is a quadlet write ATREQ */
21147c478bd9Sstevel@tonic-gate 	if (cmd->cmd_type == CMD1394_ASYNCH_WR_QUAD) {
21157c478bd9Sstevel@tonic-gate 		/*
21167c478bd9Sstevel@tonic-gate 		 * setup the tcode for a quadlet write request and copy in
21177c478bd9Sstevel@tonic-gate 		 * the quadlet data. Endian issues will be taken care of in
21187c478bd9Sstevel@tonic-gate 		 * hci1394_q_at().
21197c478bd9Sstevel@tonic-gate 		 */
21207c478bd9Sstevel@tonic-gate 		header.q1 |= DESC_ATREQ_Q1_QWR;
21217c478bd9Sstevel@tonic-gate 		header.q4 = cmd->cmd_u.q.quadlet_data;
21227c478bd9Sstevel@tonic-gate 
21237c478bd9Sstevel@tonic-gate 		/*
21247c478bd9Sstevel@tonic-gate 		 * Write the request into the ATREQ Q. If we fail, we are out
21257c478bd9Sstevel@tonic-gate 		 * of space.
21267c478bd9Sstevel@tonic-gate 		 */
21277c478bd9Sstevel@tonic-gate 		status = hci1394_q_at(async_handle->as_atreq_q,
21287c478bd9Sstevel@tonic-gate 		    &hcicmd->ac_qcmd, &header, DESC_PKT_HDRLEN_AT_WRITEQUAD,
21297c478bd9Sstevel@tonic-gate 		    result);
21307c478bd9Sstevel@tonic-gate 		if (status != DDI_SUCCESS) {
21317c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
21327c478bd9Sstevel@tonic-gate 		}
21337c478bd9Sstevel@tonic-gate 
21347c478bd9Sstevel@tonic-gate 	/* This is a block write ATREQ */
21357c478bd9Sstevel@tonic-gate 	} else {
21367c478bd9Sstevel@tonic-gate 		/* setup the tcode and the length of the block write */
21377c478bd9Sstevel@tonic-gate 		header.q1 |= DESC_ATREQ_Q1_BWR;
21387c478bd9Sstevel@tonic-gate 		header.q4 = HCI1394_DESC_DATALEN_SET(cmd_priv->mblk.length);
21397c478bd9Sstevel@tonic-gate 
21407c478bd9Sstevel@tonic-gate 		/*
21417c478bd9Sstevel@tonic-gate 		 * Write the request into the ATREQ Q. If we fail, we are out
21427c478bd9Sstevel@tonic-gate 		 * of space. The data is in a mblk(s). We use a special
21437c478bd9Sstevel@tonic-gate 		 * interface in the HAL/SL private command block to handle
21447c478bd9Sstevel@tonic-gate 		 * partial transfers out of the mblk due to packet size
21457c478bd9Sstevel@tonic-gate 		 * restrictions.
21467c478bd9Sstevel@tonic-gate 		 */
21477c478bd9Sstevel@tonic-gate 		status = hci1394_q_at_with_mblk(async_handle->as_atreq_q,
21487c478bd9Sstevel@tonic-gate 		    &hcicmd->ac_qcmd, &header, DESC_PKT_HDRLEN_AT_WRITEBLOCK,
21497c478bd9Sstevel@tonic-gate 		    &cmd_priv->mblk, result);
21507c478bd9Sstevel@tonic-gate 		if (status != DDI_SUCCESS) {
21517c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
21527c478bd9Sstevel@tonic-gate 		}
21537c478bd9Sstevel@tonic-gate 	}
21547c478bd9Sstevel@tonic-gate 
21557c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
21567c478bd9Sstevel@tonic-gate }
21577c478bd9Sstevel@tonic-gate 
21587c478bd9Sstevel@tonic-gate 
21597c478bd9Sstevel@tonic-gate /*
21607c478bd9Sstevel@tonic-gate  * hci1394_async_read()
21617c478bd9Sstevel@tonic-gate  *    Queue up ATREQ read. This could be either a block read or a quadlet
21627c478bd9Sstevel@tonic-gate  *    read.
21637c478bd9Sstevel@tonic-gate  */
21647c478bd9Sstevel@tonic-gate int
hci1394_async_read(hci1394_async_handle_t async_handle,cmd1394_cmd_t * cmd,h1394_cmd_priv_t * cmd_priv,int * result)21657c478bd9Sstevel@tonic-gate hci1394_async_read(hci1394_async_handle_t async_handle, cmd1394_cmd_t *cmd,
21667c478bd9Sstevel@tonic-gate     h1394_cmd_priv_t *cmd_priv, int *result)
21677c478bd9Sstevel@tonic-gate {
21687c478bd9Sstevel@tonic-gate 	hci1394_basic_pkt_t header;
21697c478bd9Sstevel@tonic-gate 	int status;
21707c478bd9Sstevel@tonic-gate 	hci1394_async_cmd_t *hcicmd;
21717c478bd9Sstevel@tonic-gate 
21727c478bd9Sstevel@tonic-gate 
21737c478bd9Sstevel@tonic-gate 	ASSERT(async_handle != NULL);
21747c478bd9Sstevel@tonic-gate 	ASSERT(cmd != NULL);
21757c478bd9Sstevel@tonic-gate 	ASSERT(cmd_priv != NULL);
21767c478bd9Sstevel@tonic-gate 	ASSERT(result != NULL);
21777c478bd9Sstevel@tonic-gate 
21787c478bd9Sstevel@tonic-gate 	/*
21797c478bd9Sstevel@tonic-gate 	 * make sure this call is during the current bus generation (i.e. no
21807c478bd9Sstevel@tonic-gate 	 * bus resets have occured since this request was made.
21817c478bd9Sstevel@tonic-gate 	 */
21827c478bd9Sstevel@tonic-gate 	if (cmd_priv->bus_generation != hci1394_ohci_current_busgen(
21837c478bd9Sstevel@tonic-gate 	    async_handle->as_ohci)) {
21847c478bd9Sstevel@tonic-gate 		*result = H1394_STATUS_INVALID_BUSGEN;
21857c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
21867c478bd9Sstevel@tonic-gate 	}
21877c478bd9Sstevel@tonic-gate 
21887c478bd9Sstevel@tonic-gate 	/* Initialize the private HAL command structure */
21897c478bd9Sstevel@tonic-gate 	hci1394_async_hcicmd_init(async_handle, cmd, cmd_priv, &hcicmd);
21907c478bd9Sstevel@tonic-gate 	hcicmd->ac_dest = (uint_t)(cmd->cmd_addr >> IEEE1394_ADDR_PHY_ID_SHIFT);
21917c478bd9Sstevel@tonic-gate 
21927c478bd9Sstevel@tonic-gate 	/* allocate a tlabel for this request */
21937c478bd9Sstevel@tonic-gate 	status = hci1394_tlabel_alloc(async_handle->as_tlabel, hcicmd->ac_dest,
21947c478bd9Sstevel@tonic-gate 	    &hcicmd->ac_tlabel);
21957c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
21967c478bd9Sstevel@tonic-gate 		*result = H1394_STATUS_EMPTY_TLABEL;
21977c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
21987c478bd9Sstevel@tonic-gate 	}
21997c478bd9Sstevel@tonic-gate 
22007c478bd9Sstevel@tonic-gate 	/*
22017c478bd9Sstevel@tonic-gate 	 * Setup the packet header information for a ATREQ read packet. We
22027c478bd9Sstevel@tonic-gate 	 * will set the tcode later on since this could be a block read or
22037c478bd9Sstevel@tonic-gate 	 * a quadlet read. Set SRCBusId if this read is not a local bus
22047c478bd9Sstevel@tonic-gate 	 * access. Copy in the speed, tlabel, and destination address.
22057c478bd9Sstevel@tonic-gate 	 */
22067c478bd9Sstevel@tonic-gate 	header.q1 = 0;
22077c478bd9Sstevel@tonic-gate 	if ((hcicmd->ac_dest & IEEE1394_BUS_NUM_MASK) !=
22087c478bd9Sstevel@tonic-gate 	    IEEE1394_BUS_NUM_MASK) {
22097c478bd9Sstevel@tonic-gate 		header.q1 |= DESC_AT_SRCBUSID;
22107c478bd9Sstevel@tonic-gate 	}
22117c478bd9Sstevel@tonic-gate 	header.q1 |= HCI1394_DESC_AT_SPD_SET(cmd_priv->speed) |
22127c478bd9Sstevel@tonic-gate 	    HCI1394_DESC_TLABEL_SET(hcicmd->ac_tlabel.tbi_tlabel);
22137c478bd9Sstevel@tonic-gate 	header.q2 = (uint32_t)(cmd->cmd_addr >> 32);
22147c478bd9Sstevel@tonic-gate 	header.q3 = (uint32_t)(cmd->cmd_addr & DESC_PKT_DESTOFFLO_MASK);
22157c478bd9Sstevel@tonic-gate 
22167c478bd9Sstevel@tonic-gate 	/* Register this command w/ its tlabel */
22177c478bd9Sstevel@tonic-gate 	hci1394_tlabel_register(async_handle->as_tlabel, &hcicmd->ac_tlabel,
22187c478bd9Sstevel@tonic-gate 	    hcicmd);
22197c478bd9Sstevel@tonic-gate 
22207c478bd9Sstevel@tonic-gate 	/* If this is a quadlet read ATREQ */
22217c478bd9Sstevel@tonic-gate 	if (cmd->cmd_type == CMD1394_ASYNCH_RD_QUAD) {
22227c478bd9Sstevel@tonic-gate 		/* setup the tcode for a quadlet read request */
22237c478bd9Sstevel@tonic-gate 		header.q1 |= DESC_ATREQ_Q1_QRD;
22247c478bd9Sstevel@tonic-gate 		header.q4 = 0;
22257c478bd9Sstevel@tonic-gate 
22267c478bd9Sstevel@tonic-gate 		/*
22277c478bd9Sstevel@tonic-gate 		 * Write the request into the ATREQ Q. If we fail, we are out
22287c478bd9Sstevel@tonic-gate 		 * of space.
22297c478bd9Sstevel@tonic-gate 		 */
22307c478bd9Sstevel@tonic-gate 		status = hci1394_q_at(async_handle->as_atreq_q,
22317c478bd9Sstevel@tonic-gate 		    &hcicmd->ac_qcmd, &header, DESC_PKT_HDRLEN_AT_READQUAD,
22327c478bd9Sstevel@tonic-gate 		    result);
22337c478bd9Sstevel@tonic-gate 		if (status != DDI_SUCCESS) {
22347c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
22357c478bd9Sstevel@tonic-gate 		}
22367c478bd9Sstevel@tonic-gate 
22377c478bd9Sstevel@tonic-gate 	} else {
22387c478bd9Sstevel@tonic-gate 		/* setup the tcode and the length of the block read */
22397c478bd9Sstevel@tonic-gate 		header.q1 |= DESC_ATREQ_Q1_BRD;
22407c478bd9Sstevel@tonic-gate 		header.q4 = HCI1394_DESC_DATALEN_SET(cmd_priv->mblk.length);
22417c478bd9Sstevel@tonic-gate 
22427c478bd9Sstevel@tonic-gate 		/*
22437c478bd9Sstevel@tonic-gate 		 * Write the request into the ATREQ Q. If we fail, we are out
22447c478bd9Sstevel@tonic-gate 		 * of space.
22457c478bd9Sstevel@tonic-gate 		 */
22467c478bd9Sstevel@tonic-gate 		status = hci1394_q_at(async_handle->as_atreq_q,
22477c478bd9Sstevel@tonic-gate 		    &hcicmd->ac_qcmd, &header, DESC_PKT_HDRLEN_AT_READBLOCK,
22487c478bd9Sstevel@tonic-gate 		    result);
22497c478bd9Sstevel@tonic-gate 		if (status != DDI_SUCCESS) {
22507c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
22517c478bd9Sstevel@tonic-gate 		}
22527c478bd9Sstevel@tonic-gate 	}
22537c478bd9Sstevel@tonic-gate 
22547c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
22557c478bd9Sstevel@tonic-gate }
22567c478bd9Sstevel@tonic-gate 
22577c478bd9Sstevel@tonic-gate 
22587c478bd9Sstevel@tonic-gate /*
22597c478bd9Sstevel@tonic-gate  * hci1394_async_lock()
22607c478bd9Sstevel@tonic-gate  *    Queue up ATREQ lock. This could be either a 32-bit or 64-bit lock
22617c478bd9Sstevel@tonic-gate  *    request.
22627c478bd9Sstevel@tonic-gate  */
22637c478bd9Sstevel@tonic-gate int
hci1394_async_lock(hci1394_async_handle_t async_handle,cmd1394_cmd_t * cmd,h1394_cmd_priv_t * cmd_priv,int * result)22647c478bd9Sstevel@tonic-gate hci1394_async_lock(hci1394_async_handle_t async_handle, cmd1394_cmd_t *cmd,
22657c478bd9Sstevel@tonic-gate     h1394_cmd_priv_t *cmd_priv, int *result)
22667c478bd9Sstevel@tonic-gate {
22677c478bd9Sstevel@tonic-gate 	hci1394_basic_pkt_t header;
22687c478bd9Sstevel@tonic-gate 	hci1394_async_cmd_t *hcicmd;
22697c478bd9Sstevel@tonic-gate 	uint32_t data32[2];
22707c478bd9Sstevel@tonic-gate 	uint64_t data64[2];
22717c478bd9Sstevel@tonic-gate 	uint8_t *datap;
22727c478bd9Sstevel@tonic-gate 	uint_t size;
22737c478bd9Sstevel@tonic-gate 	int status;
22747c478bd9Sstevel@tonic-gate 
22757c478bd9Sstevel@tonic-gate 
22767c478bd9Sstevel@tonic-gate 	ASSERT(async_handle != NULL);
22777c478bd9Sstevel@tonic-gate 	ASSERT(cmd != NULL);
22787c478bd9Sstevel@tonic-gate 	ASSERT(cmd_priv != NULL);
22797c478bd9Sstevel@tonic-gate 	ASSERT(result != NULL);
22807c478bd9Sstevel@tonic-gate 
22817c478bd9Sstevel@tonic-gate 	/*
22827c478bd9Sstevel@tonic-gate 	 * make sure this call is during the current bus generation (i.e. no
22837c478bd9Sstevel@tonic-gate 	 * bus resets have occured since this request was made.
22847c478bd9Sstevel@tonic-gate 	 */
22857c478bd9Sstevel@tonic-gate 	if (cmd_priv->bus_generation != hci1394_ohci_current_busgen(
22867c478bd9Sstevel@tonic-gate 	    async_handle->as_ohci)) {
22877c478bd9Sstevel@tonic-gate 		*result = H1394_STATUS_INVALID_BUSGEN;
22887c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
22897c478bd9Sstevel@tonic-gate 	}
22907c478bd9Sstevel@tonic-gate 
22917c478bd9Sstevel@tonic-gate 	/* Initialize the private HAL command structure */
22927c478bd9Sstevel@tonic-gate 	hci1394_async_hcicmd_init(async_handle, cmd, cmd_priv, &hcicmd);
22937c478bd9Sstevel@tonic-gate 	hcicmd->ac_dest = (uint_t)(cmd->cmd_addr >> IEEE1394_ADDR_PHY_ID_SHIFT);
22947c478bd9Sstevel@tonic-gate 
22957c478bd9Sstevel@tonic-gate 	/* allocate a tlabel for this request */
22967c478bd9Sstevel@tonic-gate 	status = hci1394_tlabel_alloc(async_handle->as_tlabel, hcicmd->ac_dest,
22977c478bd9Sstevel@tonic-gate 	    &hcicmd->ac_tlabel);
22987c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
22997c478bd9Sstevel@tonic-gate 		*result = H1394_STATUS_EMPTY_TLABEL;
23007c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
23017c478bd9Sstevel@tonic-gate 	}
23027c478bd9Sstevel@tonic-gate 
23037c478bd9Sstevel@tonic-gate 	/* Register this command w/ its tlabel */
23047c478bd9Sstevel@tonic-gate 	hci1394_tlabel_register(async_handle->as_tlabel, &hcicmd->ac_tlabel,
23057c478bd9Sstevel@tonic-gate 	    hcicmd);
23067c478bd9Sstevel@tonic-gate 
23077c478bd9Sstevel@tonic-gate 	/*
23087c478bd9Sstevel@tonic-gate 	 * Setup the packet header information for a ATREQ lock packet. Set
23097c478bd9Sstevel@tonic-gate 	 * the tcode up as a lock request. Set SRCBusId if this lock is not a
23107c478bd9Sstevel@tonic-gate 	 * local bus access. Copy in the speed, tlabel, and destination
23117c478bd9Sstevel@tonic-gate 	 * address.
23127c478bd9Sstevel@tonic-gate 	 */
23137c478bd9Sstevel@tonic-gate 	header.q1 = DESC_ATREQ_Q1_LCK;
23147c478bd9Sstevel@tonic-gate 	if ((hcicmd->ac_dest & IEEE1394_BUS_NUM_MASK) !=
23157c478bd9Sstevel@tonic-gate 	    IEEE1394_BUS_NUM_MASK) {
23167c478bd9Sstevel@tonic-gate 		header.q1 |= DESC_AT_SRCBUSID;
23177c478bd9Sstevel@tonic-gate 	}
23187c478bd9Sstevel@tonic-gate 	header.q1 |= HCI1394_DESC_AT_SPD_SET(cmd_priv->speed) |
23197c478bd9Sstevel@tonic-gate 	    HCI1394_DESC_TLABEL_SET(hcicmd->ac_tlabel.tbi_tlabel);
23207c478bd9Sstevel@tonic-gate 	header.q2 = (uint32_t)(cmd->cmd_addr >> 32);
23217c478bd9Sstevel@tonic-gate 	header.q3 = (uint32_t)(cmd->cmd_addr & DESC_PKT_DESTOFFLO_MASK);
23227c478bd9Sstevel@tonic-gate 
23237c478bd9Sstevel@tonic-gate 	/*
23247c478bd9Sstevel@tonic-gate 	 * Setup the lock length based on what size lock operation we are
23257c478bd9Sstevel@tonic-gate 	 * performing. If it isn't a lock32 or lock64, we have encountered an
23267c478bd9Sstevel@tonic-gate 	 * internal error. Copy the lock data into a local data buffer. Perform
23277c478bd9Sstevel@tonic-gate 	 * a byte swap if it is an arithmetic lock operation and we are on a
23287c478bd9Sstevel@tonic-gate 	 * little endian machine.
23297c478bd9Sstevel@tonic-gate 	 */
23307c478bd9Sstevel@tonic-gate 	if (cmd->cmd_type == CMD1394_ASYNCH_LOCK_32) {
23317c478bd9Sstevel@tonic-gate 		size = DESC_TWO_QUADS;
23327c478bd9Sstevel@tonic-gate 		header.q4 = HCI1394_DESC_DATALEN_SET(size) |
23337c478bd9Sstevel@tonic-gate 		    HCI1394_DESC_EXTTCODE_SET(cmd->cmd_u.l32.lock_type);
23347c478bd9Sstevel@tonic-gate 		data32[0] = HCI1394_ARITH_LOCK_SWAP32(
23357c478bd9Sstevel@tonic-gate 		    cmd->cmd_u.l32.lock_type, cmd->cmd_u.l32.arg_value);
23367c478bd9Sstevel@tonic-gate 		data32[1] = HCI1394_ARITH_LOCK_SWAP32(
23377c478bd9Sstevel@tonic-gate 		    cmd->cmd_u.l32.lock_type, cmd->cmd_u.l32.data_value);
23387c478bd9Sstevel@tonic-gate 		datap = (uint8_t *)data32;
23397c478bd9Sstevel@tonic-gate 	} else if (cmd->cmd_type == CMD1394_ASYNCH_LOCK_64) {
23407c478bd9Sstevel@tonic-gate 		size = DESC_TWO_OCTLETS;
23417c478bd9Sstevel@tonic-gate 		header.q4 = HCI1394_DESC_DATALEN_SET(size) |
23427c478bd9Sstevel@tonic-gate 		    HCI1394_DESC_EXTTCODE_SET(cmd->cmd_u.l64.lock_type);
23437c478bd9Sstevel@tonic-gate 		data64[0] = HCI1394_ARITH_LOCK_SWAP64(
23447c478bd9Sstevel@tonic-gate 		    cmd->cmd_u.l64.lock_type, cmd->cmd_u.l64.arg_value);
23457c478bd9Sstevel@tonic-gate 		data64[1] = HCI1394_ARITH_LOCK_SWAP64(
23467c478bd9Sstevel@tonic-gate 		    cmd->cmd_u.l64.lock_type, cmd->cmd_u.l64.data_value);
23477c478bd9Sstevel@tonic-gate 		datap = (uint8_t *)data64;
23487c478bd9Sstevel@tonic-gate 	} else {
23497c478bd9Sstevel@tonic-gate 		*result = H1394_STATUS_INTERNAL_ERROR;
23507c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
23517c478bd9Sstevel@tonic-gate 	}
23527c478bd9Sstevel@tonic-gate 
23537c478bd9Sstevel@tonic-gate 	/* Write request into the ATREQ Q. If we fail, we're out of space */
23547c478bd9Sstevel@tonic-gate 	status = hci1394_q_at_with_data(async_handle->as_atreq_q,
23557c478bd9Sstevel@tonic-gate 	    &hcicmd->ac_qcmd, &header, DESC_PKT_HDRLEN_AT_LOCK, datap, size,
23567c478bd9Sstevel@tonic-gate 	    result);
23577c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
23587c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
23597c478bd9Sstevel@tonic-gate 	}
23607c478bd9Sstevel@tonic-gate 
23617c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
23627c478bd9Sstevel@tonic-gate }
23637c478bd9Sstevel@tonic-gate 
23647c478bd9Sstevel@tonic-gate 
23657c478bd9Sstevel@tonic-gate /*
23667c478bd9Sstevel@tonic-gate  * hci1394_async_write_response()
23677c478bd9Sstevel@tonic-gate  *    Send a write ATRESP. This routine should be called from the Services
23687c478bd9Sstevel@tonic-gate  *    layer to send a response to a received write request (ARREQ). The same
23697c478bd9Sstevel@tonic-gate  *    response is sent to a quadlet and block write request.
23707c478bd9Sstevel@tonic-gate  */
23717c478bd9Sstevel@tonic-gate int
hci1394_async_write_response(hci1394_async_handle_t async_handle,cmd1394_cmd_t * cmd,h1394_cmd_priv_t * cmd_priv,int * result)23727c478bd9Sstevel@tonic-gate hci1394_async_write_response(hci1394_async_handle_t async_handle,
23737c478bd9Sstevel@tonic-gate     cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result)
23747c478bd9Sstevel@tonic-gate {
23757c478bd9Sstevel@tonic-gate 	hci1394_basic_pkt_t header;
23767c478bd9Sstevel@tonic-gate 	int status;
23777c478bd9Sstevel@tonic-gate 	hci1394_async_cmd_t *hcicmd;
23787c478bd9Sstevel@tonic-gate 
23797c478bd9Sstevel@tonic-gate 
23807c478bd9Sstevel@tonic-gate 	ASSERT(async_handle != NULL);
23817c478bd9Sstevel@tonic-gate 	ASSERT(cmd != NULL);
23827c478bd9Sstevel@tonic-gate 	ASSERT(cmd_priv != NULL);
23837c478bd9Sstevel@tonic-gate 	ASSERT(result != NULL);
23847c478bd9Sstevel@tonic-gate 
23857c478bd9Sstevel@tonic-gate 	/*
23867c478bd9Sstevel@tonic-gate 	 * make sure this call is during the current bus generation (i.e. no
23877c478bd9Sstevel@tonic-gate 	 * bus resets have occured since this request was made.
23887c478bd9Sstevel@tonic-gate 	 */
23897c478bd9Sstevel@tonic-gate 	if (cmd_priv->bus_generation != hci1394_ohci_current_busgen(
23907c478bd9Sstevel@tonic-gate 	    async_handle->as_ohci)) {
23917c478bd9Sstevel@tonic-gate 		*result = H1394_STATUS_INVALID_BUSGEN;
23927c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
23937c478bd9Sstevel@tonic-gate 	}
23947c478bd9Sstevel@tonic-gate 
23957c478bd9Sstevel@tonic-gate 	/*
23967c478bd9Sstevel@tonic-gate 	 * setup a shortcut to the hal private command area. Copy the generation
23977c478bd9Sstevel@tonic-gate 	 * to the Q area so that we can check the generation when the AT Q is
23987c478bd9Sstevel@tonic-gate 	 * locked. This prevents us from loosing commands due to race
23997c478bd9Sstevel@tonic-gate 	 * conditions.
24007c478bd9Sstevel@tonic-gate 	 */
24017c478bd9Sstevel@tonic-gate 	hcicmd = (hci1394_async_cmd_t *)cmd_priv->hal_overhead;
24027c478bd9Sstevel@tonic-gate 	hcicmd->ac_qcmd.qc_generation = cmd_priv->bus_generation;
24037c478bd9Sstevel@tonic-gate 
24047c478bd9Sstevel@tonic-gate 	/*
24057c478bd9Sstevel@tonic-gate 	 * Setup the packet header information for a ATRESP write packet. Set
24067c478bd9Sstevel@tonic-gate 	 * the tcode for a write response. Set SRCBusId if the addr is not a
24077c478bd9Sstevel@tonic-gate 	 * local bus address. Copy in the speed, tlabel, and response code.
24087c478bd9Sstevel@tonic-gate 	 */
24097c478bd9Sstevel@tonic-gate 	header.q1 = DESC_ATRESP_Q1_WR;
24107c478bd9Sstevel@tonic-gate 	if ((cmd->nodeID & IEEE1394_BUS_NUM_MASK) != IEEE1394_BUS_NUM_MASK) {
24117c478bd9Sstevel@tonic-gate 		header.q1 |= DESC_AT_SRCBUSID;
24127c478bd9Sstevel@tonic-gate 	}
24137c478bd9Sstevel@tonic-gate 	header.q1 |= HCI1394_DESC_AT_SPD_SET(cmd_priv->speed) |
24147c478bd9Sstevel@tonic-gate 	    HCI1394_DESC_TLABEL_SET(hcicmd->ac_tlabel.tbi_tlabel);
24157c478bd9Sstevel@tonic-gate 	header.q2 = (HCI1394_DESC_DESTID_SET(cmd->nodeID) |
24167c478bd9Sstevel@tonic-gate 	    HCI1394_DESC_RCODE_SET(cmd->cmd_result));
24177c478bd9Sstevel@tonic-gate 	header.q3 = 0;
24187c478bd9Sstevel@tonic-gate 
24197c478bd9Sstevel@tonic-gate 	/* Write response into the ATRESP Q. If we fail, we're out of space */
24207c478bd9Sstevel@tonic-gate 	status = hci1394_q_at(async_handle->as_atresp_q, &hcicmd->ac_qcmd,
24217c478bd9Sstevel@tonic-gate 	    &header, DESC_PKT_HDRLEN_AT_WRITE_RESP, result);
24227c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
24237c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
24247c478bd9Sstevel@tonic-gate 	}
24257c478bd9Sstevel@tonic-gate 
24267c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
24277c478bd9Sstevel@tonic-gate }
24287c478bd9Sstevel@tonic-gate 
24297c478bd9Sstevel@tonic-gate 
24307c478bd9Sstevel@tonic-gate /*
24317c478bd9Sstevel@tonic-gate  * hci1394_async_read_response()
24327c478bd9Sstevel@tonic-gate  *    Send a read ATRESP. This routine should be called from the Services
24337c478bd9Sstevel@tonic-gate  *    layer to send a response to a received read request (ARREQ). The
24347c478bd9Sstevel@tonic-gate  *    response will differ between quadlet/block read requests.
24357c478bd9Sstevel@tonic-gate  */
24367c478bd9Sstevel@tonic-gate int
hci1394_async_read_response(hci1394_async_handle_t async_handle,cmd1394_cmd_t * cmd,h1394_cmd_priv_t * cmd_priv,int * result)24377c478bd9Sstevel@tonic-gate hci1394_async_read_response(hci1394_async_handle_t async_handle,
24387c478bd9Sstevel@tonic-gate     cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result)
24397c478bd9Sstevel@tonic-gate {
24407c478bd9Sstevel@tonic-gate 	hci1394_basic_pkt_t header;
24417c478bd9Sstevel@tonic-gate 	int status;
24427c478bd9Sstevel@tonic-gate 	hci1394_async_cmd_t *hcicmd;
24437c478bd9Sstevel@tonic-gate 
24447c478bd9Sstevel@tonic-gate 
24457c478bd9Sstevel@tonic-gate 	ASSERT(async_handle != NULL);
24467c478bd9Sstevel@tonic-gate 	ASSERT(cmd != NULL);
24477c478bd9Sstevel@tonic-gate 	ASSERT(cmd_priv != NULL);
24487c478bd9Sstevel@tonic-gate 	ASSERT(result != NULL);
24497c478bd9Sstevel@tonic-gate 
24507c478bd9Sstevel@tonic-gate 	/*
24517c478bd9Sstevel@tonic-gate 	 * make sure this call is during the current bus generation (i.e. no
24527c478bd9Sstevel@tonic-gate 	 * bus resets have occured since this request was made.
24537c478bd9Sstevel@tonic-gate 	 */
24547c478bd9Sstevel@tonic-gate 	if (cmd_priv->bus_generation != hci1394_ohci_current_busgen(
24557c478bd9Sstevel@tonic-gate 	    async_handle->as_ohci)) {
24567c478bd9Sstevel@tonic-gate 		*result = H1394_STATUS_INVALID_BUSGEN;
24577c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
24587c478bd9Sstevel@tonic-gate 	}
24597c478bd9Sstevel@tonic-gate 
24607c478bd9Sstevel@tonic-gate 	/*
24617c478bd9Sstevel@tonic-gate 	 * setup a shortcut to the hal private command area. Copy the generation
24627c478bd9Sstevel@tonic-gate 	 * to the Q area so that we can check the generation when the AT Q is
24637c478bd9Sstevel@tonic-gate 	 * locked. This prevents us from loosing commands due to race
24647c478bd9Sstevel@tonic-gate 	 * conditions.
24657c478bd9Sstevel@tonic-gate 	 */
24667c478bd9Sstevel@tonic-gate 	hcicmd = (hci1394_async_cmd_t *)cmd_priv->hal_overhead;
24677c478bd9Sstevel@tonic-gate 	hcicmd->ac_qcmd.qc_generation = cmd_priv->bus_generation;
24687c478bd9Sstevel@tonic-gate 
24697c478bd9Sstevel@tonic-gate 	/*
24707c478bd9Sstevel@tonic-gate 	 * Setup the packet header information for a ATRESP read packet. we
24717c478bd9Sstevel@tonic-gate 	 * will set the tcode later based on type of read response. Set
24727c478bd9Sstevel@tonic-gate 	 * SRCBusId if the addr is not a local bus address. Copy in the
24737c478bd9Sstevel@tonic-gate 	 * speed, tlabel, and response code.
24747c478bd9Sstevel@tonic-gate 	 */
24757c478bd9Sstevel@tonic-gate 	header.q1 = 0;
24767c478bd9Sstevel@tonic-gate 	if ((cmd->nodeID & IEEE1394_BUS_NUM_MASK) != IEEE1394_BUS_NUM_MASK) {
24777c478bd9Sstevel@tonic-gate 		header.q1 |= DESC_AT_SRCBUSID;
24787c478bd9Sstevel@tonic-gate 	}
24797c478bd9Sstevel@tonic-gate 	header.q1 |= HCI1394_DESC_AT_SPD_SET(cmd_priv->speed) |
24807c478bd9Sstevel@tonic-gate 	    HCI1394_DESC_TLABEL_SET(hcicmd->ac_tlabel.tbi_tlabel);
24817c478bd9Sstevel@tonic-gate 	header.q2 = (uint32_t)(HCI1394_DESC_DESTID_SET(cmd->nodeID) |
24827c478bd9Sstevel@tonic-gate 	    HCI1394_DESC_RCODE_SET(cmd->cmd_result));
24837c478bd9Sstevel@tonic-gate 	header.q3 = 0;
24847c478bd9Sstevel@tonic-gate 
24857c478bd9Sstevel@tonic-gate 	/* if the response is a read quadlet response */
24867c478bd9Sstevel@tonic-gate 	if (cmd->cmd_type == CMD1394_ASYNCH_RD_QUAD) {
24877c478bd9Sstevel@tonic-gate 		/*
24887c478bd9Sstevel@tonic-gate 		 * setup the tcode for a quadlet read response, If the
24897c478bd9Sstevel@tonic-gate 		 * response code is not resp complete.
24907c478bd9Sstevel@tonic-gate 		 */
24917c478bd9Sstevel@tonic-gate 		header.q1 |= DESC_ATRESP_Q1_QRD;
24927c478bd9Sstevel@tonic-gate 		if (cmd->cmd_result == IEEE1394_RESP_COMPLETE) {
24937c478bd9Sstevel@tonic-gate 			header.q4 = cmd->cmd_u.q.quadlet_data;
24947c478bd9Sstevel@tonic-gate 		} else {
24957c478bd9Sstevel@tonic-gate 			header.q4 = 0x0;
24967c478bd9Sstevel@tonic-gate 		}
24977c478bd9Sstevel@tonic-gate 
24987c478bd9Sstevel@tonic-gate 		/*
24997c478bd9Sstevel@tonic-gate 		 * Write response into the ATRESP Q. If we fail, we're out of
25007c478bd9Sstevel@tonic-gate 		 * space.
25017c478bd9Sstevel@tonic-gate 		 */
25027c478bd9Sstevel@tonic-gate 		status = hci1394_q_at(async_handle->as_atresp_q,
25037c478bd9Sstevel@tonic-gate 		    &hcicmd->ac_qcmd, &header, DESC_PKT_HDRLEN_AT_READQUAD_RESP,
25047c478bd9Sstevel@tonic-gate 		    result);
25057c478bd9Sstevel@tonic-gate 		if (status != DDI_SUCCESS) {
25067c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
25077c478bd9Sstevel@tonic-gate 		}
25087c478bd9Sstevel@tonic-gate 
25097c478bd9Sstevel@tonic-gate 	/*
25107c478bd9Sstevel@tonic-gate 	 * the response is a block read response. If the result is not a
25117c478bd9Sstevel@tonic-gate 	 * resp complete, we are not going to send any data back.
25127c478bd9Sstevel@tonic-gate 	 */
25137c478bd9Sstevel@tonic-gate 	} else if ((cmd->cmd_type == CMD1394_ASYNCH_RD_BLOCK) &&
25147c478bd9Sstevel@tonic-gate 	    (cmd->cmd_result != IEEE1394_RESP_COMPLETE)) {
25157c478bd9Sstevel@tonic-gate 		/*
25167c478bd9Sstevel@tonic-gate 		 * Setup the tcode for a block read response, set the data
25177c478bd9Sstevel@tonic-gate 		 * length to zero since we had an error.
25187c478bd9Sstevel@tonic-gate 		 */
25197c478bd9Sstevel@tonic-gate 		header.q1 |= DESC_ATRESP_Q1_BRD;
25207c478bd9Sstevel@tonic-gate 		header.q4 = 0x0;
25217c478bd9Sstevel@tonic-gate 
25227c478bd9Sstevel@tonic-gate 		/*
25237c478bd9Sstevel@tonic-gate 		 * Write response into the ATRESP Q. If we fail, we're out of
25247c478bd9Sstevel@tonic-gate 		 * space.
25257c478bd9Sstevel@tonic-gate 		 */
25267c478bd9Sstevel@tonic-gate 		status = hci1394_q_at(async_handle->as_atresp_q,
25277c478bd9Sstevel@tonic-gate 		    &hcicmd->ac_qcmd, &header,
25287c478bd9Sstevel@tonic-gate 		    DESC_PKT_HDRLEN_AT_READBLOCK_RESP, result);
25297c478bd9Sstevel@tonic-gate 		if (status != DDI_SUCCESS) {
25307c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
25317c478bd9Sstevel@tonic-gate 		}
25327c478bd9Sstevel@tonic-gate 
25337c478bd9Sstevel@tonic-gate 	/*
25347c478bd9Sstevel@tonic-gate 	 * the response is a block read response with a resp complete for the
25357c478bd9Sstevel@tonic-gate 	 * response code. Send back the read data.
25367c478bd9Sstevel@tonic-gate 	 */
25377c478bd9Sstevel@tonic-gate 	} else {
25387c478bd9Sstevel@tonic-gate 		/*
25397c478bd9Sstevel@tonic-gate 		 * Setup the tcode for a block read response, setup the data
25407c478bd9Sstevel@tonic-gate 		 * length.
25417c478bd9Sstevel@tonic-gate 		 */
25427c478bd9Sstevel@tonic-gate 		header.q1 |= DESC_ATRESP_Q1_BRD;
25437c478bd9Sstevel@tonic-gate 		header.q4 = HCI1394_DESC_DATALEN_SET(cmd->cmd_u.b.blk_length);
25447c478bd9Sstevel@tonic-gate 
25457c478bd9Sstevel@tonic-gate 		/*
25467c478bd9Sstevel@tonic-gate 		 * Write response into the ATRESP Q. If we fail, we're out of
25477c478bd9Sstevel@tonic-gate 		 * space. Use the data in the mblk.
25487c478bd9Sstevel@tonic-gate 		 */
25497c478bd9Sstevel@tonic-gate 		status = hci1394_q_at_with_mblk(async_handle->as_atresp_q,
25507c478bd9Sstevel@tonic-gate 		    &hcicmd->ac_qcmd, &header,
25517c478bd9Sstevel@tonic-gate 		    DESC_PKT_HDRLEN_AT_READBLOCK_RESP, &cmd_priv->mblk, result);
25527c478bd9Sstevel@tonic-gate 		if (status != DDI_SUCCESS) {
25537c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
25547c478bd9Sstevel@tonic-gate 		}
25557c478bd9Sstevel@tonic-gate 	}
25567c478bd9Sstevel@tonic-gate 
25577c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
25587c478bd9Sstevel@tonic-gate }
25597c478bd9Sstevel@tonic-gate 
25607c478bd9Sstevel@tonic-gate 
25617c478bd9Sstevel@tonic-gate /*
25627c478bd9Sstevel@tonic-gate  * hci1394_async_lock_response()
25637c478bd9Sstevel@tonic-gate  *    Send a lock ATRESP. This routine should be called from the Services
25647c478bd9Sstevel@tonic-gate  *    layer to send a response to a received lock request (ARREQ). The
25657c478bd9Sstevel@tonic-gate  *    response will differ between 32-bit/64-bit lock requests.
25667c478bd9Sstevel@tonic-gate  */
25677c478bd9Sstevel@tonic-gate int
hci1394_async_lock_response(hci1394_async_handle_t async_handle,cmd1394_cmd_t * cmd,h1394_cmd_priv_t * cmd_priv,int * result)25687c478bd9Sstevel@tonic-gate hci1394_async_lock_response(hci1394_async_handle_t async_handle,
25697c478bd9Sstevel@tonic-gate     cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result)
25707c478bd9Sstevel@tonic-gate {
25717c478bd9Sstevel@tonic-gate 	hci1394_basic_pkt_t header;
25727c478bd9Sstevel@tonic-gate 	hci1394_async_cmd_t *hcicmd;
25737c478bd9Sstevel@tonic-gate 	uint32_t data32;
25747c478bd9Sstevel@tonic-gate 	uint64_t data64;
25757c478bd9Sstevel@tonic-gate 	uint8_t *datap;
25767c478bd9Sstevel@tonic-gate 	uint_t size;
25777c478bd9Sstevel@tonic-gate 	int status;
25787c478bd9Sstevel@tonic-gate 
25797c478bd9Sstevel@tonic-gate 
25807c478bd9Sstevel@tonic-gate 	ASSERT(async_handle != NULL);
25817c478bd9Sstevel@tonic-gate 	ASSERT(cmd != NULL);
25827c478bd9Sstevel@tonic-gate 	ASSERT(cmd_priv != NULL);
25837c478bd9Sstevel@tonic-gate 	ASSERT(result != NULL);
25847c478bd9Sstevel@tonic-gate 
25857c478bd9Sstevel@tonic-gate 	/*
25867c478bd9Sstevel@tonic-gate 	 * make sure this call is during the current bus generation (i.e. no
25877c478bd9Sstevel@tonic-gate 	 * bus resets have occured since this request was made.
25887c478bd9Sstevel@tonic-gate 	 */
25897c478bd9Sstevel@tonic-gate 	if (cmd_priv->bus_generation != hci1394_ohci_current_busgen(
25907c478bd9Sstevel@tonic-gate 	    async_handle->as_ohci)) {
25917c478bd9Sstevel@tonic-gate 		*result = H1394_STATUS_INVALID_BUSGEN;
25927c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
25937c478bd9Sstevel@tonic-gate 	}
25947c478bd9Sstevel@tonic-gate 
25957c478bd9Sstevel@tonic-gate 	/*
25967c478bd9Sstevel@tonic-gate 	 * setup a shortcut to the hal private command area. Copy the generation
25977c478bd9Sstevel@tonic-gate 	 * to the Q area so that we can check the generation when the AT Q is
25987c478bd9Sstevel@tonic-gate 	 * locked. This prevents us from loosing commands due to race
25997c478bd9Sstevel@tonic-gate 	 * conditions.
26007c478bd9Sstevel@tonic-gate 	 */
26017c478bd9Sstevel@tonic-gate 	hcicmd = (hci1394_async_cmd_t *)cmd_priv->hal_overhead;
26027c478bd9Sstevel@tonic-gate 	hcicmd->ac_qcmd.qc_generation = cmd_priv->bus_generation;
26037c478bd9Sstevel@tonic-gate 
26047c478bd9Sstevel@tonic-gate 	/*
26057c478bd9Sstevel@tonic-gate 	 * Setup the packet header information for a ATRESP lock packet. Set
26067c478bd9Sstevel@tonic-gate 	 * the tcode for a lock response. Set SRCBusId if the addr is not a
26077c478bd9Sstevel@tonic-gate 	 * local bus address. Copy in the speed, tlabel, and response code.
26087c478bd9Sstevel@tonic-gate 	 */
26097c478bd9Sstevel@tonic-gate 	header.q1 = DESC_ATRESP_Q1_LCK;
26107c478bd9Sstevel@tonic-gate 	if ((cmd->nodeID & IEEE1394_BUS_NUM_MASK) != IEEE1394_BUS_NUM_MASK) {
26117c478bd9Sstevel@tonic-gate 		header.q1 |= DESC_AT_SRCBUSID;
26127c478bd9Sstevel@tonic-gate 	}
26137c478bd9Sstevel@tonic-gate 	header.q1 |= HCI1394_DESC_AT_SPD_SET(cmd_priv->speed) |
26147c478bd9Sstevel@tonic-gate 	    HCI1394_DESC_TLABEL_SET(hcicmd->ac_tlabel.tbi_tlabel);
26157c478bd9Sstevel@tonic-gate 	header.q2 = (uint32_t)(HCI1394_DESC_DESTID_SET(cmd->nodeID) |
26167c478bd9Sstevel@tonic-gate 	    HCI1394_DESC_RCODE_SET(cmd->cmd_result));
26177c478bd9Sstevel@tonic-gate 	header.q3 = 0;
26187c478bd9Sstevel@tonic-gate 
26197c478bd9Sstevel@tonic-gate 	/*
26207c478bd9Sstevel@tonic-gate 	 * If the lock result is not a resp complete, we are not going to send
26217c478bd9Sstevel@tonic-gate 	 * any data back.with the response.
26227c478bd9Sstevel@tonic-gate 	 */
26237c478bd9Sstevel@tonic-gate 	if (cmd->cmd_result != IEEE1394_RESP_COMPLETE) {
26247c478bd9Sstevel@tonic-gate 		/* set response size to 0 for error. Set the extended tcode */
26257c478bd9Sstevel@tonic-gate 		size = 0;
26267c478bd9Sstevel@tonic-gate 		if (cmd->cmd_type == CMD1394_ASYNCH_LOCK_32) {
26277c478bd9Sstevel@tonic-gate 			header.q4 = HCI1394_DESC_DATALEN_SET(size) |
26287c478bd9Sstevel@tonic-gate 			    HCI1394_DESC_EXTTCODE_SET(cmd->cmd_u.l32.lock_type);
26297c478bd9Sstevel@tonic-gate 		} else {
26307c478bd9Sstevel@tonic-gate 			header.q4 = HCI1394_DESC_DATALEN_SET(size) |
26317c478bd9Sstevel@tonic-gate 			    HCI1394_DESC_EXTTCODE_SET(cmd->cmd_u.l64.lock_type);
26327c478bd9Sstevel@tonic-gate 		}
26337c478bd9Sstevel@tonic-gate 
26347c478bd9Sstevel@tonic-gate 		/*
26357c478bd9Sstevel@tonic-gate 		 * Write response into the ATRESP Q. If we fail, we're out of
26367c478bd9Sstevel@tonic-gate 		 * space.
26377c478bd9Sstevel@tonic-gate 		 */
26387c478bd9Sstevel@tonic-gate 		status = hci1394_q_at(async_handle->as_atresp_q,
26397c478bd9Sstevel@tonic-gate 		    &hcicmd->ac_qcmd, &header, DESC_PKT_HDRLEN_AT_LOCK_RESP,
26407c478bd9Sstevel@tonic-gate 		    result);
26417c478bd9Sstevel@tonic-gate 		if (status != DDI_SUCCESS) {
26427c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
26437c478bd9Sstevel@tonic-gate 		}
26447c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
26457c478bd9Sstevel@tonic-gate 	}
26467c478bd9Sstevel@tonic-gate 
26477c478bd9Sstevel@tonic-gate 	/*
26487c478bd9Sstevel@tonic-gate 	 * if the lock result is resp complete, setup the size of the response
26497c478bd9Sstevel@tonic-gate 	 * depending on the lock size and copy the lock response data into a
26507c478bd9Sstevel@tonic-gate 	 * local buffer. If the lock response is an arithmetic operation, swap
26517c478bd9Sstevel@tonic-gate 	 * the data on little endian machines. If we don't know what type of
26527c478bd9Sstevel@tonic-gate 	 * lock operation it is, someone has corrupted the command since we
26537c478bd9Sstevel@tonic-gate 	 * had received the ARREQ.
26547c478bd9Sstevel@tonic-gate 	 */
26557c478bd9Sstevel@tonic-gate 	if (cmd->cmd_type == CMD1394_ASYNCH_LOCK_32) {
26567c478bd9Sstevel@tonic-gate 		size = IEEE1394_QUADLET;
26577c478bd9Sstevel@tonic-gate 		header.q4 = HCI1394_DESC_DATALEN_SET(size) |
26587c478bd9Sstevel@tonic-gate 		    HCI1394_DESC_EXTTCODE_SET(cmd->cmd_u.l32.lock_type);
26597c478bd9Sstevel@tonic-gate 		data32 = HCI1394_ARITH_LOCK_SWAP32(
26607c478bd9Sstevel@tonic-gate 		    cmd->cmd_u.l32.lock_type, cmd->cmd_u.l32.old_value);
26617c478bd9Sstevel@tonic-gate 		datap = (uint8_t *)&data32;
26627c478bd9Sstevel@tonic-gate 	} else if (cmd->cmd_type == CMD1394_ASYNCH_LOCK_64) {
26637c478bd9Sstevel@tonic-gate 		size = IEEE1394_OCTLET;
26647c478bd9Sstevel@tonic-gate 		header.q4 = HCI1394_DESC_DATALEN_SET(size) |
26657c478bd9Sstevel@tonic-gate 		    HCI1394_DESC_EXTTCODE_SET(cmd->cmd_u.l64.lock_type);
26667c478bd9Sstevel@tonic-gate 		data64 = HCI1394_ARITH_LOCK_SWAP64(
26677c478bd9Sstevel@tonic-gate 		    cmd->cmd_u.l64.lock_type, cmd->cmd_u.l64.old_value);
26687c478bd9Sstevel@tonic-gate 		datap = (uint8_t *)&data64;
26697c478bd9Sstevel@tonic-gate 	} else {
26707c478bd9Sstevel@tonic-gate 		*result = H1394_STATUS_INTERNAL_ERROR;
26717c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
26727c478bd9Sstevel@tonic-gate 	}
26737c478bd9Sstevel@tonic-gate 
26747c478bd9Sstevel@tonic-gate 	/*
26757c478bd9Sstevel@tonic-gate 	 * Write response into the ATRESP Q. If we fail, we're out of space.
26767c478bd9Sstevel@tonic-gate 	 * Use the local data buffer that we copied the data to above.
26777c478bd9Sstevel@tonic-gate 	 */
26787c478bd9Sstevel@tonic-gate 	status = hci1394_q_at_with_data(async_handle->as_atresp_q,
26797c478bd9Sstevel@tonic-gate 	    &hcicmd->ac_qcmd, &header, DESC_PKT_HDRLEN_AT_LOCK_RESP, datap,
26807c478bd9Sstevel@tonic-gate 	    size, result);
26817c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
26827c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
26837c478bd9Sstevel@tonic-gate 	}
26847c478bd9Sstevel@tonic-gate 
26857c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
26867c478bd9Sstevel@tonic-gate }
26877c478bd9Sstevel@tonic-gate 
26887c478bd9Sstevel@tonic-gate 
26897c478bd9Sstevel@tonic-gate /*
26907c478bd9Sstevel@tonic-gate  * hci1394_async_response_complete()
26917c478bd9Sstevel@tonic-gate  *    Free up space allocted during an ARREQ.  This is called when the target
26927c478bd9Sstevel@tonic-gate  *    driver and Services Layer are done with a command which was by the HAL
26937c478bd9Sstevel@tonic-gate  *    during ARREQ processing.  This routine will also free up any allocated
26947c478bd9Sstevel@tonic-gate  *    mblks.
26957c478bd9Sstevel@tonic-gate  *
26967c478bd9Sstevel@tonic-gate  *    NOTE: a target driver can hold on to a block write ARREQ mblk by setting
26977c478bd9Sstevel@tonic-gate  *    the mblk pointer to NULL.  This ONLY applies to block write ARREQs. The
26987c478bd9Sstevel@tonic-gate  *    HAL will no longer track the mblk for this case.
26997c478bd9Sstevel@tonic-gate  */
27007c478bd9Sstevel@tonic-gate void
hci1394_async_response_complete(hci1394_async_handle_t async_handle,cmd1394_cmd_t * cmd,h1394_cmd_priv_t * cmd_priv)27017c478bd9Sstevel@tonic-gate hci1394_async_response_complete(hci1394_async_handle_t async_handle,
27027c478bd9Sstevel@tonic-gate     cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv)
27037c478bd9Sstevel@tonic-gate {
27047c478bd9Sstevel@tonic-gate 	hci1394_async_cmd_t *hcicmd;
27057c478bd9Sstevel@tonic-gate 
27067c478bd9Sstevel@tonic-gate 
27077c478bd9Sstevel@tonic-gate 	ASSERT(async_handle != NULL);
27087c478bd9Sstevel@tonic-gate 	ASSERT(cmd != NULL);
27097c478bd9Sstevel@tonic-gate 	ASSERT(cmd_priv != NULL);
27107c478bd9Sstevel@tonic-gate 
27117c478bd9Sstevel@tonic-gate 	hcicmd = (hci1394_async_cmd_t *)cmd_priv->hal_overhead;
27127c478bd9Sstevel@tonic-gate 
27137c478bd9Sstevel@tonic-gate 	/* If we allocated an mblk for this command */
27147c478bd9Sstevel@tonic-gate 	if (hcicmd->ac_mblk_alloc == B_TRUE) {
27157c478bd9Sstevel@tonic-gate 		/*
27167c478bd9Sstevel@tonic-gate 		 * Don't free mblk if it is set to NULL. This allows a target
27177c478bd9Sstevel@tonic-gate 		 * driver to hold on to it in the case of a block write ARREQ.
27187c478bd9Sstevel@tonic-gate 		 */
27197c478bd9Sstevel@tonic-gate 		if (cmd->cmd_u.b.data_block != NULL) {
27207c478bd9Sstevel@tonic-gate 			freeb(cmd->cmd_u.b.data_block);
27217c478bd9Sstevel@tonic-gate 		}
27227c478bd9Sstevel@tonic-gate 	}
27237c478bd9Sstevel@tonic-gate 
27247c478bd9Sstevel@tonic-gate 	/* free up the 1394 framework command */
27257c478bd9Sstevel@tonic-gate 	(void) h1394_free_cmd((void *)async_handle->as_drvinfo->di_sl_private,
27267c478bd9Sstevel@tonic-gate 	    &cmd);
27277c478bd9Sstevel@tonic-gate }
27287c478bd9Sstevel@tonic-gate 
27297c478bd9Sstevel@tonic-gate 
27307c478bd9Sstevel@tonic-gate /*
27317c478bd9Sstevel@tonic-gate  * hci1394_async_pending_timeout()
27327c478bd9Sstevel@tonic-gate  *    This is the ARREQ Pending timeout callback routine.  It is called from
27337c478bd9Sstevel@tonic-gate  *    the tlist code. There is a race condition with the ARRESP interrupt
27347c478bd9Sstevel@tonic-gate  *    handler (hci1394_async_arresp_process) which requires a mutex to
27357c478bd9Sstevel@tonic-gate  *    lock around the mark of the bad tlabel.
27367c478bd9Sstevel@tonic-gate  *
27377c478bd9Sstevel@tonic-gate  *    Once we enter this routine, the command has timed out. If the command is
27387c478bd9Sstevel@tonic-gate  *    in both the ARRESP handler and here, we will consider it to have timed
27397c478bd9Sstevel@tonic-gate  *    out. That code path handles the race condition more easily.
27407c478bd9Sstevel@tonic-gate  */
27417c478bd9Sstevel@tonic-gate static void
hci1394_async_pending_timeout(hci1394_tlist_node_t * node,void * arg)27427c478bd9Sstevel@tonic-gate hci1394_async_pending_timeout(hci1394_tlist_node_t *node, void *arg)
27437c478bd9Sstevel@tonic-gate {
27447c478bd9Sstevel@tonic-gate 	hci1394_async_handle_t async_handle;
27457c478bd9Sstevel@tonic-gate 	hci1394_async_cmd_t *hcicmd;
27467c478bd9Sstevel@tonic-gate 
27477c478bd9Sstevel@tonic-gate 
27487c478bd9Sstevel@tonic-gate 	async_handle = (hci1394_async_handle_t)arg;
27497c478bd9Sstevel@tonic-gate 	ASSERT(async_handle != NULL);
27507c478bd9Sstevel@tonic-gate 	ASSERT(node != NULL);
27517c478bd9Sstevel@tonic-gate 
27527c478bd9Sstevel@tonic-gate 	hcicmd = (hci1394_async_cmd_t *)node->tln_addr;
27537c478bd9Sstevel@tonic-gate 
27547c478bd9Sstevel@tonic-gate 	/*
27557c478bd9Sstevel@tonic-gate 	 * We do NOT want to set the command state here. That should only be
27567c478bd9Sstevel@tonic-gate 	 * done in the ISR. The state does nothing for us here.
27577c478bd9Sstevel@tonic-gate 	 */
27587c478bd9Sstevel@tonic-gate 
27597c478bd9Sstevel@tonic-gate 	/*
27607c478bd9Sstevel@tonic-gate 	 * We want a lock around tlabel_lookup/reading data into the cmd in the
27617c478bd9Sstevel@tonic-gate 	 * ARRESP ISR processing and a lock around the tlabel_bad in this
27627c478bd9Sstevel@tonic-gate 	 * routine. This ensures that we will not be touching the command
27637c478bd9Sstevel@tonic-gate 	 * structure after we pass it up to the Services Layer. If we mark it as
27647c478bd9Sstevel@tonic-gate 	 * bad first, the lookup will fail. If we get to the lookup first, the
27657c478bd9Sstevel@tonic-gate 	 * pending list delete will fail in arresp_process() which will tell
27667c478bd9Sstevel@tonic-gate 	 * that guy that we are in the middle of doing the timeout processing
27677c478bd9Sstevel@tonic-gate 	 * for this command.  The ARRESP logic will just drop the response and
27687c478bd9Sstevel@tonic-gate 	 * continue on.
27697c478bd9Sstevel@tonic-gate 	 */
27707c478bd9Sstevel@tonic-gate 	mutex_enter(&hcicmd->ac_async->as_atomic_lookup);
27717c478bd9Sstevel@tonic-gate 	hci1394_tlabel_bad(async_handle->as_tlabel, &hcicmd->ac_tlabel);
27727c478bd9Sstevel@tonic-gate 	mutex_exit(&hcicmd->ac_async->as_atomic_lookup);
27737c478bd9Sstevel@tonic-gate 
27747c478bd9Sstevel@tonic-gate 	/* Tell the Services Layer that the command has timed out */
27757c478bd9Sstevel@tonic-gate 	h1394_cmd_is_complete(async_handle->as_drvinfo->di_sl_private,
27767c478bd9Sstevel@tonic-gate 	    hcicmd->ac_cmd, H1394_AT_REQ, H1394_CMD_ETIMEOUT);
27777c478bd9Sstevel@tonic-gate }
27787c478bd9Sstevel@tonic-gate 
27797c478bd9Sstevel@tonic-gate 
27807c478bd9Sstevel@tonic-gate /*
27817c478bd9Sstevel@tonic-gate  * hci1394_async_timeout_calc()
27827c478bd9Sstevel@tonic-gate  *    Calculate the timeout for an ATRESP. When an ARREQ is received, this
27837c478bd9Sstevel@tonic-gate  *    routine is called with the time the ARREQ was received. It returns the
27847c478bd9Sstevel@tonic-gate  *    time when the ATRESP is considered to have timed out. We timeout after
27857c478bd9Sstevel@tonic-gate  *    split_timeout has gone by. Split timeout and the returned value are in bus
27867c478bd9Sstevel@tonic-gate  *    cycles.
27877c478bd9Sstevel@tonic-gate  */
27887c478bd9Sstevel@tonic-gate static uint_t
hci1394_async_timeout_calc(hci1394_async_handle_t async_handle,uint_t current_time)27897c478bd9Sstevel@tonic-gate hci1394_async_timeout_calc(hci1394_async_handle_t async_handle,
27907c478bd9Sstevel@tonic-gate     uint_t current_time)
27917c478bd9Sstevel@tonic-gate {
27927c478bd9Sstevel@tonic-gate 	uint_t split_timeout;
27937c478bd9Sstevel@tonic-gate 	uint_t temp;
27947c478bd9Sstevel@tonic-gate 	uint_t carry;
27957c478bd9Sstevel@tonic-gate 	uint_t z;
27967c478bd9Sstevel@tonic-gate 
27977c478bd9Sstevel@tonic-gate 	/* Get the current split timeout */
27987c478bd9Sstevel@tonic-gate 	split_timeout = hci1394_csr_split_timeout_get(async_handle->as_csr);
27997c478bd9Sstevel@tonic-gate 
28007c478bd9Sstevel@tonic-gate 	/*
28017c478bd9Sstevel@tonic-gate 	 * The cycle count is broken up into two sections, the 3-bit seconds
28027c478bd9Sstevel@tonic-gate 	 * field and the 13-bit cycle count. The cycle count is in 125uS
28037c478bd9Sstevel@tonic-gate 	 * increments.  The maximum value of cycle count is 7999 (8000 is one
28047c478bd9Sstevel@tonic-gate 	 * second). With 13-bits, we could store up to 8191. Therefore, we don't
28057c478bd9Sstevel@tonic-gate 	 * have a simple 16-bit addition. Hence, the code we see below.
28067c478bd9Sstevel@tonic-gate 	 */
28077c478bd9Sstevel@tonic-gate 
28087c478bd9Sstevel@tonic-gate 	/*
28097c478bd9Sstevel@tonic-gate 	 * calculate the new cycle count based on the cycle count from current
28107c478bd9Sstevel@tonic-gate 	 * time and the split timeout. If this new value is not greater than the
28117c478bd9Sstevel@tonic-gate 	 * maximum cycle count, we don't have a carry. Go to the next step.
28127c478bd9Sstevel@tonic-gate 	 */
28137c478bd9Sstevel@tonic-gate 	temp = (current_time & OHCI_CYCLE_CNT_MASK) + (split_timeout &
28147c478bd9Sstevel@tonic-gate 	    OHCI_CYCLE_CNT_MASK);
28157c478bd9Sstevel@tonic-gate 	if (temp < OHCI_MAX_CYCLE_CNT) {
28167c478bd9Sstevel@tonic-gate 		carry = 0;
28177c478bd9Sstevel@tonic-gate 
28187c478bd9Sstevel@tonic-gate 	/*
28197c478bd9Sstevel@tonic-gate 	 * the new cycle count adds up to more than the maximum cycle count,
28207c478bd9Sstevel@tonic-gate 	 * set the carry state and adjust the total accordingly.
28217c478bd9Sstevel@tonic-gate 	 */
28227c478bd9Sstevel@tonic-gate 	} else {
28237c478bd9Sstevel@tonic-gate 		temp = temp - OHCI_MAX_CYCLE_CNT;
28247c478bd9Sstevel@tonic-gate 		carry = 1;
28257c478bd9Sstevel@tonic-gate 	}
28267c478bd9Sstevel@tonic-gate 
28277c478bd9Sstevel@tonic-gate 	/*
28287c478bd9Sstevel@tonic-gate 	 * The timeout time equals the seconds added with the carry (1 or 0
28297c478bd9Sstevel@tonic-gate 	 * seconds), added with the adjusted (if necessary) cycle count.
28307c478bd9Sstevel@tonic-gate 	 * Mask the final value to get rid of any second rollovers.
28317c478bd9Sstevel@tonic-gate 	 */
28327c478bd9Sstevel@tonic-gate 	z = (current_time & OHCI_CYCLE_SEC_MASK) + (split_timeout &
28337c478bd9Sstevel@tonic-gate 	    OHCI_CYCLE_SEC_MASK) + (carry << OHCI_CYCLE_SEC_SHIFT) + temp;
28347c478bd9Sstevel@tonic-gate 	z = z & OHCI_TIMESTAMP_MASK;
28357c478bd9Sstevel@tonic-gate 
28367c478bd9Sstevel@tonic-gate 	return (z);
28377c478bd9Sstevel@tonic-gate }
28387c478bd9Sstevel@tonic-gate 
28397c478bd9Sstevel@tonic-gate 
28407c478bd9Sstevel@tonic-gate /*
28417c478bd9Sstevel@tonic-gate  * hci1394_async_arresp_size_get()
28427c478bd9Sstevel@tonic-gate  *    Return the size of the arresp that was received in q_handle at addr.
28437c478bd9Sstevel@tonic-gate  */
28447c478bd9Sstevel@tonic-gate static int
hci1394_async_arresp_size_get(uint_t tcode,hci1394_q_handle_t q_handle,uint32_t * addr,uint_t * size)28457c478bd9Sstevel@tonic-gate hci1394_async_arresp_size_get(uint_t tcode, hci1394_q_handle_t q_handle,
28467c478bd9Sstevel@tonic-gate     uint32_t *addr, uint_t *size)
28477c478bd9Sstevel@tonic-gate {
28487c478bd9Sstevel@tonic-gate 	uint_t data_length;
28497c478bd9Sstevel@tonic-gate 	uint32_t quadlet;
28507c478bd9Sstevel@tonic-gate 
28517c478bd9Sstevel@tonic-gate 
28527c478bd9Sstevel@tonic-gate 	ASSERT(q_handle != NULL);
28537c478bd9Sstevel@tonic-gate 	ASSERT(addr != NULL);
28547c478bd9Sstevel@tonic-gate 	ASSERT(size != NULL);
28557c478bd9Sstevel@tonic-gate 
28567c478bd9Sstevel@tonic-gate 	if (tcode == IEEE1394_TCODE_WRITE_RESP) {
28577c478bd9Sstevel@tonic-gate 		*size = DESC_PKT_HDRLEN_AT_WRITE_RESP + IEEE1394_QUADLET;
28587c478bd9Sstevel@tonic-gate 	} else if (tcode == IEEE1394_TCODE_READ_QUADLET_RESP) {
28597c478bd9Sstevel@tonic-gate 		*size = DESC_PKT_HDRLEN_AT_READQUAD_RESP + IEEE1394_QUADLET;
28607c478bd9Sstevel@tonic-gate 	} else if (tcode == IEEE1394_TCODE_READ_BLOCK_RESP) {
28617c478bd9Sstevel@tonic-gate 		quadlet = hci1394_q_ar_get32(q_handle, &addr[3]);
28627c478bd9Sstevel@tonic-gate 		data_length = HCI1394_DESC_DATALEN_GET(quadlet);
28637c478bd9Sstevel@tonic-gate 		/*
28647c478bd9Sstevel@tonic-gate 		 * response size is in quadlets, therefore we need to
28657c478bd9Sstevel@tonic-gate 		 * make sure we count in the padding when figuring out
28667c478bd9Sstevel@tonic-gate 		 * the size used up for this response
28677c478bd9Sstevel@tonic-gate 		 */
28687c478bd9Sstevel@tonic-gate 		*size = DESC_PKT_HDRLEN_AT_READBLOCK_RESP +
28697c478bd9Sstevel@tonic-gate 		    HCI1394_ALIGN_QUAD(data_length) + IEEE1394_QUADLET;
28707c478bd9Sstevel@tonic-gate 	} else if (tcode == IEEE1394_TCODE_LOCK_RESP) {
28717c478bd9Sstevel@tonic-gate 		quadlet = hci1394_q_ar_get32(q_handle, &addr[3]);
28727c478bd9Sstevel@tonic-gate 		data_length = HCI1394_DESC_DATALEN_GET(quadlet);
28737c478bd9Sstevel@tonic-gate 		/*
28747c478bd9Sstevel@tonic-gate 		 * response size is in quadlets, therefore we need to
28757c478bd9Sstevel@tonic-gate 		 * make sure we count in the padding when figuring out
28767c478bd9Sstevel@tonic-gate 		 * the size used up for this response
28777c478bd9Sstevel@tonic-gate 		 */
28787c478bd9Sstevel@tonic-gate 		*size = DESC_PKT_HDRLEN_AT_LOCK_RESP +
28797c478bd9Sstevel@tonic-gate 		    HCI1394_ALIGN_QUAD(data_length) + IEEE1394_QUADLET;
28807c478bd9Sstevel@tonic-gate 	} else {
28817c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
28827c478bd9Sstevel@tonic-gate 	}
28837c478bd9Sstevel@tonic-gate 
28847c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
28857c478bd9Sstevel@tonic-gate }
28867c478bd9Sstevel@tonic-gate 
28877c478bd9Sstevel@tonic-gate 
28887c478bd9Sstevel@tonic-gate /*
28897c478bd9Sstevel@tonic-gate  * hci1394_async_pending_list_flush()
28907c478bd9Sstevel@tonic-gate  *    Flush out the ATREQ pending list. All commands still on the ATREQ pending
28917c478bd9Sstevel@tonic-gate  *    list are considered to be completed due to a bus reset. The ATREQ and
28927c478bd9Sstevel@tonic-gate  *    ARRESP Q's should be flushed before the pending Q is flushed. The ATREQ
28937c478bd9Sstevel@tonic-gate  *    could have more ACK pendings and the ARRESP could have valid responses to
28947c478bd9Sstevel@tonic-gate  *    pended requests.
28957c478bd9Sstevel@tonic-gate  */
28967c478bd9Sstevel@tonic-gate void
hci1394_async_pending_list_flush(hci1394_async_handle_t async_handle)28977c478bd9Sstevel@tonic-gate hci1394_async_pending_list_flush(hci1394_async_handle_t async_handle)
28987c478bd9Sstevel@tonic-gate {
28997c478bd9Sstevel@tonic-gate 	hci1394_tlist_node_t *node;
29007c478bd9Sstevel@tonic-gate 	hci1394_async_cmd_t *hcicmd;
29017c478bd9Sstevel@tonic-gate 
29027c478bd9Sstevel@tonic-gate 
29037c478bd9Sstevel@tonic-gate 	ASSERT(async_handle != NULL);
29047c478bd9Sstevel@tonic-gate 
29057c478bd9Sstevel@tonic-gate 	do {
29067c478bd9Sstevel@tonic-gate 		/*
29077c478bd9Sstevel@tonic-gate 		 * get the first node on the pending list. This routine also
29087c478bd9Sstevel@tonic-gate 		 * removes the node from the list.
29097c478bd9Sstevel@tonic-gate 		 */
29107c478bd9Sstevel@tonic-gate 		hci1394_tlist_get(async_handle->as_pending_list, &node);
29117c478bd9Sstevel@tonic-gate 		if (node != NULL) {
29127c478bd9Sstevel@tonic-gate 			/* set the command state to completed */
29137c478bd9Sstevel@tonic-gate 			hcicmd = (hci1394_async_cmd_t *)node->tln_addr;
29147c478bd9Sstevel@tonic-gate 			hcicmd->ac_state = HCI1394_CMD_STATE_COMPLETED;
29157c478bd9Sstevel@tonic-gate 
29167c478bd9Sstevel@tonic-gate 			/*
29177c478bd9Sstevel@tonic-gate 			 * Send the command up to the Services Layer with
29187c478bd9Sstevel@tonic-gate 			 * completed due to the bus reset for status.
29197c478bd9Sstevel@tonic-gate 			 */
29207c478bd9Sstevel@tonic-gate 			h1394_cmd_is_complete(
29217c478bd9Sstevel@tonic-gate 			    async_handle->as_drvinfo->di_sl_private,
29227c478bd9Sstevel@tonic-gate 			    hcicmd->ac_cmd, H1394_AT_REQ,
29237c478bd9Sstevel@tonic-gate 			    H1394_CMD_EBUSRESET);
29247c478bd9Sstevel@tonic-gate 		}
29257c478bd9Sstevel@tonic-gate 	} while (node != NULL);
29267c478bd9Sstevel@tonic-gate }
29277c478bd9Sstevel@tonic-gate 
29287c478bd9Sstevel@tonic-gate 
29297c478bd9Sstevel@tonic-gate /*
29307c478bd9Sstevel@tonic-gate  * hci1394_async_atreq_start()
29317c478bd9Sstevel@tonic-gate  *    Setup the command pointer for the first descriptor to be fetched and
29327c478bd9Sstevel@tonic-gate  *    then set the run bit. This routine will be called the first time
29337c478bd9Sstevel@tonic-gate  *    a descriptor is added to the Q.
29347c478bd9Sstevel@tonic-gate  */
29357c478bd9Sstevel@tonic-gate static void
hci1394_async_atreq_start(void * async,uint32_t command_ptr)29367c478bd9Sstevel@tonic-gate hci1394_async_atreq_start(void *async, uint32_t command_ptr)
29377c478bd9Sstevel@tonic-gate {
29387c478bd9Sstevel@tonic-gate 	hci1394_async_handle_t async_handle;
29397c478bd9Sstevel@tonic-gate 	ASSERT(async != NULL);
29407c478bd9Sstevel@tonic-gate 	async_handle = (hci1394_async_handle_t)async;
29417c478bd9Sstevel@tonic-gate 	hci1394_ohci_atreq_start(async_handle->as_ohci, command_ptr);
29427c478bd9Sstevel@tonic-gate }
29437c478bd9Sstevel@tonic-gate 
29447c478bd9Sstevel@tonic-gate 
29457c478bd9Sstevel@tonic-gate /*
29467c478bd9Sstevel@tonic-gate  * hci1394_async_atreq_wake()
29477c478bd9Sstevel@tonic-gate  *    Set the wake bit for the ATREQ DMA engine. This routine will be called
29487c478bd9Sstevel@tonic-gate  *    from the Q logic after placing a descriptor on the Q.
29497c478bd9Sstevel@tonic-gate  */
29507c478bd9Sstevel@tonic-gate static void
hci1394_async_atreq_wake(void * async)29517c478bd9Sstevel@tonic-gate hci1394_async_atreq_wake(void *async)
29527c478bd9Sstevel@tonic-gate {
29537c478bd9Sstevel@tonic-gate 	hci1394_async_handle_t async_handle;
29547c478bd9Sstevel@tonic-gate 	ASSERT(async != NULL);
29557c478bd9Sstevel@tonic-gate 	async_handle = (hci1394_async_handle_t)async;
29567c478bd9Sstevel@tonic-gate 	hci1394_ohci_atreq_wake(async_handle->as_ohci);
29577c478bd9Sstevel@tonic-gate }
29587c478bd9Sstevel@tonic-gate 
29597c478bd9Sstevel@tonic-gate 
29607c478bd9Sstevel@tonic-gate /*
29617c478bd9Sstevel@tonic-gate  * hci1394_async_atreq_reset()
29627c478bd9Sstevel@tonic-gate  *    Reset the atreq Q.  The AT DMA engines must be stopped every bus reset.
29637c478bd9Sstevel@tonic-gate  *    They will restart when the next descriptor is added to the Q. We will stop
29647c478bd9Sstevel@tonic-gate  *    the DMA engine and then notify the Q logic that it has been stopped so it
29657c478bd9Sstevel@tonic-gate  *    knows to do a start next time it puts a descriptor on the Q.
29667c478bd9Sstevel@tonic-gate  */
29677c478bd9Sstevel@tonic-gate void
hci1394_async_atreq_reset(hci1394_async_handle_t async_handle)29687c478bd9Sstevel@tonic-gate hci1394_async_atreq_reset(hci1394_async_handle_t async_handle)
29697c478bd9Sstevel@tonic-gate {
29707c478bd9Sstevel@tonic-gate 	ASSERT(async_handle != NULL);
29717c478bd9Sstevel@tonic-gate 	hci1394_ohci_atreq_stop(async_handle->as_ohci);
29727c478bd9Sstevel@tonic-gate 	hci1394_q_stop(async_handle->as_atreq_q);
29737c478bd9Sstevel@tonic-gate }
29747c478bd9Sstevel@tonic-gate 
29757c478bd9Sstevel@tonic-gate 
29767c478bd9Sstevel@tonic-gate /*
29777c478bd9Sstevel@tonic-gate  * hci1394_async_atreq_flush()
29787c478bd9Sstevel@tonic-gate  *    Flush out the atreq Q. This routine is called during bus reset processing.
29797c478bd9Sstevel@tonic-gate  *    it should be called before arresp_flush() and pending_list_flush().
29807c478bd9Sstevel@tonic-gate  */
29817c478bd9Sstevel@tonic-gate static void
hci1394_async_atreq_flush(hci1394_async_handle_t async_handle)29827c478bd9Sstevel@tonic-gate hci1394_async_atreq_flush(hci1394_async_handle_t async_handle)
29837c478bd9Sstevel@tonic-gate {
29847c478bd9Sstevel@tonic-gate 	boolean_t request_available;
29857c478bd9Sstevel@tonic-gate 
29867c478bd9Sstevel@tonic-gate 	ASSERT(async_handle != NULL);
29877c478bd9Sstevel@tonic-gate 
29887c478bd9Sstevel@tonic-gate 	/* Clear reqTxComplete interrupt */
29897c478bd9Sstevel@tonic-gate 	hci1394_ohci_intr_clear(async_handle->as_ohci, OHCI_INTR_REQ_TX_CMPLT);
29907c478bd9Sstevel@tonic-gate 
29917c478bd9Sstevel@tonic-gate 	/*
29927c478bd9Sstevel@tonic-gate 	 * Processes all Q'd AT requests.  If the request is pended, it is
29937c478bd9Sstevel@tonic-gate 	 * considered complete relative the the atreq engine.
29947c478bd9Sstevel@tonic-gate 	 * flush_pending_list() will finish up the required processing for
29957c478bd9Sstevel@tonic-gate 	 * pended requests.
29967c478bd9Sstevel@tonic-gate 	 */
29977c478bd9Sstevel@tonic-gate 	do {
29987c478bd9Sstevel@tonic-gate 		/* Flush the atreq Q. Process all Q'd commands */
2999*2570281cSToomas Soome 		(void) hci1394_async_atreq_process(async_handle,
30007c478bd9Sstevel@tonic-gate 		    B_TRUE, &request_available);
30017c478bd9Sstevel@tonic-gate 	} while (request_available == B_TRUE);
30027c478bd9Sstevel@tonic-gate }
30037c478bd9Sstevel@tonic-gate 
30047c478bd9Sstevel@tonic-gate 
30057c478bd9Sstevel@tonic-gate /*
30067c478bd9Sstevel@tonic-gate  * hci1394_async_arresp_start()
30077c478bd9Sstevel@tonic-gate  *    Setup the command pointer for the first descriptor to be fetched and
30087c478bd9Sstevel@tonic-gate  *    then set the run bit. This routine will be called the first time
30097c478bd9Sstevel@tonic-gate  *    a descriptor is added to the Q.
30107c478bd9Sstevel@tonic-gate  */
30117c478bd9Sstevel@tonic-gate static void
hci1394_async_arresp_start(void * async,uint32_t command_ptr)30127c478bd9Sstevel@tonic-gate hci1394_async_arresp_start(void *async, uint32_t command_ptr)
30137c478bd9Sstevel@tonic-gate {
30147c478bd9Sstevel@tonic-gate 	hci1394_async_handle_t async_handle;
30157c478bd9Sstevel@tonic-gate 	ASSERT(async != NULL);
30167c478bd9Sstevel@tonic-gate 	async_handle = (hci1394_async_handle_t)async;
30177c478bd9Sstevel@tonic-gate 	hci1394_ohci_arresp_start(async_handle->as_ohci, command_ptr);
30187c478bd9Sstevel@tonic-gate }
30197c478bd9Sstevel@tonic-gate 
30207c478bd9Sstevel@tonic-gate 
30217c478bd9Sstevel@tonic-gate /*
30227c478bd9Sstevel@tonic-gate  * hci1394_async_arresp_wake()
30237c478bd9Sstevel@tonic-gate  *    Set the wake bit for the ARRESP DMA engine. This routine will be called
30247c478bd9Sstevel@tonic-gate  *    from the Q logic after placing a descriptor on the Q.
30257c478bd9Sstevel@tonic-gate  */
30267c478bd9Sstevel@tonic-gate static void
hci1394_async_arresp_wake(void * async)30277c478bd9Sstevel@tonic-gate hci1394_async_arresp_wake(void *async)
30287c478bd9Sstevel@tonic-gate {
30297c478bd9Sstevel@tonic-gate 	hci1394_async_handle_t async_handle;
30307c478bd9Sstevel@tonic-gate 	ASSERT(async != NULL);
30317c478bd9Sstevel@tonic-gate 	async_handle = (hci1394_async_handle_t)async;
30327c478bd9Sstevel@tonic-gate 	hci1394_ohci_arresp_wake(async_handle->as_ohci);
30337c478bd9Sstevel@tonic-gate }
30347c478bd9Sstevel@tonic-gate 
30357c478bd9Sstevel@tonic-gate 
30367c478bd9Sstevel@tonic-gate /*
30377c478bd9Sstevel@tonic-gate  * hci1394_async_arresp_flush()
30387c478bd9Sstevel@tonic-gate  *    Flush out the arresp Q. This routine is called during bus reset
30397c478bd9Sstevel@tonic-gate  *    processing. This should be called before pending_list_flush(). All
30407c478bd9Sstevel@tonic-gate  *    receive responses will be processed normally. The tlabels should
30417c478bd9Sstevel@tonic-gate  *    not be reset until after the ARRESP Q has been flushed. Otherwise
30427c478bd9Sstevel@tonic-gate  *    we would reject valid responses.
30437c478bd9Sstevel@tonic-gate  */
30447c478bd9Sstevel@tonic-gate static void
hci1394_async_arresp_flush(hci1394_async_handle_t async_handle)30457c478bd9Sstevel@tonic-gate hci1394_async_arresp_flush(hci1394_async_handle_t async_handle)
30467c478bd9Sstevel@tonic-gate {
30477c478bd9Sstevel@tonic-gate 	boolean_t response_available;
30487c478bd9Sstevel@tonic-gate 
30497c478bd9Sstevel@tonic-gate 	ASSERT(async_handle != NULL);
30507c478bd9Sstevel@tonic-gate 
30517c478bd9Sstevel@tonic-gate 	/* Clear reqTxComplete interrupt */
30527c478bd9Sstevel@tonic-gate 	hci1394_ohci_intr_clear(async_handle->as_ohci, OHCI_INTR_RSPKT);
30537c478bd9Sstevel@tonic-gate 
30547c478bd9Sstevel@tonic-gate 	do {
30557c478bd9Sstevel@tonic-gate 		/* Flush the arresp Q. Process all received commands */
3056*2570281cSToomas Soome 		(void) hci1394_async_arresp_process(async_handle,
30577c478bd9Sstevel@tonic-gate 		    &response_available);
30587c478bd9Sstevel@tonic-gate 	} while (response_available == B_TRUE);
30597c478bd9Sstevel@tonic-gate }
30607c478bd9Sstevel@tonic-gate 
30617c478bd9Sstevel@tonic-gate 
30627c478bd9Sstevel@tonic-gate /*
30637c478bd9Sstevel@tonic-gate  * hci1394_async_arreq_start()
30647c478bd9Sstevel@tonic-gate  *    Setup the command pointer for the first descriptor to be fetched and
30657c478bd9Sstevel@tonic-gate  *    then set the run bit. This routine will be called the first time
30667c478bd9Sstevel@tonic-gate  *    a descriptor is added to the Q.
30677c478bd9Sstevel@tonic-gate  */
30687c478bd9Sstevel@tonic-gate static void
hci1394_async_arreq_start(void * async,uint32_t command_ptr)30697c478bd9Sstevel@tonic-gate hci1394_async_arreq_start(void *async, uint32_t command_ptr)
30707c478bd9Sstevel@tonic-gate {
30717c478bd9Sstevel@tonic-gate 	hci1394_async_handle_t async_handle;
30727c478bd9Sstevel@tonic-gate 	ASSERT(async != NULL);
30737c478bd9Sstevel@tonic-gate 	async_handle = (hci1394_async_handle_t)async;
30747c478bd9Sstevel@tonic-gate 	hci1394_ohci_arreq_start(async_handle->as_ohci, command_ptr);
30757c478bd9Sstevel@tonic-gate }
30767c478bd9Sstevel@tonic-gate 
30777c478bd9Sstevel@tonic-gate 
30787c478bd9Sstevel@tonic-gate /*
30797c478bd9Sstevel@tonic-gate  * hci1394_async_arreq_wake()
30807c478bd9Sstevel@tonic-gate  *    Set the wake bit for the ARREQ DMA engine. This routine will be called
30817c478bd9Sstevel@tonic-gate  *    from the Q logic after placing a descriptor on the Q.
30827c478bd9Sstevel@tonic-gate  */
30837c478bd9Sstevel@tonic-gate static void
hci1394_async_arreq_wake(void * async)30847c478bd9Sstevel@tonic-gate hci1394_async_arreq_wake(void *async)
30857c478bd9Sstevel@tonic-gate {
30867c478bd9Sstevel@tonic-gate 	hci1394_async_handle_t async_handle;
30877c478bd9Sstevel@tonic-gate 	ASSERT(async != NULL);
30887c478bd9Sstevel@tonic-gate 	async_handle = (hci1394_async_handle_t)async;
30897c478bd9Sstevel@tonic-gate 	hci1394_ohci_arreq_wake(async_handle->as_ohci);
30907c478bd9Sstevel@tonic-gate }
30917c478bd9Sstevel@tonic-gate 
30927c478bd9Sstevel@tonic-gate 
30937c478bd9Sstevel@tonic-gate /*
30947c478bd9Sstevel@tonic-gate  * hci1394_async_arreq_flush()
30957c478bd9Sstevel@tonic-gate  *    Flush the ARREQ Q. This will flush up to the bus reset token in the
30967c478bd9Sstevel@tonic-gate  *    ARREQ. There is no order dependency for when routine should get called
30977c478bd9Sstevel@tonic-gate  *    (relative to the other Q flushing routines)
30987c478bd9Sstevel@tonic-gate  */
30997c478bd9Sstevel@tonic-gate static void
hci1394_async_arreq_flush(hci1394_async_handle_t async_handle)31007c478bd9Sstevel@tonic-gate hci1394_async_arreq_flush(hci1394_async_handle_t async_handle)
31017c478bd9Sstevel@tonic-gate {
31027c478bd9Sstevel@tonic-gate 	boolean_t request_available;
31037c478bd9Sstevel@tonic-gate 
31047c478bd9Sstevel@tonic-gate 	ASSERT(async_handle != NULL);
31057c478bd9Sstevel@tonic-gate 
31067c478bd9Sstevel@tonic-gate 	/*
31077c478bd9Sstevel@tonic-gate 	 * If the last bus reset token we have seen in
31087c478bd9Sstevel@tonic-gate 	 * hci1394_async_arreq_read_phy() matches the current generation, the
31097c478bd9Sstevel@tonic-gate 	 * ARREQ is already flushed.  We have nothing further to do here so
31107c478bd9Sstevel@tonic-gate 	 * return. This can happen if we are processing ARREQ's and a bus reset
31117c478bd9Sstevel@tonic-gate 	 * occurs. Since we are already in the ISR, we will see the token before
31127c478bd9Sstevel@tonic-gate 	 * the bus reset handler gets to run.
31137c478bd9Sstevel@tonic-gate 	 */
31147c478bd9Sstevel@tonic-gate 	if (async_handle->as_phy_reset == hci1394_ohci_current_busgen(
31157c478bd9Sstevel@tonic-gate 	    async_handle->as_ohci)) {
31167c478bd9Sstevel@tonic-gate 		return;
31177c478bd9Sstevel@tonic-gate 	}
31187c478bd9Sstevel@tonic-gate 
31197c478bd9Sstevel@tonic-gate 	/*
31207c478bd9Sstevel@tonic-gate 	 * set flag to tell hci1394_async_arreq_process() that we should not
31217c478bd9Sstevel@tonic-gate 	 * pass ARREQ's up to the Services Layer.  This will be set to B_FALSE
31227c478bd9Sstevel@tonic-gate 	 * in hci1394_async_arreq_read_phy() when a bus reset token matching
31237c478bd9Sstevel@tonic-gate 	 * the current generation is found.
31247c478bd9Sstevel@tonic-gate 	 */
31257c478bd9Sstevel@tonic-gate 	async_handle->as_flushing_arreq = B_TRUE;
31267c478bd9Sstevel@tonic-gate 
31277c478bd9Sstevel@tonic-gate 	/*
31287c478bd9Sstevel@tonic-gate 	 * Process all requests that have been received or until we find the
31297c478bd9Sstevel@tonic-gate 	 * correct bus reset token.
31307c478bd9Sstevel@tonic-gate 	 */
31317c478bd9Sstevel@tonic-gate 	do {
3132*2570281cSToomas Soome 		(void) hci1394_async_arreq_process(async_handle,
31337c478bd9Sstevel@tonic-gate 		    &request_available);
31347c478bd9Sstevel@tonic-gate 	} while ((request_available == B_TRUE) &&
31357c478bd9Sstevel@tonic-gate 	    (async_handle->as_flushing_arreq == B_TRUE));
31367c478bd9Sstevel@tonic-gate 
31377c478bd9Sstevel@tonic-gate 	/*
31387c478bd9Sstevel@tonic-gate 	 * Clear the asserted interrupt if there are no more ARREQ's to process.
31397c478bd9Sstevel@tonic-gate 	 * We could have ARREQ's in the Q after the bus reset token since we
31407c478bd9Sstevel@tonic-gate 	 * will set as_flushing_arreq to FALSE when we see the correct bus reset
31417c478bd9Sstevel@tonic-gate 	 * token in hci1394_async_arreq_read_phy(). If there are more ARREQ's,
31427c478bd9Sstevel@tonic-gate 	 * we will process them later after finishing the reset of bus reset
31437c478bd9Sstevel@tonic-gate 	 * processing.  That is why we will leave the interrupt asserted.
31447c478bd9Sstevel@tonic-gate 	 */
31457c478bd9Sstevel@tonic-gate 	if (request_available == B_FALSE) {
31467c478bd9Sstevel@tonic-gate 		hci1394_ohci_intr_clear(async_handle->as_ohci, OHCI_INTR_RQPKT);
31477c478bd9Sstevel@tonic-gate 	}
31487c478bd9Sstevel@tonic-gate }
31497c478bd9Sstevel@tonic-gate 
31507c478bd9Sstevel@tonic-gate 
31517c478bd9Sstevel@tonic-gate /*
31527c478bd9Sstevel@tonic-gate  * hci1394_async_atresp_start()
31537c478bd9Sstevel@tonic-gate  *    Setup the command pointer for the first descriptor to be fetched and
31547c478bd9Sstevel@tonic-gate  *    then set the run bit. This routine will be called the first time
31557c478bd9Sstevel@tonic-gate  *    a descriptor is added to the Q.
31567c478bd9Sstevel@tonic-gate  */
31577c478bd9Sstevel@tonic-gate static void
hci1394_async_atresp_start(void * async,uint32_t command_ptr)31587c478bd9Sstevel@tonic-gate hci1394_async_atresp_start(void *async, uint32_t command_ptr)
31597c478bd9Sstevel@tonic-gate {
31607c478bd9Sstevel@tonic-gate 	hci1394_async_handle_t async_handle;
31617c478bd9Sstevel@tonic-gate 	ASSERT(async != NULL);
31627c478bd9Sstevel@tonic-gate 	async_handle = (hci1394_async_handle_t)async;
31637c478bd9Sstevel@tonic-gate 	hci1394_ohci_atresp_start(async_handle->as_ohci, command_ptr);
31647c478bd9Sstevel@tonic-gate }
31657c478bd9Sstevel@tonic-gate 
31667c478bd9Sstevel@tonic-gate 
31677c478bd9Sstevel@tonic-gate /*
31687c478bd9Sstevel@tonic-gate  * hci1394_async_atresp_wake()
31697c478bd9Sstevel@tonic-gate  *    Set the wake bit for the ATRESP DMA engine. This routine will be called
31707c478bd9Sstevel@tonic-gate  *    from the Q logic after placing a descriptor on the Q.
31717c478bd9Sstevel@tonic-gate  */
31727c478bd9Sstevel@tonic-gate static void
hci1394_async_atresp_wake(void * async)31737c478bd9Sstevel@tonic-gate hci1394_async_atresp_wake(void *async)
31747c478bd9Sstevel@tonic-gate {
31757c478bd9Sstevel@tonic-gate 	hci1394_async_handle_t async_handle;
31767c478bd9Sstevel@tonic-gate 	ASSERT(async != NULL);
31777c478bd9Sstevel@tonic-gate 	async_handle = (hci1394_async_handle_t)async;
31787c478bd9Sstevel@tonic-gate 	hci1394_ohci_atresp_wake(async_handle->as_ohci);
31797c478bd9Sstevel@tonic-gate }
31807c478bd9Sstevel@tonic-gate 
31817c478bd9Sstevel@tonic-gate 
31827c478bd9Sstevel@tonic-gate /*
31837c478bd9Sstevel@tonic-gate  * hci1394_async_atresp_reset()
31847c478bd9Sstevel@tonic-gate  *    Reset the atresp Q.  The AT DMA engines must be stopped every bus reset.
31857c478bd9Sstevel@tonic-gate  *    They will restart when the next descriptor is added to the Q. We will stop
31867c478bd9Sstevel@tonic-gate  *    the DMA engine and then notify the Q logic that it has been stopped so it
31877c478bd9Sstevel@tonic-gate  *    knows to do a start next time it puts a descriptor on the Q.
31887c478bd9Sstevel@tonic-gate  */
31897c478bd9Sstevel@tonic-gate void
hci1394_async_atresp_reset(hci1394_async_handle_t async_handle)31907c478bd9Sstevel@tonic-gate hci1394_async_atresp_reset(hci1394_async_handle_t async_handle)
31917c478bd9Sstevel@tonic-gate {
31927c478bd9Sstevel@tonic-gate 	ASSERT(async_handle != NULL);
31937c478bd9Sstevel@tonic-gate 	hci1394_ohci_atresp_stop(async_handle->as_ohci);
31947c478bd9Sstevel@tonic-gate 	hci1394_q_stop(async_handle->as_atresp_q);
31957c478bd9Sstevel@tonic-gate }
31967c478bd9Sstevel@tonic-gate 
31977c478bd9Sstevel@tonic-gate 
31987c478bd9Sstevel@tonic-gate /*
31997c478bd9Sstevel@tonic-gate  * hci1394_async_atresp_flush()
32007c478bd9Sstevel@tonic-gate  *    Flush all commands out of the atresp Q. This routine will be called
32017c478bd9Sstevel@tonic-gate  *    during bus reset processing. There is no order dependency for when
32027c478bd9Sstevel@tonic-gate  *    routine should get called (relative to the other Q flushing routines)
32037c478bd9Sstevel@tonic-gate  */
32047c478bd9Sstevel@tonic-gate static void
hci1394_async_atresp_flush(hci1394_async_handle_t async_handle)32057c478bd9Sstevel@tonic-gate hci1394_async_atresp_flush(hci1394_async_handle_t async_handle)
32067c478bd9Sstevel@tonic-gate {
32077c478bd9Sstevel@tonic-gate 	boolean_t response_available;
32087c478bd9Sstevel@tonic-gate 
32097c478bd9Sstevel@tonic-gate 	ASSERT(async_handle != NULL);
32107c478bd9Sstevel@tonic-gate 
32117c478bd9Sstevel@tonic-gate 	/* Clear respTxComplete interrupt */
32127c478bd9Sstevel@tonic-gate 	hci1394_ohci_intr_clear(async_handle->as_ohci, OHCI_INTR_RESP_TX_CMPLT);
32137c478bd9Sstevel@tonic-gate 
32147c478bd9Sstevel@tonic-gate 	/* Processes all AT responses */
32157c478bd9Sstevel@tonic-gate 	do {
32167c478bd9Sstevel@tonic-gate 		/* Flush the atresp Q. Process all Q'd commands */
3217*2570281cSToomas Soome 		(void) hci1394_async_atresp_process(async_handle,
32187c478bd9Sstevel@tonic-gate 		    B_TRUE, &response_available);
32197c478bd9Sstevel@tonic-gate 	} while (response_available == B_TRUE);
32207c478bd9Sstevel@tonic-gate }
32217c478bd9Sstevel@tonic-gate 
32227c478bd9Sstevel@tonic-gate /*
32237c478bd9Sstevel@tonic-gate  * hci1394_async_hcicmd_init()
32247c478bd9Sstevel@tonic-gate  *    Initialize the private HAL command structure. This should be called from
32257c478bd9Sstevel@tonic-gate  *    ATREQ and ARREQ routines.
32267c478bd9Sstevel@tonic-gate  */
32277c478bd9Sstevel@tonic-gate static void
hci1394_async_hcicmd_init(hci1394_async_handle_t async_handle,cmd1394_cmd_t * cmd,h1394_cmd_priv_t * cmd_priv,hci1394_async_cmd_t ** hcicmd)32287c478bd9Sstevel@tonic-gate hci1394_async_hcicmd_init(hci1394_async_handle_t async_handle,
32297c478bd9Sstevel@tonic-gate     cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv,
32307c478bd9Sstevel@tonic-gate     hci1394_async_cmd_t **hcicmd)
32317c478bd9Sstevel@tonic-gate {
32327c478bd9Sstevel@tonic-gate 	*hcicmd = (hci1394_async_cmd_t *)cmd_priv->hal_overhead;
32337c478bd9Sstevel@tonic-gate 	(*hcicmd)->ac_cmd = cmd;
32347c478bd9Sstevel@tonic-gate 	(*hcicmd)->ac_priv = cmd_priv;
32357c478bd9Sstevel@tonic-gate 	(*hcicmd)->ac_async = async_handle;
32367c478bd9Sstevel@tonic-gate 	(*hcicmd)->ac_state = HCI1394_CMD_STATE_IN_PROGRESS;
32377c478bd9Sstevel@tonic-gate 	(*hcicmd)->ac_dest = 0;
32387c478bd9Sstevel@tonic-gate 	(*hcicmd)->ac_tlabel_alloc = B_TRUE;
32397c478bd9Sstevel@tonic-gate 	(*hcicmd)->ac_tlabel.tbi_tlabel = 0;
32407c478bd9Sstevel@tonic-gate 	(*hcicmd)->ac_tlabel.tbi_destination = 0;
32417c478bd9Sstevel@tonic-gate 	(*hcicmd)->ac_status = 0;
32427c478bd9Sstevel@tonic-gate 	(*hcicmd)->ac_qcmd.qc_timestamp = 0;
32437c478bd9Sstevel@tonic-gate 	(*hcicmd)->ac_qcmd.qc_arg = *hcicmd;
32447c478bd9Sstevel@tonic-gate 	(*hcicmd)->ac_qcmd.qc_generation = cmd_priv->bus_generation;
32457c478bd9Sstevel@tonic-gate 	(*hcicmd)->ac_mblk_alloc = B_FALSE;
32467c478bd9Sstevel@tonic-gate }
3247