/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* av1394 CMP (Connection Management Procedures)
*/
#include <sys/1394/targets/av1394/av1394_impl.h>
/* configuration routines */
static void av1394_cmp_cleanup(av1394_inst_t *icp);
/* ioctl routines */
static int av1394_ioctl_plug_init_local(av1394_inst_t *,
iec61883_plug_init_t *);
static int av1394_ioctl_plug_init_remote(av1394_inst_t *,
iec61883_plug_init_t *);
/* local PCR routines */
static int av1394_pcr_init(av1394_inst_t *, int, uint32_t);
static void av1394_pcr_fini(av1394_inst_t *, int);
static int av1394_pcr_alloc_addr(av1394_inst_t *, uint64_t,
t1394_addr_handle_t *);
static void av1394_pcr_free_addr(av1394_inst_t *, t1394_addr_handle_t *);
static int av1394_pcr_make_ph(int, int, int);
static int av1394_pcr_ph2idx(int);
static av1394_pcr_t *av1394_pcr_ph2pcr(av1394_cmp_t *, int);
static uint64_t av1394_pcr_idx2addr(int);
static int av1394_pcr_idx2num(int);
static boolean_t av1394_pcr_idx_is_mpr(int);
static boolean_t av1394_pcr_ph_is_mpr(int);
static boolean_t av1394_pcr_ph_is_remote(int);
/* callbacks */
static void av1394_pcr_recv_read_request(cmd1394_cmd_t *);
static void av1394_pcr_recv_lock_request(cmd1394_cmd_t *);
/* remote PCR routines */
static int av1394_pcr_remote_read(av1394_inst_t *, int, uint32_t *);
static int av1394_pcr_remote_cas(av1394_inst_t *, int, uint32_t *,
uint32_t, uint32_t);
#define AV1394_TNF_ENTER(func) \
TNF_PROBE_0_DEBUG(func##_enter, AV1394_TNF_CMP_STACK, "");
#define AV1394_TNF_EXIT(func) \
TNF_PROBE_0_DEBUG(func##_exit, AV1394_TNF_CMP_STACK, "");
int
av1394_cmp_init(av1394_inst_t *avp)
{
av1394_cmp_t *cmp = &avp->av_i.i_cmp;
ddi_iblock_cookie_t ibc = avp->av_attachinfo.iblock_cookie;
int ret;
AV1394_TNF_ENTER(av1394_cmp_init);
ret = t1394_cmp_register(avp->av_t1394_hdl, NULL, 0);
if (ret == DDI_SUCCESS) {
rw_init(&cmp->cmp_pcr_rwlock, NULL, RW_DRIVER, ibc);
}
AV1394_TNF_EXIT(av1394_cmp_init);
return (ret);
}
void
av1394_cmp_fini(av1394_inst_t *avp)
{
AV1394_TNF_ENTER(av1394_cmp_fini);
av1394_cmp_cleanup(avp);
AV1394_TNF_EXIT(av1394_cmp_fini);
}
void
av1394_cmp_bus_reset(av1394_inst_t *avp)
{
av1394_cmp_t *cmp = &avp->av_i.i_cmp;
int i;
AV1394_TNF_ENTER(av1394_cmp_bus_reset);
/* reset PCR values */
rw_enter(&cmp->cmp_pcr_rwlock, RW_WRITER);
for (i = 0; i < NELEM(cmp->cmp_pcr); i++) {
if ((i == AV1394_OMPR_IDX) || (i == AV1394_IMPR_IDX)) {
continue;
}
if (cmp->cmp_pcr[i]) {
if (i < AV1394_IMPR_IDX) {
cmp->cmp_pcr[i]->pcr_val &=
~AV1394_OPCR_BR_CLEAR_MASK;
} else {
cmp->cmp_pcr[i]->pcr_val &=
~AV1394_IPCR_BR_CLEAR_MASK;
}
}
}
rw_exit(&cmp->cmp_pcr_rwlock);
AV1394_TNF_EXIT(av1394_cmp_bus_reset);
}
/*
* on close, free iPCRs and oPCRs not finalized by application
*/
void
av1394_cmp_close(av1394_inst_t *avp)
{
av1394_cmp_t *cmp = &avp->av_i.i_cmp;
int i;
rw_enter(&cmp->cmp_pcr_rwlock, RW_WRITER);
for (i = 0; i < NELEM(cmp->cmp_pcr); i++) {
if ((i == AV1394_OMPR_IDX) || (i == AV1394_IMPR_IDX)) {
continue;
}
if (cmp->cmp_pcr[i]) {
av1394_pcr_fini(avp, i);
}
}
rw_exit(&cmp->cmp_pcr_rwlock);
}
/*
*
* --- ioctls
*
* IEC61883_PLUG_INIT
*/
int
av1394_ioctl_plug_init(av1394_inst_t *avp, void *arg, int mode)
{
int ret = 0;
iec61883_plug_init_t pi;
if (ddi_copyin(arg, &pi, sizeof (pi), mode) != 0) {
return (EFAULT);
}
/* check arguments */
if (((pi.pi_type != IEC61883_PLUG_IN) &&
(pi.pi_type != IEC61883_PLUG_OUT) &&
(pi.pi_type != IEC61883_PLUG_MASTER_IN) &&
(pi.pi_type != IEC61883_PLUG_MASTER_OUT)) ||
(((pi.pi_num < 0) || (pi.pi_num >= AV1394_NPCR)) &&
(pi.pi_num != IEC61883_PLUG_ANY))) {
return (EINVAL);
}
if (pi.pi_loc == IEC61883_LOC_LOCAL) {
ret = av1394_ioctl_plug_init_local(avp, &pi);
} else if (pi.pi_loc == IEC61883_LOC_REMOTE) {
ret = av1394_ioctl_plug_init_remote(avp, &pi);
} else {
ret = EINVAL;
}
if (ret == 0) {
if (ddi_copyout(&pi, arg, sizeof (pi), mode) != 0) {
ret = EFAULT;
}
}
return (ret);
}
/*
* IEC61883_PLUG_FINI
*/
/*ARGSUSED*/
int
av1394_ioctl_plug_fini(av1394_inst_t *avp, void *arg, int mode)
{
av1394_cmp_t *cmp = &avp->av_i.i_cmp;
int ret;
int ph;
ph = (int)(intptr_t)arg;
if (av1394_pcr_ph_is_remote(ph) || av1394_pcr_ph_is_mpr(ph)) {
return (0);
}
rw_enter(&cmp->cmp_pcr_rwlock, RW_WRITER);
if (av1394_pcr_ph2pcr(cmp, ph) != NULL) {
av1394_pcr_fini(avp, av1394_pcr_ph2idx(ph));
ret = 0;
} else {
ret = EINVAL;
}
rw_exit(&cmp->cmp_pcr_rwlock);
return (ret);
}
/*
* IEC61883_PLUG_REG_READ
*/
int
av1394_ioctl_plug_reg_read(av1394_inst_t *avp, void *arg, int mode)
{
av1394_cmp_t *cmp = &avp->av_i.i_cmp;
int ret = 0;
iec61883_plug_reg_val_t pr;
int ph;
av1394_pcr_t *pcr;
if (ddi_copyin(arg, &pr, sizeof (pr), mode) != 0) {
return (EFAULT);
}
ph = pr.pr_handle;
if (av1394_pcr_ph_is_remote(ph)) {
ret = av1394_pcr_remote_read(avp, ph, &pr.pr_val);
} else {
switch (av1394_pcr_ph2idx(ph)) {
case AV1394_OMPR_IDX:
ret = t1394_cmp_read(avp->av_t1394_hdl, T1394_CMP_OMPR,
&pr.pr_val);
break;
case AV1394_IMPR_IDX:
ret = t1394_cmp_read(avp->av_t1394_hdl, T1394_CMP_IMPR,
&pr.pr_val);
break;
default:
rw_enter(&cmp->cmp_pcr_rwlock, RW_READER);
if ((pcr = av1394_pcr_ph2pcr(cmp, ph)) != NULL) {
pr.pr_val = pcr->pcr_val;
} else {
ret = EINVAL;
}
rw_exit(&cmp->cmp_pcr_rwlock);
}
}
if (ret == 0) {
if (ddi_copyout(&pr, arg, sizeof (pr), mode) != 0) {
ret = EFAULT;
}
}
return (ret);
}
/*
* IEC61883_PLUG_REG_CAS
*/
int
av1394_ioctl_plug_reg_cas(av1394_inst_t *avp, void *arg, int mode)
{
av1394_cmp_t *cmp = &avp->av_i.i_cmp;
int ret = 0;
iec61883_plug_reg_lock_t pl;
int ph;
av1394_pcr_t *pcr;
if (ddi_copyin(arg, &pl, sizeof (pl), mode) != 0) {
return (EFAULT);
}
ph = pl.pl_handle;
if (av1394_pcr_ph_is_remote(ph)) {
ret = av1394_pcr_remote_cas(avp, ph,
&pl.pl_old, pl.pl_data, pl.pl_arg);
} else {
switch (av1394_pcr_ph2idx(ph)) {
case AV1394_OMPR_IDX:
ret = t1394_cmp_cas(avp->av_t1394_hdl, T1394_CMP_OMPR,
pl.pl_arg, pl.pl_data, &pl.pl_old);
break;
case AV1394_IMPR_IDX:
ret = t1394_cmp_cas(avp->av_t1394_hdl, T1394_CMP_IMPR,
pl.pl_arg, pl.pl_data, &pl.pl_old);
break;
default:
rw_enter(&cmp->cmp_pcr_rwlock, RW_WRITER);
if ((pcr = av1394_pcr_ph2pcr(cmp, ph)) != NULL) {
/* compare_swap */
pl.pl_old = pcr->pcr_val;
if (pcr->pcr_val == pl.pl_arg) {
pcr->pcr_val = pl.pl_data;
}
} else {
ret = EINVAL;
}
rw_exit(&cmp->cmp_pcr_rwlock);
}
}
if (ret == 0) {
if (ddi_copyout(&pl, arg, sizeof (pl), mode) != 0) {
ret = EFAULT;
}
}
return (ret);
}
/*
*
* --- configuration routines
*
*/
static void
av1394_cmp_cleanup(av1394_inst_t *avp)
{
av1394_cmp_t *cmp = &avp->av_i.i_cmp;
int i;
rw_enter(&cmp->cmp_pcr_rwlock, RW_WRITER);
for (i = 0; i < NELEM(cmp->cmp_pcr); i++) {
if (cmp->cmp_pcr[i]) {
av1394_pcr_fini(avp, i);
}
}
rw_exit(&cmp->cmp_pcr_rwlock);
rw_destroy(&cmp->cmp_pcr_rwlock);
(void) t1394_cmp_unregister(avp->av_t1394_hdl);
}
/*
*
* --- ioctl routines
*
* IEC61883_PLUG_INIT for local plugs
*/
static int
av1394_ioctl_plug_init_local(av1394_inst_t *avp, iec61883_plug_init_t *pip)
{
av1394_cmp_t *cmp = &avp->av_i.i_cmp;
int err;
int ph; /* plug handle */
int idx, max_idx; /* plug index */
/* MPR's are a special case */
if ((pip->pi_type == IEC61883_PLUG_MASTER_IN) ||
(pip->pi_type == IEC61883_PLUG_MASTER_OUT)) {
pip->pi_handle = av1394_pcr_make_ph(pip->pi_loc,
pip->pi_type, 0);
return (0);
}
/* PCR */
rw_enter(&cmp->cmp_pcr_rwlock, RW_WRITER);
if (pip->pi_num == IEC61883_PLUG_ANY) {
if (pip->pi_type == IEC61883_PLUG_OUT) {
idx = AV1394_OPCR0_IDX;
max_idx = idx + AV1394_PCR_ADDR_NOPCR - 1;
} else {
ASSERT(pip->pi_type == IEC61883_PLUG_IN);
idx = AV1394_IPCR0_IDX;
max_idx = idx + AV1394_PCR_ADDR_NIPCR - 1;
}
/* find unused PCR */
for (; idx <= max_idx; idx++) {
if (cmp->cmp_pcr[idx] != NULL) {
continue;
}
err = av1394_pcr_init(avp, idx, AV1394_PCR_INIT_VAL);
if (err == DDI_SUCCESS) {
break;
}
}
} else {
ph = av1394_pcr_make_ph(pip->pi_loc, pip->pi_type, pip->pi_num);
idx = max_idx = av1394_pcr_ph2idx(ph);
/* create PCR if not already */
if (cmp->cmp_pcr[idx] == NULL) {
err = av1394_pcr_init(avp, idx, AV1394_PCR_INIT_VAL);
}
}
rw_exit(&cmp->cmp_pcr_rwlock);
if ((err != DDI_SUCCESS) || (idx > max_idx)) {
return (EBUSY);
}
pip->pi_rnum = av1394_pcr_idx2num(idx);
pip->pi_handle = av1394_pcr_make_ph(pip->pi_loc, pip->pi_type,
pip->pi_rnum);
return (0);
}
/*
* IEC61883_PLUG_INIT for remote plugs
*/
static int
av1394_ioctl_plug_init_remote(av1394_inst_t *avp, iec61883_plug_init_t *pip)
{
int ph;
uint32_t val;
int ret;
if (pip->pi_num == IEC61883_PLUG_ANY) {
return (EINVAL);
}
ph = av1394_pcr_make_ph(pip->pi_loc, pip->pi_type, pip->pi_num);
/* check PCR existance by attempting to read it */
if ((ret = av1394_pcr_remote_read(avp, ph, &val)) == 0) {
pip->pi_handle = ph;
pip->pi_rnum = pip->pi_num;
}
return (ret);
}
/*
*
* --- plug routines
*
* initialize a PCR
*/
static int
av1394_pcr_init(av1394_inst_t *avp, int idx, uint32_t val)
{
av1394_cmp_t *cmp = &avp->av_i.i_cmp;
av1394_pcr_t *pcr;
uint64_t addr;
int ret;
pcr = kmem_zalloc(sizeof (av1394_pcr_t), KM_SLEEP);
pcr->pcr_val = val;
cmp->cmp_pcr[idx] = pcr;
addr = av1394_pcr_idx2addr(idx);
ret = av1394_pcr_alloc_addr(avp, addr, &pcr->pcr_addr_hdl);
if (ret != DDI_SUCCESS) {
kmem_free(pcr, sizeof (av1394_pcr_t));
cmp->cmp_pcr[idx] = NULL;
}
return (ret);
}
/*
* finalize a PCR
*/
static void
av1394_pcr_fini(av1394_inst_t *avp, int idx)
{
av1394_cmp_t *cmp = &avp->av_i.i_cmp;
av1394_pcr_free_addr(avp, &cmp->cmp_pcr[idx]->pcr_addr_hdl);
kmem_free(cmp->cmp_pcr[idx], sizeof (av1394_pcr_t));
cmp->cmp_pcr[idx] = NULL;
}
/*
* allocate CSR address for a PCR
*/
static int
av1394_pcr_alloc_addr(av1394_inst_t *avp, uint64_t addr,
t1394_addr_handle_t *hdlp)
{
t1394_alloc_addr_t aa;
int ret;
int result;
AV1394_TNF_ENTER(av1394_pcr_addr_alloc);
bzero(&aa, sizeof (aa));
aa.aa_address = addr;
aa.aa_length = 4;
aa.aa_type = T1394_ADDR_FIXED;
aa.aa_enable = T1394_ADDR_RDENBL | T1394_ADDR_LKENBL;
aa.aa_evts.recv_read_request = av1394_pcr_recv_read_request;
aa.aa_evts.recv_lock_request = av1394_pcr_recv_lock_request;
aa.aa_arg = avp;
ret = t1394_alloc_addr(avp->av_t1394_hdl, &aa, 0, &result);
if (ret != DDI_SUCCESS) {
TNF_PROBE_2(av1394_pcr_alloc_addr_error, AV1394_TNF_CMP_ERROR,
"", tnf_int, ret, ret, tnf_int, result, result);
} else {
*hdlp = aa.aa_hdl;
}
AV1394_TNF_EXIT(av1394_pcr_addr_alloc);
return (ret);
}
/*
* free CSR address occupied by a PCR
*/
static void
av1394_pcr_free_addr(av1394_inst_t *avp, t1394_addr_handle_t *hdlp)
{
int ret;
ret = t1394_free_addr(avp->av_t1394_hdl, hdlp, 0);
if (ret != DDI_SUCCESS) {
TNF_PROBE_1(av1394_pcr_free_addr_error, AV1394_TNF_CMP_ERROR,
"", tnf_int, ret, ret);
}
}
/*
* make plug handle. range checking should be performed by caller
*/
static int
av1394_pcr_make_ph(int loc, int type, int num)
{
int ph;
switch (type) {
case IEC61883_PLUG_IN:
ph = num + AV1394_IPCR0_IDX;
break;
case IEC61883_PLUG_OUT:
ph = num + AV1394_OPCR0_IDX;
break;
case IEC61883_PLUG_MASTER_IN:
ph = AV1394_IMPR_IDX;
break;
case IEC61883_PLUG_MASTER_OUT:
ph = AV1394_OMPR_IDX;
break;
default:
ASSERT(0);
}
if (loc == IEC61883_LOC_REMOTE) {
ph |= AV1394_PCR_REMOTE;
}
return (ph);
}
/*
* convert plug handle to PCR index
*/
static int
av1394_pcr_ph2idx(int ph)
{
return (ph & ~AV1394_PCR_REMOTE);
}
/*
* convert plug handle to PCR pointer
*/
static av1394_pcr_t *
av1394_pcr_ph2pcr(av1394_cmp_t *cmp, int ph)
{
int idx = av1394_pcr_ph2idx(ph);
if ((idx >= 0) && (idx < NELEM(cmp->cmp_pcr))) {
return (cmp->cmp_pcr[idx]);
} else {
return (NULL);
}
}
/*
* convert PCR index to CSR address
*/
static uint64_t
av1394_pcr_idx2addr(int idx)
{
return (AV1394_PCR_ADDR_START + idx * 4);
}
/*
* convert PCR index to number
*/
static int
av1394_pcr_idx2num(int idx)
{
ASSERT(!av1394_pcr_idx_is_mpr(idx));
return ((idx - 1) % 32);
}
/*
* returns B_TRUE if a master plug
*/
static boolean_t
av1394_pcr_idx_is_mpr(int idx)
{
return (idx % 32 == 0);
}
static boolean_t
av1394_pcr_ph_is_mpr(int ph)
{
return (av1394_pcr_ph2idx(ph) % 32 == 0);
}
/*
* returns B_TRUE if a remote plug
*/
static boolean_t
av1394_pcr_ph_is_remote(int ph)
{
return ((ph & AV1394_PCR_REMOTE) != 0);
}
/*
*
* --- callbacks
*
*/
static void
av1394_pcr_recv_read_request(cmd1394_cmd_t *req)
{
av1394_inst_t *avp = req->cmd_callback_arg;
av1394_cmp_t *cmp = &avp->av_i.i_cmp;
int idx; /* PCR index */
av1394_pcr_t *pcr;
int err;
AV1394_TNF_ENTER(av1394_pcr_recv_read_request);
idx = (req->cmd_addr - AV1394_PCR_ADDR_START) / 4;
if (req->cmd_type != CMD1394_ASYNCH_RD_QUAD) {
req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
} else if ((idx >= NELEM(cmp->cmp_pcr)) ||
((pcr = cmp->cmp_pcr[idx]) == NULL)) {
req->cmd_result = IEEE1394_RESP_ADDRESS_ERROR;
} else {
/* read */
rw_enter(&cmp->cmp_pcr_rwlock, RW_READER);
req->cmd_u.q.quadlet_data = pcr->pcr_val;
rw_exit(&cmp->cmp_pcr_rwlock);
req->cmd_result = IEEE1394_RESP_COMPLETE;
}
err = t1394_recv_request_done(avp->av_t1394_hdl, req, 0);
if (err != DDI_SUCCESS) {
TNF_PROBE_1(av1394_pcr_recv_read_request_done_error,
AV1394_TNF_CMP_ERROR, "", tnf_int, err, err);
}
AV1394_TNF_EXIT(av1394_pcr_recv_read_request);
}
static void
av1394_pcr_recv_lock_request(cmd1394_cmd_t *req)
{
av1394_inst_t *avp = req->cmd_callback_arg;
av1394_cmp_t *cmp = &avp->av_i.i_cmp;
int idx; /* PCR index */
av1394_pcr_t *pcr;
int err;
AV1394_TNF_ENTER(av1394_pcr_recv_lock_request);
idx = (req->cmd_addr - AV1394_PCR_ADDR_START) / 4;
if ((req->cmd_type != CMD1394_ASYNCH_LOCK_32) ||
(req->cmd_u.l32.lock_type != CMD1394_LOCK_COMPARE_SWAP)) {
req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
} else if ((idx >= NELEM(cmp->cmp_pcr)) ||
((pcr = cmp->cmp_pcr[idx]) == NULL)) {
req->cmd_result = IEEE1394_RESP_ADDRESS_ERROR;
} else {
/* compare_swap */
rw_enter(&cmp->cmp_pcr_rwlock, RW_WRITER);
if (pcr->pcr_val == req->cmd_u.l32.arg_value) {
pcr->pcr_val = req->cmd_u.l32.data_value;
}
req->cmd_u.l32.old_value = pcr->pcr_val;
rw_exit(&cmp->cmp_pcr_rwlock);
req->cmd_result = IEEE1394_RESP_COMPLETE;
}
err = t1394_recv_request_done(avp->av_t1394_hdl, req, 0);
if (err != DDI_SUCCESS) {
TNF_PROBE_2(av1394_pcr_recv_lock_request_done_error,
AV1394_TNF_CMP_ERROR, "", tnf_int, err, err,
tnf_int, result, req->cmd_result);
}
AV1394_TNF_EXIT(av1394_pcr_recv_lock_request);
}
/*
*
* --- remote PCR routines
*
* read specified PCR on the remote node
*/
static int
av1394_pcr_remote_read(av1394_inst_t *avp, int ph, uint32_t *valp)
{
cmd1394_cmd_t *cmd;
int ret = 0;
int err;
ret = t1394_alloc_cmd(avp->av_t1394_hdl, 0, &cmd);
if (ret != DDI_SUCCESS) {
return (ENOMEM);
}
cmd->cmd_addr = av1394_pcr_idx2addr(av1394_pcr_ph2idx(ph));
cmd->cmd_type = CMD1394_ASYNCH_RD_QUAD;
cmd->cmd_options = CMD1394_BLOCKING;
if (((err = t1394_read(avp->av_t1394_hdl, cmd)) == DDI_SUCCESS) &&
(cmd->cmd_result == CMD1394_CMDSUCCESS)) {
*valp = cmd->cmd_u.q.quadlet_data;
} else {
TNF_PROBE_2(av1394_pcr_remote_read_error, AV1394_TNF_CMP_ERROR,
"", tnf_int, err, err, tnf_int, result, cmd->cmd_result);
ret = EIO;
}
err = t1394_free_cmd(avp->av_t1394_hdl, 0, &cmd);
ASSERT(err == DDI_SUCCESS);
return (ret);
}
/*
* compare_swap specified PCR on the remote node
*/
static int
av1394_pcr_remote_cas(av1394_inst_t *avp, int ph, uint32_t *old_valuep,
uint32_t data_value, uint32_t arg_value)
{
cmd1394_cmd_t *cmd;
int ret = 0;
int err;
ret = t1394_alloc_cmd(avp->av_t1394_hdl, 0, &cmd);
if (ret != DDI_SUCCESS) {
return (ENOMEM);
}
cmd->cmd_addr = av1394_pcr_idx2addr(av1394_pcr_ph2idx(ph));
cmd->cmd_type = CMD1394_ASYNCH_LOCK_32;
cmd->cmd_u.l32.lock_type = CMD1394_LOCK_COMPARE_SWAP;
cmd->cmd_u.l32.data_value = data_value;
cmd->cmd_u.l32.arg_value = arg_value;
cmd->cmd_u.l32.num_retries = 0;
cmd->cmd_options = CMD1394_BLOCKING;
if (((err = t1394_lock(avp->av_t1394_hdl, cmd)) == DDI_SUCCESS) &&
(cmd->cmd_result == CMD1394_CMDSUCCESS)) {
*old_valuep = cmd->cmd_u.l32.old_value;
} else {
TNF_PROBE_2(av1394_pcr_remote_cas_error, AV1394_TNF_CMP_ERROR,
"", tnf_int, err, err, tnf_int, result, cmd->cmd_result);
ret = EIO;
}
err = t1394_free_cmd(avp->av_t1394_hdl, 0, &cmd);
ASSERT(err == DDI_SUCCESS);
return (ret);
}