17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 1999-2002 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*
287c478bd9Sstevel@tonic-gate  * hci1394_ixl_misc.c
297c478bd9Sstevel@tonic-gate  *    Isochronous IXL miscellaneous routines.
307c478bd9Sstevel@tonic-gate  *    Contains common routines used by the ixl compiler, interrupt handler and
317c478bd9Sstevel@tonic-gate  *    dynamic update.
327c478bd9Sstevel@tonic-gate  */
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
357c478bd9Sstevel@tonic-gate #include <sys/types.h>
367c478bd9Sstevel@tonic-gate #include <sys/conf.h>
377c478bd9Sstevel@tonic-gate #include <sys/1394/h1394.h>
387c478bd9Sstevel@tonic-gate #include <sys/1394/ixl1394.h>
397c478bd9Sstevel@tonic-gate #include <sys/1394/adapters/hci1394.h>
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate /* local routines */
437c478bd9Sstevel@tonic-gate static void hci1394_delete_dma_desc_mem(hci1394_state_t *soft_statep,
447c478bd9Sstevel@tonic-gate     hci1394_idma_desc_mem_t *);
457c478bd9Sstevel@tonic-gate static void hci1394_delete_xfer_ctl(hci1394_xfer_ctl_t *);
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate /*
497c478bd9Sstevel@tonic-gate  * hci1394_ixl_set_start()
507c478bd9Sstevel@tonic-gate  *    Set up the context structure with the first ixl command to process
517c478bd9Sstevel@tonic-gate  *    and the first hci descriptor to execute.
527c478bd9Sstevel@tonic-gate  *
537c478bd9Sstevel@tonic-gate  *    This function assumes the current context is stopped!
547c478bd9Sstevel@tonic-gate  *
557c478bd9Sstevel@tonic-gate  *    If ixlstp IS NOT null AND is not the first compiled ixl command and
567c478bd9Sstevel@tonic-gate  *    is not an ixl label command, returns an error.
577c478bd9Sstevel@tonic-gate  *    If ixlstp IS null, uses the first compiled ixl command (ixl_firstp)
587c478bd9Sstevel@tonic-gate  *    in place of ixlstp.
597c478bd9Sstevel@tonic-gate  *
607c478bd9Sstevel@tonic-gate  *    If no executeable xfer found along exec path from ixlstp, returns error.
617c478bd9Sstevel@tonic-gate  */
627c478bd9Sstevel@tonic-gate int
hci1394_ixl_set_start(hci1394_iso_ctxt_t * ctxtp,ixl1394_command_t * ixlstp)637c478bd9Sstevel@tonic-gate hci1394_ixl_set_start(hci1394_iso_ctxt_t *ctxtp, ixl1394_command_t *ixlstp)
647c478bd9Sstevel@tonic-gate {
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate 	ixl1394_command_t  *ixl_exec_startp;
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate 	/* if ixl start command is null, use first compiled ixl command */
697c478bd9Sstevel@tonic-gate 	if (ixlstp == NULL) {
707c478bd9Sstevel@tonic-gate 		ixlstp = ctxtp->ixl_firstp;
717c478bd9Sstevel@tonic-gate 	}
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate 	/*
747c478bd9Sstevel@tonic-gate 	 * if ixl start command is not first ixl compiled and is not a label,
757c478bd9Sstevel@tonic-gate 	 * error
767c478bd9Sstevel@tonic-gate 	 */
777c478bd9Sstevel@tonic-gate 	if ((ixlstp != ctxtp->ixl_firstp) && (ixlstp->ixl_opcode !=
787c478bd9Sstevel@tonic-gate 	    IXL1394_OP_LABEL)) {
797c478bd9Sstevel@tonic-gate 		return (-1);
807c478bd9Sstevel@tonic-gate 	}
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate 	/* follow exec path to find first ixl command that's an xfer command */
837c478bd9Sstevel@tonic-gate 	(void) hci1394_ixl_find_next_exec_xfer(ixlstp, NULL, &ixl_exec_startp);
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate 	/*
867c478bd9Sstevel@tonic-gate 	 * if there was one, then in it's compiler private, its
877c478bd9Sstevel@tonic-gate 	 * hci1394_xfer_ctl structure has the appropriate bound address
887c478bd9Sstevel@tonic-gate 	 */
897c478bd9Sstevel@tonic-gate 	if (ixl_exec_startp != NULL) {
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate 		/* set up for start of context and return done */
927c478bd9Sstevel@tonic-gate 		ctxtp->dma_mem_execp = (uint32_t)((hci1394_xfer_ctl_t *)
937c478bd9Sstevel@tonic-gate 			ixl_exec_startp->compiler_privatep)->dma[0].dma_bound;
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate 		ctxtp->dma_last_time = 0;
967c478bd9Sstevel@tonic-gate 		ctxtp->ixl_exec_depth = 0;
977c478bd9Sstevel@tonic-gate 		ctxtp->ixl_execp = ixlstp;
987c478bd9Sstevel@tonic-gate 		ctxtp->rem_noadv_intrs = ctxtp->max_noadv_intrs;
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate 		return (0);
1017c478bd9Sstevel@tonic-gate 	}
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate 	/* else no executeable xfer command found, return error */
1047c478bd9Sstevel@tonic-gate 	return (1);
1057c478bd9Sstevel@tonic-gate }
1067c478bd9Sstevel@tonic-gate #ifdef _KERNEL
1077c478bd9Sstevel@tonic-gate /*
1087c478bd9Sstevel@tonic-gate  * hci1394_ixl_reset_status()
1097c478bd9Sstevel@tonic-gate  * Reset all statuses in all hci descriptor blocks associated with the
1107c478bd9Sstevel@tonic-gate  * current linked list of compiled ixl commands.
1117c478bd9Sstevel@tonic-gate  *
1127c478bd9Sstevel@tonic-gate  * This function assumes the current context is stopped!
1137c478bd9Sstevel@tonic-gate  */
1147c478bd9Sstevel@tonic-gate void
hci1394_ixl_reset_status(hci1394_iso_ctxt_t * ctxtp)1157c478bd9Sstevel@tonic-gate hci1394_ixl_reset_status(hci1394_iso_ctxt_t *ctxtp)
1167c478bd9Sstevel@tonic-gate {
1177c478bd9Sstevel@tonic-gate 	ixl1394_command_t	*ixlcur;
1187c478bd9Sstevel@tonic-gate 	ixl1394_command_t	*ixlnext;
1197c478bd9Sstevel@tonic-gate 	hci1394_xfer_ctl_t	*xferctlp;
1207c478bd9Sstevel@tonic-gate 	uint_t			ixldepth;
1217c478bd9Sstevel@tonic-gate 	uint16_t		timestamp;
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate 	ixlnext = ctxtp->ixl_firstp;
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate 	/*
1267c478bd9Sstevel@tonic-gate 	 * Scan for next ixl xfer start command along ixl link path.
1277c478bd9Sstevel@tonic-gate 	 * Once xfer command found, clear its hci descriptor block's
1287c478bd9Sstevel@tonic-gate 	 * status. If is composite ixl xfer command, clear statuses
1297c478bd9Sstevel@tonic-gate 	 * in each of its hci descriptor blocks.
1307c478bd9Sstevel@tonic-gate 	 */
1317c478bd9Sstevel@tonic-gate 	while (ixlnext != NULL) {
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate 		/* set current and next ixl command */
1347c478bd9Sstevel@tonic-gate 		ixlcur = ixlnext;
1357c478bd9Sstevel@tonic-gate 		ixlnext = ixlcur->next_ixlp;
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate 		/* skip to examine next if this is not xfer start ixl command */
1387c478bd9Sstevel@tonic-gate 		if (((ixlcur->ixl_opcode & IXL1394_OPF_ISXFER) == 0) ||
1397c478bd9Sstevel@tonic-gate 		    ((ixlcur->ixl_opcode & IXL1394_OPTY_MASK) == 0)) {
1407c478bd9Sstevel@tonic-gate 			continue;
1417c478bd9Sstevel@tonic-gate 		}
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate 		/* get control struct for this xfer start ixl command */
1447c478bd9Sstevel@tonic-gate 		xferctlp = (hci1394_xfer_ctl_t *)ixlcur->compiler_privatep;
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate 		/* clear status in each hci descriptor block for this ixl cmd */
1477c478bd9Sstevel@tonic-gate 		ixldepth = 0;
1487c478bd9Sstevel@tonic-gate 		while (ixldepth < xferctlp->cnt) {
1497c478bd9Sstevel@tonic-gate 			(void) hci1394_ixl_check_status(
1507c478bd9Sstevel@tonic-gate 			    &xferctlp->dma[ixldepth], ixlcur->ixl_opcode,
1517c478bd9Sstevel@tonic-gate 			    &timestamp, B_TRUE);
1527c478bd9Sstevel@tonic-gate 			ixldepth++;
1537c478bd9Sstevel@tonic-gate 		}
1547c478bd9Sstevel@tonic-gate 	}
1557c478bd9Sstevel@tonic-gate }
1567c478bd9Sstevel@tonic-gate #endif
1577c478bd9Sstevel@tonic-gate /*
1587c478bd9Sstevel@tonic-gate  * hci1394_ixl_find_next_exec_xfer()
1597c478bd9Sstevel@tonic-gate  *    Follows execution path of ixl linked list until finds next xfer start IXL
1607c478bd9Sstevel@tonic-gate  *    command, including the current IXL command or finds end of IXL linked
1617c478bd9Sstevel@tonic-gate  *    list. Counts callback commands found along the way. (Previously, counted
1627c478bd9Sstevel@tonic-gate  *    store timestamp commands, as well.)
1637c478bd9Sstevel@tonic-gate  *
1647c478bd9Sstevel@tonic-gate  *    To detect an infinite loop of label<->jump without an intervening xfer,
1657c478bd9Sstevel@tonic-gate  *    a tolerance level of HCI1394_IXL_MAX_SEQ_JUMPS is used.  Once this
1667c478bd9Sstevel@tonic-gate  *    number of jumps is traversed, the IXL prog is assumed to have a loop.
1677c478bd9Sstevel@tonic-gate  *
1687c478bd9Sstevel@tonic-gate  *    Returns DDI_SUCCESS or DDI_FAILURE.  DDI_FAILURE, indicates an infinite
1697c478bd9Sstevel@tonic-gate  *    loop of labels & jumps was detected without any intervening xfers.
1707c478bd9Sstevel@tonic-gate  *    DDI_SUCCESS indicates the next_exec_ixlpp contains the next xfer ixlp
1717c478bd9Sstevel@tonic-gate  *    address, or NULL indicating the end of the list was reached.  Note that
1727c478bd9Sstevel@tonic-gate  *    DDI_FAILURE can only be returned during the IXL compilation phase, and
1737c478bd9Sstevel@tonic-gate  *    not during ixl_update processing.
1747c478bd9Sstevel@tonic-gate  */
1757c478bd9Sstevel@tonic-gate int
hci1394_ixl_find_next_exec_xfer(ixl1394_command_t * ixl_start,uint_t * callback_cnt,ixl1394_command_t ** next_exec_ixlpp)1767c478bd9Sstevel@tonic-gate hci1394_ixl_find_next_exec_xfer(ixl1394_command_t *ixl_start,
1777c478bd9Sstevel@tonic-gate     uint_t *callback_cnt, ixl1394_command_t **next_exec_ixlpp)
1787c478bd9Sstevel@tonic-gate {
1797c478bd9Sstevel@tonic-gate 	uint16_t ixlopcode;
1807c478bd9Sstevel@tonic-gate 	boolean_t xferfound;
1817c478bd9Sstevel@tonic-gate 	ixl1394_command_t *ixlp;
1827c478bd9Sstevel@tonic-gate 	int ii;
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate 	ixlp = ixl_start;
1857c478bd9Sstevel@tonic-gate 	xferfound = B_FALSE;
1867c478bd9Sstevel@tonic-gate 	ii = HCI1394_IXL_MAX_SEQ_JUMPS;
1877c478bd9Sstevel@tonic-gate 	if (callback_cnt != NULL) {
1887c478bd9Sstevel@tonic-gate 		*callback_cnt = 0;
1897c478bd9Sstevel@tonic-gate 	}
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate 	/* continue until xfer start ixl cmd or end of ixl list found */
1927c478bd9Sstevel@tonic-gate 	while ((xferfound == B_FALSE) && (ixlp != NULL) && (ii > 0)) {
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 		/* get current ixl cmd opcode without update flag */
1957c478bd9Sstevel@tonic-gate 		ixlopcode = ixlp->ixl_opcode & ~IXL1394_OPF_UPDATE;
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate 		/* if found an xfer start ixl command, are done */
1987c478bd9Sstevel@tonic-gate 		if (((ixlopcode & IXL1394_OPF_ISXFER) != 0) &&
1997c478bd9Sstevel@tonic-gate 		    ((ixlopcode & IXL1394_OPTY_MASK) != 0)) {
2007c478bd9Sstevel@tonic-gate 			xferfound = B_TRUE;
2017c478bd9Sstevel@tonic-gate 			continue;
2027c478bd9Sstevel@tonic-gate 		}
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate 		/* if found jump command, adjust to follow its path */
2057c478bd9Sstevel@tonic-gate 		if (ixlopcode == IXL1394_OP_JUMP) {
2067c478bd9Sstevel@tonic-gate 			ixlp = (ixl1394_command_t *)
2077c478bd9Sstevel@tonic-gate 			    ((ixl1394_jump_t *)ixlp)->label;
2087c478bd9Sstevel@tonic-gate 			ii--;
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate 			/* if exceeded tolerance, give up */
2117c478bd9Sstevel@tonic-gate 			if (ii == 0) {
2127c478bd9Sstevel@tonic-gate 				return (DDI_FAILURE);
2137c478bd9Sstevel@tonic-gate 			}
2147c478bd9Sstevel@tonic-gate 			continue;
2157c478bd9Sstevel@tonic-gate 		}
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate 		/* if current ixl command is a callback, count it */
2187c478bd9Sstevel@tonic-gate 		if ((ixlopcode == IXL1394_OP_CALLBACK) &&
2197c478bd9Sstevel@tonic-gate 		    (callback_cnt != NULL)) {
2207c478bd9Sstevel@tonic-gate 			(*callback_cnt)++;
2217c478bd9Sstevel@tonic-gate 		}
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate 		/* advance to next linked ixl command */
2247c478bd9Sstevel@tonic-gate 		ixlp = ixlp->next_ixlp;
2257c478bd9Sstevel@tonic-gate 	}
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 	/* return ixl xfer start command found, if any */
2287c478bd9Sstevel@tonic-gate 	*next_exec_ixlpp = ixlp;
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
2317c478bd9Sstevel@tonic-gate }
2327c478bd9Sstevel@tonic-gate #ifdef _KERNEL
2337c478bd9Sstevel@tonic-gate /*
2347c478bd9Sstevel@tonic-gate  * hci1394_ixl_check_status()
2357c478bd9Sstevel@tonic-gate  *    Read the descriptor status and hdrs, clear as appropriate.
2367c478bd9Sstevel@tonic-gate  */
2377c478bd9Sstevel@tonic-gate int32_t
hci1394_ixl_check_status(hci1394_xfer_ctl_dma_t * dma,uint16_t ixlopcode,uint16_t * timestamp,boolean_t do_status_reset)2387c478bd9Sstevel@tonic-gate hci1394_ixl_check_status(hci1394_xfer_ctl_dma_t *dma, uint16_t ixlopcode,
2397c478bd9Sstevel@tonic-gate     uint16_t *timestamp, boolean_t do_status_reset)
2407c478bd9Sstevel@tonic-gate {
2417c478bd9Sstevel@tonic-gate 	uint16_t	bufsiz;
2427c478bd9Sstevel@tonic-gate 	uint16_t	hcicnt;
2437c478bd9Sstevel@tonic-gate 	uint16_t	hcirecvcnt;
2447c478bd9Sstevel@tonic-gate 	hci1394_desc_t	*hcidescp;
2457c478bd9Sstevel@tonic-gate 	off_t		hcidesc_off;
2467c478bd9Sstevel@tonic-gate 	ddi_acc_handle_t	acc_hdl;
2477c478bd9Sstevel@tonic-gate 	ddi_dma_handle_t	dma_hdl;
2487c478bd9Sstevel@tonic-gate 	uint32_t		desc_status;
2497c478bd9Sstevel@tonic-gate 	uint32_t		desc_hdr;
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate 	/* last dma descriptor in descriptor block from dma structure */
2527c478bd9Sstevel@tonic-gate 	hcidescp = (hci1394_desc_t *)(dma->dma_descp);
2537c478bd9Sstevel@tonic-gate 	hcidesc_off = (off_t)hcidescp - (off_t)dma->dma_buf->bi_kaddr;
2547c478bd9Sstevel@tonic-gate 	acc_hdl  = dma->dma_buf->bi_handle;
2557c478bd9Sstevel@tonic-gate 	dma_hdl  = dma->dma_buf->bi_dma_handle;
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate 	/* if current ixl command opcode is xmit */
2587c478bd9Sstevel@tonic-gate 	if ((ixlopcode & IXL1394_OPF_ONXMIT) != 0) {
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate 		/* Sync the descriptor before we get the status */
261*2570281cSToomas Soome 		(void) ddi_dma_sync(dma_hdl, hcidesc_off,
2627c478bd9Sstevel@tonic-gate 		    sizeof (hci1394_desc_t), DDI_DMA_SYNC_FORCPU);
2637c478bd9Sstevel@tonic-gate 		desc_status = ddi_get32(acc_hdl, &hcidescp->status);
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate 		/* check if status is set in last dma descriptor in block */
2667c478bd9Sstevel@tonic-gate 		if ((desc_status & DESC_XFER_ACTIVE_MASK) != 0) {
2677c478bd9Sstevel@tonic-gate 			/*
2687c478bd9Sstevel@tonic-gate 			 * dma descriptor status set - I/O done.
2697c478bd9Sstevel@tonic-gate 			 * if not to reset status, just return; else extract
2707c478bd9Sstevel@tonic-gate 			 * timestamp, reset desc status and return dma
2717c478bd9Sstevel@tonic-gate 			 * descriptor block status set
2727c478bd9Sstevel@tonic-gate 			 */
2737c478bd9Sstevel@tonic-gate 			if (do_status_reset == B_FALSE) {
2747c478bd9Sstevel@tonic-gate 				return (1);
2757c478bd9Sstevel@tonic-gate 			}
2767c478bd9Sstevel@tonic-gate 			*timestamp = (uint16_t)
2777c478bd9Sstevel@tonic-gate 			    ((desc_status & DESC_ST_TIMESTAMP_MASK) >>
2787c478bd9Sstevel@tonic-gate 			    DESC_ST_TIMESTAMP_SHIFT);
2797c478bd9Sstevel@tonic-gate 			ddi_put32(acc_hdl, &hcidescp->status, 0);
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate 			/* Sync descriptor for device (status was cleared) */
282*2570281cSToomas Soome 			(void) ddi_dma_sync(dma_hdl, hcidesc_off,
2837c478bd9Sstevel@tonic-gate 			    sizeof (hci1394_desc_t), DDI_DMA_SYNC_FORDEV);
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate 			return (1);
2867c478bd9Sstevel@tonic-gate 		}
2877c478bd9Sstevel@tonic-gate 		/* else, return dma descriptor block status not set */
2887c478bd9Sstevel@tonic-gate 		return (0);
2897c478bd9Sstevel@tonic-gate 	}
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate 	/* else current ixl opcode is recv */
2927c478bd9Sstevel@tonic-gate 	hcirecvcnt = 0;
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate 	/* get count of descriptors in current dma descriptor block */
2957c478bd9Sstevel@tonic-gate 	hcicnt = dma->dma_bound & DESC_Z_MASK;
2967c478bd9Sstevel@tonic-gate 	hcidescp -= (hcicnt - 1);
2977c478bd9Sstevel@tonic-gate 	hcidesc_off = (off_t)hcidescp - (off_t)dma->dma_buf->bi_kaddr;
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 	/* iterate fwd through hci descriptors until end or find status set */
3007c478bd9Sstevel@tonic-gate 	while (hcicnt-- != 0) {
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate 		/* Sync the descriptor before we get the status */
303*2570281cSToomas Soome 		(void) ddi_dma_sync(dma_hdl, hcidesc_off,
3047c478bd9Sstevel@tonic-gate 		    hcicnt * sizeof (hci1394_desc_t), DDI_DMA_SYNC_FORCPU);
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate 		desc_hdr = ddi_get32(acc_hdl, &hcidescp->hdr);
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate 		/* get cur buffer size & accumulate potential buffr usage */
3097c478bd9Sstevel@tonic-gate 		bufsiz = (desc_hdr & DESC_HDR_REQCOUNT_MASK) >>
3107c478bd9Sstevel@tonic-gate 		    DESC_HDR_REQCOUNT_SHIFT;
3117c478bd9Sstevel@tonic-gate 		hcirecvcnt += bufsiz;
3127c478bd9Sstevel@tonic-gate 
3137c478bd9Sstevel@tonic-gate 		desc_status = ddi_get32(acc_hdl, &hcidescp->status);
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate 		/* check if status set on this descriptor block descriptor */
3167c478bd9Sstevel@tonic-gate 		if ((desc_status & DESC_XFER_ACTIVE_MASK) != 0) {
3177c478bd9Sstevel@tonic-gate 			/*
3187c478bd9Sstevel@tonic-gate 			 * dma descriptor status set - I/O done.
3197c478bd9Sstevel@tonic-gate 			 * if not to reset status, just return; else extract
3207c478bd9Sstevel@tonic-gate 			 * buffer space used, reset desc status and return dma
3217c478bd9Sstevel@tonic-gate 			 * descriptor block status set
3227c478bd9Sstevel@tonic-gate 			 */
3237c478bd9Sstevel@tonic-gate 			if (do_status_reset == B_FALSE) {
3247c478bd9Sstevel@tonic-gate 				return (1);
3257c478bd9Sstevel@tonic-gate 			}
3267c478bd9Sstevel@tonic-gate 
3277c478bd9Sstevel@tonic-gate 			hcirecvcnt -= (desc_status & DESC_ST_RESCOUNT_MASK) >>
3287c478bd9Sstevel@tonic-gate 			    DESC_ST_RESCOUNT_SHIFT;
3297c478bd9Sstevel@tonic-gate 			*timestamp = hcirecvcnt;
3307c478bd9Sstevel@tonic-gate 			desc_status = (bufsiz << DESC_ST_RESCOUNT_SHIFT) &
3317c478bd9Sstevel@tonic-gate 			    DESC_ST_RESCOUNT_MASK;
3327c478bd9Sstevel@tonic-gate 			ddi_put32(acc_hdl, &hcidescp->status, desc_status);
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate 			/* Sync descriptor for device (status was cleared) */
335*2570281cSToomas Soome 			(void) ddi_dma_sync(dma_hdl, hcidesc_off,
3367c478bd9Sstevel@tonic-gate 			    sizeof (hci1394_desc_t), DDI_DMA_SYNC_FORDEV);
3377c478bd9Sstevel@tonic-gate 
3387c478bd9Sstevel@tonic-gate 			return (1);
3397c478bd9Sstevel@tonic-gate 		} else {
3407c478bd9Sstevel@tonic-gate 			/* else, set to evaluate next descriptor. */
3417c478bd9Sstevel@tonic-gate 			hcidescp++;
3427c478bd9Sstevel@tonic-gate 			hcidesc_off = (off_t)hcidescp -
343*2570281cSToomas Soome 			    (off_t)dma->dma_buf->bi_kaddr;
3447c478bd9Sstevel@tonic-gate 		}
3457c478bd9Sstevel@tonic-gate 	}
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate 	/* return input not complete status */
3487c478bd9Sstevel@tonic-gate 	return (0);
3497c478bd9Sstevel@tonic-gate }
3507c478bd9Sstevel@tonic-gate #endif
3517c478bd9Sstevel@tonic-gate /*
3527c478bd9Sstevel@tonic-gate  * hci1394_ixl_cleanup()
3537c478bd9Sstevel@tonic-gate  *    Delete all memory that has earlier been allocated for a context's IXL prog
3547c478bd9Sstevel@tonic-gate  */
3557c478bd9Sstevel@tonic-gate void
hci1394_ixl_cleanup(hci1394_state_t * soft_statep,hci1394_iso_ctxt_t * ctxtp)3567c478bd9Sstevel@tonic-gate hci1394_ixl_cleanup(hci1394_state_t *soft_statep, hci1394_iso_ctxt_t *ctxtp)
3577c478bd9Sstevel@tonic-gate {
3587c478bd9Sstevel@tonic-gate 	hci1394_delete_xfer_ctl((hci1394_xfer_ctl_t *)ctxtp->xcs_firstp);
3597c478bd9Sstevel@tonic-gate 	hci1394_delete_dma_desc_mem(soft_statep, ctxtp->dma_firstp);
3607c478bd9Sstevel@tonic-gate }
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate /*
3637c478bd9Sstevel@tonic-gate  * hci1394_delete_dma_desc_mem()
3647c478bd9Sstevel@tonic-gate  *    Iterate through linked list of dma memory descriptors, deleting
3657c478bd9Sstevel@tonic-gate  *    allocated dma memory blocks, then deleting the dma memory
3667c478bd9Sstevel@tonic-gate  *    descriptor after advancing to next one
3677c478bd9Sstevel@tonic-gate  */
3687c478bd9Sstevel@tonic-gate static void
3697c478bd9Sstevel@tonic-gate /* ARGSUSED */
hci1394_delete_dma_desc_mem(hci1394_state_t * soft_statep,hci1394_idma_desc_mem_t * dma_firstp)3707c478bd9Sstevel@tonic-gate hci1394_delete_dma_desc_mem(hci1394_state_t *soft_statep,
3717c478bd9Sstevel@tonic-gate     hci1394_idma_desc_mem_t *dma_firstp)
3727c478bd9Sstevel@tonic-gate {
3737c478bd9Sstevel@tonic-gate 	hci1394_idma_desc_mem_t *dma_next;
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate 	while (dma_firstp != NULL) {
3767c478bd9Sstevel@tonic-gate 		dma_next = dma_firstp->dma_nextp;
3777c478bd9Sstevel@tonic-gate #ifdef _KERNEL
3787c478bd9Sstevel@tonic-gate 		/*
3797c478bd9Sstevel@tonic-gate 		 * if this dma descriptor memory block has the handles, then
3807c478bd9Sstevel@tonic-gate 		 * free the memory.  (Note that valid handles are kept only with
3817c478bd9Sstevel@tonic-gate 		 * the most recently acquired cookie, and that each cookie is in
3827c478bd9Sstevel@tonic-gate 		 * it's own idma_desc_mem_t struct.)
3837c478bd9Sstevel@tonic-gate 		 */
3847c478bd9Sstevel@tonic-gate 		if (dma_firstp->mem_handle != NULL) {
3857c478bd9Sstevel@tonic-gate 			hci1394_buf_free(&dma_firstp->mem_handle);
3867c478bd9Sstevel@tonic-gate 		}
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate 		/* free current dma memory descriptor */
3897c478bd9Sstevel@tonic-gate 		kmem_free(dma_firstp, sizeof (hci1394_idma_desc_mem_t));
3907c478bd9Sstevel@tonic-gate #else
3917c478bd9Sstevel@tonic-gate 		/* user mode free */
3927c478bd9Sstevel@tonic-gate 		/* free dma memory block and current dma mem descriptor */
3937c478bd9Sstevel@tonic-gate 		free(dma_firstp->mem.bi_kaddr);
3947c478bd9Sstevel@tonic-gate 		free(dma_firstp);
3957c478bd9Sstevel@tonic-gate #endif
3967c478bd9Sstevel@tonic-gate 		/* advance to next dma memory descriptor */
3977c478bd9Sstevel@tonic-gate 		dma_firstp = dma_next;
3987c478bd9Sstevel@tonic-gate 	}
3997c478bd9Sstevel@tonic-gate }
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate /*
4027c478bd9Sstevel@tonic-gate  * hci1394_delete_xfer_ctl()
4037c478bd9Sstevel@tonic-gate  *    Iterate thru linked list of xfer_ctl structs, deleting allocated memory.
4047c478bd9Sstevel@tonic-gate  */
4057c478bd9Sstevel@tonic-gate void
hci1394_delete_xfer_ctl(hci1394_xfer_ctl_t * xcsp)4067c478bd9Sstevel@tonic-gate hci1394_delete_xfer_ctl(hci1394_xfer_ctl_t *xcsp)
4077c478bd9Sstevel@tonic-gate {
4087c478bd9Sstevel@tonic-gate 	hci1394_xfer_ctl_t *delp;
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate 	while ((delp = xcsp) != NULL) {
4117c478bd9Sstevel@tonic-gate 		/* advance ptr to next xfer_ctl struct */
4127c478bd9Sstevel@tonic-gate 		xcsp = xcsp->ctl_nextp;
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate 		/*
4157c478bd9Sstevel@tonic-gate 		 * delete current xfer_ctl struct and included
4167c478bd9Sstevel@tonic-gate 		 * xfer_ctl_dma structs
4177c478bd9Sstevel@tonic-gate 		 */
4187c478bd9Sstevel@tonic-gate #ifdef _KERNEL
4197c478bd9Sstevel@tonic-gate 		kmem_free(delp,
4207c478bd9Sstevel@tonic-gate 		    sizeof (hci1394_xfer_ctl_t) +
4217c478bd9Sstevel@tonic-gate 		    sizeof (hci1394_xfer_ctl_dma_t) * (delp->cnt - 1));
4227c478bd9Sstevel@tonic-gate #else
4237c478bd9Sstevel@tonic-gate 		free(delp);
4247c478bd9Sstevel@tonic-gate #endif
4257c478bd9Sstevel@tonic-gate 	}
4267c478bd9Sstevel@tonic-gate }
427