#include <sys/kmem.h>
#include <sys/types.h>
#include <sys/conf.h>
#include <sys/disp.h>
#include <sys/1394/h1394.h>
#include <sys/1394/ixl1394.h>
#include <sys/1394/adapters/hci1394.h>
#define IXL_PREP_READY 1
#define IXL_PREP_SUCCESS 0
#define IXL_PREP_FAILURE (-1)
int hci1394_upd_retries_before_fail = 50;
static int hci1394_ixl_update_prepare(hci1394_ixl_update_vars_t *uvp);
static int hci1394_ixl_update_prep_jump(hci1394_ixl_update_vars_t *uvp);
static int hci1394_ixl_update_prep_set_skipmode(hci1394_ixl_update_vars_t *uvp);
static int hci1394_ixl_update_prep_set_tagsync(hci1394_ixl_update_vars_t *uvp);
static int hci1394_ixl_update_prep_recv_pkt(hci1394_ixl_update_vars_t *uvp);
static int hci1394_ixl_update_prep_recv_buf(hci1394_ixl_update_vars_t *uvp);
static int hci1394_ixl_update_prep_send_pkt(hci1394_ixl_update_vars_t *uvp);
static int hci1394_ixl_update_prep_send_buf(hci1394_ixl_update_vars_t *uvp);
static int hci1394_ixl_update_perform(hci1394_ixl_update_vars_t *uvp);
static int hci1394_ixl_update_evaluate(hci1394_ixl_update_vars_t *uvp);
static int hci1394_ixl_update_analysis(hci1394_ixl_update_vars_t *uvp);
static void hci1394_ixl_update_set_locn_info(hci1394_ixl_update_vars_t *uvp);
static int hci1394_ixl_update_enable(hci1394_ixl_update_vars_t *uvp);
static int hci1394_ixl_update_endup(hci1394_ixl_update_vars_t *uvp);
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)
{
hci1394_ixl_update_vars_t uv;
int prepstatus;
int ret;
uv.soft_statep = soft_statep;
uv.ctxtp = ctxtp;
uv.ixlnewp = ixlnewp;
uv.ixloldp = ixloldp;
uv.risklevel = riskoverride;
uv.ixlxferp = NULL;
uv.skipxferp = NULL;
uv.skipmode = 0;
uv.skipaddr = 0;
uv.jumpaddr = 0;
uv.pkthdr1 = 0;
uv.pkthdr2 = 0;
uv.bufaddr = 0;
uv.bufsize = 0;
uv.ixl_opcode = uv.ixlnewp->ixl_opcode;
uv.hcihdr = 0;
uv.hcistatus = 0;
uv.hci_offset = 0;
uv.hdr_offset = 0;
uv.upd_status = 0;
prepstatus = hci1394_ixl_update_prepare(&uv);
if (prepstatus != IXL_PREP_READY) {
*resultp = uv.upd_status;
if (prepstatus != IXL_PREP_SUCCESS) {
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
ret = hci1394_ixl_update_enable(&uv);
if (ret != DDI_SUCCESS) {
*resultp = uv.upd_status;
return (DDI_FAILURE);
}
if (hci1394_ixl_update_analysis(&uv) != DDI_SUCCESS) {
if (uv.upd_status != IXL1394_EPRE_UPD_DMALOST) {
(void) hci1394_ixl_update_endup(&uv);
} else {
mutex_enter(&ctxtp->intrprocmutex);
ctxtp->intr_flags &= ~HCI1394_ISO_CTXT_INUPDATE;
mutex_exit(&ctxtp->intrprocmutex);
}
*resultp = uv.upd_status;
return (DDI_FAILURE);
}
if (hci1394_ixl_update_perform(&uv) != DDI_SUCCESS) {
(void) hci1394_ixl_update_endup(&uv);
*resultp = uv.upd_status;
return (DDI_FAILURE);
}
if (hci1394_ixl_update_evaluate(&uv) != DDI_SUCCESS) {
mutex_enter(&ctxtp->intrprocmutex);
ctxtp->intr_flags &= ~HCI1394_ISO_CTXT_INUPDATE;
mutex_exit(&ctxtp->intrprocmutex);
if (uv.upd_status == HCI1394_IXL_INTR_DMASTOP) {
hci1394_do_stop(soft_statep, ctxtp, B_TRUE,
ID1394_DONE);
} else if (uv.upd_status == HCI1394_IXL_INTR_DMALOST) {
hci1394_do_stop(soft_statep, ctxtp, B_TRUE,
ID1394_FAIL);
}
*resultp = uv.upd_status;
return (DDI_FAILURE);
}
uv.upd_status = hci1394_ixl_update_endup(&uv);
*resultp = uv.upd_status;
return (DDI_SUCCESS);
}
static int
hci1394_ixl_update_enable(hci1394_ixl_update_vars_t *uvp)
{
int status;
boolean_t retry;
uint_t remretries;
retry = B_TRUE;
remretries = hci1394_upd_retries_before_fail;
status = DDI_SUCCESS;
ASSERT(MUTEX_NOT_HELD(&uvp->ctxtp->intrprocmutex));
mutex_enter(&uvp->ctxtp->intrprocmutex);
while (retry == B_TRUE) {
retry = B_FALSE;
remretries--;
if (uvp->ctxtp->intr_flags & HCI1394_ISO_CTXT_INUPDATE) {
uvp->upd_status = IXL1394_EUPDATE_DISALLOWED;
status = DDI_FAILURE;
} else if (uvp->ctxtp->intr_flags & HCI1394_ISO_CTXT_ININTR) {
if ((remretries <= 0) ||
(servicing_interrupt())) {
uvp->upd_status = IXL1394_EUPDATE_DISALLOWED;
status = DDI_FAILURE;
} else {
retry = B_TRUE;
mutex_exit(&uvp->ctxtp->intrprocmutex);
drv_usecwait(1);
mutex_enter(&uvp->ctxtp->intrprocmutex);
continue;
}
} else if (uvp->ctxtp->intr_flags & HCI1394_ISO_CTXT_INCALL) {
uvp->upd_status = IXL1394_EINTERNAL_ERROR;
status = DDI_FAILURE;
}
}
if (status == DDI_SUCCESS) {
uvp->ctxtp->intr_flags |= HCI1394_ISO_CTXT_INUPDATE;
}
ASSERT(MUTEX_HELD(&uvp->ctxtp->intrprocmutex));
mutex_exit(&uvp->ctxtp->intrprocmutex);
return (status);
}
static int
hci1394_ixl_update_endup(hci1394_ixl_update_vars_t *uvp)
{
uint_t status;
hci1394_iso_ctxt_t *ctxtp;
status = HCI1394_IXL_INTR_NOERROR;
ctxtp = uvp->ctxtp;
while (ctxtp->intr_flags & HCI1394_ISO_CTXT_INUPDATE) {
if (ctxtp->intr_flags & HCI1394_ISO_CTXT_INTRSET) {
ctxtp->intr_flags &= ~HCI1394_ISO_CTXT_INTRSET;
status = hci1394_ixl_dma_sync(uvp->soft_statep, ctxtp);
if (status == HCI1394_IXL_INTR_DMALOST) {
mutex_enter(&uvp->ctxtp->intrprocmutex);
ctxtp->intr_flags &= ~HCI1394_ISO_CTXT_INUPDATE;
mutex_exit(&uvp->ctxtp->intrprocmutex);
continue;
}
}
ASSERT(MUTEX_NOT_HELD(&uvp->ctxtp->intrprocmutex));
mutex_enter(&uvp->ctxtp->intrprocmutex);
if (!(ctxtp->intr_flags & HCI1394_ISO_CTXT_INTRSET)) {
ctxtp->intr_flags &= ~HCI1394_ISO_CTXT_INUPDATE;
}
mutex_exit(&uvp->ctxtp->intrprocmutex);
}
if (status == HCI1394_IXL_INTR_DMASTOP) {
hci1394_do_stop(uvp->soft_statep, ctxtp, B_TRUE, ID1394_DONE);
} else if (status == HCI1394_IXL_INTR_DMALOST) {
hci1394_do_stop(uvp->soft_statep, ctxtp, B_TRUE, ID1394_FAIL);
}
return (status);
}
static int
hci1394_ixl_update_prepare(hci1394_ixl_update_vars_t *uvp)
{
int ret;
if (uvp->ixlnewp->ixl_opcode != uvp->ixloldp->ixl_opcode) {
uvp->upd_status = IXL1394_EOPCODE_MISMATCH;
return (IXL_PREP_FAILURE);
}
switch (uvp->ixl_opcode) {
case IXL1394_OP_CALLBACK_U: {
ixl1394_callback_t *old_callback_ixlp;
ixl1394_callback_t *new_callback_ixlp;
old_callback_ixlp = (ixl1394_callback_t *)uvp->ixloldp;
new_callback_ixlp = (ixl1394_callback_t *)uvp->ixlnewp;
old_callback_ixlp->callback_arg =
new_callback_ixlp->callback_arg;
old_callback_ixlp->callback = new_callback_ixlp->callback;
return (IXL_PREP_SUCCESS);
}
case IXL1394_OP_JUMP_U:
ret = hci1394_ixl_update_prep_jump(uvp);
return (ret);
case IXL1394_OP_SET_SKIPMODE_U:
ret = hci1394_ixl_update_prep_set_skipmode(uvp);
return (ret);
case IXL1394_OP_SET_TAGSYNC_U:
ret = hci1394_ixl_update_prep_set_tagsync(uvp);
return (ret);
case IXL1394_OP_RECV_PKT_U:
case IXL1394_OP_RECV_PKT_ST_U:
ret = hci1394_ixl_update_prep_recv_pkt(uvp);
return (ret);
case IXL1394_OP_RECV_BUF_U:
ret = hci1394_ixl_update_prep_recv_buf(uvp);
return (ret);
case IXL1394_OP_SEND_PKT_U:
case IXL1394_OP_SEND_PKT_ST_U:
case IXL1394_OP_SEND_PKT_WHDR_ST_U:
ret = hci1394_ixl_update_prep_send_pkt(uvp);
return (ret);
case IXL1394_OP_SEND_BUF_U:
ret = hci1394_ixl_update_prep_send_buf(uvp);
return (ret);
default:
uvp->upd_status = IXL1394_EOPCODE_DISALLOWED;
return (IXL_PREP_FAILURE);
}
}
static int
hci1394_ixl_update_prep_jump(hci1394_ixl_update_vars_t *uvp)
{
ixl1394_jump_t *old_jump_ixlp;
ixl1394_jump_t *new_jump_ixlp;
ixl1394_command_t *ixlp;
hci1394_xfer_ctl_t *xferctlp;
hci1394_desc_t *hcidescp;
uint_t cbcnt;
ddi_acc_handle_t acc_hdl;
ddi_dma_handle_t dma_hdl;
uint32_t desc_hdr;
int err;
old_jump_ixlp = (ixl1394_jump_t *)uvp->ixloldp;
new_jump_ixlp = (ixl1394_jump_t *)uvp->ixlnewp;
if (new_jump_ixlp->label == old_jump_ixlp->label) {
return (IXL_PREP_SUCCESS);
}
if ((new_jump_ixlp->label != NULL) &&
(new_jump_ixlp->label->ixl_opcode != IXL1394_OP_LABEL)) {
uvp->upd_status = IXL1394_EJUMP_NOT_TO_LABEL;
return (IXL_PREP_FAILURE);
}
(void) hci1394_ixl_find_next_exec_xfer(new_jump_ixlp->label, &cbcnt,
&ixlp);
if (ixlp != NULL) {
uvp->jumpaddr = ((hci1394_xfer_ctl_t *)
ixlp->compiler_privatep)->dma[0].dma_bound;
}
if ((uvp->ixlxferp = (ixl1394_command_t *)
old_jump_ixlp->compiler_privatep) == NULL) {
uvp->upd_status = IXL1394_EORIG_IXL_CORRUPTED;
return (IXL_PREP_FAILURE);
}
xferctlp = (hci1394_xfer_ctl_t *)uvp->ixlxferp->compiler_privatep;
hcidescp = (hci1394_desc_t *)xferctlp->dma[xferctlp->cnt - 1].dma_descp;
acc_hdl = xferctlp->dma[xferctlp->cnt - 1].dma_buf->bi_handle;
dma_hdl = xferctlp->dma[xferctlp->cnt - 1].dma_buf->bi_dma_handle;
err = ddi_dma_sync(dma_hdl, (off_t)hcidescp, sizeof (hci1394_desc_t),
DDI_DMA_SYNC_FORCPU);
if (err != DDI_SUCCESS) {
uvp->upd_status = IXL1394_EINTERNAL_ERROR;
return (IXL_PREP_FAILURE);
}
desc_hdr = ddi_get32(acc_hdl, &hcidescp->hdr);
uvp->hcihdr = desc_hdr & ~DESC_INTR_ENBL;
uvp->ixldepth = xferctlp->cnt - 1;
uvp->ixlcount = 1;
if (((xferctlp->cnt == 1) &&
((xferctlp->ctl_flags & XCTL_LABELLED) != 0)) || (cbcnt != 0)) {
uvp->hcihdr |= DESC_INTR_ENBL;
}
if ((new_jump_ixlp->label == NULL) || (old_jump_ixlp->label == NULL)) {
uvp->hcihdr |= DESC_INTR_ENBL;
}
uvp->skipmode = IXL1394_SKIP_TO_STOP;
if ((uvp->ixlxferp->ixl_opcode & IXL1394_OPF_ONXMIT) != 0) {
if ((xferctlp->skipmodep && (((ixl1394_set_skipmode_t *)
xferctlp->skipmodep)->skipmode == IXL1394_SKIP_TO_NEXT)) ||
(uvp->ctxtp->default_skipmode == IXL1394_OPF_ONXMIT)) {
uvp->skipmode = IXL1394_SKIP_TO_NEXT;
uvp->skipaddr = uvp->jumpaddr;
if (uvp->ixlxferp->ixl_opcode ==
IXL1394_OP_SEND_HDR_ONLY) {
uvp->hci_offset -= 2;
} else {
uvp->hci_offset -= 1;
}
}
}
return (IXL_PREP_READY);
}
static int
hci1394_ixl_update_prep_set_skipmode(hci1394_ixl_update_vars_t *uvp)
{
ixl1394_set_skipmode_t *old_set_skipmode_ixlp;
ixl1394_set_skipmode_t *new_set_skipmode_ixlp;
ixl1394_command_t *ixlp;
hci1394_xfer_ctl_t *xferctlp;
old_set_skipmode_ixlp = (ixl1394_set_skipmode_t *)uvp->ixloldp;
new_set_skipmode_ixlp = (ixl1394_set_skipmode_t *)uvp->ixlnewp;
if (new_set_skipmode_ixlp->skipmode ==
old_set_skipmode_ixlp->skipmode) {
if ((new_set_skipmode_ixlp->skipmode !=
IXL1394_SKIP_TO_LABEL) ||
(old_set_skipmode_ixlp->label ==
new_set_skipmode_ixlp->label)) {
return (IXL_PREP_SUCCESS);
}
}
uvp->ixlxferp = uvp->ixloldp->next_ixlp;
while ((uvp->ixlxferp != NULL) && (((uvp->ixlxferp->ixl_opcode &
IXL1394_OPF_ISXFER) == 0) ||
((uvp->ixlxferp->ixl_opcode & IXL1394_OPTY_MASK) != 0))) {
uvp->ixlxferp = uvp->ixlxferp->next_ixlp;
}
if (uvp->ixlxferp == NULL) {
uvp->upd_status = IXL1394_EORIG_IXL_CORRUPTED;
return (IXL_PREP_FAILURE);
}
if ((xferctlp = (hci1394_xfer_ctl_t *)
uvp->ixlxferp->compiler_privatep) == NULL) {
uvp->upd_status = IXL1394_EORIG_IXL_CORRUPTED;
return (IXL_PREP_FAILURE);
}
uvp->hci_offset = xferctlp->dma[0].dma_bound & DESC_Z_MASK;
if (uvp->ixlxferp->ixl_opcode == IXL1394_OP_SEND_HDR_ONLY) {
uvp->hci_offset -= 2;
} else {
uvp->hci_offset -= 1;
}
uvp->ixldepth = 0;
uvp->ixlcount = xferctlp->cnt;
uvp->skipmode = new_set_skipmode_ixlp->skipmode;
if ((uvp->skipmode != IXL1394_SKIP_TO_NEXT) &&
(uvp->skipmode != IXL1394_SKIP_TO_SELF) &&
(uvp->skipmode != IXL1394_SKIP_TO_STOP) &&
(uvp->skipmode != IXL1394_SKIP_TO_LABEL)) {
uvp->upd_status = IXL1394_EBAD_SKIPMODE;
return (IXL_PREP_FAILURE);
}
if (uvp->skipmode == IXL1394_SKIP_TO_LABEL) {
if ((new_set_skipmode_ixlp->label == NULL) ||
(new_set_skipmode_ixlp->label->ixl_opcode !=
IXL1394_OP_LABEL)) {
uvp->upd_status = IXL1394_EBAD_SKIP_LABEL;
return (IXL_PREP_FAILURE);
}
(void) hci1394_ixl_find_next_exec_xfer(
new_set_skipmode_ixlp->label, NULL, &ixlp);
if ((uvp->skipxferp = ixlp) != NULL) {
xferctlp = (hci1394_xfer_ctl_t *)
ixlp->compiler_privatep;
uvp->skipaddr = xferctlp->dma[0].dma_bound;
}
}
if (uvp->skipmode == IXL1394_SKIP_TO_NEXT) {
(void) hci1394_ixl_find_next_exec_xfer(uvp->ixlxferp->next_ixlp,
NULL, &ixlp);
if (ixlp != NULL) {
xferctlp = (hci1394_xfer_ctl_t *)
ixlp->compiler_privatep;
uvp->skipaddr = xferctlp->dma[0].dma_bound;
}
}
return (IXL_PREP_READY);
}
static int
hci1394_ixl_update_prep_set_tagsync(hci1394_ixl_update_vars_t *uvp)
{
ixl1394_set_tagsync_t *old_set_tagsync_ixlp;
ixl1394_set_tagsync_t *new_set_tagsync_ixlp;
hci1394_xfer_ctl_t *xferctlp;
old_set_tagsync_ixlp = (ixl1394_set_tagsync_t *)uvp->ixloldp;
new_set_tagsync_ixlp = (ixl1394_set_tagsync_t *)uvp->ixlnewp;
if ((new_set_tagsync_ixlp->tag == old_set_tagsync_ixlp->tag) &&
(new_set_tagsync_ixlp->sync == old_set_tagsync_ixlp->sync)) {
return (IXL_PREP_SUCCESS);
}
uvp->ixlxferp = uvp->ixloldp->next_ixlp;
while ((uvp->ixlxferp != NULL) && (((uvp->ixlxferp->ixl_opcode &
IXL1394_OPF_ISXFER) == 0) ||
((uvp->ixlxferp->ixl_opcode & IXL1394_OPTY_MASK) != 0))) {
uvp->ixlxferp = uvp->ixlxferp->next_ixlp;
}
if (uvp->ixlxferp == NULL) {
uvp->upd_status = IXL1394_EORIG_IXL_CORRUPTED;
return (IXL_PREP_FAILURE);
}
if (uvp->ixlxferp->ixl_opcode == IXL1394_OP_SEND_NO_PKT) {
return (IXL_PREP_SUCCESS);
}
uvp->pkthdr1 = (uvp->ctxtp->isospd << DESC_PKT_SPD_SHIFT) |
(new_set_tagsync_ixlp->tag << DESC_PKT_TAG_SHIFT) |
(uvp->ctxtp->isochan << DESC_PKT_CHAN_SHIFT) |
(new_set_tagsync_ixlp->sync << DESC_PKT_SY_SHIFT);
if ((xferctlp = (hci1394_xfer_ctl_t *)
uvp->ixlxferp->compiler_privatep) == NULL) {
uvp->upd_status = IXL1394_EORIG_IXL_CORRUPTED;
return (IXL_PREP_FAILURE);
}
uvp->hdr_offset = xferctlp->dma[0].dma_bound & DESC_Z_MASK;
if (uvp->ixlxferp->ixl_opcode == IXL1394_OP_SEND_HDR_ONLY) {
uvp->hdr_offset = 0;
} else {
uvp->hdr_offset -= 1;
}
uvp->ixldepth = 0;
uvp->ixlcount = xferctlp->cnt;
return (IXL_PREP_READY);
}
static int
hci1394_ixl_update_prep_recv_pkt(hci1394_ixl_update_vars_t *uvp)
{
ixl1394_xfer_pkt_t *old_xfer_pkt_ixlp;
ixl1394_xfer_pkt_t *new_xfer_pkt_ixlp;
hci1394_xfer_ctl_t *xferctlp;
hci1394_desc_t *hcidescp;
ddi_acc_handle_t acc_hdl;
ddi_dma_handle_t dma_hdl;
uint32_t desc_hdr;
int err;
old_xfer_pkt_ixlp = (ixl1394_xfer_pkt_t *)uvp->ixloldp;
new_xfer_pkt_ixlp = (ixl1394_xfer_pkt_t *)uvp->ixlnewp;
if ((new_xfer_pkt_ixlp->size == old_xfer_pkt_ixlp->size) &&
(new_xfer_pkt_ixlp->ixl_buf.ixldmac_addr ==
old_xfer_pkt_ixlp->ixl_buf.ixldmac_addr) &&
(new_xfer_pkt_ixlp->mem_bufp == old_xfer_pkt_ixlp->mem_bufp)) {
return (IXL_PREP_SUCCESS);
}
if ((new_xfer_pkt_ixlp->ixl_buf.ixldmac_addr == 0) ||
(new_xfer_pkt_ixlp->mem_bufp == NULL)) {
uvp->upd_status = IXL1394_EXFER_BUF_MISSING;
return (IXL_PREP_FAILURE);
}
if (uvp->ixl_opcode == IXL1394_OP_RECV_PKT_U) {
uvp->ixlxferp = (ixl1394_command_t *)
uvp->ixloldp->compiler_privatep;
if (uvp->ixlxferp == NULL) {
uvp->upd_status = IXL1394_EORIG_IXL_CORRUPTED;
return (IXL_PREP_FAILURE);
}
} else {
uvp->ixlxferp = uvp->ixloldp;
}
if ((xferctlp = (hci1394_xfer_ctl_t *)
uvp->ixlxferp->compiler_privatep) == NULL) {
uvp->upd_status = IXL1394_EORIG_IXL_CORRUPTED;
return (IXL_PREP_FAILURE);
}
uvp->ixldepth = 0;
uvp->ixlcount = 1;
uvp->hci_offset = xferctlp->dma[0].dma_bound & DESC_Z_MASK;
uvp->hci_offset -= (1 + uvp->ixloldp->compiler_resv);
uvp->bufsize = ((ixl1394_xfer_pkt_t *)uvp->ixlnewp)->size;
uvp->bufaddr = ((ixl1394_xfer_pkt_t *)
uvp->ixlnewp)->ixl_buf.ixldmac_addr;
hcidescp = (hci1394_desc_t *)xferctlp->dma[0].dma_descp -
uvp->hci_offset;
acc_hdl = xferctlp->dma[0].dma_buf->bi_handle;
dma_hdl = xferctlp->dma[0].dma_buf->bi_dma_handle;
err = ddi_dma_sync(dma_hdl, (off_t)hcidescp, sizeof (hci1394_desc_t),
DDI_DMA_SYNC_FORCPU);
if (err != DDI_SUCCESS) {
uvp->upd_status = IXL1394_EINTERNAL_ERROR;
return (IXL_PREP_FAILURE);
}
desc_hdr = ddi_get32(acc_hdl, &hcidescp->hdr);
uvp->hcihdr = desc_hdr;
uvp->hcihdr &= ~DESC_HDR_REQCOUNT_MASK;
uvp->hcihdr |= (uvp->bufsize << DESC_HDR_REQCOUNT_SHIFT) &
DESC_HDR_REQCOUNT_MASK;
uvp->hcistatus = (uvp->bufsize << DESC_ST_RESCOUNT_SHIFT) &
DESC_ST_RESCOUNT_MASK;
return (IXL_PREP_READY);
}
static int
hci1394_ixl_update_prep_recv_buf(hci1394_ixl_update_vars_t *uvp)
{
ixl1394_xfer_buf_t *old_xfer_buf_ixlp;
ixl1394_xfer_buf_t *new_xfer_buf_ixlp;
hci1394_xfer_ctl_t *xferctlp;
old_xfer_buf_ixlp = (ixl1394_xfer_buf_t *)uvp->ixloldp;
new_xfer_buf_ixlp = (ixl1394_xfer_buf_t *)uvp->ixlnewp;
if ((new_xfer_buf_ixlp->size == old_xfer_buf_ixlp->size) &&
(new_xfer_buf_ixlp->ixl_buf.ixldmac_addr ==
old_xfer_buf_ixlp->ixl_buf.ixldmac_addr) &&
(new_xfer_buf_ixlp->mem_bufp == old_xfer_buf_ixlp->mem_bufp)) {
if (((uvp->ctxtp->ctxt_flags & HCI1394_ISO_CTXT_BFFILL) != 0) ||
(new_xfer_buf_ixlp->pkt_size ==
old_xfer_buf_ixlp->pkt_size)) {
return (IXL_PREP_SUCCESS);
}
}
if ((new_xfer_buf_ixlp->ixl_buf.ixldmac_addr == 0) ||
(new_xfer_buf_ixlp->mem_bufp == NULL)) {
uvp->upd_status = IXL1394_EXFER_BUF_MISSING;
return (IXL_PREP_FAILURE);
}
if ((uvp->ctxtp->ctxt_flags & HCI1394_ISO_CTXT_BFFILL) == 0) {
if ((new_xfer_buf_ixlp->pkt_size == 0) ||
((new_xfer_buf_ixlp->size / new_xfer_buf_ixlp->pkt_size) !=
(old_xfer_buf_ixlp->size / old_xfer_buf_ixlp->pkt_size))) {
uvp->upd_status = IXL1394_EXFER_BUF_CNT_DIFF;
return (IXL_PREP_FAILURE);
}
}
uvp->ixlxferp = uvp->ixloldp;
if ((xferctlp = (hci1394_xfer_ctl_t *)uvp->ixlxferp->compiler_privatep)
== NULL) {
uvp->upd_status = IXL1394_EORIG_IXL_CORRUPTED;
return (IXL_PREP_FAILURE);
}
uvp->ixldepth = 0;
uvp->ixlcount = xferctlp->cnt;
if ((uvp->ctxtp->ctxt_flags & HCI1394_ISO_CTXT_BFFILL) == 0) {
uvp->bufsize = new_xfer_buf_ixlp->pkt_size;
} else {
uvp->bufsize = new_xfer_buf_ixlp->size;
}
uvp->bufaddr = new_xfer_buf_ixlp->ixl_buf.ixldmac_addr;
uvp->hci_offset = 0;
uvp->hcihdr = (uvp->bufsize << DESC_HDR_REQCOUNT_SHIFT) &
DESC_HDR_REQCOUNT_MASK;
uvp->hcistatus = (uvp->bufsize << DESC_ST_RESCOUNT_SHIFT) &
DESC_ST_RESCOUNT_MASK;
return (IXL_PREP_READY);
}
static int
hci1394_ixl_update_prep_send_pkt(hci1394_ixl_update_vars_t *uvp)
{
ixl1394_xfer_pkt_t *old_xfer_pkt_ixlp;
ixl1394_xfer_pkt_t *new_xfer_pkt_ixlp;
hci1394_xfer_ctl_t *xferctlp;
hci1394_desc_imm_t *hcidescp;
ddi_acc_handle_t acc_hdl;
ddi_dma_handle_t dma_hdl;
uint32_t desc_hdr, desc_hdr2;
int err;
old_xfer_pkt_ixlp = (ixl1394_xfer_pkt_t *)uvp->ixloldp;
new_xfer_pkt_ixlp = (ixl1394_xfer_pkt_t *)uvp->ixlnewp;
if ((new_xfer_pkt_ixlp->size == old_xfer_pkt_ixlp->size) &&
(new_xfer_pkt_ixlp->ixl_buf.ixldmac_addr ==
old_xfer_pkt_ixlp->ixl_buf.ixldmac_addr) &&
(new_xfer_pkt_ixlp->mem_bufp == old_xfer_pkt_ixlp->mem_bufp)) {
return (IXL_PREP_SUCCESS);
}
if ((new_xfer_pkt_ixlp->ixl_buf.ixldmac_addr == 0) ||
(new_xfer_pkt_ixlp->mem_bufp == NULL)) {
uvp->upd_status = IXL1394_EXFER_BUF_MISSING;
return (IXL_PREP_FAILURE);
}
if ((uvp->ixl_opcode == IXL1394_OP_SEND_PKT_WHDR_ST_U) &&
(new_xfer_pkt_ixlp->size < 4)) {
uvp->upd_status = IXL1394_EPKT_HDR_MISSING;
return (IXL_PREP_FAILURE);
}
if (uvp->ixl_opcode == IXL1394_OP_SEND_PKT_U) {
uvp->ixlxferp = (ixl1394_command_t *)
old_xfer_pkt_ixlp->compiler_privatep;
if (uvp->ixlxferp == NULL) {
uvp->upd_status = IXL1394_EORIG_IXL_CORRUPTED;
return (IXL_PREP_FAILURE);
}
} else {
uvp->ixlxferp = uvp->ixloldp;
}
if ((xferctlp = (hci1394_xfer_ctl_t *)
uvp->ixlxferp->compiler_privatep) == NULL) {
uvp->upd_status = IXL1394_EORIG_IXL_CORRUPTED;
return (IXL_PREP_FAILURE);
}
uvp->ixldepth = 0;
uvp->ixlcount = 1;
uvp->hdr_offset = xferctlp->dma[0].dma_bound & DESC_Z_MASK - 1;
uvp->hci_offset = uvp->hdr_offset - 2 - uvp->ixloldp->compiler_resv;
uvp->bufsize = new_xfer_pkt_ixlp->size;
uvp->bufaddr = new_xfer_pkt_ixlp->ixl_buf.ixldmac_addr;
if (uvp->ixl_opcode == IXL1394_OP_SEND_PKT_WHDR_ST_U) {
uvp->bufsize -= 4;
uvp->bufaddr += 4;
}
hcidescp = (hci1394_desc_imm_t *)xferctlp->dma[0].dma_descp -
uvp->hci_offset;
acc_hdl = xferctlp->dma[0].dma_buf->bi_handle;
dma_hdl = xferctlp->dma[0].dma_buf->bi_dma_handle;
err = ddi_dma_sync(dma_hdl, (off_t)hcidescp,
sizeof (hci1394_desc_imm_t), DDI_DMA_SYNC_FORCPU);
if (err != DDI_SUCCESS) {
uvp->upd_status = IXL1394_EINTERNAL_ERROR;
return (IXL_PREP_FAILURE);
}
desc_hdr = ddi_get32(acc_hdl, &hcidescp->hdr);
uvp->hcihdr = desc_hdr;
uvp->hcihdr &= ~DESC_HDR_REQCOUNT_MASK;
uvp->hcihdr |= (uvp->bufsize << DESC_HDR_REQCOUNT_SHIFT) &
DESC_HDR_REQCOUNT_MASK;
desc_hdr2 = ddi_get32(acc_hdl, &hcidescp->q2);
uvp->pkthdr2 = desc_hdr2;
uvp->pkthdr2 = (uvp->pkthdr2 & DESC_PKT_DATALEN_MASK) >>
DESC_PKT_DATALEN_SHIFT;
uvp->pkthdr2 -= old_xfer_pkt_ixlp->size;
uvp->pkthdr2 += uvp->bufsize;
if (uvp->pkthdr2 > 0xFFFF) {
uvp->upd_status = IXL1394_EPKTSIZE_MAX_OFLO;
return (IXL_PREP_FAILURE);
}
uvp->pkthdr2 = (uvp->pkthdr2 << DESC_PKT_DATALEN_SHIFT) &
DESC_PKT_DATALEN_MASK;
return (IXL_PREP_READY);
}
static int
hci1394_ixl_update_prep_send_buf(hci1394_ixl_update_vars_t *uvp)
{
ixl1394_xfer_buf_t *old_xfer_buf_ixlp;
ixl1394_xfer_buf_t *new_xfer_buf_ixlp;
hci1394_xfer_ctl_t *xferctlp;
old_xfer_buf_ixlp = (ixl1394_xfer_buf_t *)uvp->ixloldp;
new_xfer_buf_ixlp = (ixl1394_xfer_buf_t *)uvp->ixlnewp;
if ((new_xfer_buf_ixlp->size == old_xfer_buf_ixlp->size) &&
(new_xfer_buf_ixlp->pkt_size == old_xfer_buf_ixlp->pkt_size) &&
(new_xfer_buf_ixlp->ixl_buf.ixldmac_addr ==
old_xfer_buf_ixlp->ixl_buf.ixldmac_addr) &&
(new_xfer_buf_ixlp->mem_bufp == old_xfer_buf_ixlp->mem_bufp)) {
return (IXL_PREP_SUCCESS);
}
if ((new_xfer_buf_ixlp->ixl_buf.ixldmac_addr == 0) ||
(new_xfer_buf_ixlp->mem_bufp == NULL)) {
uvp->upd_status = IXL1394_EXFER_BUF_MISSING;
return (IXL_PREP_FAILURE);
}
if ((new_xfer_buf_ixlp->pkt_size == 0) ||
((new_xfer_buf_ixlp->size / new_xfer_buf_ixlp->pkt_size) !=
(old_xfer_buf_ixlp->size / old_xfer_buf_ixlp->pkt_size))) {
uvp->upd_status = IXL1394_EXFER_BUF_CNT_DIFF;
return (IXL_PREP_FAILURE);
}
uvp->ixlxferp = uvp->ixloldp;
if ((xferctlp = (hci1394_xfer_ctl_t *)
uvp->ixlxferp->compiler_privatep) == NULL) {
uvp->upd_status = IXL1394_EORIG_IXL_CORRUPTED;
return (IXL_PREP_FAILURE);
}
uvp->ixldepth = 0;
uvp->ixlcount = xferctlp->cnt;
uvp->hdr_offset = xferctlp->dma[0].dma_bound & DESC_Z_MASK - 1;
uvp->hci_offset = 0;
uvp->bufsize = new_xfer_buf_ixlp->pkt_size;
uvp->bufaddr = new_xfer_buf_ixlp->ixl_buf.ixldmac_addr;
if (uvp->ixl_opcode == IXL1394_OP_SEND_PKT_WHDR_ST_U) {
uvp->bufsize -= 4;
uvp->bufaddr += 4;
}
uvp->hcihdr = (uvp->bufsize << DESC_HDR_REQCOUNT_SHIFT) &
DESC_HDR_REQCOUNT_MASK;
uvp->pkthdr2 = (uvp->bufsize << DESC_PKT_DATALEN_SHIFT) &
DESC_PKT_DATALEN_MASK;
return (IXL_PREP_READY);
}
static int
hci1394_ixl_update_perform(hci1394_ixl_update_vars_t *uvp)
{
int ii;
uint_t skipaddrlast;
hci1394_xfer_ctl_t *xferctlp;
hci1394_desc_imm_t *hcidescp;
hci1394_iso_ctxt_t *ctxtp;
ddi_acc_handle_t acc_hdl;
ddi_dma_handle_t dma_hdl;
int err;
ctxtp = uvp->ctxtp;
if ((uvp->ixlxferp == NULL) ||
((xferctlp = (hci1394_xfer_ctl_t *)
uvp->ixlxferp->compiler_privatep) == NULL)) {
uvp->upd_status = IXL1394_EINTERNAL_ERROR;
return (DDI_FAILURE);
}
switch (uvp->ixl_opcode) {
case IXL1394_OP_JUMP_U: {
ixl1394_jump_t *old_jump_ixlp;
ixl1394_jump_t *new_jump_ixlp;
old_jump_ixlp = (ixl1394_jump_t *)uvp->ixloldp;
new_jump_ixlp = (ixl1394_jump_t *)uvp->ixlnewp;
hcidescp = (hci1394_desc_imm_t *)
xferctlp->dma[xferctlp->cnt - 1].dma_descp;
acc_hdl = xferctlp->dma[xferctlp->cnt - 1].dma_buf->bi_handle;
dma_hdl =
xferctlp->dma[xferctlp->cnt - 1].dma_buf->bi_dma_handle;
ddi_put32(acc_hdl, &hcidescp->hdr, uvp->hcihdr);
ddi_put32(acc_hdl, &hcidescp->branch, uvp->jumpaddr);
if (uvp->skipmode == IXL1394_SKIP_TO_NEXT) {
hcidescp -= uvp->hci_offset;
ddi_put32(acc_hdl, &hcidescp->branch, uvp->skipaddr);
}
err = ddi_dma_sync(dma_hdl, (off_t)hcidescp,
sizeof (hci1394_desc_imm_t), DDI_DMA_SYNC_FORDEV);
if (err != DDI_SUCCESS) {
uvp->upd_status = IXL1394_EINTERNAL_ERROR;
return (DDI_FAILURE);
}
old_jump_ixlp->label = new_jump_ixlp->label;
break;
}
case IXL1394_OP_SET_SKIPMODE_U: {
ixl1394_set_skipmode_t *old_set_skipmode_ixlp;
ixl1394_set_skipmode_t *new_set_skipmode_ixlp;
old_set_skipmode_ixlp = (ixl1394_set_skipmode_t *)uvp->ixloldp;
new_set_skipmode_ixlp = (ixl1394_set_skipmode_t *)uvp->ixlnewp;
if (uvp->skipmode == IXL1394_SKIP_TO_NEXT) {
skipaddrlast = uvp->skipaddr;
}
for (ii = 0; ii < xferctlp->cnt; ii++) {
hcidescp = (hci1394_desc_imm_t *)
xferctlp->dma[ii].dma_descp - uvp->hci_offset;
acc_hdl = xferctlp->dma[ii].dma_buf->bi_handle;
dma_hdl = xferctlp->dma[ii].dma_buf->bi_dma_handle;
if (uvp->skipmode == IXL1394_SKIP_TO_NEXT) {
if (ii < (xferctlp->cnt - 1)) {
uvp->skipaddr =
xferctlp->dma[ii + 1].dma_bound;
} else {
uvp->skipaddr = skipaddrlast;
}
} else if (uvp->skipmode == IXL1394_SKIP_TO_SELF) {
uvp->skipaddr = xferctlp->dma[ii].dma_bound;
}
ddi_put32(acc_hdl, &hcidescp->branch, uvp->skipaddr);
err = ddi_dma_sync(dma_hdl, (off_t)hcidescp,
sizeof (hci1394_desc_imm_t), DDI_DMA_SYNC_FORDEV);
if (err != DDI_SUCCESS) {
uvp->upd_status = IXL1394_EINTERNAL_ERROR;
return (DDI_FAILURE);
}
}
old_set_skipmode_ixlp->skipmode = uvp->skipmode;
old_set_skipmode_ixlp->label = new_set_skipmode_ixlp->label;
old_set_skipmode_ixlp->compiler_privatep =
(ixl1394_priv_t)uvp->skipxferp;
break;
}
case IXL1394_OP_SET_TAGSYNC_U: {
ixl1394_set_tagsync_t *old_set_tagsync_ixlp;
ixl1394_set_tagsync_t *new_set_tagsync_ixlp;
old_set_tagsync_ixlp = (ixl1394_set_tagsync_t *)uvp->ixloldp;
new_set_tagsync_ixlp = (ixl1394_set_tagsync_t *)uvp->ixlnewp;
for (ii = 0; ii < xferctlp->cnt; ii++) {
hcidescp = (hci1394_desc_imm_t *)
xferctlp->dma[ii].dma_descp - uvp->hdr_offset;
acc_hdl = xferctlp->dma[ii].dma_buf->bi_handle;
dma_hdl = xferctlp->dma[ii].dma_buf->bi_dma_handle;
ddi_put32(acc_hdl, &hcidescp->q1, uvp->pkthdr1);
err = ddi_dma_sync(dma_hdl, (off_t)hcidescp,
sizeof (hci1394_desc_imm_t), DDI_DMA_SYNC_FORDEV);
if (err != DDI_SUCCESS) {
uvp->upd_status = IXL1394_EINTERNAL_ERROR;
return (DDI_FAILURE);
}
}
old_set_tagsync_ixlp->tag = new_set_tagsync_ixlp->tag;
old_set_tagsync_ixlp->sync = new_set_tagsync_ixlp->sync;
break;
}
case IXL1394_OP_RECV_PKT_U:
case IXL1394_OP_RECV_PKT_ST_U: {
ixl1394_xfer_pkt_t *old_xfer_pkt_ixlp;
ixl1394_xfer_pkt_t *new_xfer_pkt_ixlp;
uint32_t desc_status;
old_xfer_pkt_ixlp = (ixl1394_xfer_pkt_t *)uvp->ixloldp;
new_xfer_pkt_ixlp = (ixl1394_xfer_pkt_t *)uvp->ixlnewp;
hcidescp = (hci1394_desc_imm_t *)
xferctlp->dma[0].dma_descp - uvp->hci_offset;
acc_hdl = xferctlp->dma[0].dma_buf->bi_handle;
dma_hdl = xferctlp->dma[0].dma_buf->bi_dma_handle;
ddi_put32(acc_hdl, &hcidescp->hdr, uvp->hcihdr);
ddi_put32(acc_hdl, &hcidescp->data_addr, uvp->bufaddr);
err = ddi_dma_sync(dma_hdl, (off_t)hcidescp,
sizeof (hci1394_desc_imm_t), DDI_DMA_SYNC_FORCPU);
if (err != DDI_SUCCESS) {
uvp->upd_status = IXL1394_EINTERNAL_ERROR;
return (DDI_FAILURE);
}
desc_status = ddi_get32(acc_hdl, &hcidescp->status);
desc_status = (desc_status & ~DESC_ST_RESCOUNT_MASK) |
uvp->hcistatus;
ddi_put32(acc_hdl, &hcidescp->status, desc_status);
err = ddi_dma_sync(dma_hdl, (off_t)hcidescp,
sizeof (hci1394_desc_imm_t), DDI_DMA_SYNC_FORDEV);
if (err != DDI_SUCCESS) {
uvp->upd_status = IXL1394_EINTERNAL_ERROR;
return (DDI_FAILURE);
}
old_xfer_pkt_ixlp->size = new_xfer_pkt_ixlp->size;
old_xfer_pkt_ixlp->ixl_buf.ixldmac_addr =
new_xfer_pkt_ixlp->ixl_buf.ixldmac_addr;
old_xfer_pkt_ixlp->mem_bufp = new_xfer_pkt_ixlp->mem_bufp;
break;
}
case IXL1394_OP_RECV_BUF_U: {
ixl1394_xfer_buf_t *old_xfer_buf_ixlp;
ixl1394_xfer_buf_t *new_xfer_buf_ixlp;
uint32_t desc_hdr;
uint32_t desc_status;
old_xfer_buf_ixlp = (ixl1394_xfer_buf_t *)uvp->ixloldp;
new_xfer_buf_ixlp = (ixl1394_xfer_buf_t *)uvp->ixlnewp;
for (ii = 0; ii < xferctlp->cnt; ii++) {
hcidescp = (hci1394_desc_imm_t *)
xferctlp->dma[ii].dma_descp - uvp->hci_offset;
acc_hdl = xferctlp->dma[ii].dma_buf->bi_handle;
dma_hdl = xferctlp->dma[ii].dma_buf->bi_dma_handle;
ddi_put32(acc_hdl, &hcidescp->data_addr, uvp->bufaddr);
uvp->bufaddr += uvp->bufsize;
err = ddi_dma_sync(dma_hdl, (off_t)hcidescp,
sizeof (hci1394_desc_imm_t), DDI_DMA_SYNC_FORCPU);
if (err != DDI_SUCCESS) {
uvp->upd_status = IXL1394_EINTERNAL_ERROR;
return (DDI_FAILURE);
}
desc_hdr = ddi_get32(acc_hdl, &hcidescp->hdr);
desc_hdr = (desc_hdr & ~DESC_HDR_REQCOUNT_MASK) |
uvp->hcihdr;
ddi_put32(acc_hdl, &hcidescp->hdr, desc_hdr);
desc_status = ddi_get32(acc_hdl, &hcidescp->status);
desc_status = (desc_status & ~DESC_ST_RESCOUNT_MASK) |
uvp->hcistatus;
ddi_put32(acc_hdl, &hcidescp->status, desc_status);
err = ddi_dma_sync(dma_hdl, (off_t)hcidescp,
sizeof (hci1394_desc_imm_t), DDI_DMA_SYNC_FORDEV);
if (err != DDI_SUCCESS) {
uvp->upd_status = IXL1394_EINTERNAL_ERROR;
return (DDI_FAILURE);
}
}
old_xfer_buf_ixlp->pkt_size = new_xfer_buf_ixlp->pkt_size;
old_xfer_buf_ixlp->size = new_xfer_buf_ixlp->size;
old_xfer_buf_ixlp->ixl_buf.ixldmac_addr =
new_xfer_buf_ixlp->ixl_buf.ixldmac_addr;
old_xfer_buf_ixlp->mem_bufp = new_xfer_buf_ixlp->mem_bufp;
break;
}
case IXL1394_OP_SEND_PKT_U:
case IXL1394_OP_SEND_PKT_ST_U:
case IXL1394_OP_SEND_PKT_WHDR_ST_U: {
ixl1394_xfer_pkt_t *old_xfer_pkt_ixlp;
ixl1394_xfer_pkt_t *new_xfer_pkt_ixlp;
old_xfer_pkt_ixlp = (ixl1394_xfer_pkt_t *)uvp->ixloldp;
new_xfer_pkt_ixlp = (ixl1394_xfer_pkt_t *)uvp->ixlnewp;
hcidescp = (hci1394_desc_imm_t *)xferctlp->dma[0].dma_descp -
uvp->hdr_offset;
acc_hdl = xferctlp->dma[0].dma_buf->bi_handle;
dma_hdl = xferctlp->dma[0].dma_buf->bi_dma_handle;
ddi_put32(acc_hdl, &hcidescp->q2, uvp->pkthdr2);
ddi_put32(acc_hdl, &hcidescp->hdr, uvp->hcihdr);
ddi_put32(acc_hdl, &hcidescp->data_addr, uvp->bufaddr);
err = ddi_dma_sync(dma_hdl, (off_t)hcidescp,
sizeof (hci1394_desc_imm_t), DDI_DMA_SYNC_FORDEV);
if (err != DDI_SUCCESS) {
uvp->upd_status = IXL1394_EINTERNAL_ERROR;
return (DDI_FAILURE);
}
old_xfer_pkt_ixlp->size = new_xfer_pkt_ixlp->size;
old_xfer_pkt_ixlp->ixl_buf.ixldmac_addr =
new_xfer_pkt_ixlp->ixl_buf.ixldmac_addr;
old_xfer_pkt_ixlp->mem_bufp = new_xfer_pkt_ixlp->mem_bufp;
break;
}
case IXL1394_OP_SEND_BUF_U: {
ixl1394_xfer_buf_t *old_xfer_buf_ixlp;
ixl1394_xfer_buf_t *new_xfer_buf_ixlp;
uint32_t desc_hdr;
old_xfer_buf_ixlp = (ixl1394_xfer_buf_t *)uvp->ixloldp;
new_xfer_buf_ixlp = (ixl1394_xfer_buf_t *)uvp->ixlnewp;
for (ii = 0; ii < xferctlp->cnt; ii++) {
hcidescp = (hci1394_desc_imm_t *)
xferctlp->dma[ii].dma_descp - uvp->hdr_offset;
acc_hdl = xferctlp->dma[ii].dma_buf->bi_handle;
dma_hdl = xferctlp->dma[ii].dma_buf->bi_dma_handle;
ddi_put32(acc_hdl, &hcidescp->q2, uvp->pkthdr2);
ddi_put32(acc_hdl, &hcidescp->data_addr, uvp->bufaddr);
uvp->bufaddr += uvp->bufsize;
err = ddi_dma_sync(dma_hdl, (off_t)hcidescp,
sizeof (hci1394_desc_imm_t), DDI_DMA_SYNC_FORCPU);
if (err != DDI_SUCCESS) {
uvp->upd_status = IXL1394_EINTERNAL_ERROR;
return (DDI_FAILURE);
}
desc_hdr = ddi_get32(acc_hdl, &hcidescp->hdr);
desc_hdr = (desc_hdr & ~DESC_HDR_REQCOUNT_MASK) |
uvp->hcihdr;
ddi_put32(acc_hdl, &hcidescp->hdr, desc_hdr);
err = ddi_dma_sync(dma_hdl, (off_t)hcidescp,
sizeof (hci1394_desc_imm_t), DDI_DMA_SYNC_FORDEV);
if (err != DDI_SUCCESS) {
uvp->upd_status = IXL1394_EINTERNAL_ERROR;
return (DDI_FAILURE);
}
}
old_xfer_buf_ixlp->pkt_size = new_xfer_buf_ixlp->pkt_size;
old_xfer_buf_ixlp->size = new_xfer_buf_ixlp->size;
old_xfer_buf_ixlp->ixl_buf.ixldmac_addr =
new_xfer_buf_ixlp->ixl_buf.ixldmac_addr;
old_xfer_buf_ixlp->mem_bufp = new_xfer_buf_ixlp->mem_bufp;
break;
}
default:
uvp->upd_status = IXL1394_EINTERNAL_ERROR;
return (DDI_FAILURE);
}
if (ctxtp->ctxt_flags & HCI1394_ISO_CTXT_RECV) {
HCI1394_IRCTXT_CTRL_SET(uvp->soft_statep, ctxtp->ctxt_index,
0, 0, 0, 0, 0, 1 );
} else {
HCI1394_ITCTXT_CTRL_SET(uvp->soft_statep, ctxtp->ctxt_index,
0, 0, 0, 1 );
}
return (DDI_SUCCESS);
}
static int
hci1394_ixl_update_evaluate(hci1394_ixl_update_vars_t *uvp)
{
hci1394_iso_ctxt_t *ctxtp;
ixl1394_command_t *ixlp;
int ixldepth;
int ii;
ctxtp = uvp->ctxtp;
ixlp = NULL;
ixldepth = 0xFFFFFFFF;
while ((ixlp != ctxtp->ixl_execp) ||
(ixldepth != ctxtp->ixl_exec_depth)) {
ixlp = ctxtp->ixl_execp;
ixldepth = ctxtp->ixl_exec_depth;
ctxtp->intr_flags &= ~HCI1394_ISO_CTXT_INTRSET;
if (hci1394_ixl_dma_sync(uvp->soft_statep, ctxtp) ==
HCI1394_IXL_INTR_DMALOST) {
uvp->upd_status = IXL1394_EPOST_UPD_DMALOST;
return (DDI_FAILURE);
}
}
for (ii = 0; ii < IXL_MAX_LOCN; ii++) {
if ((uvp->locn_info[ii].ixlp == ixlp) &&
(uvp->locn_info[ii].ixldepth == ixldepth)) {
return (DDI_SUCCESS);
}
}
uvp->upd_status = IXL1394_EPOST_UPD_DMALOST;
return (DDI_FAILURE);
}
static int
hci1394_ixl_update_analysis(hci1394_ixl_update_vars_t *uvp)
{
hci1394_iso_ctxt_t *ctxtp;
ixl1394_command_t *ixlp;
int ixldepth;
int ii;
int status;
ctxtp = uvp->ctxtp;
ixlp = NULL;
ixldepth = 0xFFFFFFFF;
while ((ixlp != ctxtp->ixl_execp) ||
(ixldepth != ctxtp->ixl_exec_depth)) {
ixlp = ctxtp->ixl_execp;
ixldepth = ctxtp->ixl_exec_depth;
ctxtp->intr_flags &= ~HCI1394_ISO_CTXT_INTRSET;
status = hci1394_ixl_dma_sync(uvp->soft_statep, ctxtp);
if (status == HCI1394_IXL_INTR_DMALOST) {
uvp->upd_status = IXL1394_EPRE_UPD_DMALOST;
return (DDI_FAILURE);
}
}
hci1394_ixl_update_set_locn_info(uvp);
for (ii = 0; ii < IXL_MAX_LOCN; ii++) {
if ((uvp->locn_info[ii].ixlp == uvp->ixlxferp) &&
(uvp->locn_info[ii].ixldepth >= uvp->ixldepth) &&
(uvp->locn_info[ii].ixldepth <
(uvp->ixldepth + uvp->ixlcount))) {
uvp->upd_status = IXL1394_ERISK_PROHIBITS_UPD;
return (DDI_FAILURE);
}
}
return (DDI_SUCCESS);
}
static void
hci1394_ixl_update_set_locn_info(hci1394_ixl_update_vars_t *uvp)
{
hci1394_iso_ctxt_t *ctxtp;
ixl1394_command_t *ixlp;
int ixldepth;
int ii;
ctxtp = uvp->ctxtp;
ixldepth = ctxtp->ixl_exec_depth;
(void) hci1394_ixl_find_next_exec_xfer(ctxtp->ixl_execp, NULL, &ixlp);
if (ixlp != ctxtp->ixl_execp)
ixldepth = 0;
for (ii = 0; ii < IXL_MAX_LOCN; ii++) {
uvp->locn_info[ii].ixlp = ixlp;
uvp->locn_info[ii].ixldepth = ixldepth;
if (ixlp) {
if (++ixldepth >= ((hci1394_xfer_ctl_t *)
ixlp->compiler_privatep)->cnt) {
(void) hci1394_ixl_find_next_exec_xfer(
ixlp->next_ixlp, NULL, &ixlp);
ixldepth = 0;
}
}
}
}