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