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
580a70ef3Sap  * Common Development and Distribution License (the "License").
680a70ef3Sap  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
2280a70ef3Sap  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate  * hci1394_ixl_update.c
287c478bd9Sstevel@tonic-gate  *    Isochronous IXL update routines.
297c478bd9Sstevel@tonic-gate  *    Routines used to dynamically update a compiled and presumably running
307c478bd9Sstevel@tonic-gate  *    IXL program.
317c478bd9Sstevel@tonic-gate  */
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
347c478bd9Sstevel@tonic-gate #include <sys/types.h>
357c478bd9Sstevel@tonic-gate #include <sys/conf.h>
3680a70ef3Sap #include <sys/disp.h>
377c478bd9Sstevel@tonic-gate #include <sys/1394/h1394.h>
387c478bd9Sstevel@tonic-gate #include <sys/1394/ixl1394.h>	/* IXL opcodes & data structs */
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate #include <sys/1394/adapters/hci1394.h>
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate /* local defines for hci1394_ixl_update_prepare return codes */
447c478bd9Sstevel@tonic-gate #define	IXL_PREP_READY	    1
457c478bd9Sstevel@tonic-gate #define	IXL_PREP_SUCCESS    0
467c478bd9Sstevel@tonic-gate #define	IXL_PREP_FAILURE    (-1)
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate /*
497c478bd9Sstevel@tonic-gate  * variable used to indicate the number of times update will wait for
507c478bd9Sstevel@tonic-gate  * interrupt routine to complete.
517c478bd9Sstevel@tonic-gate  */
527c478bd9Sstevel@tonic-gate int hci1394_upd_retries_before_fail = 50;
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate /* IXL runtime update static functions */
557c478bd9Sstevel@tonic-gate static int hci1394_ixl_update_prepare(hci1394_ixl_update_vars_t *uvp);
567c478bd9Sstevel@tonic-gate static int hci1394_ixl_update_prep_jump(hci1394_ixl_update_vars_t *uvp);
577c478bd9Sstevel@tonic-gate static int hci1394_ixl_update_prep_set_skipmode(hci1394_ixl_update_vars_t *uvp);
587c478bd9Sstevel@tonic-gate static int hci1394_ixl_update_prep_set_tagsync(hci1394_ixl_update_vars_t *uvp);
597c478bd9Sstevel@tonic-gate static int hci1394_ixl_update_prep_recv_pkt(hci1394_ixl_update_vars_t *uvp);
607c478bd9Sstevel@tonic-gate static int hci1394_ixl_update_prep_recv_buf(hci1394_ixl_update_vars_t *uvp);
617c478bd9Sstevel@tonic-gate static int hci1394_ixl_update_prep_send_pkt(hci1394_ixl_update_vars_t *uvp);
627c478bd9Sstevel@tonic-gate static int hci1394_ixl_update_prep_send_buf(hci1394_ixl_update_vars_t *uvp);
637c478bd9Sstevel@tonic-gate static int hci1394_ixl_update_perform(hci1394_ixl_update_vars_t *uvp);
647c478bd9Sstevel@tonic-gate static int hci1394_ixl_update_evaluate(hci1394_ixl_update_vars_t *uvp);
657c478bd9Sstevel@tonic-gate static int hci1394_ixl_update_analysis(hci1394_ixl_update_vars_t *uvp);
667c478bd9Sstevel@tonic-gate static void hci1394_ixl_update_set_locn_info(hci1394_ixl_update_vars_t *uvp);
677c478bd9Sstevel@tonic-gate static int hci1394_ixl_update_enable(hci1394_ixl_update_vars_t *uvp);
687c478bd9Sstevel@tonic-gate static int hci1394_ixl_update_endup(hci1394_ixl_update_vars_t *uvp);
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate /*
717c478bd9Sstevel@tonic-gate  *	IXL commands and included fields which can be updated
727c478bd9Sstevel@tonic-gate  * IXL1394_OP_CALLBACK:		callback(), callback_data
737c478bd9Sstevel@tonic-gate  * IXL1394_OP_JUMP:		label
747c478bd9Sstevel@tonic-gate  * IXL1394_OP_RECV_PKT		ixl_buf, size, mem_bufp
757c478bd9Sstevel@tonic-gate  * IXL1394_OP_RECV_PKT_ST	ixl_buf, size, mem_bufp
767c478bd9Sstevel@tonic-gate  * IXL1394_OP_RECV_BUF(ppb)	ixl_buf, size, pkt_size, mem_bufp, buf_offset
777c478bd9Sstevel@tonic-gate  * IXL1394_OP_RECV_BUF(fill)	ixl_buf, size, pkt_size, mem_bufp, buf_offset
787c478bd9Sstevel@tonic-gate  * IXL1394_OP_SEND_PKT		ixl_buf, size, mem_bufp
797c478bd9Sstevel@tonic-gate  * IXL1394_OP_SEND_PKT_ST	ixl_buf, size, mem_bufp
807c478bd9Sstevel@tonic-gate  * IXL1394_OP_SEND_PKT_WHDR_ST	ixl_buf, size, mem_bufp
817c478bd9Sstevel@tonic-gate  * IXL1394_OP_SEND_BUF		ixl_buf, size, pkt_size, mem_bufp, buf_offset
827c478bd9Sstevel@tonic-gate  * IXL1394_OP_SET_TAGSYNC	tag, sync
837c478bd9Sstevel@tonic-gate  * IXL1394_OP_SET_SKIPMODE	skipmode, label
847c478bd9Sstevel@tonic-gate  *
857c478bd9Sstevel@tonic-gate  *	IXL commands which can not be updated
867c478bd9Sstevel@tonic-gate  * IXL1394_OP_LABEL
877c478bd9Sstevel@tonic-gate  * IXL1394_OP_SEND_HDR_ONLY
887c478bd9Sstevel@tonic-gate  * IXL1394_OP_SEND_NOPKT
897c478bd9Sstevel@tonic-gate  * IXL1394_OP_STORE_VALUE
907c478bd9Sstevel@tonic-gate  * IXL1394_OP_STORE_TIMESTAMP
917c478bd9Sstevel@tonic-gate  * IXL1394_OP_SET_SYNCWAIT
927c478bd9Sstevel@tonic-gate  */
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate /*
957c478bd9Sstevel@tonic-gate  * hci1394_ixl_update
967c478bd9Sstevel@tonic-gate  *    main entrypoint into dynamic update code: initializes temporary
977c478bd9Sstevel@tonic-gate  *    update variables, evaluates request, coordinates with potentially
987c478bd9Sstevel@tonic-gate  *    simultaneous run of interrupt stack, evaluates likelyhood of success,
997c478bd9Sstevel@tonic-gate  *    performs the update, checks if completed, performs cleanup
1007c478bd9Sstevel@tonic-gate  *    resulting from coordination with interrupt stack.
1017c478bd9Sstevel@tonic-gate  */
1027c478bd9Sstevel@tonic-gate int
hci1394_ixl_update(hci1394_state_t * soft_statep,hci1394_iso_ctxt_t * ctxtp,ixl1394_command_t * ixlnewp,ixl1394_command_t * ixloldp,uint_t riskoverride,int * resultp)1037c478bd9Sstevel@tonic-gate hci1394_ixl_update(hci1394_state_t *soft_statep, hci1394_iso_ctxt_t *ctxtp,
1047c478bd9Sstevel@tonic-gate     ixl1394_command_t *ixlnewp, ixl1394_command_t *ixloldp,
1057c478bd9Sstevel@tonic-gate     uint_t riskoverride, int *resultp)
1067c478bd9Sstevel@tonic-gate {
1077c478bd9Sstevel@tonic-gate 	hci1394_ixl_update_vars_t uv;	/* update work variables structure */
1087c478bd9Sstevel@tonic-gate 	int prepstatus;
1097c478bd9Sstevel@tonic-gate 	int ret;
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate 	/* save caller specified values in update work variables structure */
1127c478bd9Sstevel@tonic-gate 	uv.soft_statep = soft_statep;
1137c478bd9Sstevel@tonic-gate 	uv.ctxtp = ctxtp;
1147c478bd9Sstevel@tonic-gate 	uv.ixlnewp = ixlnewp;
1157c478bd9Sstevel@tonic-gate 	uv.ixloldp = ixloldp;
1167c478bd9Sstevel@tonic-gate 	uv.risklevel = riskoverride;
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate 	/* initialize remainder of update work variables */
1197c478bd9Sstevel@tonic-gate 	uv.ixlxferp = NULL;
1207c478bd9Sstevel@tonic-gate 	uv.skipxferp = NULL;
1217c478bd9Sstevel@tonic-gate 	uv.skipmode = 0;
1227c478bd9Sstevel@tonic-gate 	uv.skipaddr = 0;
1237c478bd9Sstevel@tonic-gate 	uv.jumpaddr = 0;
1247c478bd9Sstevel@tonic-gate 	uv.pkthdr1 = 0;
1257c478bd9Sstevel@tonic-gate 	uv.pkthdr2 = 0;
1267c478bd9Sstevel@tonic-gate 	uv.bufaddr = 0;
1277c478bd9Sstevel@tonic-gate 	uv.bufsize = 0;
1287c478bd9Sstevel@tonic-gate 	uv.ixl_opcode = uv.ixlnewp->ixl_opcode;
1297c478bd9Sstevel@tonic-gate 	uv.hcihdr = 0;
1307c478bd9Sstevel@tonic-gate 	uv.hcistatus = 0;
1317c478bd9Sstevel@tonic-gate 	uv.hci_offset = 0;
1327c478bd9Sstevel@tonic-gate 	uv.hdr_offset = 0;
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate 	/* set done ok return status */
1357c478bd9Sstevel@tonic-gate 	uv.upd_status = 0;
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate 	/* evaluate request and prepare to perform update */
1387c478bd9Sstevel@tonic-gate 	prepstatus = hci1394_ixl_update_prepare(&uv);
1397c478bd9Sstevel@tonic-gate 	if (prepstatus != IXL_PREP_READY) {
1407c478bd9Sstevel@tonic-gate 		/*
1417c478bd9Sstevel@tonic-gate 		 * if either done or nothing to do or an evaluation error,
1427c478bd9Sstevel@tonic-gate 		 * return update status
1437c478bd9Sstevel@tonic-gate 		 */
1447c478bd9Sstevel@tonic-gate 		*resultp = uv.upd_status;
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate 		/* if prep evaluation error, return failure */
1477c478bd9Sstevel@tonic-gate 		if (prepstatus != IXL_PREP_SUCCESS) {
1487c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
1497c478bd9Sstevel@tonic-gate 		}
1507c478bd9Sstevel@tonic-gate 		/* if no action or update done, return update successful */
1517c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
1527c478bd9Sstevel@tonic-gate 	}
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 	/* perform update processing reservation of interrupt context */
1557c478bd9Sstevel@tonic-gate 	ret = hci1394_ixl_update_enable(&uv);
1567c478bd9Sstevel@tonic-gate 	if (ret != DDI_SUCCESS) {
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate 		/* error acquiring control of context - return */
1597c478bd9Sstevel@tonic-gate 		*resultp = uv.upd_status;
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
1627c478bd9Sstevel@tonic-gate 	}
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 	/* perform update risk analysis */
1657c478bd9Sstevel@tonic-gate 	if (hci1394_ixl_update_analysis(&uv) != DDI_SUCCESS) {
1667c478bd9Sstevel@tonic-gate 		/*
1677c478bd9Sstevel@tonic-gate 		 * return, if excessive risk or dma execution processing lost
1687c478bd9Sstevel@tonic-gate 		 * (note: caller risk override not yet implemented)
1697c478bd9Sstevel@tonic-gate 		 */
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate 		/* attempt intr processing cleanup, unless err is dmalost */
1727c478bd9Sstevel@tonic-gate 		if (uv.upd_status != IXL1394_EPRE_UPD_DMALOST) {
1737c478bd9Sstevel@tonic-gate 			(void) hci1394_ixl_update_endup(&uv);
1747c478bd9Sstevel@tonic-gate 		} else {
1757c478bd9Sstevel@tonic-gate 			/*
1767c478bd9Sstevel@tonic-gate 			 * error is dmalost, just release interrupt context.
1777c478bd9Sstevel@tonic-gate 			 * take the lock here to ensure an atomic read, modify,
1787c478bd9Sstevel@tonic-gate 			 * write of the "intr_flags" field while we try to
1797c478bd9Sstevel@tonic-gate 			 * clear the "in update" flag.  protects from the
1807c478bd9Sstevel@tonic-gate 			 * interrupt routine.
1817c478bd9Sstevel@tonic-gate 			 */
1827c478bd9Sstevel@tonic-gate 			mutex_enter(&ctxtp->intrprocmutex);
1837c478bd9Sstevel@tonic-gate 			ctxtp->intr_flags &= ~HCI1394_ISO_CTXT_INUPDATE;
1847c478bd9Sstevel@tonic-gate 			mutex_exit(&ctxtp->intrprocmutex);
1857c478bd9Sstevel@tonic-gate 		}
1867c478bd9Sstevel@tonic-gate 		*resultp = uv.upd_status;
1877c478bd9Sstevel@tonic-gate 
1887c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
1897c478bd9Sstevel@tonic-gate 	}
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate 	/* perform requested update */
1937c478bd9Sstevel@tonic-gate 	if (hci1394_ixl_update_perform(&uv) != DDI_SUCCESS) {
1947c478bd9Sstevel@tonic-gate 		/*
1957c478bd9Sstevel@tonic-gate 		 * if non-completion condition, return update status
1967c478bd9Sstevel@tonic-gate 		 * attempt interrupt processing cleanup first
1977c478bd9Sstevel@tonic-gate 		 */
1987c478bd9Sstevel@tonic-gate 		(void) hci1394_ixl_update_endup(&uv);
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 		*resultp = uv.upd_status;
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
2037c478bd9Sstevel@tonic-gate 	}
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate 	/* evaluate update completion, setting completion status */
2067c478bd9Sstevel@tonic-gate 	if (hci1394_ixl_update_evaluate(&uv) != DDI_SUCCESS) {
2077c478bd9Sstevel@tonic-gate 		/*
2087c478bd9Sstevel@tonic-gate 		 * update failed - bad, just release interrupt context
2097c478bd9Sstevel@tonic-gate 		 * take the lock here too (jsut like above) to ensure an
2107c478bd9Sstevel@tonic-gate 		 * atomic read, modify, write of the "intr_flags" field
2117c478bd9Sstevel@tonic-gate 		 * while we try to clear the "in update" flag.  protects
2127c478bd9Sstevel@tonic-gate 		 * from the interrupt routine.
2137c478bd9Sstevel@tonic-gate 		 */
2147c478bd9Sstevel@tonic-gate 		mutex_enter(&ctxtp->intrprocmutex);
2157c478bd9Sstevel@tonic-gate 		ctxtp->intr_flags &= ~HCI1394_ISO_CTXT_INUPDATE;
2167c478bd9Sstevel@tonic-gate 		mutex_exit(&ctxtp->intrprocmutex);
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate 		/* if DMA stopped or lost, formally stop context */
2197c478bd9Sstevel@tonic-gate 		if (uv.upd_status == HCI1394_IXL_INTR_DMASTOP) {
2207c478bd9Sstevel@tonic-gate 			hci1394_do_stop(soft_statep, ctxtp, B_TRUE,
2217c478bd9Sstevel@tonic-gate 			    ID1394_DONE);
2227c478bd9Sstevel@tonic-gate 		} else if (uv.upd_status == HCI1394_IXL_INTR_DMALOST) {
2237c478bd9Sstevel@tonic-gate 			hci1394_do_stop(soft_statep, ctxtp, B_TRUE,
2247c478bd9Sstevel@tonic-gate 			    ID1394_FAIL);
2257c478bd9Sstevel@tonic-gate 		}
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 		*resultp = uv.upd_status;
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
2307c478bd9Sstevel@tonic-gate 	}
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate 	/* perform interrupt processing cleanup */
2337c478bd9Sstevel@tonic-gate 	uv.upd_status = hci1394_ixl_update_endup(&uv);
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate 	/* return update completion status */
2367c478bd9Sstevel@tonic-gate 	*resultp = uv.upd_status;
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
2397c478bd9Sstevel@tonic-gate }
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate /*
2427c478bd9Sstevel@tonic-gate  * hci1394_ixl_update_enable
2437c478bd9Sstevel@tonic-gate  *	Used to coordinate dynamic update activities with simultaneous
2447c478bd9Sstevel@tonic-gate  *	interrupt handler processing, while holding the context mutex
2457c478bd9Sstevel@tonic-gate  *      for as short a time as possible.
2467c478bd9Sstevel@tonic-gate  */
2477c478bd9Sstevel@tonic-gate static int
hci1394_ixl_update_enable(hci1394_ixl_update_vars_t * uvp)2487c478bd9Sstevel@tonic-gate hci1394_ixl_update_enable(hci1394_ixl_update_vars_t *uvp)
2497c478bd9Sstevel@tonic-gate {
2507c478bd9Sstevel@tonic-gate 	int	status;
2517c478bd9Sstevel@tonic-gate 	boolean_t retry;
2527c478bd9Sstevel@tonic-gate 	uint_t	remretries;
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate 	retry = B_TRUE;
2557c478bd9Sstevel@tonic-gate 	/* set arbitrary number of retries before giving up */
2567c478bd9Sstevel@tonic-gate 	remretries = hci1394_upd_retries_before_fail;
2577c478bd9Sstevel@tonic-gate 	status = DDI_SUCCESS;
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate 	/*
2607c478bd9Sstevel@tonic-gate 	 * if waited for completion of interrupt processing generated callback,
2617c478bd9Sstevel@tonic-gate 	 * retry here
2627c478bd9Sstevel@tonic-gate 	 */
2637c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_NOT_HELD(&uvp->ctxtp->intrprocmutex));
2647c478bd9Sstevel@tonic-gate 	mutex_enter(&uvp->ctxtp->intrprocmutex);
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate 	while (retry == B_TRUE) {
2677c478bd9Sstevel@tonic-gate 		retry = B_FALSE;
2687c478bd9Sstevel@tonic-gate 		remretries--;
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate 		/* failure if update processing is already in progress */
2717c478bd9Sstevel@tonic-gate 		if (uvp->ctxtp->intr_flags & HCI1394_ISO_CTXT_INUPDATE) {
2727c478bd9Sstevel@tonic-gate 			uvp->upd_status = IXL1394_EUPDATE_DISALLOWED;
2737c478bd9Sstevel@tonic-gate 			status = DDI_FAILURE;
2747c478bd9Sstevel@tonic-gate 		} else if (uvp->ctxtp->intr_flags & HCI1394_ISO_CTXT_ININTR) {
2757c478bd9Sstevel@tonic-gate 			/*
2767c478bd9Sstevel@tonic-gate 			 * if have retried max number of times or if this update
2777c478bd9Sstevel@tonic-gate 			 * request is on the interrupt stack, which means that
2787c478bd9Sstevel@tonic-gate 			 * the callback function of the target driver initiated
2797c478bd9Sstevel@tonic-gate 			 * the update, set update failure.
2807c478bd9Sstevel@tonic-gate 			 */
2817c478bd9Sstevel@tonic-gate 			if ((remretries <= 0) ||
28280a70ef3Sap 			    (servicing_interrupt())) {
2837c478bd9Sstevel@tonic-gate 				uvp->upd_status = IXL1394_EUPDATE_DISALLOWED;
2847c478bd9Sstevel@tonic-gate 				status = DDI_FAILURE;
2857c478bd9Sstevel@tonic-gate 			} else {
2867c478bd9Sstevel@tonic-gate 				/*
2877c478bd9Sstevel@tonic-gate 				 * if not on interrupt stack and retries not
2887c478bd9Sstevel@tonic-gate 				 * exhausted, free mutex, wait a short time
2897c478bd9Sstevel@tonic-gate 				 * and then retry.
2907c478bd9Sstevel@tonic-gate 				 */
2917c478bd9Sstevel@tonic-gate 				retry = B_TRUE;
2927c478bd9Sstevel@tonic-gate 				mutex_exit(&uvp->ctxtp->intrprocmutex);
2937c478bd9Sstevel@tonic-gate 				drv_usecwait(1);
2947c478bd9Sstevel@tonic-gate 				mutex_enter(&uvp->ctxtp->intrprocmutex);
2957c478bd9Sstevel@tonic-gate 				continue;
2967c478bd9Sstevel@tonic-gate 			}
2977c478bd9Sstevel@tonic-gate 		} else if (uvp->ctxtp->intr_flags & HCI1394_ISO_CTXT_INCALL) {
2987c478bd9Sstevel@tonic-gate 			uvp->upd_status = IXL1394_EINTERNAL_ERROR;
2997c478bd9Sstevel@tonic-gate 			status = DDI_FAILURE;
3007c478bd9Sstevel@tonic-gate 		}
3017c478bd9Sstevel@tonic-gate 	}
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 	/* if context is available, reserve it for this update request */
3047c478bd9Sstevel@tonic-gate 	if (status == DDI_SUCCESS) {
3057c478bd9Sstevel@tonic-gate 		uvp->ctxtp->intr_flags |= HCI1394_ISO_CTXT_INUPDATE;
3067c478bd9Sstevel@tonic-gate 	}
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&uvp->ctxtp->intrprocmutex));
3097c478bd9Sstevel@tonic-gate 	mutex_exit(&uvp->ctxtp->intrprocmutex);
3107c478bd9Sstevel@tonic-gate 
3117c478bd9Sstevel@tonic-gate 	return (status);
3127c478bd9Sstevel@tonic-gate }
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate /*
3157c478bd9Sstevel@tonic-gate  * hci1394_ixl_update_endup()
3167c478bd9Sstevel@tonic-gate  *    The ending stage of coordinating with simultaneously running interrupts.
3177c478bd9Sstevel@tonic-gate  *    Perform interrupt processing sync tasks if we (update) had blocked the
3187c478bd9Sstevel@tonic-gate  *    interrupt out when it wanted a turn.
3197c478bd9Sstevel@tonic-gate  */
3207c478bd9Sstevel@tonic-gate static int
hci1394_ixl_update_endup(hci1394_ixl_update_vars_t * uvp)3217c478bd9Sstevel@tonic-gate hci1394_ixl_update_endup(hci1394_ixl_update_vars_t *uvp)
3227c478bd9Sstevel@tonic-gate {
3237c478bd9Sstevel@tonic-gate 	uint_t status;
3247c478bd9Sstevel@tonic-gate 	hci1394_iso_ctxt_t *ctxtp;
3257c478bd9Sstevel@tonic-gate 
3267c478bd9Sstevel@tonic-gate 	status = HCI1394_IXL_INTR_NOERROR;
3277c478bd9Sstevel@tonic-gate 	ctxtp = uvp->ctxtp;
3287c478bd9Sstevel@tonic-gate 
3297c478bd9Sstevel@tonic-gate 	while (ctxtp->intr_flags & HCI1394_ISO_CTXT_INUPDATE) {
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate 		if (ctxtp->intr_flags & HCI1394_ISO_CTXT_INTRSET) {
3327c478bd9Sstevel@tonic-gate 			/*
3337c478bd9Sstevel@tonic-gate 			 * We don't need to grab the lock here because
3347c478bd9Sstevel@tonic-gate 			 * the "intr_flags" field is only modified in two
3357c478bd9Sstevel@tonic-gate 			 * ways - one in UPDATE and one in INTR routine. Since
3367c478bd9Sstevel@tonic-gate 			 * we know that it can't be modified simulataneously
3377c478bd9Sstevel@tonic-gate 			 * in another UDPATE thread - that is assured by the
3387c478bd9Sstevel@tonic-gate 			 * checks in "update_enable" - we would only be trying
3397c478bd9Sstevel@tonic-gate 			 * to protect against the INTR thread.  And since we
3407c478bd9Sstevel@tonic-gate 			 * are going to clear a bit here (and check it again
3417c478bd9Sstevel@tonic-gate 			 * at the top of the loop) we are not really concerned
3427c478bd9Sstevel@tonic-gate 			 * about missing its being set by the INTR routine.
3437c478bd9Sstevel@tonic-gate 			 */
3447c478bd9Sstevel@tonic-gate 			ctxtp->intr_flags &= ~HCI1394_ISO_CTXT_INTRSET;
3457c478bd9Sstevel@tonic-gate 
3467c478bd9Sstevel@tonic-gate 			status = hci1394_ixl_dma_sync(uvp->soft_statep, ctxtp);
3477c478bd9Sstevel@tonic-gate 			if (status ==  HCI1394_IXL_INTR_DMALOST) {
3487c478bd9Sstevel@tonic-gate 				/*
3497c478bd9Sstevel@tonic-gate 				 * Unlike above, we do care here as we are
3507c478bd9Sstevel@tonic-gate 				 * trying to clear the "in update" flag, and
3517c478bd9Sstevel@tonic-gate 				 * we don't want that lost because the INTR
3527c478bd9Sstevel@tonic-gate 				 * routine is trying to set its flag.
3537c478bd9Sstevel@tonic-gate 				 */
3547c478bd9Sstevel@tonic-gate 				mutex_enter(&uvp->ctxtp->intrprocmutex);
3557c478bd9Sstevel@tonic-gate 				ctxtp->intr_flags &= ~HCI1394_ISO_CTXT_INUPDATE;
3567c478bd9Sstevel@tonic-gate 				mutex_exit(&uvp->ctxtp->intrprocmutex);
3577c478bd9Sstevel@tonic-gate 				continue;
3587c478bd9Sstevel@tonic-gate 			}
3597c478bd9Sstevel@tonic-gate 		}
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 		ASSERT(MUTEX_NOT_HELD(&uvp->ctxtp->intrprocmutex));
3627c478bd9Sstevel@tonic-gate 		mutex_enter(&uvp->ctxtp->intrprocmutex);
3637c478bd9Sstevel@tonic-gate 		if (!(ctxtp->intr_flags & HCI1394_ISO_CTXT_INTRSET)) {
3647c478bd9Sstevel@tonic-gate 			ctxtp->intr_flags &= ~HCI1394_ISO_CTXT_INUPDATE;
3657c478bd9Sstevel@tonic-gate 		}
3667c478bd9Sstevel@tonic-gate 		mutex_exit(&uvp->ctxtp->intrprocmutex);
3677c478bd9Sstevel@tonic-gate 	}
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 	/* if DMA stopped or lost, formally stop context */
3707c478bd9Sstevel@tonic-gate 	if (status == HCI1394_IXL_INTR_DMASTOP) {
3717c478bd9Sstevel@tonic-gate 		hci1394_do_stop(uvp->soft_statep, ctxtp, B_TRUE, ID1394_DONE);
3727c478bd9Sstevel@tonic-gate 	} else if (status == HCI1394_IXL_INTR_DMALOST) {
3737c478bd9Sstevel@tonic-gate 		hci1394_do_stop(uvp->soft_statep, ctxtp, B_TRUE, ID1394_FAIL);
3747c478bd9Sstevel@tonic-gate 	}
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate 	return (status);
3777c478bd9Sstevel@tonic-gate }
3787c478bd9Sstevel@tonic-gate 
3797c478bd9Sstevel@tonic-gate /*
3807c478bd9Sstevel@tonic-gate  * hci1394_ixl_update_prepare()
3817c478bd9Sstevel@tonic-gate  *    Preparation for the actual update (using temp uvp struct)
3827c478bd9Sstevel@tonic-gate  */
3837c478bd9Sstevel@tonic-gate static int
hci1394_ixl_update_prepare(hci1394_ixl_update_vars_t * uvp)3847c478bd9Sstevel@tonic-gate hci1394_ixl_update_prepare(hci1394_ixl_update_vars_t *uvp)
3857c478bd9Sstevel@tonic-gate {
3867c478bd9Sstevel@tonic-gate 	int		    ret;
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate 	/* both new and old ixl commands must be the same */
3897c478bd9Sstevel@tonic-gate 	if (uvp->ixlnewp->ixl_opcode != uvp->ixloldp->ixl_opcode) {
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate 		uvp->upd_status = IXL1394_EOPCODE_MISMATCH;
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate 		return (IXL_PREP_FAILURE);
3947c478bd9Sstevel@tonic-gate 	}
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate 	/*
3977c478bd9Sstevel@tonic-gate 	 * perform evaluation and prepare update based on specific
3987c478bd9Sstevel@tonic-gate 	 * IXL command type
3997c478bd9Sstevel@tonic-gate 	 */
4007c478bd9Sstevel@tonic-gate 	switch (uvp->ixl_opcode) {
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate 	case IXL1394_OP_CALLBACK_U: {
4037c478bd9Sstevel@tonic-gate 		ixl1394_callback_t *old_callback_ixlp;
4047c478bd9Sstevel@tonic-gate 		ixl1394_callback_t *new_callback_ixlp;
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate 		old_callback_ixlp = (ixl1394_callback_t *)uvp->ixloldp;
4077c478bd9Sstevel@tonic-gate 		new_callback_ixlp = (ixl1394_callback_t *)uvp->ixlnewp;
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate 		/* perform update now without further evaluation */
4107c478bd9Sstevel@tonic-gate 		old_callback_ixlp->callback_arg =
4117c478bd9Sstevel@tonic-gate 		    new_callback_ixlp->callback_arg;
4127c478bd9Sstevel@tonic-gate 		old_callback_ixlp->callback = new_callback_ixlp->callback;
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate 		/* nothing else to do, return with done ok status */
4157c478bd9Sstevel@tonic-gate 		return (IXL_PREP_SUCCESS);
4167c478bd9Sstevel@tonic-gate 	}
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate 	case IXL1394_OP_JUMP_U:
4197c478bd9Sstevel@tonic-gate 		ret = hci1394_ixl_update_prep_jump(uvp);
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate 		return (ret);
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate 	case IXL1394_OP_SET_SKIPMODE_U:
4247c478bd9Sstevel@tonic-gate 		ret = hci1394_ixl_update_prep_set_skipmode(uvp);
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate 		return (ret);
4277c478bd9Sstevel@tonic-gate 
4287c478bd9Sstevel@tonic-gate 	case IXL1394_OP_SET_TAGSYNC_U:
4297c478bd9Sstevel@tonic-gate 		ret = hci1394_ixl_update_prep_set_tagsync(uvp);
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate 		return (ret);
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate 	case IXL1394_OP_RECV_PKT_U:
4347c478bd9Sstevel@tonic-gate 	case IXL1394_OP_RECV_PKT_ST_U:
4357c478bd9Sstevel@tonic-gate 		ret = hci1394_ixl_update_prep_recv_pkt(uvp);
4367c478bd9Sstevel@tonic-gate 
4377c478bd9Sstevel@tonic-gate 		return (ret);
4387c478bd9Sstevel@tonic-gate 
4397c478bd9Sstevel@tonic-gate 	case IXL1394_OP_RECV_BUF_U:
4407c478bd9Sstevel@tonic-gate 		ret = hci1394_ixl_update_prep_recv_buf(uvp);
4417c478bd9Sstevel@tonic-gate 
4427c478bd9Sstevel@tonic-gate 		return (ret);
4437c478bd9Sstevel@tonic-gate 
4447c478bd9Sstevel@tonic-gate 	case IXL1394_OP_SEND_PKT_U:
4457c478bd9Sstevel@tonic-gate 	case IXL1394_OP_SEND_PKT_ST_U:
4467c478bd9Sstevel@tonic-gate 	case IXL1394_OP_SEND_PKT_WHDR_ST_U:
4477c478bd9Sstevel@tonic-gate 		ret = hci1394_ixl_update_prep_send_pkt(uvp);
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate 		return (ret);
4507c478bd9Sstevel@tonic-gate 
4517c478bd9Sstevel@tonic-gate 	case IXL1394_OP_SEND_BUF_U:
4527c478bd9Sstevel@tonic-gate 		ret = hci1394_ixl_update_prep_send_buf(uvp);
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate 		return (ret);
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate 	default:
4577c478bd9Sstevel@tonic-gate 		/* ixl command being updated must be one of above, else error */
4587c478bd9Sstevel@tonic-gate 		uvp->upd_status = IXL1394_EOPCODE_DISALLOWED;
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 		return (IXL_PREP_FAILURE);
4617c478bd9Sstevel@tonic-gate 	}
4627c478bd9Sstevel@tonic-gate }
4637c478bd9Sstevel@tonic-gate 
4647c478bd9Sstevel@tonic-gate /*
4657c478bd9Sstevel@tonic-gate  * hci1394_ixl_update_prep_jump()
4667c478bd9Sstevel@tonic-gate  *    Preparation for update of an IXL1394_OP_JUMP_U command.
4677c478bd9Sstevel@tonic-gate  */
4687c478bd9Sstevel@tonic-gate static int
hci1394_ixl_update_prep_jump(hci1394_ixl_update_vars_t * uvp)4697c478bd9Sstevel@tonic-gate hci1394_ixl_update_prep_jump(hci1394_ixl_update_vars_t *uvp)
4707c478bd9Sstevel@tonic-gate {
4717c478bd9Sstevel@tonic-gate 	ixl1394_jump_t	    *old_jump_ixlp;
4727c478bd9Sstevel@tonic-gate 	ixl1394_jump_t	    *new_jump_ixlp;
4737c478bd9Sstevel@tonic-gate 	ixl1394_command_t   *ixlp;
4747c478bd9Sstevel@tonic-gate 	hci1394_xfer_ctl_t  *xferctlp;
4757c478bd9Sstevel@tonic-gate 	hci1394_desc_t	    *hcidescp;
4767c478bd9Sstevel@tonic-gate 	uint_t		    cbcnt;
4777c478bd9Sstevel@tonic-gate 	ddi_acc_handle_t    acc_hdl;
4787c478bd9Sstevel@tonic-gate 	ddi_dma_handle_t    dma_hdl;
4797c478bd9Sstevel@tonic-gate 	uint32_t	    desc_hdr;
4807c478bd9Sstevel@tonic-gate 	int		    err;
4817c478bd9Sstevel@tonic-gate 
4827c478bd9Sstevel@tonic-gate 	old_jump_ixlp = (ixl1394_jump_t *)uvp->ixloldp;
4837c478bd9Sstevel@tonic-gate 	new_jump_ixlp = (ixl1394_jump_t *)uvp->ixlnewp;
4847c478bd9Sstevel@tonic-gate 
4857c478bd9Sstevel@tonic-gate 	/* check if any change between new and old ixl jump command */
4867c478bd9Sstevel@tonic-gate 	if (new_jump_ixlp->label == old_jump_ixlp->label) {
4877c478bd9Sstevel@tonic-gate 
4887c478bd9Sstevel@tonic-gate 		/* if none, return with done ok status */
4897c478bd9Sstevel@tonic-gate 		return (IXL_PREP_SUCCESS);
4907c478bd9Sstevel@tonic-gate 	}
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate 	/* new ixl jump command label must be ptr to valid ixl label or NULL */
4937c478bd9Sstevel@tonic-gate 	if ((new_jump_ixlp->label != NULL) &&
4947c478bd9Sstevel@tonic-gate 	    (new_jump_ixlp->label->ixl_opcode != IXL1394_OP_LABEL)) {
4957c478bd9Sstevel@tonic-gate 
4967c478bd9Sstevel@tonic-gate 		/* if not jumping to label, return an error */
4977c478bd9Sstevel@tonic-gate 		uvp->upd_status = IXL1394_EJUMP_NOT_TO_LABEL;
4987c478bd9Sstevel@tonic-gate 
4997c478bd9Sstevel@tonic-gate 		return (IXL_PREP_FAILURE);
5007c478bd9Sstevel@tonic-gate 	}
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate 	/*
5037c478bd9Sstevel@tonic-gate 	 * follow exec path from new ixl jump command label to determine new
5047c478bd9Sstevel@tonic-gate 	 * jump destination ixl xfer command
5057c478bd9Sstevel@tonic-gate 	 */
5067c478bd9Sstevel@tonic-gate 	(void) hci1394_ixl_find_next_exec_xfer(new_jump_ixlp->label, &cbcnt,
5077c478bd9Sstevel@tonic-gate 	    &ixlp);
5087c478bd9Sstevel@tonic-gate 	if (ixlp != NULL) {
5097c478bd9Sstevel@tonic-gate 		/*
5107c478bd9Sstevel@tonic-gate 		 * get the bound address of the first descriptor block reached
5117c478bd9Sstevel@tonic-gate 		 * by the jump destination.  (This descriptor is the first
5127c478bd9Sstevel@tonic-gate 		 * transfer command following the jumped-to label.)  Set the
5137c478bd9Sstevel@tonic-gate 		 * descriptor's address (with Z bits) into jumpaddr.
5147c478bd9Sstevel@tonic-gate 		 */
5157c478bd9Sstevel@tonic-gate 		uvp->jumpaddr = ((hci1394_xfer_ctl_t *)
5167c478bd9Sstevel@tonic-gate 		    ixlp->compiler_privatep)->dma[0].dma_bound;
5177c478bd9Sstevel@tonic-gate 	}
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate 	/*
5207c478bd9Sstevel@tonic-gate 	 * get associated xfer IXL command from compiler_privatep of old
5217c478bd9Sstevel@tonic-gate 	 * jump command
5227c478bd9Sstevel@tonic-gate 	 */
5237c478bd9Sstevel@tonic-gate 	if ((uvp->ixlxferp = (ixl1394_command_t *)
5247c478bd9Sstevel@tonic-gate 	    old_jump_ixlp->compiler_privatep) == NULL) {
5257c478bd9Sstevel@tonic-gate 
5267c478bd9Sstevel@tonic-gate 		/* if none, return an error */
5277c478bd9Sstevel@tonic-gate 		uvp->upd_status = IXL1394_EORIG_IXL_CORRUPTED;
5287c478bd9Sstevel@tonic-gate 
5297c478bd9Sstevel@tonic-gate 		return (IXL_PREP_FAILURE);
5307c478bd9Sstevel@tonic-gate 	}
5317c478bd9Sstevel@tonic-gate 
5327c478bd9Sstevel@tonic-gate 	/*
5337c478bd9Sstevel@tonic-gate 	 * get the associated IXL xfer command's last dma descriptor block
5347c478bd9Sstevel@tonic-gate 	 * last descriptor, then get hcihdr from its hdr field,
5357c478bd9Sstevel@tonic-gate 	 * removing interrupt enabled bits
5367c478bd9Sstevel@tonic-gate 	 */
5377c478bd9Sstevel@tonic-gate 	xferctlp = (hci1394_xfer_ctl_t *)uvp->ixlxferp->compiler_privatep;
5387c478bd9Sstevel@tonic-gate 	hcidescp = (hci1394_desc_t *)xferctlp->dma[xferctlp->cnt - 1].dma_descp;
5397c478bd9Sstevel@tonic-gate 	acc_hdl  = xferctlp->dma[xferctlp->cnt - 1].dma_buf->bi_handle;
5407c478bd9Sstevel@tonic-gate 	dma_hdl  = xferctlp->dma[xferctlp->cnt - 1].dma_buf->bi_dma_handle;
5417c478bd9Sstevel@tonic-gate 
5427c478bd9Sstevel@tonic-gate 	/* Sync the descriptor before we grab the header(s) */
5437c478bd9Sstevel@tonic-gate 	err = ddi_dma_sync(dma_hdl, (off_t)hcidescp, sizeof (hci1394_desc_t),
5447c478bd9Sstevel@tonic-gate 	    DDI_DMA_SYNC_FORCPU);
5457c478bd9Sstevel@tonic-gate 	if (err != DDI_SUCCESS) {
5467c478bd9Sstevel@tonic-gate 		uvp->upd_status = IXL1394_EINTERNAL_ERROR;
5477c478bd9Sstevel@tonic-gate 
5487c478bd9Sstevel@tonic-gate 		return (IXL_PREP_FAILURE);
5497c478bd9Sstevel@tonic-gate 	}
5507c478bd9Sstevel@tonic-gate 
5517c478bd9Sstevel@tonic-gate 	desc_hdr = ddi_get32(acc_hdl, &hcidescp->hdr);
5527c478bd9Sstevel@tonic-gate 	uvp->hcihdr = desc_hdr & ~DESC_INTR_ENBL;
5537c478bd9Sstevel@tonic-gate 
5547c478bd9Sstevel@tonic-gate 	/* set depth to last dma descriptor block & update count to 1 */
5557c478bd9Sstevel@tonic-gate 	uvp->ixldepth = xferctlp->cnt - 1;
5567c478bd9Sstevel@tonic-gate 	uvp->ixlcount = 1;
5577c478bd9Sstevel@tonic-gate 
5587c478bd9Sstevel@tonic-gate 	/*
5597c478bd9Sstevel@tonic-gate 	 * if there is only one dma descriptor block and IXL xfer command
5607c478bd9Sstevel@tonic-gate 	 * inited by a label or have found callbacks along the exec path to the
5617c478bd9Sstevel@tonic-gate 	 * new destination IXL xfer command, enable interrupt in hcihdr value
5627c478bd9Sstevel@tonic-gate 	 */
5637c478bd9Sstevel@tonic-gate 	if (((xferctlp->cnt == 1) &&
5647c478bd9Sstevel@tonic-gate 	    ((xferctlp->ctl_flags & XCTL_LABELLED) != 0)) || (cbcnt != 0)) {
5657c478bd9Sstevel@tonic-gate 
5667c478bd9Sstevel@tonic-gate 		uvp->hcihdr |= DESC_INTR_ENBL;
5677c478bd9Sstevel@tonic-gate 	}
5687c478bd9Sstevel@tonic-gate 
5697c478bd9Sstevel@tonic-gate 	/* If either old or new destination was/is NULL, enable interrupt */
5707c478bd9Sstevel@tonic-gate 	if ((new_jump_ixlp->label == NULL) || (old_jump_ixlp->label == NULL)) {
5717c478bd9Sstevel@tonic-gate 		uvp->hcihdr |= DESC_INTR_ENBL;
5727c478bd9Sstevel@tonic-gate 	}
5737c478bd9Sstevel@tonic-gate 
5747c478bd9Sstevel@tonic-gate 	/*
5757c478bd9Sstevel@tonic-gate 	 * if xfer type is xmit and skip mode for this for this xfer command is
5767c478bd9Sstevel@tonic-gate 	 * IXL1394_SKIP_TO_NEXT then set uvp->skipmode to IXL1394_SKIP_TO_NEXT
5777c478bd9Sstevel@tonic-gate 	 * and set uvp->skipxferp to uvp->jumpaddr and set uvp->hci_offset to
5787c478bd9Sstevel@tonic-gate 	 * offset from last dma descriptor to first dma descriptor
5797c478bd9Sstevel@tonic-gate 	 * (where skipaddr goes).
5807c478bd9Sstevel@tonic-gate 	 *
5817c478bd9Sstevel@tonic-gate 	 * update perform processing will have to set skip branch address to
5827c478bd9Sstevel@tonic-gate 	 * same location as jump destination in this case.
5837c478bd9Sstevel@tonic-gate 	 */
5847c478bd9Sstevel@tonic-gate 	uvp->skipmode = IXL1394_SKIP_TO_STOP;
5857c478bd9Sstevel@tonic-gate 	if ((uvp->ixlxferp->ixl_opcode & IXL1394_OPF_ONXMIT) != 0) {
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate 		if ((xferctlp->skipmodep && (((ixl1394_set_skipmode_t *)
5887c478bd9Sstevel@tonic-gate 		    xferctlp->skipmodep)->skipmode == IXL1394_SKIP_TO_NEXT)) ||
5897c478bd9Sstevel@tonic-gate 		    (uvp->ctxtp->default_skipmode == IXL1394_OPF_ONXMIT)) {
5907c478bd9Sstevel@tonic-gate 
5917c478bd9Sstevel@tonic-gate 			uvp->skipmode = IXL1394_SKIP_TO_NEXT;
5927c478bd9Sstevel@tonic-gate 			uvp->skipaddr = uvp->jumpaddr;
5937c478bd9Sstevel@tonic-gate 
5947c478bd9Sstevel@tonic-gate 			/*
5957c478bd9Sstevel@tonic-gate 			 * calc hci_offset to first descriptor (where skipaddr
5967c478bd9Sstevel@tonic-gate 			 * goes) of dma descriptor block from current (last)
5977c478bd9Sstevel@tonic-gate 			 * descriptor of the descriptor block (accessed in
5987c478bd9Sstevel@tonic-gate 			 * xfer_ctl dma_descp of IXL xfer command)
5997c478bd9Sstevel@tonic-gate 			 */
6007c478bd9Sstevel@tonic-gate 			if (uvp->ixlxferp->ixl_opcode ==
6017c478bd9Sstevel@tonic-gate 			    IXL1394_OP_SEND_HDR_ONLY) {
6027c478bd9Sstevel@tonic-gate 				/*
6037c478bd9Sstevel@tonic-gate 				 * send header only is (Z bits - 2)
6047c478bd9Sstevel@tonic-gate 				 * descriptor components back from last one
6057c478bd9Sstevel@tonic-gate 				 */
6067c478bd9Sstevel@tonic-gate 				uvp->hci_offset -= 2;
6077c478bd9Sstevel@tonic-gate 			} else {
6087c478bd9Sstevel@tonic-gate 				/*
6097c478bd9Sstevel@tonic-gate 				 * all others are (Z bits - 1) descriptor
6107c478bd9Sstevel@tonic-gate 				 * components back from last component
6117c478bd9Sstevel@tonic-gate 				 */
6127c478bd9Sstevel@tonic-gate 				uvp->hci_offset -= 1;
6137c478bd9Sstevel@tonic-gate 			}
6147c478bd9Sstevel@tonic-gate 		}
6157c478bd9Sstevel@tonic-gate 	}
6167c478bd9Sstevel@tonic-gate 	return (IXL_PREP_READY);
6177c478bd9Sstevel@tonic-gate }
6187c478bd9Sstevel@tonic-gate 
6197c478bd9Sstevel@tonic-gate /*
6207c478bd9Sstevel@tonic-gate  * hci1394_ixl_update_prep_set_skipmode()
6217c478bd9Sstevel@tonic-gate  *    Preparation for update of an IXL1394_OP_SET_SKIPMODE_U command.
6227c478bd9Sstevel@tonic-gate  */
6237c478bd9Sstevel@tonic-gate static int
hci1394_ixl_update_prep_set_skipmode(hci1394_ixl_update_vars_t * uvp)6247c478bd9Sstevel@tonic-gate hci1394_ixl_update_prep_set_skipmode(hci1394_ixl_update_vars_t *uvp)
6257c478bd9Sstevel@tonic-gate {
6267c478bd9Sstevel@tonic-gate 	ixl1394_set_skipmode_t	*old_set_skipmode_ixlp;
6277c478bd9Sstevel@tonic-gate 	ixl1394_set_skipmode_t	*new_set_skipmode_ixlp;
6287c478bd9Sstevel@tonic-gate 	ixl1394_command_t	*ixlp;
6297c478bd9Sstevel@tonic-gate 	hci1394_xfer_ctl_t	*xferctlp;
6307c478bd9Sstevel@tonic-gate 
6317c478bd9Sstevel@tonic-gate 	old_set_skipmode_ixlp = (ixl1394_set_skipmode_t *)uvp->ixloldp;
6327c478bd9Sstevel@tonic-gate 	new_set_skipmode_ixlp = (ixl1394_set_skipmode_t *)uvp->ixlnewp;
6337c478bd9Sstevel@tonic-gate 
6347c478bd9Sstevel@tonic-gate 	/* check if new set skipmode is change from old set skipmode */
6357c478bd9Sstevel@tonic-gate 	if (new_set_skipmode_ixlp->skipmode ==
6367c478bd9Sstevel@tonic-gate 	    old_set_skipmode_ixlp->skipmode) {
6377c478bd9Sstevel@tonic-gate 
6387c478bd9Sstevel@tonic-gate 		if ((new_set_skipmode_ixlp->skipmode !=
6397c478bd9Sstevel@tonic-gate 		    IXL1394_SKIP_TO_LABEL) ||
6407c478bd9Sstevel@tonic-gate 		    (old_set_skipmode_ixlp->label ==
6417c478bd9Sstevel@tonic-gate 		    new_set_skipmode_ixlp->label)) {
6427c478bd9Sstevel@tonic-gate 			/* No change, return with done ok status */
6437c478bd9Sstevel@tonic-gate 			return (IXL_PREP_SUCCESS);
6447c478bd9Sstevel@tonic-gate 		}
6457c478bd9Sstevel@tonic-gate 	}
6467c478bd9Sstevel@tonic-gate 
6477c478bd9Sstevel@tonic-gate 	/* find associated ixl xfer commnd by following old ixl links */
6487c478bd9Sstevel@tonic-gate 	uvp->ixlxferp = uvp->ixloldp->next_ixlp;
6497c478bd9Sstevel@tonic-gate 	while ((uvp->ixlxferp != NULL) && (((uvp->ixlxferp->ixl_opcode &
6507c478bd9Sstevel@tonic-gate 	    IXL1394_OPF_ISXFER) == 0) ||
6517c478bd9Sstevel@tonic-gate 	    ((uvp->ixlxferp->ixl_opcode & IXL1394_OPTY_MASK) !=	0))) {
6527c478bd9Sstevel@tonic-gate 
6537c478bd9Sstevel@tonic-gate 		uvp->ixlxferp = uvp->ixlxferp->next_ixlp;
6547c478bd9Sstevel@tonic-gate 	}
6557c478bd9Sstevel@tonic-gate 
6567c478bd9Sstevel@tonic-gate 	/* return an error if no ixl xfer command found */
6577c478bd9Sstevel@tonic-gate 	if (uvp->ixlxferp == NULL) {
6587c478bd9Sstevel@tonic-gate 
6597c478bd9Sstevel@tonic-gate 		uvp->upd_status = IXL1394_EORIG_IXL_CORRUPTED;
6607c478bd9Sstevel@tonic-gate 
6617c478bd9Sstevel@tonic-gate 		return (IXL_PREP_FAILURE);
6627c478bd9Sstevel@tonic-gate 	}
6637c478bd9Sstevel@tonic-gate 
6647c478bd9Sstevel@tonic-gate 	/*
6657c478bd9Sstevel@tonic-gate 	 * get Z bits (number of descriptor components in descriptor block)
6667c478bd9Sstevel@tonic-gate 	 * from a dma bound addr in the xfer_ctl struct of the IXL xfer command
6677c478bd9Sstevel@tonic-gate 	 */
6687c478bd9Sstevel@tonic-gate 	if ((xferctlp = (hci1394_xfer_ctl_t *)
6697c478bd9Sstevel@tonic-gate 	    uvp->ixlxferp->compiler_privatep) == NULL) {
6707c478bd9Sstevel@tonic-gate 
6717c478bd9Sstevel@tonic-gate 		uvp->upd_status = IXL1394_EORIG_IXL_CORRUPTED;
6727c478bd9Sstevel@tonic-gate 
6737c478bd9Sstevel@tonic-gate 		return (IXL_PREP_FAILURE);
6747c478bd9Sstevel@tonic-gate 	}
6757c478bd9Sstevel@tonic-gate 	uvp->hci_offset = xferctlp->dma[0].dma_bound & DESC_Z_MASK;
6767c478bd9Sstevel@tonic-gate 
6777c478bd9Sstevel@tonic-gate 	/*
6787c478bd9Sstevel@tonic-gate 	 * determine hci_offset to first component (where skipaddr goes) of
6797c478bd9Sstevel@tonic-gate 	 * dma descriptor block from current (last) descriptor component of
6807c478bd9Sstevel@tonic-gate 	 * desciptor block (accessed in xfer_ctl dma_descp of IXL xfer command)
6817c478bd9Sstevel@tonic-gate 	 */
6827c478bd9Sstevel@tonic-gate 	if (uvp->ixlxferp->ixl_opcode == IXL1394_OP_SEND_HDR_ONLY) {
6837c478bd9Sstevel@tonic-gate 		/*
6847c478bd9Sstevel@tonic-gate 		 * "send header only" is (Z bits - 2) descriptors back
6857c478bd9Sstevel@tonic-gate 		 * from last one
6867c478bd9Sstevel@tonic-gate 		 */
6877c478bd9Sstevel@tonic-gate 		uvp->hci_offset -= 2;
6887c478bd9Sstevel@tonic-gate 	} else {
6897c478bd9Sstevel@tonic-gate 		/*
6907c478bd9Sstevel@tonic-gate 		 * all others are (Z bits - 1) descroptors back from
6917c478bd9Sstevel@tonic-gate 		 * last descriptor.
6927c478bd9Sstevel@tonic-gate 		 */
6937c478bd9Sstevel@tonic-gate 		uvp->hci_offset -= 1;
6947c478bd9Sstevel@tonic-gate 	}
6957c478bd9Sstevel@tonic-gate 
6967c478bd9Sstevel@tonic-gate 	/* set depth to zero and count to update all dma descriptors */
6977c478bd9Sstevel@tonic-gate 	uvp->ixldepth = 0;
6987c478bd9Sstevel@tonic-gate 	uvp->ixlcount = xferctlp->cnt;
6997c478bd9Sstevel@tonic-gate 
7007c478bd9Sstevel@tonic-gate 	/* set new skipmode and validate */
7017c478bd9Sstevel@tonic-gate 	uvp->skipmode = new_set_skipmode_ixlp->skipmode;
7027c478bd9Sstevel@tonic-gate 
7037c478bd9Sstevel@tonic-gate 	if ((uvp->skipmode != IXL1394_SKIP_TO_NEXT) &&
7047c478bd9Sstevel@tonic-gate 	    (uvp->skipmode != IXL1394_SKIP_TO_SELF) &&
7057c478bd9Sstevel@tonic-gate 	    (uvp->skipmode != IXL1394_SKIP_TO_STOP) &&
7067c478bd9Sstevel@tonic-gate 	    (uvp->skipmode != IXL1394_SKIP_TO_LABEL)) {
7077c478bd9Sstevel@tonic-gate 
7087c478bd9Sstevel@tonic-gate 		/* return an error if invalid mode */
7097c478bd9Sstevel@tonic-gate 		uvp->upd_status = IXL1394_EBAD_SKIPMODE;
7107c478bd9Sstevel@tonic-gate 
7117c478bd9Sstevel@tonic-gate 		return (IXL_PREP_FAILURE);
7127c478bd9Sstevel@tonic-gate 	}
7137c478bd9Sstevel@tonic-gate 
7147c478bd9Sstevel@tonic-gate 	/* if mode is skip to label */
7157c478bd9Sstevel@tonic-gate 	if (uvp->skipmode == IXL1394_SKIP_TO_LABEL) {
7167c478bd9Sstevel@tonic-gate 
7177c478bd9Sstevel@tonic-gate 		/* verify label field is valid ixl label cmd */
7187c478bd9Sstevel@tonic-gate 		if ((new_set_skipmode_ixlp->label == NULL) ||
7197c478bd9Sstevel@tonic-gate 		    (new_set_skipmode_ixlp->label->ixl_opcode !=
72046776310SToomas Soome 		    IXL1394_OP_LABEL)) {
7217c478bd9Sstevel@tonic-gate 
7227c478bd9Sstevel@tonic-gate 			/* Error - not skipping to valid label */
7237c478bd9Sstevel@tonic-gate 			uvp->upd_status = IXL1394_EBAD_SKIP_LABEL;
7247c478bd9Sstevel@tonic-gate 
7257c478bd9Sstevel@tonic-gate 			return (IXL_PREP_FAILURE);
7267c478bd9Sstevel@tonic-gate 		}
7277c478bd9Sstevel@tonic-gate 
7287c478bd9Sstevel@tonic-gate 		/*
7297c478bd9Sstevel@tonic-gate 		 * follow new skip exec path after label to next xfer
7307c478bd9Sstevel@tonic-gate 		 * IXL command
7317c478bd9Sstevel@tonic-gate 		 */
7327c478bd9Sstevel@tonic-gate 		(void) hci1394_ixl_find_next_exec_xfer(
73346776310SToomas Soome 		    new_set_skipmode_ixlp->label, NULL, &ixlp);
7347c478bd9Sstevel@tonic-gate 
7357c478bd9Sstevel@tonic-gate 		/*
7367c478bd9Sstevel@tonic-gate 		 * set skip destination IXL xfer command.
7377c478bd9Sstevel@tonic-gate 		 * after update set into old set skip mode IXL compiler_privatep
7387c478bd9Sstevel@tonic-gate 		 */
7397c478bd9Sstevel@tonic-gate 		if ((uvp->skipxferp = ixlp) != NULL) {
7407c478bd9Sstevel@tonic-gate 			/*
7417c478bd9Sstevel@tonic-gate 			 * set skipaddr to be the first dma descriptor block's
7427c478bd9Sstevel@tonic-gate 			 * dma bound address w/Z bits
7437c478bd9Sstevel@tonic-gate 			 */
7447c478bd9Sstevel@tonic-gate 			xferctlp = (hci1394_xfer_ctl_t *)
7457c478bd9Sstevel@tonic-gate 			    ixlp->compiler_privatep;
7467c478bd9Sstevel@tonic-gate 			uvp->skipaddr = xferctlp->dma[0].dma_bound;
7477c478bd9Sstevel@tonic-gate 		}
7487c478bd9Sstevel@tonic-gate 	}
7497c478bd9Sstevel@tonic-gate 
7507c478bd9Sstevel@tonic-gate 	/*
7517c478bd9Sstevel@tonic-gate 	 * if mode is skip to next, get skipaddr for last dma descriptor block
7527c478bd9Sstevel@tonic-gate 	 */
7537c478bd9Sstevel@tonic-gate 	if (uvp->skipmode == IXL1394_SKIP_TO_NEXT) {
7547c478bd9Sstevel@tonic-gate 		/* follow normal exec path to next xfer ixl command */
7557c478bd9Sstevel@tonic-gate 		(void) hci1394_ixl_find_next_exec_xfer(uvp->ixlxferp->next_ixlp,
7567c478bd9Sstevel@tonic-gate 		    NULL, &ixlp);
7577c478bd9Sstevel@tonic-gate 
7587c478bd9Sstevel@tonic-gate 		/*
7597c478bd9Sstevel@tonic-gate 		 * get skip_next destination IXL xfer command
7607c478bd9Sstevel@tonic-gate 		 * (for last iteration)
7617c478bd9Sstevel@tonic-gate 		 */
7627c478bd9Sstevel@tonic-gate 		if (ixlp != NULL) {
7637c478bd9Sstevel@tonic-gate 			/*
7647c478bd9Sstevel@tonic-gate 			 * set skipaddr to first dma descriptor block's
7657c478bd9Sstevel@tonic-gate 			 * dma bound address w/Z bits
7667c478bd9Sstevel@tonic-gate 			 */
7677c478bd9Sstevel@tonic-gate 			xferctlp = (hci1394_xfer_ctl_t *)
7687c478bd9Sstevel@tonic-gate 			    ixlp->compiler_privatep;
7697c478bd9Sstevel@tonic-gate 			uvp->skipaddr = xferctlp->dma[0].dma_bound;
7707c478bd9Sstevel@tonic-gate 		}
7717c478bd9Sstevel@tonic-gate 	}
7727c478bd9Sstevel@tonic-gate 	return (IXL_PREP_READY);
7737c478bd9Sstevel@tonic-gate }
7747c478bd9Sstevel@tonic-gate 
7757c478bd9Sstevel@tonic-gate /*
7767c478bd9Sstevel@tonic-gate  * hci1394_ixl_update_prep_set_tagsync()
7777c478bd9Sstevel@tonic-gate  *    Preparation for update of an IXL1394_OP_SET_TAGSYNC_U command.
7787c478bd9Sstevel@tonic-gate  */
7797c478bd9Sstevel@tonic-gate static int
hci1394_ixl_update_prep_set_tagsync(hci1394_ixl_update_vars_t * uvp)7807c478bd9Sstevel@tonic-gate hci1394_ixl_update_prep_set_tagsync(hci1394_ixl_update_vars_t *uvp)
7817c478bd9Sstevel@tonic-gate {
7827c478bd9Sstevel@tonic-gate 	ixl1394_set_tagsync_t	*old_set_tagsync_ixlp;
7837c478bd9Sstevel@tonic-gate 	ixl1394_set_tagsync_t	*new_set_tagsync_ixlp;
7847c478bd9Sstevel@tonic-gate 	hci1394_xfer_ctl_t	*xferctlp;
7857c478bd9Sstevel@tonic-gate 
7867c478bd9Sstevel@tonic-gate 	old_set_tagsync_ixlp = (ixl1394_set_tagsync_t *)uvp->ixloldp;
7877c478bd9Sstevel@tonic-gate 	new_set_tagsync_ixlp = (ixl1394_set_tagsync_t *)uvp->ixlnewp;
7887c478bd9Sstevel@tonic-gate 
7897c478bd9Sstevel@tonic-gate 	/* check if new set tagsync is change from old set tagsync. */
7907c478bd9Sstevel@tonic-gate 	if ((new_set_tagsync_ixlp->tag == old_set_tagsync_ixlp->tag) &&
7917c478bd9Sstevel@tonic-gate 	    (new_set_tagsync_ixlp->sync == old_set_tagsync_ixlp->sync)) {
7927c478bd9Sstevel@tonic-gate 
7937c478bd9Sstevel@tonic-gate 		/* no change, return with done ok status */
7947c478bd9Sstevel@tonic-gate 		return (IXL_PREP_SUCCESS);
7957c478bd9Sstevel@tonic-gate 	}
7967c478bd9Sstevel@tonic-gate 
7977c478bd9Sstevel@tonic-gate 	/* find associated IXL xfer commnd by following old ixl links */
7987c478bd9Sstevel@tonic-gate 	uvp->ixlxferp = uvp->ixloldp->next_ixlp;
7997c478bd9Sstevel@tonic-gate 	while ((uvp->ixlxferp != NULL) && (((uvp->ixlxferp->ixl_opcode &
8007c478bd9Sstevel@tonic-gate 	    IXL1394_OPF_ISXFER) == 0) ||
8017c478bd9Sstevel@tonic-gate 	    ((uvp->ixlxferp->ixl_opcode & IXL1394_OPTY_MASK) != 0))) {
8027c478bd9Sstevel@tonic-gate 
8037c478bd9Sstevel@tonic-gate 		uvp->ixlxferp = uvp->ixlxferp->next_ixlp;
8047c478bd9Sstevel@tonic-gate 	}
8057c478bd9Sstevel@tonic-gate 
8067c478bd9Sstevel@tonic-gate 	/* return an error if no IXL xfer command found */
8077c478bd9Sstevel@tonic-gate 	if (uvp->ixlxferp == NULL) {
8087c478bd9Sstevel@tonic-gate 
8097c478bd9Sstevel@tonic-gate 		uvp->upd_status = IXL1394_EORIG_IXL_CORRUPTED;
8107c478bd9Sstevel@tonic-gate 
8117c478bd9Sstevel@tonic-gate 		return (IXL_PREP_FAILURE);
8127c478bd9Sstevel@tonic-gate 	}
8137c478bd9Sstevel@tonic-gate 
8147c478bd9Sstevel@tonic-gate 	/* is IXL xfer command an IXL1394_OP_SEND_NO_PKT? */
8157c478bd9Sstevel@tonic-gate 	if (uvp->ixlxferp->ixl_opcode == IXL1394_OP_SEND_NO_PKT) {
8167c478bd9Sstevel@tonic-gate 		/* no update needed, return done ok status */
8177c478bd9Sstevel@tonic-gate 		return (IXL_PREP_SUCCESS);
8187c478bd9Sstevel@tonic-gate 	}
8197c478bd9Sstevel@tonic-gate 
8207c478bd9Sstevel@tonic-gate 	/* build new pkthdr1 from new IXL tag/sync bits */
8217c478bd9Sstevel@tonic-gate 	uvp->pkthdr1 = (uvp->ctxtp->isospd << DESC_PKT_SPD_SHIFT) |
8227c478bd9Sstevel@tonic-gate 	    (new_set_tagsync_ixlp->tag << DESC_PKT_TAG_SHIFT) |
8237c478bd9Sstevel@tonic-gate 	    (uvp->ctxtp->isochan << DESC_PKT_CHAN_SHIFT) |
8247c478bd9Sstevel@tonic-gate 	    (new_set_tagsync_ixlp->sync << DESC_PKT_SY_SHIFT);
8257c478bd9Sstevel@tonic-gate 
8267c478bd9Sstevel@tonic-gate 	/*
8277c478bd9Sstevel@tonic-gate 	 * get Z bits (# of descriptor components in descriptor block) from
8287c478bd9Sstevel@tonic-gate 	 * any dma bound address in the xfer_ctl struct of the IXL xfer cmd
8297c478bd9Sstevel@tonic-gate 	 */
8307c478bd9Sstevel@tonic-gate 	if ((xferctlp =	(hci1394_xfer_ctl_t *)
8317c478bd9Sstevel@tonic-gate 	    uvp->ixlxferp->compiler_privatep) == NULL) {
8327c478bd9Sstevel@tonic-gate 
8337c478bd9Sstevel@tonic-gate 		uvp->upd_status = IXL1394_EORIG_IXL_CORRUPTED;
8347c478bd9Sstevel@tonic-gate 
8357c478bd9Sstevel@tonic-gate 		return (IXL_PREP_FAILURE);
8367c478bd9Sstevel@tonic-gate 	}
8377c478bd9Sstevel@tonic-gate 	uvp->hdr_offset = xferctlp->dma[0].dma_bound & DESC_Z_MASK;
8387c478bd9Sstevel@tonic-gate 
8397c478bd9Sstevel@tonic-gate 	/*
8407c478bd9Sstevel@tonic-gate 	 * determine hdr_offset from the current(last) descriptor of the
8417c478bd9Sstevel@tonic-gate 	 * DMA descriptor block to the descriptor where pkthdr1 goes
8427c478bd9Sstevel@tonic-gate 	 * by examining IXL xfer command
8437c478bd9Sstevel@tonic-gate 	 */
8447c478bd9Sstevel@tonic-gate 	if (uvp->ixlxferp->ixl_opcode == IXL1394_OP_SEND_HDR_ONLY) {
8457c478bd9Sstevel@tonic-gate 		/*
8467c478bd9Sstevel@tonic-gate 		 * if IXL send header only, the current (last)
8477c478bd9Sstevel@tonic-gate 		 * descriptor is the one
8487c478bd9Sstevel@tonic-gate 		 */
8497c478bd9Sstevel@tonic-gate 		uvp->hdr_offset = 0;
8507c478bd9Sstevel@tonic-gate 	} else {
8517c478bd9Sstevel@tonic-gate 		/*
8527c478bd9Sstevel@tonic-gate 		 * all others are the first descriptor (Z bits - 1)
8537c478bd9Sstevel@tonic-gate 		 * back from the last
8547c478bd9Sstevel@tonic-gate 		 */
8557c478bd9Sstevel@tonic-gate 		uvp->hdr_offset -= 1;
8567c478bd9Sstevel@tonic-gate 	}
8577c478bd9Sstevel@tonic-gate 
8587c478bd9Sstevel@tonic-gate 	/* set depth to zero and count to update all dma descriptors */
8597c478bd9Sstevel@tonic-gate 	uvp->ixldepth = 0;
8607c478bd9Sstevel@tonic-gate 	uvp->ixlcount = xferctlp->cnt;
8617c478bd9Sstevel@tonic-gate 
8627c478bd9Sstevel@tonic-gate 	return (IXL_PREP_READY);
8637c478bd9Sstevel@tonic-gate }
8647c478bd9Sstevel@tonic-gate 
8657c478bd9Sstevel@tonic-gate /*
8667c478bd9Sstevel@tonic-gate  * hci1394_ixl_update_prep_recv_pkt()
8677c478bd9Sstevel@tonic-gate  *    Preparation for update of an IXL1394_OP_RECV_PKT_U or
8687c478bd9Sstevel@tonic-gate  *    IXL1394_OP_RECV_PKT_ST_U command.
8697c478bd9Sstevel@tonic-gate  */
8707c478bd9Sstevel@tonic-gate static int
hci1394_ixl_update_prep_recv_pkt(hci1394_ixl_update_vars_t * uvp)8717c478bd9Sstevel@tonic-gate hci1394_ixl_update_prep_recv_pkt(hci1394_ixl_update_vars_t *uvp)
8727c478bd9Sstevel@tonic-gate {
8737c478bd9Sstevel@tonic-gate 	ixl1394_xfer_pkt_t *old_xfer_pkt_ixlp;
8747c478bd9Sstevel@tonic-gate 	ixl1394_xfer_pkt_t *new_xfer_pkt_ixlp;
8757c478bd9Sstevel@tonic-gate 	hci1394_xfer_ctl_t *xferctlp;
8767c478bd9Sstevel@tonic-gate 	hci1394_desc_t	   *hcidescp;
8777c478bd9Sstevel@tonic-gate 	ddi_acc_handle_t   acc_hdl;
8787c478bd9Sstevel@tonic-gate 	ddi_dma_handle_t   dma_hdl;
8797c478bd9Sstevel@tonic-gate 	uint32_t	   desc_hdr;
8807c478bd9Sstevel@tonic-gate 	int		   err;
8817c478bd9Sstevel@tonic-gate 
8827c478bd9Sstevel@tonic-gate 	old_xfer_pkt_ixlp = (ixl1394_xfer_pkt_t *)uvp->ixloldp;
8837c478bd9Sstevel@tonic-gate 	new_xfer_pkt_ixlp = (ixl1394_xfer_pkt_t *)uvp->ixlnewp;
8847c478bd9Sstevel@tonic-gate 
8857c478bd9Sstevel@tonic-gate 	/* check if any change between new and old IXL xfer commands */
8867c478bd9Sstevel@tonic-gate 	if ((new_xfer_pkt_ixlp->size == old_xfer_pkt_ixlp->size) &&
8877c478bd9Sstevel@tonic-gate 	    (new_xfer_pkt_ixlp->ixl_buf.ixldmac_addr ==
88846776310SToomas Soome 	    old_xfer_pkt_ixlp->ixl_buf.ixldmac_addr) &&
8897c478bd9Sstevel@tonic-gate 	    (new_xfer_pkt_ixlp->mem_bufp == old_xfer_pkt_ixlp->mem_bufp)) {
8907c478bd9Sstevel@tonic-gate 		/* no change. return with done ok status */
8917c478bd9Sstevel@tonic-gate 		return (IXL_PREP_SUCCESS);
8927c478bd9Sstevel@tonic-gate 	}
8937c478bd9Sstevel@tonic-gate 
8947c478bd9Sstevel@tonic-gate 	/* if new IXL buffer addrs are null, return error */
895*ffc2b7d4SToomas Soome 	if ((new_xfer_pkt_ixlp->ixl_buf.ixldmac_addr == 0) ||
8967c478bd9Sstevel@tonic-gate 	    (new_xfer_pkt_ixlp->mem_bufp == NULL)) {
8977c478bd9Sstevel@tonic-gate 
8987c478bd9Sstevel@tonic-gate 		uvp->upd_status = IXL1394_EXFER_BUF_MISSING;
8997c478bd9Sstevel@tonic-gate 
9007c478bd9Sstevel@tonic-gate 		return (IXL_PREP_FAILURE);
9017c478bd9Sstevel@tonic-gate 	}
9027c478bd9Sstevel@tonic-gate 
9037c478bd9Sstevel@tonic-gate 	/* if IXL xfer command is not xfer start command */
9047c478bd9Sstevel@tonic-gate 	if (uvp->ixl_opcode == IXL1394_OP_RECV_PKT_U) {
9057c478bd9Sstevel@tonic-gate 		/*
9067c478bd9Sstevel@tonic-gate 		 * find IXL xfer start command in the compiler_privatep of the
9077c478bd9Sstevel@tonic-gate 		 * old IXL xfer command
9087c478bd9Sstevel@tonic-gate 		 */
9097c478bd9Sstevel@tonic-gate 		uvp->ixlxferp = (ixl1394_command_t *)
9107c478bd9Sstevel@tonic-gate 		    uvp->ixloldp->compiler_privatep;
9117c478bd9Sstevel@tonic-gate 
9127c478bd9Sstevel@tonic-gate 		if (uvp->ixlxferp == NULL) {
9137c478bd9Sstevel@tonic-gate 			/* Error - no IXL xfer start command found */
9147c478bd9Sstevel@tonic-gate 			uvp->upd_status = IXL1394_EORIG_IXL_CORRUPTED;
9157c478bd9Sstevel@tonic-gate 			return (IXL_PREP_FAILURE);
9167c478bd9Sstevel@tonic-gate 		}
9177c478bd9Sstevel@tonic-gate 	} else {
9187c478bd9Sstevel@tonic-gate 		/* IXL xfer command is the IXL xfer start command */
9197c478bd9Sstevel@tonic-gate 		uvp->ixlxferp = uvp->ixloldp;
9207c478bd9Sstevel@tonic-gate 	}
9217c478bd9Sstevel@tonic-gate 
9227c478bd9Sstevel@tonic-gate 	/* check that xfer_ctl is present in the IXL xfer start command */
9237c478bd9Sstevel@tonic-gate 	if ((xferctlp = (hci1394_xfer_ctl_t *)
9247c478bd9Sstevel@tonic-gate 	    uvp->ixlxferp->compiler_privatep) == NULL) {
9257c478bd9Sstevel@tonic-gate 		/* Error - no xfer_ctl struct found */
9267c478bd9Sstevel@tonic-gate 		uvp->upd_status = IXL1394_EORIG_IXL_CORRUPTED;
9277c478bd9Sstevel@tonic-gate 		return (IXL_PREP_FAILURE);
9287c478bd9Sstevel@tonic-gate 	}
9297c478bd9Sstevel@tonic-gate 
9307c478bd9Sstevel@tonic-gate 	/* set depth to zero and count to 1 to update dma descriptor */
9317c478bd9Sstevel@tonic-gate 	uvp->ixldepth = 0;
9327c478bd9Sstevel@tonic-gate 	uvp->ixlcount = 1;
9337c478bd9Sstevel@tonic-gate 
9347c478bd9Sstevel@tonic-gate 	/*
9357c478bd9Sstevel@tonic-gate 	 * get Z bits (number of descriptors in descriptor block) from the DMA
9367c478bd9Sstevel@tonic-gate 	 * bound address in the xfer_ctl struct of the IXL xfer start cpmmand.
9377c478bd9Sstevel@tonic-gate 	 */
9387c478bd9Sstevel@tonic-gate 	uvp->hci_offset = xferctlp->dma[0].dma_bound & DESC_Z_MASK;
9397c478bd9Sstevel@tonic-gate 
9407c478bd9Sstevel@tonic-gate 	/*
9417c478bd9Sstevel@tonic-gate 	 * set offset from the current(last) descriptor to the descriptor for
9427c478bd9Sstevel@tonic-gate 	 * this packet command
9437c478bd9Sstevel@tonic-gate 	 */
9447c478bd9Sstevel@tonic-gate 	uvp->hci_offset -= (1 + uvp->ixloldp->compiler_resv);
9457c478bd9Sstevel@tonic-gate 
9467c478bd9Sstevel@tonic-gate 	/*
9477c478bd9Sstevel@tonic-gate 	 * set bufsize to the new IXL xfer size, and bufaddr to the new
9487c478bd9Sstevel@tonic-gate 	 * IXL xfer bufp
9497c478bd9Sstevel@tonic-gate 	 */
9507c478bd9Sstevel@tonic-gate 	uvp->bufsize = ((ixl1394_xfer_pkt_t *)uvp->ixlnewp)->size;
9517c478bd9Sstevel@tonic-gate 	uvp->bufaddr = ((ixl1394_xfer_pkt_t *)
9527c478bd9Sstevel@tonic-gate 	    uvp->ixlnewp)->ixl_buf.ixldmac_addr;
9537c478bd9Sstevel@tonic-gate 
9547c478bd9Sstevel@tonic-gate 	/*
9557c478bd9Sstevel@tonic-gate 	 * update old hcihdr w/new bufsize, set hcistatus rescnt to
9567c478bd9Sstevel@tonic-gate 	 * new bufsize
9577c478bd9Sstevel@tonic-gate 	 */
9587c478bd9Sstevel@tonic-gate 	hcidescp = (hci1394_desc_t *)xferctlp->dma[0].dma_descp -
9597c478bd9Sstevel@tonic-gate 	    uvp->hci_offset;
9607c478bd9Sstevel@tonic-gate 	acc_hdl  = xferctlp->dma[0].dma_buf->bi_handle;
9617c478bd9Sstevel@tonic-gate 	dma_hdl  = xferctlp->dma[0].dma_buf->bi_dma_handle;
9627c478bd9Sstevel@tonic-gate 
9637c478bd9Sstevel@tonic-gate 	/* Sync the descriptor before we grab the header(s) */
9647c478bd9Sstevel@tonic-gate 	err = ddi_dma_sync(dma_hdl, (off_t)hcidescp, sizeof (hci1394_desc_t),
9657c478bd9Sstevel@tonic-gate 	    DDI_DMA_SYNC_FORCPU);
9667c478bd9Sstevel@tonic-gate 	if (err != DDI_SUCCESS) {
9677c478bd9Sstevel@tonic-gate 		uvp->upd_status = IXL1394_EINTERNAL_ERROR;
9687c478bd9Sstevel@tonic-gate 		return (IXL_PREP_FAILURE);
9697c478bd9Sstevel@tonic-gate 	}
9707c478bd9Sstevel@tonic-gate 
9717c478bd9Sstevel@tonic-gate 	desc_hdr = ddi_get32(acc_hdl, &hcidescp->hdr);
9727c478bd9Sstevel@tonic-gate 	uvp->hcihdr = desc_hdr;
9737c478bd9Sstevel@tonic-gate 	uvp->hcihdr &= ~DESC_HDR_REQCOUNT_MASK;
9747c478bd9Sstevel@tonic-gate 	uvp->hcihdr |= (uvp->bufsize << DESC_HDR_REQCOUNT_SHIFT) &
9757c478bd9Sstevel@tonic-gate 	    DESC_HDR_REQCOUNT_MASK;
9767c478bd9Sstevel@tonic-gate 	uvp->hcistatus = (uvp->bufsize << DESC_ST_RESCOUNT_SHIFT) &
9777c478bd9Sstevel@tonic-gate 	    DESC_ST_RESCOUNT_MASK;
9787c478bd9Sstevel@tonic-gate 
9797c478bd9Sstevel@tonic-gate 	return (IXL_PREP_READY);
9807c478bd9Sstevel@tonic-gate }
9817c478bd9Sstevel@tonic-gate 
9827c478bd9Sstevel@tonic-gate /*
9837c478bd9Sstevel@tonic-gate  * hci1394_ixl_update_prep_recv_buf()
9847c478bd9Sstevel@tonic-gate  *    Preparation for update of an IXL1394_OP_RECV_BUF_U command.
9857c478bd9Sstevel@tonic-gate  */
9867c478bd9Sstevel@tonic-gate static int
hci1394_ixl_update_prep_recv_buf(hci1394_ixl_update_vars_t * uvp)9877c478bd9Sstevel@tonic-gate hci1394_ixl_update_prep_recv_buf(hci1394_ixl_update_vars_t *uvp)
9887c478bd9Sstevel@tonic-gate {
9897c478bd9Sstevel@tonic-gate 	ixl1394_xfer_buf_t *old_xfer_buf_ixlp;
9907c478bd9Sstevel@tonic-gate 	ixl1394_xfer_buf_t *new_xfer_buf_ixlp;
9917c478bd9Sstevel@tonic-gate 	hci1394_xfer_ctl_t *xferctlp;
9927c478bd9Sstevel@tonic-gate 
9937c478bd9Sstevel@tonic-gate 	old_xfer_buf_ixlp = (ixl1394_xfer_buf_t *)uvp->ixloldp;
9947c478bd9Sstevel@tonic-gate 	new_xfer_buf_ixlp = (ixl1394_xfer_buf_t *)uvp->ixlnewp;
9957c478bd9Sstevel@tonic-gate 
9967c478bd9Sstevel@tonic-gate 	/* check if any change between new and old IXL xfer commands */
9977c478bd9Sstevel@tonic-gate 	if ((new_xfer_buf_ixlp->size ==	old_xfer_buf_ixlp->size) &&
9987c478bd9Sstevel@tonic-gate 	    (new_xfer_buf_ixlp->ixl_buf.ixldmac_addr ==
99946776310SToomas Soome 	    old_xfer_buf_ixlp->ixl_buf.ixldmac_addr) &&
100046776310SToomas Soome 	    (new_xfer_buf_ixlp->mem_bufp == old_xfer_buf_ixlp->mem_bufp)) {
10017c478bd9Sstevel@tonic-gate 
10027c478bd9Sstevel@tonic-gate 		if (((uvp->ctxtp->ctxt_flags & HCI1394_ISO_CTXT_BFFILL) != 0) ||
10037c478bd9Sstevel@tonic-gate 		    (new_xfer_buf_ixlp->pkt_size ==
100446776310SToomas Soome 		    old_xfer_buf_ixlp->pkt_size)) {
10057c478bd9Sstevel@tonic-gate 			/* no change. return with done ok status */
10067c478bd9Sstevel@tonic-gate 			return (IXL_PREP_SUCCESS);
10077c478bd9Sstevel@tonic-gate 		}
10087c478bd9Sstevel@tonic-gate 	}
10097c478bd9Sstevel@tonic-gate 
10107c478bd9Sstevel@tonic-gate 	/* if new IXL buffer addrs are null, return error */
1011*ffc2b7d4SToomas Soome 	if ((new_xfer_buf_ixlp->ixl_buf.ixldmac_addr == 0) ||
10127c478bd9Sstevel@tonic-gate 	    (new_xfer_buf_ixlp->mem_bufp == NULL)) {
10137c478bd9Sstevel@tonic-gate 		uvp->upd_status = IXL1394_EXFER_BUF_MISSING;
10147c478bd9Sstevel@tonic-gate 		return (IXL_PREP_FAILURE);
10157c478bd9Sstevel@tonic-gate 	}
10167c478bd9Sstevel@tonic-gate 
10177c478bd9Sstevel@tonic-gate 	/*
10187c478bd9Sstevel@tonic-gate 	 * if not buffer fill mode, check that the new pkt_size > 0 and
10197c478bd9Sstevel@tonic-gate 	 * new size/pkt_size doesn't change the count of dma descriptor
10207c478bd9Sstevel@tonic-gate 	 * blocks required
10217c478bd9Sstevel@tonic-gate 	 */
10227c478bd9Sstevel@tonic-gate 	if ((uvp->ctxtp->ctxt_flags & HCI1394_ISO_CTXT_BFFILL) == 0) {
10237c478bd9Sstevel@tonic-gate 		if ((new_xfer_buf_ixlp->pkt_size == 0) ||
10247c478bd9Sstevel@tonic-gate 		    ((new_xfer_buf_ixlp->size /	new_xfer_buf_ixlp->pkt_size) !=
10257c478bd9Sstevel@tonic-gate 		    (old_xfer_buf_ixlp->size / old_xfer_buf_ixlp->pkt_size))) {
10267c478bd9Sstevel@tonic-gate 			/* count changes. return an error */
10277c478bd9Sstevel@tonic-gate 			uvp->upd_status = IXL1394_EXFER_BUF_CNT_DIFF;
10287c478bd9Sstevel@tonic-gate 			return (IXL_PREP_FAILURE);
10297c478bd9Sstevel@tonic-gate 		}
10307c478bd9Sstevel@tonic-gate 	}
10317c478bd9Sstevel@tonic-gate 
10327c478bd9Sstevel@tonic-gate 	/* set old IXL xfer command as the current IXL xfer command */
10337c478bd9Sstevel@tonic-gate 	uvp->ixlxferp = uvp->ixloldp;
10347c478bd9Sstevel@tonic-gate 
10357c478bd9Sstevel@tonic-gate 	/* check that the xfer_ctl struct is present in IXL xfer command */
10367c478bd9Sstevel@tonic-gate 	if ((xferctlp = (hci1394_xfer_ctl_t *)uvp->ixlxferp->compiler_privatep)
10377c478bd9Sstevel@tonic-gate 	    == NULL) {
10387c478bd9Sstevel@tonic-gate 		/* return an error if no xfer_ctl struct is found for command */
10397c478bd9Sstevel@tonic-gate 		uvp->upd_status = IXL1394_EORIG_IXL_CORRUPTED;
10407c478bd9Sstevel@tonic-gate 		return (IXL_PREP_FAILURE);
10417c478bd9Sstevel@tonic-gate 	}
10427c478bd9Sstevel@tonic-gate 
10437c478bd9Sstevel@tonic-gate 	/* set depth to zero and count to update all dma descriptors */
10447c478bd9Sstevel@tonic-gate 	uvp->ixldepth = 0;
10457c478bd9Sstevel@tonic-gate 	uvp->ixlcount = xferctlp->cnt;
10467c478bd9Sstevel@tonic-gate 
10477c478bd9Sstevel@tonic-gate 	/* set bufsize to new pkt_size (or to new size if buffer fill mode) */
10487c478bd9Sstevel@tonic-gate 	if ((uvp->ctxtp->ctxt_flags & HCI1394_ISO_CTXT_BFFILL) == 0) {
10497c478bd9Sstevel@tonic-gate 		uvp->bufsize = new_xfer_buf_ixlp->pkt_size;
10507c478bd9Sstevel@tonic-gate 	} else {
10517c478bd9Sstevel@tonic-gate 		uvp->bufsize = new_xfer_buf_ixlp->size;
10527c478bd9Sstevel@tonic-gate 	}
10537c478bd9Sstevel@tonic-gate 
10547c478bd9Sstevel@tonic-gate 	/* set bufaddr to new ixl_buf */
10557c478bd9Sstevel@tonic-gate 	uvp->bufaddr = new_xfer_buf_ixlp->ixl_buf.ixldmac_addr;
10567c478bd9Sstevel@tonic-gate 
10577c478bd9Sstevel@tonic-gate 	/* set hcihdr reqcnt and hcistatus rescnt to new bufsize */
10587c478bd9Sstevel@tonic-gate 	uvp->hci_offset = 0;
10597c478bd9Sstevel@tonic-gate 	uvp->hcihdr = (uvp->bufsize << DESC_HDR_REQCOUNT_SHIFT) &
10607c478bd9Sstevel@tonic-gate 	    DESC_HDR_REQCOUNT_MASK;
10617c478bd9Sstevel@tonic-gate 	uvp->hcistatus = (uvp->bufsize << DESC_ST_RESCOUNT_SHIFT) &
10627c478bd9Sstevel@tonic-gate 	    DESC_ST_RESCOUNT_MASK;
10637c478bd9Sstevel@tonic-gate 
10647c478bd9Sstevel@tonic-gate 	return (IXL_PREP_READY);
10657c478bd9Sstevel@tonic-gate }
10667c478bd9Sstevel@tonic-gate 
10677c478bd9Sstevel@tonic-gate /*
10687c478bd9Sstevel@tonic-gate  * hci1394_ixl_update_prep_send_pkt()
10697c478bd9Sstevel@tonic-gate  *    Preparation for update of an IXL1394_OP_SEND_PKT_U command,
10707c478bd9Sstevel@tonic-gate  *    IXL1394_OP_SEND_PKT_ST_U command and IXL1394_OP_SEND_PKT_WHDR_ST_U
10717c478bd9Sstevel@tonic-gate  *    command.
10727c478bd9Sstevel@tonic-gate  */
10737c478bd9Sstevel@tonic-gate static int
hci1394_ixl_update_prep_send_pkt(hci1394_ixl_update_vars_t * uvp)10747c478bd9Sstevel@tonic-gate hci1394_ixl_update_prep_send_pkt(hci1394_ixl_update_vars_t *uvp)
10757c478bd9Sstevel@tonic-gate {
10767c478bd9Sstevel@tonic-gate 	ixl1394_xfer_pkt_t *old_xfer_pkt_ixlp;
10777c478bd9Sstevel@tonic-gate 	ixl1394_xfer_pkt_t *new_xfer_pkt_ixlp;
10787c478bd9Sstevel@tonic-gate 	hci1394_xfer_ctl_t *xferctlp;
10797c478bd9Sstevel@tonic-gate 	hci1394_desc_imm_t *hcidescp;
10807c478bd9Sstevel@tonic-gate 	ddi_acc_handle_t   acc_hdl;
10817c478bd9Sstevel@tonic-gate 	ddi_dma_handle_t   dma_hdl;
10827c478bd9Sstevel@tonic-gate 	uint32_t	   desc_hdr, desc_hdr2;
10837c478bd9Sstevel@tonic-gate 	int		   err;
10847c478bd9Sstevel@tonic-gate 
10857c478bd9Sstevel@tonic-gate 	old_xfer_pkt_ixlp = (ixl1394_xfer_pkt_t *)uvp->ixloldp;
10867c478bd9Sstevel@tonic-gate 	new_xfer_pkt_ixlp = (ixl1394_xfer_pkt_t *)uvp->ixlnewp;
10877c478bd9Sstevel@tonic-gate 
10887c478bd9Sstevel@tonic-gate 	/* check if any change between new and old IXL xfer commands */
10897c478bd9Sstevel@tonic-gate 	if ((new_xfer_pkt_ixlp->size ==	old_xfer_pkt_ixlp->size) &&
10907c478bd9Sstevel@tonic-gate 	    (new_xfer_pkt_ixlp->ixl_buf.ixldmac_addr ==
109146776310SToomas Soome 	    old_xfer_pkt_ixlp->ixl_buf.ixldmac_addr) &&
10927c478bd9Sstevel@tonic-gate 	    (new_xfer_pkt_ixlp->mem_bufp == old_xfer_pkt_ixlp->mem_bufp)) {
10937c478bd9Sstevel@tonic-gate 
10947c478bd9Sstevel@tonic-gate 		/* if none, return with done ok status */
10957c478bd9Sstevel@tonic-gate 		return (IXL_PREP_SUCCESS);
10967c478bd9Sstevel@tonic-gate 	}
10977c478bd9Sstevel@tonic-gate 
10987c478bd9Sstevel@tonic-gate 	/* if new ixl buffer addrs are null, return error */
1099*ffc2b7d4SToomas Soome 	if ((new_xfer_pkt_ixlp->ixl_buf.ixldmac_addr == 0) ||
11007c478bd9Sstevel@tonic-gate 	    (new_xfer_pkt_ixlp->mem_bufp == NULL)) {
11017c478bd9Sstevel@tonic-gate 
11027c478bd9Sstevel@tonic-gate 		uvp->upd_status = IXL1394_EXFER_BUF_MISSING;
11037c478bd9Sstevel@tonic-gate 
11047c478bd9Sstevel@tonic-gate 		return (IXL_PREP_FAILURE);
11057c478bd9Sstevel@tonic-gate 	}
11067c478bd9Sstevel@tonic-gate 
11077c478bd9Sstevel@tonic-gate 	/* error if IXL1394_OP_SEND_PKT_WHDR_ST_U opcode and size < 4 */
11087c478bd9Sstevel@tonic-gate 	if ((uvp->ixl_opcode == IXL1394_OP_SEND_PKT_WHDR_ST_U) &&
11097c478bd9Sstevel@tonic-gate 	    (new_xfer_pkt_ixlp->size < 4)) {
11107c478bd9Sstevel@tonic-gate 
11117c478bd9Sstevel@tonic-gate 		uvp->upd_status = IXL1394_EPKT_HDR_MISSING;
11127c478bd9Sstevel@tonic-gate 
11137c478bd9Sstevel@tonic-gate 		return (IXL_PREP_FAILURE);
11147c478bd9Sstevel@tonic-gate 	}
11157c478bd9Sstevel@tonic-gate 
11167c478bd9Sstevel@tonic-gate 	/* if IXL xfer command is not an IXL xfer start command */
11177c478bd9Sstevel@tonic-gate 	if (uvp->ixl_opcode == IXL1394_OP_SEND_PKT_U) {
11187c478bd9Sstevel@tonic-gate 		/*
11197c478bd9Sstevel@tonic-gate 		 * find IXL xfer start command in the compiler_privatep of the
11207c478bd9Sstevel@tonic-gate 		 * old IXL xfer command
11217c478bd9Sstevel@tonic-gate 		 */
11227c478bd9Sstevel@tonic-gate 		uvp->ixlxferp = (ixl1394_command_t *)
11237c478bd9Sstevel@tonic-gate 		    old_xfer_pkt_ixlp->compiler_privatep;
11247c478bd9Sstevel@tonic-gate 
11257c478bd9Sstevel@tonic-gate 		if (uvp->ixlxferp == NULL) {
11267c478bd9Sstevel@tonic-gate 			/* error if no IXL xfer start command found */
11277c478bd9Sstevel@tonic-gate 			uvp->upd_status = IXL1394_EORIG_IXL_CORRUPTED;
11287c478bd9Sstevel@tonic-gate 
11297c478bd9Sstevel@tonic-gate 			return (IXL_PREP_FAILURE);
11307c478bd9Sstevel@tonic-gate 		}
11317c478bd9Sstevel@tonic-gate 	} else {
11327c478bd9Sstevel@tonic-gate 		/* IXL xfer command is the IXL xfer start command */
11337c478bd9Sstevel@tonic-gate 		uvp->ixlxferp = uvp->ixloldp;
11347c478bd9Sstevel@tonic-gate 	}
11357c478bd9Sstevel@tonic-gate 
11367c478bd9Sstevel@tonic-gate 	/*
11377c478bd9Sstevel@tonic-gate 	 * get Z bits (number of descriptor components in the descriptor block)
11387c478bd9Sstevel@tonic-gate 	 * from a dma bound address in the xfer_ctl structure of the IXL
11397c478bd9Sstevel@tonic-gate 	 * xfer start command
11407c478bd9Sstevel@tonic-gate 	 */
11417c478bd9Sstevel@tonic-gate 	if ((xferctlp = (hci1394_xfer_ctl_t *)
11427c478bd9Sstevel@tonic-gate 	    uvp->ixlxferp->compiler_privatep) == NULL) {
11437c478bd9Sstevel@tonic-gate 
11447c478bd9Sstevel@tonic-gate 		uvp->upd_status = IXL1394_EORIG_IXL_CORRUPTED;
11457c478bd9Sstevel@tonic-gate 
11467c478bd9Sstevel@tonic-gate 		return (IXL_PREP_FAILURE);
11477c478bd9Sstevel@tonic-gate 	}
11487c478bd9Sstevel@tonic-gate 
11497c478bd9Sstevel@tonic-gate 	/* set depth to zero and count to 1 to update dma descriptor */
11507c478bd9Sstevel@tonic-gate 	uvp->ixldepth = 0;
11517c478bd9Sstevel@tonic-gate 	uvp->ixlcount = 1;
11527c478bd9Sstevel@tonic-gate 
11537c478bd9Sstevel@tonic-gate 	/*
11547c478bd9Sstevel@tonic-gate 	 * set offset to the header(first) descriptor from the
11557c478bd9Sstevel@tonic-gate 	 * current(last) descriptor
11567c478bd9Sstevel@tonic-gate 	 */
11577c478bd9Sstevel@tonic-gate 	uvp->hdr_offset = xferctlp->dma[0].dma_bound & DESC_Z_MASK - 1;
11587c478bd9Sstevel@tonic-gate 
11597c478bd9Sstevel@tonic-gate 	/*
11607c478bd9Sstevel@tonic-gate 	 * set offset from the current(last) descriptor to the descriptor for
11617c478bd9Sstevel@tonic-gate 	 * this packet command
11627c478bd9Sstevel@tonic-gate 	 */
11637c478bd9Sstevel@tonic-gate 	uvp->hci_offset = uvp->hdr_offset - 2 - uvp->ixloldp->compiler_resv;
11647c478bd9Sstevel@tonic-gate 
11657c478bd9Sstevel@tonic-gate 	/* set bufsize to new pkt buffr size, set bufaddr to new bufp */
11667c478bd9Sstevel@tonic-gate 	uvp->bufsize = new_xfer_pkt_ixlp->size;
11677c478bd9Sstevel@tonic-gate 	uvp->bufaddr = new_xfer_pkt_ixlp->ixl_buf.ixldmac_addr;
11687c478bd9Sstevel@tonic-gate 
11697c478bd9Sstevel@tonic-gate 	/*
11707c478bd9Sstevel@tonic-gate 	 * if IXL1394_OP_SEND_PKT_WHDR_ST_U opcode, adjust size & buff,
11717c478bd9Sstevel@tonic-gate 	 * step over hdr
11727c478bd9Sstevel@tonic-gate 	 */
11737c478bd9Sstevel@tonic-gate 	if (uvp->ixl_opcode == IXL1394_OP_SEND_PKT_WHDR_ST_U) {
11747c478bd9Sstevel@tonic-gate 		uvp->bufsize -= 4;
11757c478bd9Sstevel@tonic-gate 		uvp->bufaddr += 4;
11767c478bd9Sstevel@tonic-gate 	}
11777c478bd9Sstevel@tonic-gate 
11787c478bd9Sstevel@tonic-gate 	/* update old hcihdr w/new bufsize */
11797c478bd9Sstevel@tonic-gate 	hcidescp = (hci1394_desc_imm_t *)xferctlp->dma[0].dma_descp -
11807c478bd9Sstevel@tonic-gate 	    uvp->hci_offset;
11817c478bd9Sstevel@tonic-gate 	acc_hdl  = xferctlp->dma[0].dma_buf->bi_handle;
11827c478bd9Sstevel@tonic-gate 	dma_hdl  = xferctlp->dma[0].dma_buf->bi_dma_handle;
11837c478bd9Sstevel@tonic-gate 
11847c478bd9Sstevel@tonic-gate 	/* Sync the descriptor before we grab the header(s) */
11857c478bd9Sstevel@tonic-gate 	err = ddi_dma_sync(dma_hdl, (off_t)hcidescp,
11867c478bd9Sstevel@tonic-gate 	    sizeof (hci1394_desc_imm_t), DDI_DMA_SYNC_FORCPU);
11877c478bd9Sstevel@tonic-gate 	if (err != DDI_SUCCESS) {
11887c478bd9Sstevel@tonic-gate 		uvp->upd_status = IXL1394_EINTERNAL_ERROR;
11897c478bd9Sstevel@tonic-gate 
11907c478bd9Sstevel@tonic-gate 		return (IXL_PREP_FAILURE);
11917c478bd9Sstevel@tonic-gate 	}
11927c478bd9Sstevel@tonic-gate 
11937c478bd9Sstevel@tonic-gate 	desc_hdr = ddi_get32(acc_hdl, &hcidescp->hdr);
11947c478bd9Sstevel@tonic-gate 	uvp->hcihdr = desc_hdr;
11957c478bd9Sstevel@tonic-gate 	uvp->hcihdr &= ~DESC_HDR_REQCOUNT_MASK;
11967c478bd9Sstevel@tonic-gate 	uvp->hcihdr |= (uvp->bufsize << DESC_HDR_REQCOUNT_SHIFT) &
11977c478bd9Sstevel@tonic-gate 	    DESC_HDR_REQCOUNT_MASK;
11987c478bd9Sstevel@tonic-gate 
11997c478bd9Sstevel@tonic-gate 	/* update old pkthdr2 w/new bufsize. error if exceeds 16k */
12007c478bd9Sstevel@tonic-gate 	desc_hdr2 = ddi_get32(acc_hdl, &hcidescp->q2);
12017c478bd9Sstevel@tonic-gate 	uvp->pkthdr2 = desc_hdr2;
12027c478bd9Sstevel@tonic-gate 	uvp->pkthdr2 = (uvp->pkthdr2 & DESC_PKT_DATALEN_MASK) >>
12037c478bd9Sstevel@tonic-gate 	    DESC_PKT_DATALEN_SHIFT;
12047c478bd9Sstevel@tonic-gate 	uvp->pkthdr2 -= old_xfer_pkt_ixlp->size;
12057c478bd9Sstevel@tonic-gate 	uvp->pkthdr2 += uvp->bufsize;
12067c478bd9Sstevel@tonic-gate 
12077c478bd9Sstevel@tonic-gate 	if (uvp->pkthdr2 > 0xFFFF) {
12087c478bd9Sstevel@tonic-gate 		uvp->upd_status = IXL1394_EPKTSIZE_MAX_OFLO;
12097c478bd9Sstevel@tonic-gate 
12107c478bd9Sstevel@tonic-gate 		return (IXL_PREP_FAILURE);
12117c478bd9Sstevel@tonic-gate 	}
12127c478bd9Sstevel@tonic-gate 	uvp->pkthdr2 = (uvp->pkthdr2 << DESC_PKT_DATALEN_SHIFT) &
12137c478bd9Sstevel@tonic-gate 	    DESC_PKT_DATALEN_MASK;
12147c478bd9Sstevel@tonic-gate 
12157c478bd9Sstevel@tonic-gate 	return (IXL_PREP_READY);
12167c478bd9Sstevel@tonic-gate }
12177c478bd9Sstevel@tonic-gate 
12187c478bd9Sstevel@tonic-gate /*
12197c478bd9Sstevel@tonic-gate  * hci1394_ixl_update_prep_send_buf()
12207c478bd9Sstevel@tonic-gate  *    Preparation for update of an IXL1394_OP_SEND_BUF_U command.
12217c478bd9Sstevel@tonic-gate  */
12227c478bd9Sstevel@tonic-gate static int
hci1394_ixl_update_prep_send_buf(hci1394_ixl_update_vars_t * uvp)12237c478bd9Sstevel@tonic-gate hci1394_ixl_update_prep_send_buf(hci1394_ixl_update_vars_t *uvp)
12247c478bd9Sstevel@tonic-gate {
12257c478bd9Sstevel@tonic-gate 	ixl1394_xfer_buf_t *old_xfer_buf_ixlp;
12267c478bd9Sstevel@tonic-gate 	ixl1394_xfer_buf_t *new_xfer_buf_ixlp;
12277c478bd9Sstevel@tonic-gate 	hci1394_xfer_ctl_t *xferctlp;
12287c478bd9Sstevel@tonic-gate 
12297c478bd9Sstevel@tonic-gate 	old_xfer_buf_ixlp = (ixl1394_xfer_buf_t *)uvp->ixloldp;
12307c478bd9Sstevel@tonic-gate 	new_xfer_buf_ixlp = (ixl1394_xfer_buf_t *)uvp->ixlnewp;
12317c478bd9Sstevel@tonic-gate 
12327c478bd9Sstevel@tonic-gate 	/* check if any change between new and old IXL xfer commands */
12337c478bd9Sstevel@tonic-gate 	if ((new_xfer_buf_ixlp->size == old_xfer_buf_ixlp->size) &&
12347c478bd9Sstevel@tonic-gate 	    (new_xfer_buf_ixlp->pkt_size == old_xfer_buf_ixlp->pkt_size) &&
12357c478bd9Sstevel@tonic-gate 	    (new_xfer_buf_ixlp->ixl_buf.ixldmac_addr ==
123646776310SToomas Soome 	    old_xfer_buf_ixlp->ixl_buf.ixldmac_addr) &&
12377c478bd9Sstevel@tonic-gate 	    (new_xfer_buf_ixlp->mem_bufp == old_xfer_buf_ixlp->mem_bufp)) {
12387c478bd9Sstevel@tonic-gate 		/* no change, return with done ok status */
12397c478bd9Sstevel@tonic-gate 		return (IXL_PREP_SUCCESS);
12407c478bd9Sstevel@tonic-gate 	}
12417c478bd9Sstevel@tonic-gate 
12427c478bd9Sstevel@tonic-gate 	/* if new IXL buffer addresses are null, return error */
1243*ffc2b7d4SToomas Soome 	if ((new_xfer_buf_ixlp->ixl_buf.ixldmac_addr == 0) ||
12447c478bd9Sstevel@tonic-gate 	    (new_xfer_buf_ixlp->mem_bufp == NULL)) {
12457c478bd9Sstevel@tonic-gate 
12467c478bd9Sstevel@tonic-gate 		uvp->upd_status = IXL1394_EXFER_BUF_MISSING;
12477c478bd9Sstevel@tonic-gate 
12487c478bd9Sstevel@tonic-gate 		return (IXL_PREP_FAILURE);
12497c478bd9Sstevel@tonic-gate 	}
12507c478bd9Sstevel@tonic-gate 
12517c478bd9Sstevel@tonic-gate 	/*
12527c478bd9Sstevel@tonic-gate 	 * check that the new pkt_size > 0 and the new size/pkt_size
12537c478bd9Sstevel@tonic-gate 	 * doesn't change the count of DMA descriptor blocks required
12547c478bd9Sstevel@tonic-gate 	 */
12557c478bd9Sstevel@tonic-gate 	if ((new_xfer_buf_ixlp->pkt_size == 0) ||
12567c478bd9Sstevel@tonic-gate 	    ((new_xfer_buf_ixlp->size / new_xfer_buf_ixlp->pkt_size) !=
12577c478bd9Sstevel@tonic-gate 	    (old_xfer_buf_ixlp->size / old_xfer_buf_ixlp->pkt_size))) {
12587c478bd9Sstevel@tonic-gate 
12597c478bd9Sstevel@tonic-gate 		/* Error - new has different pkt count than old */
12607c478bd9Sstevel@tonic-gate 		uvp->upd_status = IXL1394_EXFER_BUF_CNT_DIFF;
12617c478bd9Sstevel@tonic-gate 
12627c478bd9Sstevel@tonic-gate 		return (IXL_PREP_FAILURE);
12637c478bd9Sstevel@tonic-gate 	}
12647c478bd9Sstevel@tonic-gate 
12657c478bd9Sstevel@tonic-gate 	/* set the old IXL xfer command as the current IXL xfer command */
12667c478bd9Sstevel@tonic-gate 	uvp->ixlxferp = uvp->ixloldp;
12677c478bd9Sstevel@tonic-gate 
12687c478bd9Sstevel@tonic-gate 	/*
12697c478bd9Sstevel@tonic-gate 	 * get Z bits (number of descriptor components in descriptor block)
12707c478bd9Sstevel@tonic-gate 	 * from a DMA bound address in the xfer_ctl struct of the
12717c478bd9Sstevel@tonic-gate 	 * IXL xfer command
12727c478bd9Sstevel@tonic-gate 	 */
12737c478bd9Sstevel@tonic-gate 	if ((xferctlp = (hci1394_xfer_ctl_t *)
12747c478bd9Sstevel@tonic-gate 	    uvp->ixlxferp->compiler_privatep) == NULL) {
12757c478bd9Sstevel@tonic-gate 
12767c478bd9Sstevel@tonic-gate 		uvp->upd_status = IXL1394_EORIG_IXL_CORRUPTED;
12777c478bd9Sstevel@tonic-gate 
12787c478bd9Sstevel@tonic-gate 		return (IXL_PREP_FAILURE);
12797c478bd9Sstevel@tonic-gate 	}
12807c478bd9Sstevel@tonic-gate 
12817c478bd9Sstevel@tonic-gate 	/* set depth to zero and count to update all dma descriptors */
12827c478bd9Sstevel@tonic-gate 	uvp->ixldepth = 0;
12837c478bd9Sstevel@tonic-gate 	uvp->ixlcount = xferctlp->cnt;
12847c478bd9Sstevel@tonic-gate 
12857c478bd9Sstevel@tonic-gate 	/*
12867c478bd9Sstevel@tonic-gate 	 * set offset to the header(first) descriptor from the current (last)
12877c478bd9Sstevel@tonic-gate 	 * descriptor.
12887c478bd9Sstevel@tonic-gate 	 */
12897c478bd9Sstevel@tonic-gate 	uvp->hdr_offset = xferctlp->dma[0].dma_bound & DESC_Z_MASK - 1;
12907c478bd9Sstevel@tonic-gate 
12917c478bd9Sstevel@tonic-gate 	/* set offset to the only(last) xfer descriptor */
12927c478bd9Sstevel@tonic-gate 	uvp->hci_offset = 0;
12937c478bd9Sstevel@tonic-gate 
12947c478bd9Sstevel@tonic-gate 	/* set bufsize to the new pkt_size, set bufaddr to the new bufp */
12957c478bd9Sstevel@tonic-gate 	uvp->bufsize = new_xfer_buf_ixlp->pkt_size;
12967c478bd9Sstevel@tonic-gate 	uvp->bufaddr = new_xfer_buf_ixlp->ixl_buf.ixldmac_addr;
12977c478bd9Sstevel@tonic-gate 
12987c478bd9Sstevel@tonic-gate 	/*
12997c478bd9Sstevel@tonic-gate 	 * if IXL1394_OP_SEND_PKT_WHDR_ST_U opcode, adjust size & buff,
13007c478bd9Sstevel@tonic-gate 	 * step over header (a quadlet)
13017c478bd9Sstevel@tonic-gate 	 */
13027c478bd9Sstevel@tonic-gate 	if (uvp->ixl_opcode == IXL1394_OP_SEND_PKT_WHDR_ST_U) {
13037c478bd9Sstevel@tonic-gate 		uvp->bufsize -= 4;
13047c478bd9Sstevel@tonic-gate 		uvp->bufaddr += 4;
13057c478bd9Sstevel@tonic-gate 	}
13067c478bd9Sstevel@tonic-gate 
13077c478bd9Sstevel@tonic-gate 	/* set hcihdr to new bufsize */
13087c478bd9Sstevel@tonic-gate 	uvp->hcihdr = (uvp->bufsize << DESC_HDR_REQCOUNT_SHIFT) &
13097c478bd9Sstevel@tonic-gate 	    DESC_HDR_REQCOUNT_MASK;
13107c478bd9Sstevel@tonic-gate 
13117c478bd9Sstevel@tonic-gate 	/* set pkthdr2 to new bufsize */
13127c478bd9Sstevel@tonic-gate 	uvp->pkthdr2 = (uvp->bufsize << DESC_PKT_DATALEN_SHIFT) &
13137c478bd9Sstevel@tonic-gate 	    DESC_PKT_DATALEN_MASK;
13147c478bd9Sstevel@tonic-gate 
13157c478bd9Sstevel@tonic-gate 	return (IXL_PREP_READY);
13167c478bd9Sstevel@tonic-gate }
13177c478bd9Sstevel@tonic-gate 
13187c478bd9Sstevel@tonic-gate /*
13197c478bd9Sstevel@tonic-gate  * hci1394_ixl_update_perform()
13207c478bd9Sstevel@tonic-gate  *    performs the actual update into DMA memory.
13217c478bd9Sstevel@tonic-gate  */
13227c478bd9Sstevel@tonic-gate static int
hci1394_ixl_update_perform(hci1394_ixl_update_vars_t * uvp)13237c478bd9Sstevel@tonic-gate hci1394_ixl_update_perform(hci1394_ixl_update_vars_t *uvp)
13247c478bd9Sstevel@tonic-gate {
13257c478bd9Sstevel@tonic-gate 	int			ii;
13267c478bd9Sstevel@tonic-gate 	uint_t			skipaddrlast;
13277c478bd9Sstevel@tonic-gate 	hci1394_xfer_ctl_t	*xferctlp;
13287c478bd9Sstevel@tonic-gate 	hci1394_desc_imm_t	*hcidescp;
13297c478bd9Sstevel@tonic-gate 	hci1394_iso_ctxt_t	*ctxtp;
13307c478bd9Sstevel@tonic-gate 	ddi_acc_handle_t	acc_hdl;
13317c478bd9Sstevel@tonic-gate 	ddi_dma_handle_t	dma_hdl;
13327c478bd9Sstevel@tonic-gate 	int			err;
13337c478bd9Sstevel@tonic-gate 
13347c478bd9Sstevel@tonic-gate 	ctxtp = uvp->ctxtp;
13357c478bd9Sstevel@tonic-gate 
13367c478bd9Sstevel@tonic-gate 	/*
13377c478bd9Sstevel@tonic-gate 	 * if no target ixl xfer command to be updated or it has
13387c478bd9Sstevel@tonic-gate 	 * no xfer_ctl struct, then internal error.
13397c478bd9Sstevel@tonic-gate 	 */
13407c478bd9Sstevel@tonic-gate 	if ((uvp->ixlxferp == NULL) ||
13417c478bd9Sstevel@tonic-gate 	    ((xferctlp = (hci1394_xfer_ctl_t *)
13427c478bd9Sstevel@tonic-gate 	    uvp->ixlxferp->compiler_privatep) == NULL)) {
13437c478bd9Sstevel@tonic-gate 
13447c478bd9Sstevel@tonic-gate 		uvp->upd_status = IXL1394_EINTERNAL_ERROR;
13457c478bd9Sstevel@tonic-gate 
13467c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
13477c478bd9Sstevel@tonic-gate 	}
13487c478bd9Sstevel@tonic-gate 
13497c478bd9Sstevel@tonic-gate 	/* perform update based on specific ixl command type */
13507c478bd9Sstevel@tonic-gate 	switch (uvp->ixl_opcode) {
13517c478bd9Sstevel@tonic-gate 
13527c478bd9Sstevel@tonic-gate 	case IXL1394_OP_JUMP_U: {
13537c478bd9Sstevel@tonic-gate 		ixl1394_jump_t *old_jump_ixlp;
13547c478bd9Sstevel@tonic-gate 		ixl1394_jump_t *new_jump_ixlp;
13557c478bd9Sstevel@tonic-gate 
13567c478bd9Sstevel@tonic-gate 		old_jump_ixlp = (ixl1394_jump_t *)uvp->ixloldp;
13577c478bd9Sstevel@tonic-gate 		new_jump_ixlp = (ixl1394_jump_t *)uvp->ixlnewp;
13587c478bd9Sstevel@tonic-gate 
13597c478bd9Sstevel@tonic-gate 		/*
13607c478bd9Sstevel@tonic-gate 		 * set new hdr and new branch fields into last component of last
13617c478bd9Sstevel@tonic-gate 		 * dma descriptor block of ixl xfer cmd associated with
13627c478bd9Sstevel@tonic-gate 		 * ixl jump cmd
13637c478bd9Sstevel@tonic-gate 		 */
13647c478bd9Sstevel@tonic-gate 		hcidescp = (hci1394_desc_imm_t *)
13657c478bd9Sstevel@tonic-gate 		    xferctlp->dma[xferctlp->cnt - 1].dma_descp;
13667c478bd9Sstevel@tonic-gate 		acc_hdl	 = xferctlp->dma[xferctlp->cnt - 1].dma_buf->bi_handle;
13677c478bd9Sstevel@tonic-gate 		dma_hdl	 =
13687c478bd9Sstevel@tonic-gate 		    xferctlp->dma[xferctlp->cnt - 1].dma_buf->bi_dma_handle;
13697c478bd9Sstevel@tonic-gate 
13707c478bd9Sstevel@tonic-gate 		ddi_put32(acc_hdl, &hcidescp->hdr, uvp->hcihdr);
13717c478bd9Sstevel@tonic-gate 		ddi_put32(acc_hdl, &hcidescp->branch, uvp->jumpaddr);
13727c478bd9Sstevel@tonic-gate 
13737c478bd9Sstevel@tonic-gate 		/*
13747c478bd9Sstevel@tonic-gate 		 * if xfer type is send and skip mode is IXL1394__SKIP_TO_NEXT
13757c478bd9Sstevel@tonic-gate 		 * also set branch location into branch field of first
13767c478bd9Sstevel@tonic-gate 		 * component (skip to address) of last dma descriptor block
13777c478bd9Sstevel@tonic-gate 		 */
13787c478bd9Sstevel@tonic-gate 		if (uvp->skipmode == IXL1394_SKIP_TO_NEXT) {
13797c478bd9Sstevel@tonic-gate 			hcidescp -= uvp->hci_offset;
13807c478bd9Sstevel@tonic-gate 			ddi_put32(acc_hdl, &hcidescp->branch, uvp->skipaddr);
13817c478bd9Sstevel@tonic-gate 		}
13827c478bd9Sstevel@tonic-gate 
13837c478bd9Sstevel@tonic-gate 		/* Sync descriptor for device (desc was modified) */
13847c478bd9Sstevel@tonic-gate 		err = ddi_dma_sync(dma_hdl, (off_t)hcidescp,
13857c478bd9Sstevel@tonic-gate 		    sizeof (hci1394_desc_imm_t), DDI_DMA_SYNC_FORDEV);
13867c478bd9Sstevel@tonic-gate 		if (err != DDI_SUCCESS) {
13877c478bd9Sstevel@tonic-gate 			uvp->upd_status = IXL1394_EINTERNAL_ERROR;
13887c478bd9Sstevel@tonic-gate 
13897c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
13907c478bd9Sstevel@tonic-gate 		}
13917c478bd9Sstevel@tonic-gate 
13927c478bd9Sstevel@tonic-gate 		/* set old ixl jump cmd label from new ixl jump cmd label */
13937c478bd9Sstevel@tonic-gate 		old_jump_ixlp->label = new_jump_ixlp->label;
13947c478bd9Sstevel@tonic-gate 		break;
13957c478bd9Sstevel@tonic-gate 	}
13967c478bd9Sstevel@tonic-gate 	case IXL1394_OP_SET_SKIPMODE_U: {
13977c478bd9Sstevel@tonic-gate 		ixl1394_set_skipmode_t *old_set_skipmode_ixlp;
13987c478bd9Sstevel@tonic-gate 		ixl1394_set_skipmode_t *new_set_skipmode_ixlp;
13997c478bd9Sstevel@tonic-gate 
14007c478bd9Sstevel@tonic-gate 		old_set_skipmode_ixlp = (ixl1394_set_skipmode_t *)uvp->ixloldp;
14017c478bd9Sstevel@tonic-gate 		new_set_skipmode_ixlp = (ixl1394_set_skipmode_t *)uvp->ixlnewp;
14027c478bd9Sstevel@tonic-gate 
14037c478bd9Sstevel@tonic-gate 		/*
14047c478bd9Sstevel@tonic-gate 		 * if skip to next mode, save skip addr for last iteration
14057c478bd9Sstevel@tonic-gate 		 * thru dma descriptor blocks for associated ixl xfer command
14067c478bd9Sstevel@tonic-gate 		 */
14077c478bd9Sstevel@tonic-gate 		if (uvp->skipmode == IXL1394_SKIP_TO_NEXT) {
14087c478bd9Sstevel@tonic-gate 			skipaddrlast = uvp->skipaddr;
14097c478bd9Sstevel@tonic-gate 		}
14107c478bd9Sstevel@tonic-gate 
14117c478bd9Sstevel@tonic-gate 		/*
14127c478bd9Sstevel@tonic-gate 		 * iterate through set of dma descriptor blocks for associated
14137c478bd9Sstevel@tonic-gate 		 * ixl xfer start cmd and set new skip address into first hci
14147c478bd9Sstevel@tonic-gate 		 * descriptor of each if skip next or skip self, first determine
14157c478bd9Sstevel@tonic-gate 		 * address in each iteration
14167c478bd9Sstevel@tonic-gate 		 */
14177c478bd9Sstevel@tonic-gate 		for (ii = 0; ii < xferctlp->cnt; ii++) {
14187c478bd9Sstevel@tonic-gate 			hcidescp = (hci1394_desc_imm_t *)
14197c478bd9Sstevel@tonic-gate 			    xferctlp->dma[ii].dma_descp - uvp->hci_offset;
14207c478bd9Sstevel@tonic-gate 			acc_hdl	 = xferctlp->dma[ii].dma_buf->bi_handle;
14217c478bd9Sstevel@tonic-gate 			dma_hdl	 = xferctlp->dma[ii].dma_buf->bi_dma_handle;
14227c478bd9Sstevel@tonic-gate 
14237c478bd9Sstevel@tonic-gate 			if (uvp->skipmode == IXL1394_SKIP_TO_NEXT) {
14247c478bd9Sstevel@tonic-gate 				if (ii < (xferctlp->cnt - 1)) {
14257c478bd9Sstevel@tonic-gate 					uvp->skipaddr =
14267c478bd9Sstevel@tonic-gate 					    xferctlp->dma[ii + 1].dma_bound;
14277c478bd9Sstevel@tonic-gate 				} else {
14287c478bd9Sstevel@tonic-gate 					uvp->skipaddr = skipaddrlast;
14297c478bd9Sstevel@tonic-gate 				}
14307c478bd9Sstevel@tonic-gate 			} else if (uvp->skipmode == IXL1394_SKIP_TO_SELF) {
14317c478bd9Sstevel@tonic-gate 				uvp->skipaddr = xferctlp->dma[ii].dma_bound;
14327c478bd9Sstevel@tonic-gate 			}
14337c478bd9Sstevel@tonic-gate 
14347c478bd9Sstevel@tonic-gate 			ddi_put32(acc_hdl, &hcidescp->branch, uvp->skipaddr);
14357c478bd9Sstevel@tonic-gate 
14367c478bd9Sstevel@tonic-gate 			/* Sync descriptor for device (desc was modified) */
14377c478bd9Sstevel@tonic-gate 			err = ddi_dma_sync(dma_hdl, (off_t)hcidescp,
14387c478bd9Sstevel@tonic-gate 			    sizeof (hci1394_desc_imm_t), DDI_DMA_SYNC_FORDEV);
14397c478bd9Sstevel@tonic-gate 			if (err != DDI_SUCCESS) {
14407c478bd9Sstevel@tonic-gate 				uvp->upd_status = IXL1394_EINTERNAL_ERROR;
14417c478bd9Sstevel@tonic-gate 
14427c478bd9Sstevel@tonic-gate 				return (DDI_FAILURE);
14437c478bd9Sstevel@tonic-gate 			}
14447c478bd9Sstevel@tonic-gate 		}
14457c478bd9Sstevel@tonic-gate 
14467c478bd9Sstevel@tonic-gate 		/*
14477c478bd9Sstevel@tonic-gate 		 * set old ixl set skip mode cmd mode and label from new ixl cmd
14487c478bd9Sstevel@tonic-gate 		 * set old ixl set skip mode cmd compilier_privatep to
14497c478bd9Sstevel@tonic-gate 		 * uvp->skipxferp
14507c478bd9Sstevel@tonic-gate 		 */
14517c478bd9Sstevel@tonic-gate 		old_set_skipmode_ixlp->skipmode = uvp->skipmode;
14527c478bd9Sstevel@tonic-gate 		old_set_skipmode_ixlp->label = new_set_skipmode_ixlp->label;
14537c478bd9Sstevel@tonic-gate 		old_set_skipmode_ixlp->compiler_privatep =
14547c478bd9Sstevel@tonic-gate 		    (ixl1394_priv_t)uvp->skipxferp;
14557c478bd9Sstevel@tonic-gate 		break;
14567c478bd9Sstevel@tonic-gate 	}
14577c478bd9Sstevel@tonic-gate 	case IXL1394_OP_SET_TAGSYNC_U: {
14587c478bd9Sstevel@tonic-gate 		ixl1394_set_tagsync_t *old_set_tagsync_ixlp;
14597c478bd9Sstevel@tonic-gate 		ixl1394_set_tagsync_t *new_set_tagsync_ixlp;
14607c478bd9Sstevel@tonic-gate 
14617c478bd9Sstevel@tonic-gate 		old_set_tagsync_ixlp = (ixl1394_set_tagsync_t *)uvp->ixloldp;
14627c478bd9Sstevel@tonic-gate 		new_set_tagsync_ixlp = (ixl1394_set_tagsync_t *)uvp->ixlnewp;
14637c478bd9Sstevel@tonic-gate 
14647c478bd9Sstevel@tonic-gate 		/*
14657c478bd9Sstevel@tonic-gate 		 * iterate through set of descriptor blocks for associated IXL
14667c478bd9Sstevel@tonic-gate 		 * xfer command and set new pkthdr1 value into output more/last
14677c478bd9Sstevel@tonic-gate 		 * immediate hci descriptor (first/last hci descriptor of each
14687c478bd9Sstevel@tonic-gate 		 * descriptor block)
14697c478bd9Sstevel@tonic-gate 		 */
14707c478bd9Sstevel@tonic-gate 		for (ii = 0; ii < xferctlp->cnt; ii++) {
14717c478bd9Sstevel@tonic-gate 			hcidescp = (hci1394_desc_imm_t *)
14727c478bd9Sstevel@tonic-gate 			    xferctlp->dma[ii].dma_descp - uvp->hdr_offset;
14737c478bd9Sstevel@tonic-gate 			acc_hdl	 = xferctlp->dma[ii].dma_buf->bi_handle;
14747c478bd9Sstevel@tonic-gate 			dma_hdl	 = xferctlp->dma[ii].dma_buf->bi_dma_handle;
14757c478bd9Sstevel@tonic-gate 			ddi_put32(acc_hdl, &hcidescp->q1, uvp->pkthdr1);
14767c478bd9Sstevel@tonic-gate 
14777c478bd9Sstevel@tonic-gate 			/* Sync descriptor for device (desc was modified) */
14787c478bd9Sstevel@tonic-gate 			err = ddi_dma_sync(dma_hdl, (off_t)hcidescp,
14797c478bd9Sstevel@tonic-gate 			    sizeof (hci1394_desc_imm_t), DDI_DMA_SYNC_FORDEV);
14807c478bd9Sstevel@tonic-gate 			if (err != DDI_SUCCESS) {
14817c478bd9Sstevel@tonic-gate 				uvp->upd_status = IXL1394_EINTERNAL_ERROR;
14827c478bd9Sstevel@tonic-gate 
14837c478bd9Sstevel@tonic-gate 				return (DDI_FAILURE);
14847c478bd9Sstevel@tonic-gate 			}
14857c478bd9Sstevel@tonic-gate 		}
14867c478bd9Sstevel@tonic-gate 
14877c478bd9Sstevel@tonic-gate 		/*
14887c478bd9Sstevel@tonic-gate 		 * set old ixl set tagsync cmd tag & sync from new ixl set
14897c478bd9Sstevel@tonic-gate 		 * tagsync cmd
14907c478bd9Sstevel@tonic-gate 		 */
14917c478bd9Sstevel@tonic-gate 		old_set_tagsync_ixlp->tag = new_set_tagsync_ixlp->tag;
14927c478bd9Sstevel@tonic-gate 		old_set_tagsync_ixlp->sync = new_set_tagsync_ixlp->sync;
14937c478bd9Sstevel@tonic-gate 		break;
14947c478bd9Sstevel@tonic-gate 	}
14957c478bd9Sstevel@tonic-gate 	case IXL1394_OP_RECV_PKT_U:
14967c478bd9Sstevel@tonic-gate 	case IXL1394_OP_RECV_PKT_ST_U: {
14977c478bd9Sstevel@tonic-gate 		ixl1394_xfer_pkt_t *old_xfer_pkt_ixlp;
14987c478bd9Sstevel@tonic-gate 		ixl1394_xfer_pkt_t *new_xfer_pkt_ixlp;
14997c478bd9Sstevel@tonic-gate 		uint32_t	   desc_status;
15007c478bd9Sstevel@tonic-gate 
15017c478bd9Sstevel@tonic-gate 		old_xfer_pkt_ixlp = (ixl1394_xfer_pkt_t *)uvp->ixloldp;
15027c478bd9Sstevel@tonic-gate 		new_xfer_pkt_ixlp = (ixl1394_xfer_pkt_t *)uvp->ixlnewp;
15037c478bd9Sstevel@tonic-gate 
15047c478bd9Sstevel@tonic-gate 		/*
15057c478bd9Sstevel@tonic-gate 		 * alter buffer address, count and rescount in ixl recv pkt cmd
15067c478bd9Sstevel@tonic-gate 		 * related hci component in dma descriptor block
15077c478bd9Sstevel@tonic-gate 		 */
15087c478bd9Sstevel@tonic-gate 		hcidescp = (hci1394_desc_imm_t *)
15097c478bd9Sstevel@tonic-gate 		    xferctlp->dma[0].dma_descp - uvp->hci_offset;
15107c478bd9Sstevel@tonic-gate 		acc_hdl	 = xferctlp->dma[0].dma_buf->bi_handle;
15117c478bd9Sstevel@tonic-gate 		dma_hdl	 = xferctlp->dma[0].dma_buf->bi_dma_handle;
15127c478bd9Sstevel@tonic-gate 		ddi_put32(acc_hdl, &hcidescp->hdr, uvp->hcihdr);
15137c478bd9Sstevel@tonic-gate 		ddi_put32(acc_hdl, &hcidescp->data_addr, uvp->bufaddr);
15147c478bd9Sstevel@tonic-gate 
15157c478bd9Sstevel@tonic-gate 		/* Sync the descriptor before we grab the status */
15167c478bd9Sstevel@tonic-gate 		err = ddi_dma_sync(dma_hdl, (off_t)hcidescp,
15177c478bd9Sstevel@tonic-gate 		    sizeof (hci1394_desc_imm_t), DDI_DMA_SYNC_FORCPU);
15187c478bd9Sstevel@tonic-gate 		if (err != DDI_SUCCESS) {
15197c478bd9Sstevel@tonic-gate 			uvp->upd_status = IXL1394_EINTERNAL_ERROR;
15207c478bd9Sstevel@tonic-gate 
15217c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
15227c478bd9Sstevel@tonic-gate 		}
15237c478bd9Sstevel@tonic-gate 
15247c478bd9Sstevel@tonic-gate 		/* change only low 1/2 word and leave status bits unchanged */
15257c478bd9Sstevel@tonic-gate 		desc_status = ddi_get32(acc_hdl, &hcidescp->status);
15267c478bd9Sstevel@tonic-gate 		desc_status = (desc_status & ~DESC_ST_RESCOUNT_MASK) |
15277c478bd9Sstevel@tonic-gate 		    uvp->hcistatus;
15287c478bd9Sstevel@tonic-gate 		ddi_put32(acc_hdl, &hcidescp->status, desc_status);
15297c478bd9Sstevel@tonic-gate 
15307c478bd9Sstevel@tonic-gate 		/* Sync descriptor for device (desc was modified) */
15317c478bd9Sstevel@tonic-gate 		err = ddi_dma_sync(dma_hdl, (off_t)hcidescp,
15327c478bd9Sstevel@tonic-gate 		    sizeof (hci1394_desc_imm_t), DDI_DMA_SYNC_FORDEV);
15337c478bd9Sstevel@tonic-gate 		if (err != DDI_SUCCESS) {
15347c478bd9Sstevel@tonic-gate 			uvp->upd_status = IXL1394_EINTERNAL_ERROR;
15357c478bd9Sstevel@tonic-gate 
15367c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
15377c478bd9Sstevel@tonic-gate 		}
15387c478bd9Sstevel@tonic-gate 
15397c478bd9Sstevel@tonic-gate 		/*
15407c478bd9Sstevel@tonic-gate 		 * set old ixl recv pkt size and buffers from new
15417c478bd9Sstevel@tonic-gate 		 * ixl recv pkt command
15427c478bd9Sstevel@tonic-gate 		 */
15437c478bd9Sstevel@tonic-gate 		old_xfer_pkt_ixlp->size = new_xfer_pkt_ixlp->size;
15447c478bd9Sstevel@tonic-gate 		old_xfer_pkt_ixlp->ixl_buf.ixldmac_addr =
15457c478bd9Sstevel@tonic-gate 		    new_xfer_pkt_ixlp->ixl_buf.ixldmac_addr;
15467c478bd9Sstevel@tonic-gate 		old_xfer_pkt_ixlp->mem_bufp = new_xfer_pkt_ixlp->mem_bufp;
15477c478bd9Sstevel@tonic-gate 		break;
15487c478bd9Sstevel@tonic-gate 	}
15497c478bd9Sstevel@tonic-gate 	case IXL1394_OP_RECV_BUF_U: {
15507c478bd9Sstevel@tonic-gate 		ixl1394_xfer_buf_t *old_xfer_buf_ixlp;
15517c478bd9Sstevel@tonic-gate 		ixl1394_xfer_buf_t *new_xfer_buf_ixlp;
15527c478bd9Sstevel@tonic-gate 		uint32_t	   desc_hdr;
15537c478bd9Sstevel@tonic-gate 		uint32_t	   desc_status;
15547c478bd9Sstevel@tonic-gate 
15557c478bd9Sstevel@tonic-gate 		old_xfer_buf_ixlp = (ixl1394_xfer_buf_t *)uvp->ixloldp;
15567c478bd9Sstevel@tonic-gate 		new_xfer_buf_ixlp = (ixl1394_xfer_buf_t *)uvp->ixlnewp;
15577c478bd9Sstevel@tonic-gate 
15587c478bd9Sstevel@tonic-gate 		/*
15597c478bd9Sstevel@tonic-gate 		 * iterate through set of descriptor blocks for this IXL xfer
15607c478bd9Sstevel@tonic-gate 		 * command altering buffer, count and rescount in each
15617c478bd9Sstevel@tonic-gate 		 * input more/last(the only) hci descriptor block descriptor.
15627c478bd9Sstevel@tonic-gate 		 */
15637c478bd9Sstevel@tonic-gate 		for (ii = 0; ii < xferctlp->cnt; ii++) {
15647c478bd9Sstevel@tonic-gate 
15657c478bd9Sstevel@tonic-gate 			hcidescp = (hci1394_desc_imm_t *)
15667c478bd9Sstevel@tonic-gate 			    xferctlp->dma[ii].dma_descp - uvp->hci_offset;
15677c478bd9Sstevel@tonic-gate 			acc_hdl	 = xferctlp->dma[ii].dma_buf->bi_handle;
15687c478bd9Sstevel@tonic-gate 			dma_hdl	 = xferctlp->dma[ii].dma_buf->bi_dma_handle;
15697c478bd9Sstevel@tonic-gate 
15707c478bd9Sstevel@tonic-gate 			ddi_put32(acc_hdl, &hcidescp->data_addr, uvp->bufaddr);
15717c478bd9Sstevel@tonic-gate 
15727c478bd9Sstevel@tonic-gate 			/*
15737c478bd9Sstevel@tonic-gate 			 * advance to next buffer segment, adjust over header
15747c478bd9Sstevel@tonic-gate 			 * if appropriate
15757c478bd9Sstevel@tonic-gate 			 */
15767c478bd9Sstevel@tonic-gate 			uvp->bufaddr += uvp->bufsize;
15777c478bd9Sstevel@tonic-gate 
15787c478bd9Sstevel@tonic-gate 			/* Sync the descriptor before we grab the header(s) */
15797c478bd9Sstevel@tonic-gate 			err = ddi_dma_sync(dma_hdl, (off_t)hcidescp,
15807c478bd9Sstevel@tonic-gate 			    sizeof (hci1394_desc_imm_t), DDI_DMA_SYNC_FORCPU);
15817c478bd9Sstevel@tonic-gate 			if (err != DDI_SUCCESS) {
15827c478bd9Sstevel@tonic-gate 				uvp->upd_status = IXL1394_EINTERNAL_ERROR;
15837c478bd9Sstevel@tonic-gate 
15847c478bd9Sstevel@tonic-gate 				return (DDI_FAILURE);
15857c478bd9Sstevel@tonic-gate 			}
15867c478bd9Sstevel@tonic-gate 
15877c478bd9Sstevel@tonic-gate 			/*
15887c478bd9Sstevel@tonic-gate 			 * this preserves interrupt enable bits, et al. in each
15897c478bd9Sstevel@tonic-gate 			 * descriptor block header.
15907c478bd9Sstevel@tonic-gate 			 */
15917c478bd9Sstevel@tonic-gate 			desc_hdr = ddi_get32(acc_hdl, &hcidescp->hdr);
15927c478bd9Sstevel@tonic-gate 			desc_hdr = (desc_hdr & ~DESC_HDR_REQCOUNT_MASK) |
15937c478bd9Sstevel@tonic-gate 			    uvp->hcihdr;
15947c478bd9Sstevel@tonic-gate 			ddi_put32(acc_hdl, &hcidescp->hdr, desc_hdr);
15957c478bd9Sstevel@tonic-gate 
15967c478bd9Sstevel@tonic-gate 			/*
15977c478bd9Sstevel@tonic-gate 			 * change only low 1/2 word leaving status bits
15987c478bd9Sstevel@tonic-gate 			 * unchanged
15997c478bd9Sstevel@tonic-gate 			 */
16007c478bd9Sstevel@tonic-gate 			desc_status = ddi_get32(acc_hdl, &hcidescp->status);
16017c478bd9Sstevel@tonic-gate 			desc_status = (desc_status & ~DESC_ST_RESCOUNT_MASK) |
16027c478bd9Sstevel@tonic-gate 			    uvp->hcistatus;
16037c478bd9Sstevel@tonic-gate 			ddi_put32(acc_hdl, &hcidescp->status, desc_status);
16047c478bd9Sstevel@tonic-gate 
16057c478bd9Sstevel@tonic-gate 			/* Sync descriptor for device (desc was modified) */
16067c478bd9Sstevel@tonic-gate 			err = ddi_dma_sync(dma_hdl, (off_t)hcidescp,
16077c478bd9Sstevel@tonic-gate 			    sizeof (hci1394_desc_imm_t), DDI_DMA_SYNC_FORDEV);
16087c478bd9Sstevel@tonic-gate 			if (err != DDI_SUCCESS) {
16097c478bd9Sstevel@tonic-gate 				uvp->upd_status = IXL1394_EINTERNAL_ERROR;
16107c478bd9Sstevel@tonic-gate 
16117c478bd9Sstevel@tonic-gate 				return (DDI_FAILURE);
16127c478bd9Sstevel@tonic-gate 			}
16137c478bd9Sstevel@tonic-gate 		}
16147c478bd9Sstevel@tonic-gate 
16157c478bd9Sstevel@tonic-gate 		/*
16167c478bd9Sstevel@tonic-gate 		 * set old ixl recv buf sizes and buffers from
16177c478bd9Sstevel@tonic-gate 		 * new ixl recv pkt cmd
16187c478bd9Sstevel@tonic-gate 		 */
16197c478bd9Sstevel@tonic-gate 		old_xfer_buf_ixlp->pkt_size = new_xfer_buf_ixlp->pkt_size;
16207c478bd9Sstevel@tonic-gate 		old_xfer_buf_ixlp->size = new_xfer_buf_ixlp->size;
16217c478bd9Sstevel@tonic-gate 		old_xfer_buf_ixlp->ixl_buf.ixldmac_addr =
16227c478bd9Sstevel@tonic-gate 		    new_xfer_buf_ixlp->ixl_buf.ixldmac_addr;
16237c478bd9Sstevel@tonic-gate 		old_xfer_buf_ixlp->mem_bufp = new_xfer_buf_ixlp->mem_bufp;
16247c478bd9Sstevel@tonic-gate 		break;
16257c478bd9Sstevel@tonic-gate 	}
16267c478bd9Sstevel@tonic-gate 	case IXL1394_OP_SEND_PKT_U:
16277c478bd9Sstevel@tonic-gate 	case IXL1394_OP_SEND_PKT_ST_U:
16287c478bd9Sstevel@tonic-gate 	case IXL1394_OP_SEND_PKT_WHDR_ST_U: {
16297c478bd9Sstevel@tonic-gate 		ixl1394_xfer_pkt_t *old_xfer_pkt_ixlp;
16307c478bd9Sstevel@tonic-gate 		ixl1394_xfer_pkt_t *new_xfer_pkt_ixlp;
16317c478bd9Sstevel@tonic-gate 
16327c478bd9Sstevel@tonic-gate 		old_xfer_pkt_ixlp = (ixl1394_xfer_pkt_t *)uvp->ixloldp;
16337c478bd9Sstevel@tonic-gate 		new_xfer_pkt_ixlp = (ixl1394_xfer_pkt_t *)uvp->ixlnewp;
16347c478bd9Sstevel@tonic-gate 
16357c478bd9Sstevel@tonic-gate 		/*
16367c478bd9Sstevel@tonic-gate 		 * replace pkthdr2 in output more immediate (the first) hci
16377c478bd9Sstevel@tonic-gate 		 * descriptor in block, then alter buffer address and count in
16387c478bd9Sstevel@tonic-gate 		 * IXL send pkt command related output more/last hci descriptor.
16397c478bd9Sstevel@tonic-gate 		 */
16407c478bd9Sstevel@tonic-gate 		hcidescp = (hci1394_desc_imm_t *)xferctlp->dma[0].dma_descp -
16417c478bd9Sstevel@tonic-gate 		    uvp->hdr_offset;
16427c478bd9Sstevel@tonic-gate 		acc_hdl	 = xferctlp->dma[0].dma_buf->bi_handle;
16437c478bd9Sstevel@tonic-gate 		dma_hdl	 = xferctlp->dma[0].dma_buf->bi_dma_handle;
16447c478bd9Sstevel@tonic-gate 
16457c478bd9Sstevel@tonic-gate 		ddi_put32(acc_hdl, &hcidescp->q2, uvp->pkthdr2);
16467c478bd9Sstevel@tonic-gate 		ddi_put32(acc_hdl, &hcidescp->hdr, uvp->hcihdr);
16477c478bd9Sstevel@tonic-gate 		ddi_put32(acc_hdl, &hcidescp->data_addr, uvp->bufaddr);
16487c478bd9Sstevel@tonic-gate 
16497c478bd9Sstevel@tonic-gate 		/* Sync descriptor for device (desc was modified) */
16507c478bd9Sstevel@tonic-gate 		err = ddi_dma_sync(dma_hdl, (off_t)hcidescp,
16517c478bd9Sstevel@tonic-gate 		    sizeof (hci1394_desc_imm_t), DDI_DMA_SYNC_FORDEV);
16527c478bd9Sstevel@tonic-gate 		if (err != DDI_SUCCESS) {
16537c478bd9Sstevel@tonic-gate 			uvp->upd_status = IXL1394_EINTERNAL_ERROR;
16547c478bd9Sstevel@tonic-gate 
16557c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
16567c478bd9Sstevel@tonic-gate 		}
16577c478bd9Sstevel@tonic-gate 
16587c478bd9Sstevel@tonic-gate 		/*
16597c478bd9Sstevel@tonic-gate 		 * set old ixl recv pkt size and buffers from
16607c478bd9Sstevel@tonic-gate 		 * new ixl recv pkt cmd
16617c478bd9Sstevel@tonic-gate 		 */
16627c478bd9Sstevel@tonic-gate 		old_xfer_pkt_ixlp->size = new_xfer_pkt_ixlp->size;
16637c478bd9Sstevel@tonic-gate 		old_xfer_pkt_ixlp->ixl_buf.ixldmac_addr =
16647c478bd9Sstevel@tonic-gate 		    new_xfer_pkt_ixlp->ixl_buf.ixldmac_addr;
16657c478bd9Sstevel@tonic-gate 		old_xfer_pkt_ixlp->mem_bufp = new_xfer_pkt_ixlp->mem_bufp;
16667c478bd9Sstevel@tonic-gate 		break;
16677c478bd9Sstevel@tonic-gate 	}
16687c478bd9Sstevel@tonic-gate 	case IXL1394_OP_SEND_BUF_U: {
16697c478bd9Sstevel@tonic-gate 		ixl1394_xfer_buf_t *old_xfer_buf_ixlp;
16707c478bd9Sstevel@tonic-gate 		ixl1394_xfer_buf_t *new_xfer_buf_ixlp;
16717c478bd9Sstevel@tonic-gate 		uint32_t	   desc_hdr;
16727c478bd9Sstevel@tonic-gate 
16737c478bd9Sstevel@tonic-gate 		old_xfer_buf_ixlp = (ixl1394_xfer_buf_t *)uvp->ixloldp;
16747c478bd9Sstevel@tonic-gate 		new_xfer_buf_ixlp = (ixl1394_xfer_buf_t *)uvp->ixlnewp;
16757c478bd9Sstevel@tonic-gate 
16767c478bd9Sstevel@tonic-gate 		/*
16777c478bd9Sstevel@tonic-gate 		 * iterate through set of descriptor blocks for this IXL xfer
16787c478bd9Sstevel@tonic-gate 		 * command replacing pkthdr2 in output more immediate
16797c478bd9Sstevel@tonic-gate 		 * (the first) hci descriptor block descriptor, then altering
16807c478bd9Sstevel@tonic-gate 		 * buffer address and count in each output last (the only other)
16817c478bd9Sstevel@tonic-gate 		 * hci descriptor block descriptor.
16827c478bd9Sstevel@tonic-gate 		 */
16837c478bd9Sstevel@tonic-gate 		for (ii = 0; ii < xferctlp->cnt; ii++) {
16847c478bd9Sstevel@tonic-gate 			hcidescp = (hci1394_desc_imm_t *)
16857c478bd9Sstevel@tonic-gate 			    xferctlp->dma[ii].dma_descp - uvp->hdr_offset;
16867c478bd9Sstevel@tonic-gate 			acc_hdl	 = xferctlp->dma[ii].dma_buf->bi_handle;
16877c478bd9Sstevel@tonic-gate 			dma_hdl	 = xferctlp->dma[ii].dma_buf->bi_dma_handle;
16887c478bd9Sstevel@tonic-gate 
16897c478bd9Sstevel@tonic-gate 			ddi_put32(acc_hdl, &hcidescp->q2, uvp->pkthdr2);
16907c478bd9Sstevel@tonic-gate 			ddi_put32(acc_hdl, &hcidescp->data_addr, uvp->bufaddr);
16917c478bd9Sstevel@tonic-gate 
16927c478bd9Sstevel@tonic-gate 			/* advance to next buffer segment */
16937c478bd9Sstevel@tonic-gate 			uvp->bufaddr += uvp->bufsize;
16947c478bd9Sstevel@tonic-gate 
16957c478bd9Sstevel@tonic-gate 			/* Sync the descriptor before we grab the header(s) */
16967c478bd9Sstevel@tonic-gate 			err = ddi_dma_sync(dma_hdl, (off_t)hcidescp,
16977c478bd9Sstevel@tonic-gate 			    sizeof (hci1394_desc_imm_t), DDI_DMA_SYNC_FORCPU);
16987c478bd9Sstevel@tonic-gate 			if (err != DDI_SUCCESS) {
16997c478bd9Sstevel@tonic-gate 				uvp->upd_status = IXL1394_EINTERNAL_ERROR;
17007c478bd9Sstevel@tonic-gate 
17017c478bd9Sstevel@tonic-gate 				return (DDI_FAILURE);
17027c478bd9Sstevel@tonic-gate 			}
17037c478bd9Sstevel@tonic-gate 
17047c478bd9Sstevel@tonic-gate 			/*
17057c478bd9Sstevel@tonic-gate 			 * this preserves interrupt enable bits, et al
17067c478bd9Sstevel@tonic-gate 			 * in each desc block hdr
17077c478bd9Sstevel@tonic-gate 			 */
17087c478bd9Sstevel@tonic-gate 			desc_hdr = ddi_get32(acc_hdl, &hcidescp->hdr);
17097c478bd9Sstevel@tonic-gate 			desc_hdr = (desc_hdr & ~DESC_HDR_REQCOUNT_MASK) |
17107c478bd9Sstevel@tonic-gate 			    uvp->hcihdr;
17117c478bd9Sstevel@tonic-gate 			ddi_put32(acc_hdl, &hcidescp->hdr, desc_hdr);
17127c478bd9Sstevel@tonic-gate 
17137c478bd9Sstevel@tonic-gate 			/* Sync descriptor for device (desc was modified) */
17147c478bd9Sstevel@tonic-gate 			err = ddi_dma_sync(dma_hdl, (off_t)hcidescp,
17157c478bd9Sstevel@tonic-gate 			    sizeof (hci1394_desc_imm_t), DDI_DMA_SYNC_FORDEV);
17167c478bd9Sstevel@tonic-gate 			if (err != DDI_SUCCESS) {
17177c478bd9Sstevel@tonic-gate 				uvp->upd_status = IXL1394_EINTERNAL_ERROR;
17187c478bd9Sstevel@tonic-gate 
17197c478bd9Sstevel@tonic-gate 				return (DDI_FAILURE);
17207c478bd9Sstevel@tonic-gate 			}
17217c478bd9Sstevel@tonic-gate 		}
17227c478bd9Sstevel@tonic-gate 
17237c478bd9Sstevel@tonic-gate 		/*
17247c478bd9Sstevel@tonic-gate 		 * set old ixl recv buf sizes and buffers from
17257c478bd9Sstevel@tonic-gate 		 * new ixl recv pkt cmd
17267c478bd9Sstevel@tonic-gate 		 */
17277c478bd9Sstevel@tonic-gate 		old_xfer_buf_ixlp->pkt_size = new_xfer_buf_ixlp->pkt_size;
17287c478bd9Sstevel@tonic-gate 		old_xfer_buf_ixlp->size = new_xfer_buf_ixlp->size;
17297c478bd9Sstevel@tonic-gate 		old_xfer_buf_ixlp->ixl_buf.ixldmac_addr =
17307c478bd9Sstevel@tonic-gate 		    new_xfer_buf_ixlp->ixl_buf.ixldmac_addr;
17317c478bd9Sstevel@tonic-gate 		old_xfer_buf_ixlp->mem_bufp = new_xfer_buf_ixlp->mem_bufp;
17327c478bd9Sstevel@tonic-gate 		break;
17337c478bd9Sstevel@tonic-gate 	}
17347c478bd9Sstevel@tonic-gate 	default:
17357c478bd9Sstevel@tonic-gate 		/* ixl command being updated must be one of above, else error */
17367c478bd9Sstevel@tonic-gate 		uvp->upd_status = IXL1394_EINTERNAL_ERROR;
17377c478bd9Sstevel@tonic-gate 
17387c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
17397c478bd9Sstevel@tonic-gate 	}
17407c478bd9Sstevel@tonic-gate 
17417c478bd9Sstevel@tonic-gate 	/* hit the WAKE bit in the context control register */
17427c478bd9Sstevel@tonic-gate 	if (ctxtp->ctxt_flags & HCI1394_ISO_CTXT_RECV) {
17437c478bd9Sstevel@tonic-gate 		HCI1394_IRCTXT_CTRL_SET(uvp->soft_statep, ctxtp->ctxt_index,
17447c478bd9Sstevel@tonic-gate 		    0, 0, 0, 0, 0, 1 /* wake */);
17457c478bd9Sstevel@tonic-gate 	} else {
17467c478bd9Sstevel@tonic-gate 		HCI1394_ITCTXT_CTRL_SET(uvp->soft_statep, ctxtp->ctxt_index,
17477c478bd9Sstevel@tonic-gate 		    0, 0, 0, 1 /* wake */);
17487c478bd9Sstevel@tonic-gate 	}
17497c478bd9Sstevel@tonic-gate 
17507c478bd9Sstevel@tonic-gate 	/* perform update completed successfully */
17517c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
17527c478bd9Sstevel@tonic-gate }
17537c478bd9Sstevel@tonic-gate 
17547c478bd9Sstevel@tonic-gate /*
17557c478bd9Sstevel@tonic-gate  * hci1394_ixl_update_evaluate()
17567c478bd9Sstevel@tonic-gate  *    Evaluate where the hardware is in running through the DMA descriptor
17577c478bd9Sstevel@tonic-gate  *    blocks.
17587c478bd9Sstevel@tonic-gate  */
17597c478bd9Sstevel@tonic-gate static int
hci1394_ixl_update_evaluate(hci1394_ixl_update_vars_t * uvp)17607c478bd9Sstevel@tonic-gate hci1394_ixl_update_evaluate(hci1394_ixl_update_vars_t *uvp)
17617c478bd9Sstevel@tonic-gate {
17627c478bd9Sstevel@tonic-gate 	hci1394_iso_ctxt_t	*ctxtp;
17637c478bd9Sstevel@tonic-gate 	ixl1394_command_t	*ixlp;
17647c478bd9Sstevel@tonic-gate 	int			ixldepth;
17657c478bd9Sstevel@tonic-gate 	int			ii;
17667c478bd9Sstevel@tonic-gate 
17677c478bd9Sstevel@tonic-gate 	ctxtp = uvp->ctxtp;
17687c478bd9Sstevel@tonic-gate 
17697c478bd9Sstevel@tonic-gate 	ixlp = NULL;
17707c478bd9Sstevel@tonic-gate 	ixldepth = 0xFFFFFFFF;
17717c478bd9Sstevel@tonic-gate 
17727c478bd9Sstevel@tonic-gate 	/*
17737c478bd9Sstevel@tonic-gate 	 * repeat until IXL execution status evaluation function returns error
17747c478bd9Sstevel@tonic-gate 	 * or until pointer to currently executing IXL command and its depth
17757c478bd9Sstevel@tonic-gate 	 * stablize
17767c478bd9Sstevel@tonic-gate 	 */
17777c478bd9Sstevel@tonic-gate 	while ((ixlp != ctxtp->ixl_execp) ||
17787c478bd9Sstevel@tonic-gate 	    (ixldepth != ctxtp->ixl_exec_depth)) {
17797c478bd9Sstevel@tonic-gate 
17807c478bd9Sstevel@tonic-gate 		ixlp = ctxtp->ixl_execp;
17817c478bd9Sstevel@tonic-gate 		ixldepth = ctxtp->ixl_exec_depth;
17827c478bd9Sstevel@tonic-gate 
17837c478bd9Sstevel@tonic-gate 		/*
17847c478bd9Sstevel@tonic-gate 		 * call IXL execution status evaluation (ixl_dma_sync)
17857c478bd9Sstevel@tonic-gate 		 * function returning if error (HCI1394_IXL_INTR_DMALOST is
17867c478bd9Sstevel@tonic-gate 		 * only error condition).
17877c478bd9Sstevel@tonic-gate 		 *
17887c478bd9Sstevel@tonic-gate 		 * Note: interrupt processing function can only return one of
17897c478bd9Sstevel@tonic-gate 		 * the following statuses here:
17907c478bd9Sstevel@tonic-gate 		 *    HCI1394_IXL_INTR_NOERROR, HCI1394_IXL_INTR_DMASTOP,
17917c478bd9Sstevel@tonic-gate 		 *    HCI1394_IXL_INTR_DMALOST
17927c478bd9Sstevel@tonic-gate 		 *
17937c478bd9Sstevel@tonic-gate 		 * it can not return the following status here:
17947c478bd9Sstevel@tonic-gate 		 *    HCI1394_IXL_INTR_NOADV
17957c478bd9Sstevel@tonic-gate 		 *
17967c478bd9Sstevel@tonic-gate 		 * Don't need to grab the lock here... for the same reason
17977c478bd9Sstevel@tonic-gate 		 * explained in hci1394_ixl_update_endup() above.
17987c478bd9Sstevel@tonic-gate 		 */
17997c478bd9Sstevel@tonic-gate 		ctxtp->intr_flags &= ~HCI1394_ISO_CTXT_INTRSET;
18007c478bd9Sstevel@tonic-gate 		if (hci1394_ixl_dma_sync(uvp->soft_statep, ctxtp) ==
18017c478bd9Sstevel@tonic-gate 		    HCI1394_IXL_INTR_DMALOST) {
18027c478bd9Sstevel@tonic-gate 
18037c478bd9Sstevel@tonic-gate 			/* return post-perform update failed status */
18047c478bd9Sstevel@tonic-gate 			uvp->upd_status = IXL1394_EPOST_UPD_DMALOST;
18057c478bd9Sstevel@tonic-gate 
18067c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
18077c478bd9Sstevel@tonic-gate 		}
18087c478bd9Sstevel@tonic-gate 	}
18097c478bd9Sstevel@tonic-gate 
18107c478bd9Sstevel@tonic-gate 	/*
18117c478bd9Sstevel@tonic-gate 	 * if the currently executing IXL command is one of the IXL_MAX_LOCN
18127c478bd9Sstevel@tonic-gate 	 * locations saved before update was performed, return update
18137c478bd9Sstevel@tonic-gate 	 * successful status.
18147c478bd9Sstevel@tonic-gate 	 */
18157c478bd9Sstevel@tonic-gate 	for (ii = 0; ii < IXL_MAX_LOCN; ii++) {
18167c478bd9Sstevel@tonic-gate 		if ((uvp->locn_info[ii].ixlp == ixlp) &&
18177c478bd9Sstevel@tonic-gate 		    (uvp->locn_info[ii].ixldepth == ixldepth)) {
18187c478bd9Sstevel@tonic-gate 
18197c478bd9Sstevel@tonic-gate 			return (DDI_SUCCESS);
18207c478bd9Sstevel@tonic-gate 		}
18217c478bd9Sstevel@tonic-gate 	}
18227c478bd9Sstevel@tonic-gate 
18237c478bd9Sstevel@tonic-gate 	/*
18247c478bd9Sstevel@tonic-gate 	 * else return post-perform update failed status.
18257c478bd9Sstevel@tonic-gate 	 * note: later can make more sophisticated evaluations about where
18267c478bd9Sstevel@tonic-gate 	 * execution processing went, and if update has really failed.
18277c478bd9Sstevel@tonic-gate 	 */
18287c478bd9Sstevel@tonic-gate 	uvp->upd_status = IXL1394_EPOST_UPD_DMALOST;
18297c478bd9Sstevel@tonic-gate 
18307c478bd9Sstevel@tonic-gate 	return (DDI_FAILURE);
18317c478bd9Sstevel@tonic-gate }
18327c478bd9Sstevel@tonic-gate 
18337c478bd9Sstevel@tonic-gate /*
18347c478bd9Sstevel@tonic-gate  * hci1394_ixl_update_analysis()
18357c478bd9Sstevel@tonic-gate  *    Determine if the hardware is within the range we expected it to be.
18367c478bd9Sstevel@tonic-gate  *    If so the update succeeded.
18377c478bd9Sstevel@tonic-gate  */
18387c478bd9Sstevel@tonic-gate static int
hci1394_ixl_update_analysis(hci1394_ixl_update_vars_t * uvp)18397c478bd9Sstevel@tonic-gate hci1394_ixl_update_analysis(hci1394_ixl_update_vars_t *uvp)
18407c478bd9Sstevel@tonic-gate {
18417c478bd9Sstevel@tonic-gate 	hci1394_iso_ctxt_t	*ctxtp;
18427c478bd9Sstevel@tonic-gate 	ixl1394_command_t	*ixlp;
18437c478bd9Sstevel@tonic-gate 	int			ixldepth;
18447c478bd9Sstevel@tonic-gate 	int			ii;
18457c478bd9Sstevel@tonic-gate 	int			status;
18467c478bd9Sstevel@tonic-gate 
18477c478bd9Sstevel@tonic-gate 	ctxtp = uvp->ctxtp;
18487c478bd9Sstevel@tonic-gate 
18497c478bd9Sstevel@tonic-gate 	ixlp = NULL;
18507c478bd9Sstevel@tonic-gate 	ixldepth = 0xFFFFFFFF;
18517c478bd9Sstevel@tonic-gate 
18527c478bd9Sstevel@tonic-gate 	/*
18537c478bd9Sstevel@tonic-gate 	 * repeat until ixl execution status evaluation function returns error
18547c478bd9Sstevel@tonic-gate 	 * or until pointer to currently executing ixl command and its depth
18557c478bd9Sstevel@tonic-gate 	 * stablize.
18567c478bd9Sstevel@tonic-gate 	 */
18577c478bd9Sstevel@tonic-gate 	while ((ixlp != ctxtp->ixl_execp) ||
18587c478bd9Sstevel@tonic-gate 	    (ixldepth != ctxtp->ixl_exec_depth)) {
18597c478bd9Sstevel@tonic-gate 
18607c478bd9Sstevel@tonic-gate 		ixlp = ctxtp->ixl_execp;
18617c478bd9Sstevel@tonic-gate 		ixldepth = ctxtp->ixl_exec_depth;
18627c478bd9Sstevel@tonic-gate 
18637c478bd9Sstevel@tonic-gate 		/*
18647c478bd9Sstevel@tonic-gate 		 * call ixl execution status evaluation (interrupt processing).
18657c478bd9Sstevel@tonic-gate 		 * set IXL1394_EIDU_PRE_UPD_DMALOST if status INTR_DMALOST and
18667c478bd9Sstevel@tonic-gate 		 * return.
18677c478bd9Sstevel@tonic-gate 		 *
18687c478bd9Sstevel@tonic-gate 		 * Note: interrupt processing function can only return one of
18697c478bd9Sstevel@tonic-gate 		 * the following statuses here:
18707c478bd9Sstevel@tonic-gate 		 *    HCI1394_IXL_INTR_NOERROR, HCI1394_IXL_INTR_DMASTOP or
18717c478bd9Sstevel@tonic-gate 		 *    HCI1394_IXL_INTR_DMALOST
18727c478bd9Sstevel@tonic-gate 		 *
18737c478bd9Sstevel@tonic-gate 		 * it can not return the following status here:
18747c478bd9Sstevel@tonic-gate 		 *    HCI1394_IXL_INTR_NOADV
18757c478bd9Sstevel@tonic-gate 		 *
18767c478bd9Sstevel@tonic-gate 		 * Don't need to grab the lock here... for the same reason
18777c478bd9Sstevel@tonic-gate 		 * explained in hci1394_ixl_update_endup() above.
18787c478bd9Sstevel@tonic-gate 		 */
18797c478bd9Sstevel@tonic-gate 		ctxtp->intr_flags &= ~HCI1394_ISO_CTXT_INTRSET;
18807c478bd9Sstevel@tonic-gate 
18817c478bd9Sstevel@tonic-gate 		status = hci1394_ixl_dma_sync(uvp->soft_statep, ctxtp);
18827c478bd9Sstevel@tonic-gate 		if (status == HCI1394_IXL_INTR_DMALOST) {
18837c478bd9Sstevel@tonic-gate 			/*
18847c478bd9Sstevel@tonic-gate 			 * set pre-update dma processing lost status and
18857c478bd9Sstevel@tonic-gate 			 * return error
18867c478bd9Sstevel@tonic-gate 			 */
18877c478bd9Sstevel@tonic-gate 			uvp->upd_status = IXL1394_EPRE_UPD_DMALOST;
18887c478bd9Sstevel@tonic-gate 
18897c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
18907c478bd9Sstevel@tonic-gate 		}
18917c478bd9Sstevel@tonic-gate 	}
18927c478bd9Sstevel@tonic-gate 
18937c478bd9Sstevel@tonic-gate 	/*
18947c478bd9Sstevel@tonic-gate 	 * save locations of currently executing ixl command and the
18957c478bd9Sstevel@tonic-gate 	 * 3 following it.
18967c478bd9Sstevel@tonic-gate 	 */
18977c478bd9Sstevel@tonic-gate 	hci1394_ixl_update_set_locn_info(uvp);
18987c478bd9Sstevel@tonic-gate 
18997c478bd9Sstevel@tonic-gate 	/*
19007c478bd9Sstevel@tonic-gate 	 * if xfer_ixl_cmd associated with the IXL_command being updated is one
19017c478bd9Sstevel@tonic-gate 	 * of the saved (currently executing) IXL commands, risk is too great to
19027c478bd9Sstevel@tonic-gate 	 * perform update now, set IXL1394_ERISK_PROHIBITS_UPD status and
19037c478bd9Sstevel@tonic-gate 	 * return error.
19047c478bd9Sstevel@tonic-gate 	 *
19057c478bd9Sstevel@tonic-gate 	 * Note: later can implement more sophisticated risk override
19067c478bd9Sstevel@tonic-gate 	 * evaluations and processing.
19077c478bd9Sstevel@tonic-gate 	 */
19087c478bd9Sstevel@tonic-gate 	for (ii = 0; ii < IXL_MAX_LOCN; ii++) {
19097c478bd9Sstevel@tonic-gate 
19107c478bd9Sstevel@tonic-gate 		if ((uvp->locn_info[ii].ixlp == uvp->ixlxferp) &&
19117c478bd9Sstevel@tonic-gate 		    (uvp->locn_info[ii].ixldepth >= uvp->ixldepth) &&
19127c478bd9Sstevel@tonic-gate 		    (uvp->locn_info[ii].ixldepth <
191346776310SToomas Soome 		    (uvp->ixldepth + uvp->ixlcount))) {
19147c478bd9Sstevel@tonic-gate 
19157c478bd9Sstevel@tonic-gate 			uvp->upd_status = IXL1394_ERISK_PROHIBITS_UPD;
19167c478bd9Sstevel@tonic-gate 
19177c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
19187c478bd9Sstevel@tonic-gate 		}
19197c478bd9Sstevel@tonic-gate 	}
19207c478bd9Sstevel@tonic-gate 
19217c478bd9Sstevel@tonic-gate 	/* is save for update to be performed, return ok status */
19227c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
19237c478bd9Sstevel@tonic-gate }
19247c478bd9Sstevel@tonic-gate 
19257c478bd9Sstevel@tonic-gate /*
19267c478bd9Sstevel@tonic-gate  * hci1394_ixl_update_set_locn_info()
19277c478bd9Sstevel@tonic-gate  *    set up the local list of the IXL_MAX_LOCN next commandPtr locations we
19287c478bd9Sstevel@tonic-gate  *    expect the hardware to get to in the next 125 microseconds.
19297c478bd9Sstevel@tonic-gate  */
19307c478bd9Sstevel@tonic-gate static void
hci1394_ixl_update_set_locn_info(hci1394_ixl_update_vars_t * uvp)19317c478bd9Sstevel@tonic-gate hci1394_ixl_update_set_locn_info(hci1394_ixl_update_vars_t *uvp)
19327c478bd9Sstevel@tonic-gate {
19337c478bd9Sstevel@tonic-gate 	hci1394_iso_ctxt_t	*ctxtp;
19347c478bd9Sstevel@tonic-gate 	ixl1394_command_t	*ixlp;
19357c478bd9Sstevel@tonic-gate 	int			ixldepth;
19367c478bd9Sstevel@tonic-gate 	int			ii;
19377c478bd9Sstevel@tonic-gate 
19387c478bd9Sstevel@tonic-gate 	/*
19397c478bd9Sstevel@tonic-gate 	 * find next xfer start ixl command, starting with current ixl command
19407c478bd9Sstevel@tonic-gate 	 * where execution last left off
19417c478bd9Sstevel@tonic-gate 	 */
19427c478bd9Sstevel@tonic-gate 	ctxtp = uvp->ctxtp;
19437c478bd9Sstevel@tonic-gate 
19447c478bd9Sstevel@tonic-gate 	ixldepth = ctxtp->ixl_exec_depth;
19457c478bd9Sstevel@tonic-gate 	(void) hci1394_ixl_find_next_exec_xfer(ctxtp->ixl_execp, NULL, &ixlp);
19467c478bd9Sstevel@tonic-gate 
19477c478bd9Sstevel@tonic-gate 	/*
19487c478bd9Sstevel@tonic-gate 	 * if the current IXL command wasn't a xfer start command, then reset
19497c478bd9Sstevel@tonic-gate 	 * the depth to 0 for xfer command found
19507c478bd9Sstevel@tonic-gate 	 */
19517c478bd9Sstevel@tonic-gate 	if (ixlp != ctxtp->ixl_execp)
19527c478bd9Sstevel@tonic-gate 		ixldepth = 0;
19537c478bd9Sstevel@tonic-gate 
19547c478bd9Sstevel@tonic-gate 	/*
19557c478bd9Sstevel@tonic-gate 	 * save xfer start IXL command & its depth and also save location and
19567c478bd9Sstevel@tonic-gate 	 * depth of the next IXL_MAX_LOCN-1 xfer start IXL commands following
19577c478bd9Sstevel@tonic-gate 	 * it (if any)
19587c478bd9Sstevel@tonic-gate 	 */
19597c478bd9Sstevel@tonic-gate 	for (ii = 0; ii < IXL_MAX_LOCN; ii++) {
19607c478bd9Sstevel@tonic-gate 		uvp->locn_info[ii].ixlp = ixlp;
19617c478bd9Sstevel@tonic-gate 		uvp->locn_info[ii].ixldepth = ixldepth;
19627c478bd9Sstevel@tonic-gate 
19637c478bd9Sstevel@tonic-gate 		if (ixlp) {
19647c478bd9Sstevel@tonic-gate 			/*
19657c478bd9Sstevel@tonic-gate 			 * if more dma commands generated by this xfer command
19667c478bd9Sstevel@tonic-gate 			 * still follow, use them. else, find the next xfer
19677c478bd9Sstevel@tonic-gate 			 * start IXL command and set its depth to 0.
19687c478bd9Sstevel@tonic-gate 			 */
19697c478bd9Sstevel@tonic-gate 			if (++ixldepth >= ((hci1394_xfer_ctl_t *)
19707c478bd9Sstevel@tonic-gate 			    ixlp->compiler_privatep)->cnt) {
19717c478bd9Sstevel@tonic-gate 
19727c478bd9Sstevel@tonic-gate 				(void) hci1394_ixl_find_next_exec_xfer(
19737c478bd9Sstevel@tonic-gate 				    ixlp->next_ixlp, NULL, &ixlp);
19747c478bd9Sstevel@tonic-gate 				ixldepth = 0;
19757c478bd9Sstevel@tonic-gate 			}
19767c478bd9Sstevel@tonic-gate 		}
19777c478bd9Sstevel@tonic-gate 	}
19787c478bd9Sstevel@tonic-gate }
1979