1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * hci1394_ixl_update.c 28 * Isochronous IXL update routines. 29 * Routines used to dynamically update a compiled and presumably running 30 * IXL program. 31 */ 32 33 #include <sys/kmem.h> 34 #include <sys/types.h> 35 #include <sys/conf.h> 36 #include <sys/disp.h> 37 #include <sys/1394/h1394.h> 38 #include <sys/1394/ixl1394.h> /* IXL opcodes & data structs */ 39 40 #include <sys/1394/adapters/hci1394.h> 41 42 43 /* local defines for hci1394_ixl_update_prepare return codes */ 44 #define IXL_PREP_READY 1 45 #define IXL_PREP_SUCCESS 0 46 #define IXL_PREP_FAILURE (-1) 47 48 /* 49 * variable used to indicate the number of times update will wait for 50 * interrupt routine to complete. 51 */ 52 int hci1394_upd_retries_before_fail = 50; 53 54 /* IXL runtime update static functions */ 55 static int hci1394_ixl_update_prepare(hci1394_ixl_update_vars_t *uvp); 56 static int hci1394_ixl_update_prep_jump(hci1394_ixl_update_vars_t *uvp); 57 static int hci1394_ixl_update_prep_set_skipmode(hci1394_ixl_update_vars_t *uvp); 58 static int hci1394_ixl_update_prep_set_tagsync(hci1394_ixl_update_vars_t *uvp); 59 static int hci1394_ixl_update_prep_recv_pkt(hci1394_ixl_update_vars_t *uvp); 60 static int hci1394_ixl_update_prep_recv_buf(hci1394_ixl_update_vars_t *uvp); 61 static int hci1394_ixl_update_prep_send_pkt(hci1394_ixl_update_vars_t *uvp); 62 static int hci1394_ixl_update_prep_send_buf(hci1394_ixl_update_vars_t *uvp); 63 static int hci1394_ixl_update_perform(hci1394_ixl_update_vars_t *uvp); 64 static int hci1394_ixl_update_evaluate(hci1394_ixl_update_vars_t *uvp); 65 static int hci1394_ixl_update_analysis(hci1394_ixl_update_vars_t *uvp); 66 static void hci1394_ixl_update_set_locn_info(hci1394_ixl_update_vars_t *uvp); 67 static int hci1394_ixl_update_enable(hci1394_ixl_update_vars_t *uvp); 68 static int hci1394_ixl_update_endup(hci1394_ixl_update_vars_t *uvp); 69 70 /* 71 * IXL commands and included fields which can be updated 72 * IXL1394_OP_CALLBACK: callback(), callback_data 73 * IXL1394_OP_JUMP: label 74 * IXL1394_OP_RECV_PKT ixl_buf, size, mem_bufp 75 * IXL1394_OP_RECV_PKT_ST ixl_buf, size, mem_bufp 76 * IXL1394_OP_RECV_BUF(ppb) ixl_buf, size, pkt_size, mem_bufp, buf_offset 77 * IXL1394_OP_RECV_BUF(fill) ixl_buf, size, pkt_size, mem_bufp, buf_offset 78 * IXL1394_OP_SEND_PKT ixl_buf, size, mem_bufp 79 * IXL1394_OP_SEND_PKT_ST ixl_buf, size, mem_bufp 80 * IXL1394_OP_SEND_PKT_WHDR_ST ixl_buf, size, mem_bufp 81 * IXL1394_OP_SEND_BUF ixl_buf, size, pkt_size, mem_bufp, buf_offset 82 * IXL1394_OP_SET_TAGSYNC tag, sync 83 * IXL1394_OP_SET_SKIPMODE skipmode, label 84 * 85 * IXL commands which can not be updated 86 * IXL1394_OP_LABEL 87 * IXL1394_OP_SEND_HDR_ONLY 88 * IXL1394_OP_SEND_NOPKT 89 * IXL1394_OP_STORE_VALUE 90 * IXL1394_OP_STORE_TIMESTAMP 91 * IXL1394_OP_SET_SYNCWAIT 92 */ 93 94 /* 95 * hci1394_ixl_update 96 * main entrypoint into dynamic update code: initializes temporary 97 * update variables, evaluates request, coordinates with potentially 98 * simultaneous run of interrupt stack, evaluates likelyhood of success, 99 * performs the update, checks if completed, performs cleanup 100 * resulting from coordination with interrupt stack. 101 */ 102 int 103 hci1394_ixl_update(hci1394_state_t *soft_statep, hci1394_iso_ctxt_t *ctxtp, 104 ixl1394_command_t *ixlnewp, ixl1394_command_t *ixloldp, 105 uint_t riskoverride, int *resultp) 106 { 107 hci1394_ixl_update_vars_t uv; /* update work variables structure */ 108 int prepstatus; 109 int ret; 110 111 /* save caller specified values in update work variables structure */ 112 uv.soft_statep = soft_statep; 113 uv.ctxtp = ctxtp; 114 uv.ixlnewp = ixlnewp; 115 uv.ixloldp = ixloldp; 116 uv.risklevel = riskoverride; 117 118 /* initialize remainder of update work variables */ 119 uv.ixlxferp = NULL; 120 uv.skipxferp = NULL; 121 uv.skipmode = 0; 122 uv.skipaddr = 0; 123 uv.jumpaddr = 0; 124 uv.pkthdr1 = 0; 125 uv.pkthdr2 = 0; 126 uv.bufaddr = 0; 127 uv.bufsize = 0; 128 uv.ixl_opcode = uv.ixlnewp->ixl_opcode; 129 uv.hcihdr = 0; 130 uv.hcistatus = 0; 131 uv.hci_offset = 0; 132 uv.hdr_offset = 0; 133 134 /* set done ok return status */ 135 uv.upd_status = 0; 136 137 /* evaluate request and prepare to perform update */ 138 prepstatus = hci1394_ixl_update_prepare(&uv); 139 if (prepstatus != IXL_PREP_READY) { 140 /* 141 * if either done or nothing to do or an evaluation error, 142 * return update status 143 */ 144 *resultp = uv.upd_status; 145 146 /* if prep evaluation error, return failure */ 147 if (prepstatus != IXL_PREP_SUCCESS) { 148 return (DDI_FAILURE); 149 } 150 /* if no action or update done, return update successful */ 151 return (DDI_SUCCESS); 152 } 153 154 /* perform update processing reservation of interrupt context */ 155 ret = hci1394_ixl_update_enable(&uv); 156 if (ret != DDI_SUCCESS) { 157 158 /* error acquiring control of context - return */ 159 *resultp = uv.upd_status; 160 161 return (DDI_FAILURE); 162 } 163 164 /* perform update risk analysis */ 165 if (hci1394_ixl_update_analysis(&uv) != DDI_SUCCESS) { 166 /* 167 * return, if excessive risk or dma execution processing lost 168 * (note: caller risk override not yet implemented) 169 */ 170 171 /* attempt intr processing cleanup, unless err is dmalost */ 172 if (uv.upd_status != IXL1394_EPRE_UPD_DMALOST) { 173 (void) hci1394_ixl_update_endup(&uv); 174 } else { 175 /* 176 * error is dmalost, just release interrupt context. 177 * take the lock here to ensure an atomic read, modify, 178 * write of the "intr_flags" field while we try to 179 * clear the "in update" flag. protects from the 180 * interrupt routine. 181 */ 182 mutex_enter(&ctxtp->intrprocmutex); 183 ctxtp->intr_flags &= ~HCI1394_ISO_CTXT_INUPDATE; 184 mutex_exit(&ctxtp->intrprocmutex); 185 } 186 *resultp = uv.upd_status; 187 188 return (DDI_FAILURE); 189 } 190 191 192 /* perform requested update */ 193 if (hci1394_ixl_update_perform(&uv) != DDI_SUCCESS) { 194 /* 195 * if non-completion condition, return update status 196 * attempt interrupt processing cleanup first 197 */ 198 (void) hci1394_ixl_update_endup(&uv); 199 200 *resultp = uv.upd_status; 201 202 return (DDI_FAILURE); 203 } 204 205 /* evaluate update completion, setting completion status */ 206 if (hci1394_ixl_update_evaluate(&uv) != DDI_SUCCESS) { 207 /* 208 * update failed - bad, just release interrupt context 209 * take the lock here too (jsut like above) to ensure an 210 * atomic read, modify, write of the "intr_flags" field 211 * while we try to clear the "in update" flag. protects 212 * from the interrupt routine. 213 */ 214 mutex_enter(&ctxtp->intrprocmutex); 215 ctxtp->intr_flags &= ~HCI1394_ISO_CTXT_INUPDATE; 216 mutex_exit(&ctxtp->intrprocmutex); 217 218 /* if DMA stopped or lost, formally stop context */ 219 if (uv.upd_status == HCI1394_IXL_INTR_DMASTOP) { 220 hci1394_do_stop(soft_statep, ctxtp, B_TRUE, 221 ID1394_DONE); 222 } else if (uv.upd_status == HCI1394_IXL_INTR_DMALOST) { 223 hci1394_do_stop(soft_statep, ctxtp, B_TRUE, 224 ID1394_FAIL); 225 } 226 227 *resultp = uv.upd_status; 228 229 return (DDI_FAILURE); 230 } 231 232 /* perform interrupt processing cleanup */ 233 uv.upd_status = hci1394_ixl_update_endup(&uv); 234 235 /* return update completion status */ 236 *resultp = uv.upd_status; 237 238 return (DDI_SUCCESS); 239 } 240 241 /* 242 * hci1394_ixl_update_enable 243 * Used to coordinate dynamic update activities with simultaneous 244 * interrupt handler processing, while holding the context mutex 245 * for as short a time as possible. 246 */ 247 static int 248 hci1394_ixl_update_enable(hci1394_ixl_update_vars_t *uvp) 249 { 250 int status; 251 boolean_t retry; 252 uint_t remretries; 253 254 retry = B_TRUE; 255 /* set arbitrary number of retries before giving up */ 256 remretries = hci1394_upd_retries_before_fail; 257 status = DDI_SUCCESS; 258 259 /* 260 * if waited for completion of interrupt processing generated callback, 261 * retry here 262 */ 263 ASSERT(MUTEX_NOT_HELD(&uvp->ctxtp->intrprocmutex)); 264 mutex_enter(&uvp->ctxtp->intrprocmutex); 265 266 while (retry == B_TRUE) { 267 retry = B_FALSE; 268 remretries--; 269 270 /* failure if update processing is already in progress */ 271 if (uvp->ctxtp->intr_flags & HCI1394_ISO_CTXT_INUPDATE) { 272 uvp->upd_status = IXL1394_EUPDATE_DISALLOWED; 273 status = DDI_FAILURE; 274 } else if (uvp->ctxtp->intr_flags & HCI1394_ISO_CTXT_ININTR) { 275 /* 276 * if have retried max number of times or if this update 277 * request is on the interrupt stack, which means that 278 * the callback function of the target driver initiated 279 * the update, set update failure. 280 */ 281 if ((remretries <= 0) || 282 (servicing_interrupt())) { 283 uvp->upd_status = IXL1394_EUPDATE_DISALLOWED; 284 status = DDI_FAILURE; 285 } else { 286 /* 287 * if not on interrupt stack and retries not 288 * exhausted, free mutex, wait a short time 289 * and then retry. 290 */ 291 retry = B_TRUE; 292 mutex_exit(&uvp->ctxtp->intrprocmutex); 293 drv_usecwait(1); 294 mutex_enter(&uvp->ctxtp->intrprocmutex); 295 continue; 296 } 297 } else if (uvp->ctxtp->intr_flags & HCI1394_ISO_CTXT_INCALL) { 298 uvp->upd_status = IXL1394_EINTERNAL_ERROR; 299 status = DDI_FAILURE; 300 } 301 } 302 303 /* if context is available, reserve it for this update request */ 304 if (status == DDI_SUCCESS) { 305 uvp->ctxtp->intr_flags |= HCI1394_ISO_CTXT_INUPDATE; 306 } 307 308 ASSERT(MUTEX_HELD(&uvp->ctxtp->intrprocmutex)); 309 mutex_exit(&uvp->ctxtp->intrprocmutex); 310 311 return (status); 312 } 313 314 /* 315 * hci1394_ixl_update_endup() 316 * The ending stage of coordinating with simultaneously running interrupts. 317 * Perform interrupt processing sync tasks if we (update) had blocked the 318 * interrupt out when it wanted a turn. 319 */ 320 static int 321 hci1394_ixl_update_endup(hci1394_ixl_update_vars_t *uvp) 322 { 323 uint_t status; 324 hci1394_iso_ctxt_t *ctxtp; 325 326 status = HCI1394_IXL_INTR_NOERROR; 327 ctxtp = uvp->ctxtp; 328 329 while (ctxtp->intr_flags & HCI1394_ISO_CTXT_INUPDATE) { 330 331 if (ctxtp->intr_flags & HCI1394_ISO_CTXT_INTRSET) { 332 /* 333 * We don't need to grab the lock here because 334 * the "intr_flags" field is only modified in two 335 * ways - one in UPDATE and one in INTR routine. Since 336 * we know that it can't be modified simulataneously 337 * in another UDPATE thread - that is assured by the 338 * checks in "update_enable" - we would only be trying 339 * to protect against the INTR thread. And since we 340 * are going to clear a bit here (and check it again 341 * at the top of the loop) we are not really concerned 342 * about missing its being set by the INTR routine. 343 */ 344 ctxtp->intr_flags &= ~HCI1394_ISO_CTXT_INTRSET; 345 346 status = hci1394_ixl_dma_sync(uvp->soft_statep, ctxtp); 347 if (status == HCI1394_IXL_INTR_DMALOST) { 348 /* 349 * Unlike above, we do care here as we are 350 * trying to clear the "in update" flag, and 351 * we don't want that lost because the INTR 352 * routine is trying to set its flag. 353 */ 354 mutex_enter(&uvp->ctxtp->intrprocmutex); 355 ctxtp->intr_flags &= ~HCI1394_ISO_CTXT_INUPDATE; 356 mutex_exit(&uvp->ctxtp->intrprocmutex); 357 continue; 358 } 359 } 360 361 ASSERT(MUTEX_NOT_HELD(&uvp->ctxtp->intrprocmutex)); 362 mutex_enter(&uvp->ctxtp->intrprocmutex); 363 if (!(ctxtp->intr_flags & HCI1394_ISO_CTXT_INTRSET)) { 364 ctxtp->intr_flags &= ~HCI1394_ISO_CTXT_INUPDATE; 365 } 366 mutex_exit(&uvp->ctxtp->intrprocmutex); 367 } 368 369 /* if DMA stopped or lost, formally stop context */ 370 if (status == HCI1394_IXL_INTR_DMASTOP) { 371 hci1394_do_stop(uvp->soft_statep, ctxtp, B_TRUE, ID1394_DONE); 372 } else if (status == HCI1394_IXL_INTR_DMALOST) { 373 hci1394_do_stop(uvp->soft_statep, ctxtp, B_TRUE, ID1394_FAIL); 374 } 375 376 return (status); 377 } 378 379 /* 380 * hci1394_ixl_update_prepare() 381 * Preparation for the actual update (using temp uvp struct) 382 */ 383 static int 384 hci1394_ixl_update_prepare(hci1394_ixl_update_vars_t *uvp) 385 { 386 int ret; 387 388 /* both new and old ixl commands must be the same */ 389 if (uvp->ixlnewp->ixl_opcode != uvp->ixloldp->ixl_opcode) { 390 391 uvp->upd_status = IXL1394_EOPCODE_MISMATCH; 392 393 return (IXL_PREP_FAILURE); 394 } 395 396 /* 397 * perform evaluation and prepare update based on specific 398 * IXL command type 399 */ 400 switch (uvp->ixl_opcode) { 401 402 case IXL1394_OP_CALLBACK_U: { 403 ixl1394_callback_t *old_callback_ixlp; 404 ixl1394_callback_t *new_callback_ixlp; 405 406 old_callback_ixlp = (ixl1394_callback_t *)uvp->ixloldp; 407 new_callback_ixlp = (ixl1394_callback_t *)uvp->ixlnewp; 408 409 /* perform update now without further evaluation */ 410 old_callback_ixlp->callback_arg = 411 new_callback_ixlp->callback_arg; 412 old_callback_ixlp->callback = new_callback_ixlp->callback; 413 414 /* nothing else to do, return with done ok status */ 415 return (IXL_PREP_SUCCESS); 416 } 417 418 case IXL1394_OP_JUMP_U: 419 ret = hci1394_ixl_update_prep_jump(uvp); 420 421 return (ret); 422 423 case IXL1394_OP_SET_SKIPMODE_U: 424 ret = hci1394_ixl_update_prep_set_skipmode(uvp); 425 426 return (ret); 427 428 case IXL1394_OP_SET_TAGSYNC_U: 429 ret = hci1394_ixl_update_prep_set_tagsync(uvp); 430 431 return (ret); 432 433 case IXL1394_OP_RECV_PKT_U: 434 case IXL1394_OP_RECV_PKT_ST_U: 435 ret = hci1394_ixl_update_prep_recv_pkt(uvp); 436 437 return (ret); 438 439 case IXL1394_OP_RECV_BUF_U: 440 ret = hci1394_ixl_update_prep_recv_buf(uvp); 441 442 return (ret); 443 444 case IXL1394_OP_SEND_PKT_U: 445 case IXL1394_OP_SEND_PKT_ST_U: 446 case IXL1394_OP_SEND_PKT_WHDR_ST_U: 447 ret = hci1394_ixl_update_prep_send_pkt(uvp); 448 449 return (ret); 450 451 case IXL1394_OP_SEND_BUF_U: 452 ret = hci1394_ixl_update_prep_send_buf(uvp); 453 454 return (ret); 455 456 default: 457 /* ixl command being updated must be one of above, else error */ 458 uvp->upd_status = IXL1394_EOPCODE_DISALLOWED; 459 460 return (IXL_PREP_FAILURE); 461 } 462 } 463 464 /* 465 * hci1394_ixl_update_prep_jump() 466 * Preparation for update of an IXL1394_OP_JUMP_U command. 467 */ 468 static int 469 hci1394_ixl_update_prep_jump(hci1394_ixl_update_vars_t *uvp) 470 { 471 ixl1394_jump_t *old_jump_ixlp; 472 ixl1394_jump_t *new_jump_ixlp; 473 ixl1394_command_t *ixlp; 474 hci1394_xfer_ctl_t *xferctlp; 475 hci1394_desc_t *hcidescp; 476 uint_t cbcnt; 477 ddi_acc_handle_t acc_hdl; 478 ddi_dma_handle_t dma_hdl; 479 uint32_t desc_hdr; 480 int err; 481 482 old_jump_ixlp = (ixl1394_jump_t *)uvp->ixloldp; 483 new_jump_ixlp = (ixl1394_jump_t *)uvp->ixlnewp; 484 485 /* check if any change between new and old ixl jump command */ 486 if (new_jump_ixlp->label == old_jump_ixlp->label) { 487 488 /* if none, return with done ok status */ 489 return (IXL_PREP_SUCCESS); 490 } 491 492 /* new ixl jump command label must be ptr to valid ixl label or NULL */ 493 if ((new_jump_ixlp->label != NULL) && 494 (new_jump_ixlp->label->ixl_opcode != IXL1394_OP_LABEL)) { 495 496 /* if not jumping to label, return an error */ 497 uvp->upd_status = IXL1394_EJUMP_NOT_TO_LABEL; 498 499 return (IXL_PREP_FAILURE); 500 } 501 502 /* 503 * follow exec path from new ixl jump command label to determine new 504 * jump destination ixl xfer command 505 */ 506 (void) hci1394_ixl_find_next_exec_xfer(new_jump_ixlp->label, &cbcnt, 507 &ixlp); 508 if (ixlp != NULL) { 509 /* 510 * get the bound address of the first descriptor block reached 511 * by the jump destination. (This descriptor is the first 512 * transfer command following the jumped-to label.) Set the 513 * descriptor's address (with Z bits) into jumpaddr. 514 */ 515 uvp->jumpaddr = ((hci1394_xfer_ctl_t *) 516 ixlp->compiler_privatep)->dma[0].dma_bound; 517 } 518 519 /* 520 * get associated xfer IXL command from compiler_privatep of old 521 * jump command 522 */ 523 if ((uvp->ixlxferp = (ixl1394_command_t *) 524 old_jump_ixlp->compiler_privatep) == NULL) { 525 526 /* if none, return an error */ 527 uvp->upd_status = IXL1394_EORIG_IXL_CORRUPTED; 528 529 return (IXL_PREP_FAILURE); 530 } 531 532 /* 533 * get the associated IXL xfer command's last dma descriptor block 534 * last descriptor, then get hcihdr from its hdr field, 535 * removing interrupt enabled bits 536 */ 537 xferctlp = (hci1394_xfer_ctl_t *)uvp->ixlxferp->compiler_privatep; 538 hcidescp = (hci1394_desc_t *)xferctlp->dma[xferctlp->cnt - 1].dma_descp; 539 acc_hdl = xferctlp->dma[xferctlp->cnt - 1].dma_buf->bi_handle; 540 dma_hdl = xferctlp->dma[xferctlp->cnt - 1].dma_buf->bi_dma_handle; 541 542 /* Sync the descriptor before we grab the header(s) */ 543 err = ddi_dma_sync(dma_hdl, (off_t)hcidescp, sizeof (hci1394_desc_t), 544 DDI_DMA_SYNC_FORCPU); 545 if (err != DDI_SUCCESS) { 546 uvp->upd_status = IXL1394_EINTERNAL_ERROR; 547 548 return (IXL_PREP_FAILURE); 549 } 550 551 desc_hdr = ddi_get32(acc_hdl, &hcidescp->hdr); 552 uvp->hcihdr = desc_hdr & ~DESC_INTR_ENBL; 553 554 /* set depth to last dma descriptor block & update count to 1 */ 555 uvp->ixldepth = xferctlp->cnt - 1; 556 uvp->ixlcount = 1; 557 558 /* 559 * if there is only one dma descriptor block and IXL xfer command 560 * inited by a label or have found callbacks along the exec path to the 561 * new destination IXL xfer command, enable interrupt in hcihdr value 562 */ 563 if (((xferctlp->cnt == 1) && 564 ((xferctlp->ctl_flags & XCTL_LABELLED) != 0)) || (cbcnt != 0)) { 565 566 uvp->hcihdr |= DESC_INTR_ENBL; 567 } 568 569 /* If either old or new destination was/is NULL, enable interrupt */ 570 if ((new_jump_ixlp->label == NULL) || (old_jump_ixlp->label == NULL)) { 571 uvp->hcihdr |= DESC_INTR_ENBL; 572 } 573 574 /* 575 * if xfer type is xmit and skip mode for this for this xfer command is 576 * IXL1394_SKIP_TO_NEXT then set uvp->skipmode to IXL1394_SKIP_TO_NEXT 577 * and set uvp->skipxferp to uvp->jumpaddr and set uvp->hci_offset to 578 * offset from last dma descriptor to first dma descriptor 579 * (where skipaddr goes). 580 * 581 * update perform processing will have to set skip branch address to 582 * same location as jump destination in this case. 583 */ 584 uvp->skipmode = IXL1394_SKIP_TO_STOP; 585 if ((uvp->ixlxferp->ixl_opcode & IXL1394_OPF_ONXMIT) != 0) { 586 587 if ((xferctlp->skipmodep && (((ixl1394_set_skipmode_t *) 588 xferctlp->skipmodep)->skipmode == IXL1394_SKIP_TO_NEXT)) || 589 (uvp->ctxtp->default_skipmode == IXL1394_OPF_ONXMIT)) { 590 591 uvp->skipmode = IXL1394_SKIP_TO_NEXT; 592 uvp->skipaddr = uvp->jumpaddr; 593 594 /* 595 * calc hci_offset to first descriptor (where skipaddr 596 * goes) of dma descriptor block from current (last) 597 * descriptor of the descriptor block (accessed in 598 * xfer_ctl dma_descp of IXL xfer command) 599 */ 600 if (uvp->ixlxferp->ixl_opcode == 601 IXL1394_OP_SEND_HDR_ONLY) { 602 /* 603 * send header only is (Z bits - 2) 604 * descriptor components back from last one 605 */ 606 uvp->hci_offset -= 2; 607 } else { 608 /* 609 * all others are (Z bits - 1) descriptor 610 * components back from last component 611 */ 612 uvp->hci_offset -= 1; 613 } 614 } 615 } 616 return (IXL_PREP_READY); 617 } 618 619 /* 620 * hci1394_ixl_update_prep_set_skipmode() 621 * Preparation for update of an IXL1394_OP_SET_SKIPMODE_U command. 622 */ 623 static int 624 hci1394_ixl_update_prep_set_skipmode(hci1394_ixl_update_vars_t *uvp) 625 { 626 ixl1394_set_skipmode_t *old_set_skipmode_ixlp; 627 ixl1394_set_skipmode_t *new_set_skipmode_ixlp; 628 ixl1394_command_t *ixlp; 629 hci1394_xfer_ctl_t *xferctlp; 630 631 old_set_skipmode_ixlp = (ixl1394_set_skipmode_t *)uvp->ixloldp; 632 new_set_skipmode_ixlp = (ixl1394_set_skipmode_t *)uvp->ixlnewp; 633 634 /* check if new set skipmode is change from old set skipmode */ 635 if (new_set_skipmode_ixlp->skipmode == 636 old_set_skipmode_ixlp->skipmode) { 637 638 if ((new_set_skipmode_ixlp->skipmode != 639 IXL1394_SKIP_TO_LABEL) || 640 (old_set_skipmode_ixlp->label == 641 new_set_skipmode_ixlp->label)) { 642 /* No change, return with done ok status */ 643 return (IXL_PREP_SUCCESS); 644 } 645 } 646 647 /* find associated ixl xfer commnd by following old ixl links */ 648 uvp->ixlxferp = uvp->ixloldp->next_ixlp; 649 while ((uvp->ixlxferp != NULL) && (((uvp->ixlxferp->ixl_opcode & 650 IXL1394_OPF_ISXFER) == 0) || 651 ((uvp->ixlxferp->ixl_opcode & IXL1394_OPTY_MASK) != 0))) { 652 653 uvp->ixlxferp = uvp->ixlxferp->next_ixlp; 654 } 655 656 /* return an error if no ixl xfer command found */ 657 if (uvp->ixlxferp == NULL) { 658 659 uvp->upd_status = IXL1394_EORIG_IXL_CORRUPTED; 660 661 return (IXL_PREP_FAILURE); 662 } 663 664 /* 665 * get Z bits (number of descriptor components in descriptor block) 666 * from a dma bound addr in the xfer_ctl struct of the IXL xfer command 667 */ 668 if ((xferctlp = (hci1394_xfer_ctl_t *) 669 uvp->ixlxferp->compiler_privatep) == NULL) { 670 671 uvp->upd_status = IXL1394_EORIG_IXL_CORRUPTED; 672 673 return (IXL_PREP_FAILURE); 674 } 675 uvp->hci_offset = xferctlp->dma[0].dma_bound & DESC_Z_MASK; 676 677 /* 678 * determine hci_offset to first component (where skipaddr goes) of 679 * dma descriptor block from current (last) descriptor component of 680 * desciptor block (accessed in xfer_ctl dma_descp of IXL xfer command) 681 */ 682 if (uvp->ixlxferp->ixl_opcode == IXL1394_OP_SEND_HDR_ONLY) { 683 /* 684 * "send header only" is (Z bits - 2) descriptors back 685 * from last one 686 */ 687 uvp->hci_offset -= 2; 688 } else { 689 /* 690 * all others are (Z bits - 1) descroptors back from 691 * last descriptor. 692 */ 693 uvp->hci_offset -= 1; 694 } 695 696 /* set depth to zero and count to update all dma descriptors */ 697 uvp->ixldepth = 0; 698 uvp->ixlcount = xferctlp->cnt; 699 700 /* set new skipmode and validate */ 701 uvp->skipmode = new_set_skipmode_ixlp->skipmode; 702 703 if ((uvp->skipmode != IXL1394_SKIP_TO_NEXT) && 704 (uvp->skipmode != IXL1394_SKIP_TO_SELF) && 705 (uvp->skipmode != IXL1394_SKIP_TO_STOP) && 706 (uvp->skipmode != IXL1394_SKIP_TO_LABEL)) { 707 708 /* return an error if invalid mode */ 709 uvp->upd_status = IXL1394_EBAD_SKIPMODE; 710 711 return (IXL_PREP_FAILURE); 712 } 713 714 /* if mode is skip to label */ 715 if (uvp->skipmode == IXL1394_SKIP_TO_LABEL) { 716 717 /* verify label field is valid ixl label cmd */ 718 if ((new_set_skipmode_ixlp->label == NULL) || 719 (new_set_skipmode_ixlp->label->ixl_opcode != 720 IXL1394_OP_LABEL)) { 721 722 /* Error - not skipping to valid label */ 723 uvp->upd_status = IXL1394_EBAD_SKIP_LABEL; 724 725 return (IXL_PREP_FAILURE); 726 } 727 728 /* 729 * follow new skip exec path after label to next xfer 730 * IXL command 731 */ 732 (void) hci1394_ixl_find_next_exec_xfer( 733 new_set_skipmode_ixlp->label, NULL, &ixlp); 734 735 /* 736 * set skip destination IXL xfer command. 737 * after update set into old set skip mode IXL compiler_privatep 738 */ 739 if ((uvp->skipxferp = ixlp) != NULL) { 740 /* 741 * set skipaddr to be the first dma descriptor block's 742 * dma bound address w/Z bits 743 */ 744 xferctlp = (hci1394_xfer_ctl_t *) 745 ixlp->compiler_privatep; 746 uvp->skipaddr = xferctlp->dma[0].dma_bound; 747 } 748 } 749 750 /* 751 * if mode is skip to next, get skipaddr for last dma descriptor block 752 */ 753 if (uvp->skipmode == IXL1394_SKIP_TO_NEXT) { 754 /* follow normal exec path to next xfer ixl command */ 755 (void) hci1394_ixl_find_next_exec_xfer(uvp->ixlxferp->next_ixlp, 756 NULL, &ixlp); 757 758 /* 759 * get skip_next destination IXL xfer command 760 * (for last iteration) 761 */ 762 if (ixlp != NULL) { 763 /* 764 * set skipaddr to first dma descriptor block's 765 * dma bound address w/Z bits 766 */ 767 xferctlp = (hci1394_xfer_ctl_t *) 768 ixlp->compiler_privatep; 769 uvp->skipaddr = xferctlp->dma[0].dma_bound; 770 } 771 } 772 return (IXL_PREP_READY); 773 } 774 775 /* 776 * hci1394_ixl_update_prep_set_tagsync() 777 * Preparation for update of an IXL1394_OP_SET_TAGSYNC_U command. 778 */ 779 static int 780 hci1394_ixl_update_prep_set_tagsync(hci1394_ixl_update_vars_t *uvp) 781 { 782 ixl1394_set_tagsync_t *old_set_tagsync_ixlp; 783 ixl1394_set_tagsync_t *new_set_tagsync_ixlp; 784 hci1394_xfer_ctl_t *xferctlp; 785 786 old_set_tagsync_ixlp = (ixl1394_set_tagsync_t *)uvp->ixloldp; 787 new_set_tagsync_ixlp = (ixl1394_set_tagsync_t *)uvp->ixlnewp; 788 789 /* check if new set tagsync is change from old set tagsync. */ 790 if ((new_set_tagsync_ixlp->tag == old_set_tagsync_ixlp->tag) && 791 (new_set_tagsync_ixlp->sync == old_set_tagsync_ixlp->sync)) { 792 793 /* no change, return with done ok status */ 794 return (IXL_PREP_SUCCESS); 795 } 796 797 /* find associated IXL xfer commnd by following old ixl links */ 798 uvp->ixlxferp = uvp->ixloldp->next_ixlp; 799 while ((uvp->ixlxferp != NULL) && (((uvp->ixlxferp->ixl_opcode & 800 IXL1394_OPF_ISXFER) == 0) || 801 ((uvp->ixlxferp->ixl_opcode & IXL1394_OPTY_MASK) != 0))) { 802 803 uvp->ixlxferp = uvp->ixlxferp->next_ixlp; 804 } 805 806 /* return an error if no IXL xfer command found */ 807 if (uvp->ixlxferp == NULL) { 808 809 uvp->upd_status = IXL1394_EORIG_IXL_CORRUPTED; 810 811 return (IXL_PREP_FAILURE); 812 } 813 814 /* is IXL xfer command an IXL1394_OP_SEND_NO_PKT? */ 815 if (uvp->ixlxferp->ixl_opcode == IXL1394_OP_SEND_NO_PKT) { 816 /* no update needed, return done ok status */ 817 return (IXL_PREP_SUCCESS); 818 } 819 820 /* build new pkthdr1 from new IXL tag/sync bits */ 821 uvp->pkthdr1 = (uvp->ctxtp->isospd << DESC_PKT_SPD_SHIFT) | 822 (new_set_tagsync_ixlp->tag << DESC_PKT_TAG_SHIFT) | 823 (uvp->ctxtp->isochan << DESC_PKT_CHAN_SHIFT) | 824 (new_set_tagsync_ixlp->sync << DESC_PKT_SY_SHIFT); 825 826 /* 827 * get Z bits (# of descriptor components in descriptor block) from 828 * any dma bound address in the xfer_ctl struct of the IXL xfer cmd 829 */ 830 if ((xferctlp = (hci1394_xfer_ctl_t *) 831 uvp->ixlxferp->compiler_privatep) == NULL) { 832 833 uvp->upd_status = IXL1394_EORIG_IXL_CORRUPTED; 834 835 return (IXL_PREP_FAILURE); 836 } 837 uvp->hdr_offset = xferctlp->dma[0].dma_bound & DESC_Z_MASK; 838 839 /* 840 * determine hdr_offset from the current(last) descriptor of the 841 * DMA descriptor block to the descriptor where pkthdr1 goes 842 * by examining IXL xfer command 843 */ 844 if (uvp->ixlxferp->ixl_opcode == IXL1394_OP_SEND_HDR_ONLY) { 845 /* 846 * if IXL send header only, the current (last) 847 * descriptor is the one 848 */ 849 uvp->hdr_offset = 0; 850 } else { 851 /* 852 * all others are the first descriptor (Z bits - 1) 853 * back from the last 854 */ 855 uvp->hdr_offset -= 1; 856 } 857 858 /* set depth to zero and count to update all dma descriptors */ 859 uvp->ixldepth = 0; 860 uvp->ixlcount = xferctlp->cnt; 861 862 return (IXL_PREP_READY); 863 } 864 865 /* 866 * hci1394_ixl_update_prep_recv_pkt() 867 * Preparation for update of an IXL1394_OP_RECV_PKT_U or 868 * IXL1394_OP_RECV_PKT_ST_U command. 869 */ 870 static int 871 hci1394_ixl_update_prep_recv_pkt(hci1394_ixl_update_vars_t *uvp) 872 { 873 ixl1394_xfer_pkt_t *old_xfer_pkt_ixlp; 874 ixl1394_xfer_pkt_t *new_xfer_pkt_ixlp; 875 hci1394_xfer_ctl_t *xferctlp; 876 hci1394_desc_t *hcidescp; 877 ddi_acc_handle_t acc_hdl; 878 ddi_dma_handle_t dma_hdl; 879 uint32_t desc_hdr; 880 int err; 881 882 old_xfer_pkt_ixlp = (ixl1394_xfer_pkt_t *)uvp->ixloldp; 883 new_xfer_pkt_ixlp = (ixl1394_xfer_pkt_t *)uvp->ixlnewp; 884 885 /* check if any change between new and old IXL xfer commands */ 886 if ((new_xfer_pkt_ixlp->size == old_xfer_pkt_ixlp->size) && 887 (new_xfer_pkt_ixlp->ixl_buf.ixldmac_addr == 888 old_xfer_pkt_ixlp->ixl_buf.ixldmac_addr) && 889 (new_xfer_pkt_ixlp->mem_bufp == old_xfer_pkt_ixlp->mem_bufp)) { 890 /* no change. return with done ok status */ 891 return (IXL_PREP_SUCCESS); 892 } 893 894 /* if new IXL buffer addrs are null, return error */ 895 if ((new_xfer_pkt_ixlp->ixl_buf.ixldmac_addr == 0) || 896 (new_xfer_pkt_ixlp->mem_bufp == NULL)) { 897 898 uvp->upd_status = IXL1394_EXFER_BUF_MISSING; 899 900 return (IXL_PREP_FAILURE); 901 } 902 903 /* if IXL xfer command is not xfer start command */ 904 if (uvp->ixl_opcode == IXL1394_OP_RECV_PKT_U) { 905 /* 906 * find IXL xfer start command in the compiler_privatep of the 907 * old IXL xfer command 908 */ 909 uvp->ixlxferp = (ixl1394_command_t *) 910 uvp->ixloldp->compiler_privatep; 911 912 if (uvp->ixlxferp == NULL) { 913 /* Error - no IXL xfer start command found */ 914 uvp->upd_status = IXL1394_EORIG_IXL_CORRUPTED; 915 return (IXL_PREP_FAILURE); 916 } 917 } else { 918 /* IXL xfer command is the IXL xfer start command */ 919 uvp->ixlxferp = uvp->ixloldp; 920 } 921 922 /* check that xfer_ctl is present in the IXL xfer start command */ 923 if ((xferctlp = (hci1394_xfer_ctl_t *) 924 uvp->ixlxferp->compiler_privatep) == NULL) { 925 /* Error - no xfer_ctl struct found */ 926 uvp->upd_status = IXL1394_EORIG_IXL_CORRUPTED; 927 return (IXL_PREP_FAILURE); 928 } 929 930 /* set depth to zero and count to 1 to update dma descriptor */ 931 uvp->ixldepth = 0; 932 uvp->ixlcount = 1; 933 934 /* 935 * get Z bits (number of descriptors in descriptor block) from the DMA 936 * bound address in the xfer_ctl struct of the IXL xfer start cpmmand. 937 */ 938 uvp->hci_offset = xferctlp->dma[0].dma_bound & DESC_Z_MASK; 939 940 /* 941 * set offset from the current(last) descriptor to the descriptor for 942 * this packet command 943 */ 944 uvp->hci_offset -= (1 + uvp->ixloldp->compiler_resv); 945 946 /* 947 * set bufsize to the new IXL xfer size, and bufaddr to the new 948 * IXL xfer bufp 949 */ 950 uvp->bufsize = ((ixl1394_xfer_pkt_t *)uvp->ixlnewp)->size; 951 uvp->bufaddr = ((ixl1394_xfer_pkt_t *) 952 uvp->ixlnewp)->ixl_buf.ixldmac_addr; 953 954 /* 955 * update old hcihdr w/new bufsize, set hcistatus rescnt to 956 * new bufsize 957 */ 958 hcidescp = (hci1394_desc_t *)xferctlp->dma[0].dma_descp - 959 uvp->hci_offset; 960 acc_hdl = xferctlp->dma[0].dma_buf->bi_handle; 961 dma_hdl = xferctlp->dma[0].dma_buf->bi_dma_handle; 962 963 /* Sync the descriptor before we grab the header(s) */ 964 err = ddi_dma_sync(dma_hdl, (off_t)hcidescp, sizeof (hci1394_desc_t), 965 DDI_DMA_SYNC_FORCPU); 966 if (err != DDI_SUCCESS) { 967 uvp->upd_status = IXL1394_EINTERNAL_ERROR; 968 return (IXL_PREP_FAILURE); 969 } 970 971 desc_hdr = ddi_get32(acc_hdl, &hcidescp->hdr); 972 uvp->hcihdr = desc_hdr; 973 uvp->hcihdr &= ~DESC_HDR_REQCOUNT_MASK; 974 uvp->hcihdr |= (uvp->bufsize << DESC_HDR_REQCOUNT_SHIFT) & 975 DESC_HDR_REQCOUNT_MASK; 976 uvp->hcistatus = (uvp->bufsize << DESC_ST_RESCOUNT_SHIFT) & 977 DESC_ST_RESCOUNT_MASK; 978 979 return (IXL_PREP_READY); 980 } 981 982 /* 983 * hci1394_ixl_update_prep_recv_buf() 984 * Preparation for update of an IXL1394_OP_RECV_BUF_U command. 985 */ 986 static int 987 hci1394_ixl_update_prep_recv_buf(hci1394_ixl_update_vars_t *uvp) 988 { 989 ixl1394_xfer_buf_t *old_xfer_buf_ixlp; 990 ixl1394_xfer_buf_t *new_xfer_buf_ixlp; 991 hci1394_xfer_ctl_t *xferctlp; 992 993 old_xfer_buf_ixlp = (ixl1394_xfer_buf_t *)uvp->ixloldp; 994 new_xfer_buf_ixlp = (ixl1394_xfer_buf_t *)uvp->ixlnewp; 995 996 /* check if any change between new and old IXL xfer commands */ 997 if ((new_xfer_buf_ixlp->size == old_xfer_buf_ixlp->size) && 998 (new_xfer_buf_ixlp->ixl_buf.ixldmac_addr == 999 old_xfer_buf_ixlp->ixl_buf.ixldmac_addr) && 1000 (new_xfer_buf_ixlp->mem_bufp == old_xfer_buf_ixlp->mem_bufp)) { 1001 1002 if (((uvp->ctxtp->ctxt_flags & HCI1394_ISO_CTXT_BFFILL) != 0) || 1003 (new_xfer_buf_ixlp->pkt_size == 1004 old_xfer_buf_ixlp->pkt_size)) { 1005 /* no change. return with done ok status */ 1006 return (IXL_PREP_SUCCESS); 1007 } 1008 } 1009 1010 /* if new IXL buffer addrs are null, return error */ 1011 if ((new_xfer_buf_ixlp->ixl_buf.ixldmac_addr == 0) || 1012 (new_xfer_buf_ixlp->mem_bufp == NULL)) { 1013 uvp->upd_status = IXL1394_EXFER_BUF_MISSING; 1014 return (IXL_PREP_FAILURE); 1015 } 1016 1017 /* 1018 * if not buffer fill mode, check that the new pkt_size > 0 and 1019 * new size/pkt_size doesn't change the count of dma descriptor 1020 * blocks required 1021 */ 1022 if ((uvp->ctxtp->ctxt_flags & HCI1394_ISO_CTXT_BFFILL) == 0) { 1023 if ((new_xfer_buf_ixlp->pkt_size == 0) || 1024 ((new_xfer_buf_ixlp->size / new_xfer_buf_ixlp->pkt_size) != 1025 (old_xfer_buf_ixlp->size / old_xfer_buf_ixlp->pkt_size))) { 1026 /* count changes. return an error */ 1027 uvp->upd_status = IXL1394_EXFER_BUF_CNT_DIFF; 1028 return (IXL_PREP_FAILURE); 1029 } 1030 } 1031 1032 /* set old IXL xfer command as the current IXL xfer command */ 1033 uvp->ixlxferp = uvp->ixloldp; 1034 1035 /* check that the xfer_ctl struct is present in IXL xfer command */ 1036 if ((xferctlp = (hci1394_xfer_ctl_t *)uvp->ixlxferp->compiler_privatep) 1037 == NULL) { 1038 /* return an error if no xfer_ctl struct is found for command */ 1039 uvp->upd_status = IXL1394_EORIG_IXL_CORRUPTED; 1040 return (IXL_PREP_FAILURE); 1041 } 1042 1043 /* set depth to zero and count to update all dma descriptors */ 1044 uvp->ixldepth = 0; 1045 uvp->ixlcount = xferctlp->cnt; 1046 1047 /* set bufsize to new pkt_size (or to new size if buffer fill mode) */ 1048 if ((uvp->ctxtp->ctxt_flags & HCI1394_ISO_CTXT_BFFILL) == 0) { 1049 uvp->bufsize = new_xfer_buf_ixlp->pkt_size; 1050 } else { 1051 uvp->bufsize = new_xfer_buf_ixlp->size; 1052 } 1053 1054 /* set bufaddr to new ixl_buf */ 1055 uvp->bufaddr = new_xfer_buf_ixlp->ixl_buf.ixldmac_addr; 1056 1057 /* set hcihdr reqcnt and hcistatus rescnt to new bufsize */ 1058 uvp->hci_offset = 0; 1059 uvp->hcihdr = (uvp->bufsize << DESC_HDR_REQCOUNT_SHIFT) & 1060 DESC_HDR_REQCOUNT_MASK; 1061 uvp->hcistatus = (uvp->bufsize << DESC_ST_RESCOUNT_SHIFT) & 1062 DESC_ST_RESCOUNT_MASK; 1063 1064 return (IXL_PREP_READY); 1065 } 1066 1067 /* 1068 * hci1394_ixl_update_prep_send_pkt() 1069 * Preparation for update of an IXL1394_OP_SEND_PKT_U command, 1070 * IXL1394_OP_SEND_PKT_ST_U command and IXL1394_OP_SEND_PKT_WHDR_ST_U 1071 * command. 1072 */ 1073 static int 1074 hci1394_ixl_update_prep_send_pkt(hci1394_ixl_update_vars_t *uvp) 1075 { 1076 ixl1394_xfer_pkt_t *old_xfer_pkt_ixlp; 1077 ixl1394_xfer_pkt_t *new_xfer_pkt_ixlp; 1078 hci1394_xfer_ctl_t *xferctlp; 1079 hci1394_desc_imm_t *hcidescp; 1080 ddi_acc_handle_t acc_hdl; 1081 ddi_dma_handle_t dma_hdl; 1082 uint32_t desc_hdr, desc_hdr2; 1083 int err; 1084 1085 old_xfer_pkt_ixlp = (ixl1394_xfer_pkt_t *)uvp->ixloldp; 1086 new_xfer_pkt_ixlp = (ixl1394_xfer_pkt_t *)uvp->ixlnewp; 1087 1088 /* check if any change between new and old IXL xfer commands */ 1089 if ((new_xfer_pkt_ixlp->size == old_xfer_pkt_ixlp->size) && 1090 (new_xfer_pkt_ixlp->ixl_buf.ixldmac_addr == 1091 old_xfer_pkt_ixlp->ixl_buf.ixldmac_addr) && 1092 (new_xfer_pkt_ixlp->mem_bufp == old_xfer_pkt_ixlp->mem_bufp)) { 1093 1094 /* if none, return with done ok status */ 1095 return (IXL_PREP_SUCCESS); 1096 } 1097 1098 /* if new ixl buffer addrs are null, return error */ 1099 if ((new_xfer_pkt_ixlp->ixl_buf.ixldmac_addr == 0) || 1100 (new_xfer_pkt_ixlp->mem_bufp == NULL)) { 1101 1102 uvp->upd_status = IXL1394_EXFER_BUF_MISSING; 1103 1104 return (IXL_PREP_FAILURE); 1105 } 1106 1107 /* error if IXL1394_OP_SEND_PKT_WHDR_ST_U opcode and size < 4 */ 1108 if ((uvp->ixl_opcode == IXL1394_OP_SEND_PKT_WHDR_ST_U) && 1109 (new_xfer_pkt_ixlp->size < 4)) { 1110 1111 uvp->upd_status = IXL1394_EPKT_HDR_MISSING; 1112 1113 return (IXL_PREP_FAILURE); 1114 } 1115 1116 /* if IXL xfer command is not an IXL xfer start command */ 1117 if (uvp->ixl_opcode == IXL1394_OP_SEND_PKT_U) { 1118 /* 1119 * find IXL xfer start command in the compiler_privatep of the 1120 * old IXL xfer command 1121 */ 1122 uvp->ixlxferp = (ixl1394_command_t *) 1123 old_xfer_pkt_ixlp->compiler_privatep; 1124 1125 if (uvp->ixlxferp == NULL) { 1126 /* error if no IXL xfer start command found */ 1127 uvp->upd_status = IXL1394_EORIG_IXL_CORRUPTED; 1128 1129 return (IXL_PREP_FAILURE); 1130 } 1131 } else { 1132 /* IXL xfer command is the IXL xfer start command */ 1133 uvp->ixlxferp = uvp->ixloldp; 1134 } 1135 1136 /* 1137 * get Z bits (number of descriptor components in the descriptor block) 1138 * from a dma bound address in the xfer_ctl structure of the IXL 1139 * xfer start command 1140 */ 1141 if ((xferctlp = (hci1394_xfer_ctl_t *) 1142 uvp->ixlxferp->compiler_privatep) == NULL) { 1143 1144 uvp->upd_status = IXL1394_EORIG_IXL_CORRUPTED; 1145 1146 return (IXL_PREP_FAILURE); 1147 } 1148 1149 /* set depth to zero and count to 1 to update dma descriptor */ 1150 uvp->ixldepth = 0; 1151 uvp->ixlcount = 1; 1152 1153 /* 1154 * set offset to the header(first) descriptor from the 1155 * current(last) descriptor 1156 */ 1157 uvp->hdr_offset = xferctlp->dma[0].dma_bound & DESC_Z_MASK - 1; 1158 1159 /* 1160 * set offset from the current(last) descriptor to the descriptor for 1161 * this packet command 1162 */ 1163 uvp->hci_offset = uvp->hdr_offset - 2 - uvp->ixloldp->compiler_resv; 1164 1165 /* set bufsize to new pkt buffr size, set bufaddr to new bufp */ 1166 uvp->bufsize = new_xfer_pkt_ixlp->size; 1167 uvp->bufaddr = new_xfer_pkt_ixlp->ixl_buf.ixldmac_addr; 1168 1169 /* 1170 * if IXL1394_OP_SEND_PKT_WHDR_ST_U opcode, adjust size & buff, 1171 * step over hdr 1172 */ 1173 if (uvp->ixl_opcode == IXL1394_OP_SEND_PKT_WHDR_ST_U) { 1174 uvp->bufsize -= 4; 1175 uvp->bufaddr += 4; 1176 } 1177 1178 /* update old hcihdr w/new bufsize */ 1179 hcidescp = (hci1394_desc_imm_t *)xferctlp->dma[0].dma_descp - 1180 uvp->hci_offset; 1181 acc_hdl = xferctlp->dma[0].dma_buf->bi_handle; 1182 dma_hdl = xferctlp->dma[0].dma_buf->bi_dma_handle; 1183 1184 /* Sync the descriptor before we grab the header(s) */ 1185 err = ddi_dma_sync(dma_hdl, (off_t)hcidescp, 1186 sizeof (hci1394_desc_imm_t), DDI_DMA_SYNC_FORCPU); 1187 if (err != DDI_SUCCESS) { 1188 uvp->upd_status = IXL1394_EINTERNAL_ERROR; 1189 1190 return (IXL_PREP_FAILURE); 1191 } 1192 1193 desc_hdr = ddi_get32(acc_hdl, &hcidescp->hdr); 1194 uvp->hcihdr = desc_hdr; 1195 uvp->hcihdr &= ~DESC_HDR_REQCOUNT_MASK; 1196 uvp->hcihdr |= (uvp->bufsize << DESC_HDR_REQCOUNT_SHIFT) & 1197 DESC_HDR_REQCOUNT_MASK; 1198 1199 /* update old pkthdr2 w/new bufsize. error if exceeds 16k */ 1200 desc_hdr2 = ddi_get32(acc_hdl, &hcidescp->q2); 1201 uvp->pkthdr2 = desc_hdr2; 1202 uvp->pkthdr2 = (uvp->pkthdr2 & DESC_PKT_DATALEN_MASK) >> 1203 DESC_PKT_DATALEN_SHIFT; 1204 uvp->pkthdr2 -= old_xfer_pkt_ixlp->size; 1205 uvp->pkthdr2 += uvp->bufsize; 1206 1207 if (uvp->pkthdr2 > 0xFFFF) { 1208 uvp->upd_status = IXL1394_EPKTSIZE_MAX_OFLO; 1209 1210 return (IXL_PREP_FAILURE); 1211 } 1212 uvp->pkthdr2 = (uvp->pkthdr2 << DESC_PKT_DATALEN_SHIFT) & 1213 DESC_PKT_DATALEN_MASK; 1214 1215 return (IXL_PREP_READY); 1216 } 1217 1218 /* 1219 * hci1394_ixl_update_prep_send_buf() 1220 * Preparation for update of an IXL1394_OP_SEND_BUF_U command. 1221 */ 1222 static int 1223 hci1394_ixl_update_prep_send_buf(hci1394_ixl_update_vars_t *uvp) 1224 { 1225 ixl1394_xfer_buf_t *old_xfer_buf_ixlp; 1226 ixl1394_xfer_buf_t *new_xfer_buf_ixlp; 1227 hci1394_xfer_ctl_t *xferctlp; 1228 1229 old_xfer_buf_ixlp = (ixl1394_xfer_buf_t *)uvp->ixloldp; 1230 new_xfer_buf_ixlp = (ixl1394_xfer_buf_t *)uvp->ixlnewp; 1231 1232 /* check if any change between new and old IXL xfer commands */ 1233 if ((new_xfer_buf_ixlp->size == old_xfer_buf_ixlp->size) && 1234 (new_xfer_buf_ixlp->pkt_size == old_xfer_buf_ixlp->pkt_size) && 1235 (new_xfer_buf_ixlp->ixl_buf.ixldmac_addr == 1236 old_xfer_buf_ixlp->ixl_buf.ixldmac_addr) && 1237 (new_xfer_buf_ixlp->mem_bufp == old_xfer_buf_ixlp->mem_bufp)) { 1238 /* no change, return with done ok status */ 1239 return (IXL_PREP_SUCCESS); 1240 } 1241 1242 /* if new IXL buffer addresses are null, return error */ 1243 if ((new_xfer_buf_ixlp->ixl_buf.ixldmac_addr == 0) || 1244 (new_xfer_buf_ixlp->mem_bufp == NULL)) { 1245 1246 uvp->upd_status = IXL1394_EXFER_BUF_MISSING; 1247 1248 return (IXL_PREP_FAILURE); 1249 } 1250 1251 /* 1252 * check that the new pkt_size > 0 and the new size/pkt_size 1253 * doesn't change the count of DMA descriptor blocks required 1254 */ 1255 if ((new_xfer_buf_ixlp->pkt_size == 0) || 1256 ((new_xfer_buf_ixlp->size / new_xfer_buf_ixlp->pkt_size) != 1257 (old_xfer_buf_ixlp->size / old_xfer_buf_ixlp->pkt_size))) { 1258 1259 /* Error - new has different pkt count than old */ 1260 uvp->upd_status = IXL1394_EXFER_BUF_CNT_DIFF; 1261 1262 return (IXL_PREP_FAILURE); 1263 } 1264 1265 /* set the old IXL xfer command as the current IXL xfer command */ 1266 uvp->ixlxferp = uvp->ixloldp; 1267 1268 /* 1269 * get Z bits (number of descriptor components in descriptor block) 1270 * from a DMA bound address in the xfer_ctl struct of the 1271 * IXL xfer command 1272 */ 1273 if ((xferctlp = (hci1394_xfer_ctl_t *) 1274 uvp->ixlxferp->compiler_privatep) == NULL) { 1275 1276 uvp->upd_status = IXL1394_EORIG_IXL_CORRUPTED; 1277 1278 return (IXL_PREP_FAILURE); 1279 } 1280 1281 /* set depth to zero and count to update all dma descriptors */ 1282 uvp->ixldepth = 0; 1283 uvp->ixlcount = xferctlp->cnt; 1284 1285 /* 1286 * set offset to the header(first) descriptor from the current (last) 1287 * descriptor. 1288 */ 1289 uvp->hdr_offset = xferctlp->dma[0].dma_bound & DESC_Z_MASK - 1; 1290 1291 /* set offset to the only(last) xfer descriptor */ 1292 uvp->hci_offset = 0; 1293 1294 /* set bufsize to the new pkt_size, set bufaddr to the new bufp */ 1295 uvp->bufsize = new_xfer_buf_ixlp->pkt_size; 1296 uvp->bufaddr = new_xfer_buf_ixlp->ixl_buf.ixldmac_addr; 1297 1298 /* 1299 * if IXL1394_OP_SEND_PKT_WHDR_ST_U opcode, adjust size & buff, 1300 * step over header (a quadlet) 1301 */ 1302 if (uvp->ixl_opcode == IXL1394_OP_SEND_PKT_WHDR_ST_U) { 1303 uvp->bufsize -= 4; 1304 uvp->bufaddr += 4; 1305 } 1306 1307 /* set hcihdr to new bufsize */ 1308 uvp->hcihdr = (uvp->bufsize << DESC_HDR_REQCOUNT_SHIFT) & 1309 DESC_HDR_REQCOUNT_MASK; 1310 1311 /* set pkthdr2 to new bufsize */ 1312 uvp->pkthdr2 = (uvp->bufsize << DESC_PKT_DATALEN_SHIFT) & 1313 DESC_PKT_DATALEN_MASK; 1314 1315 return (IXL_PREP_READY); 1316 } 1317 1318 /* 1319 * hci1394_ixl_update_perform() 1320 * performs the actual update into DMA memory. 1321 */ 1322 static int 1323 hci1394_ixl_update_perform(hci1394_ixl_update_vars_t *uvp) 1324 { 1325 int ii; 1326 uint_t skipaddrlast; 1327 hci1394_xfer_ctl_t *xferctlp; 1328 hci1394_desc_imm_t *hcidescp; 1329 hci1394_iso_ctxt_t *ctxtp; 1330 ddi_acc_handle_t acc_hdl; 1331 ddi_dma_handle_t dma_hdl; 1332 int err; 1333 1334 ctxtp = uvp->ctxtp; 1335 1336 /* 1337 * if no target ixl xfer command to be updated or it has 1338 * no xfer_ctl struct, then internal error. 1339 */ 1340 if ((uvp->ixlxferp == NULL) || 1341 ((xferctlp = (hci1394_xfer_ctl_t *) 1342 uvp->ixlxferp->compiler_privatep) == NULL)) { 1343 1344 uvp->upd_status = IXL1394_EINTERNAL_ERROR; 1345 1346 return (DDI_FAILURE); 1347 } 1348 1349 /* perform update based on specific ixl command type */ 1350 switch (uvp->ixl_opcode) { 1351 1352 case IXL1394_OP_JUMP_U: { 1353 ixl1394_jump_t *old_jump_ixlp; 1354 ixl1394_jump_t *new_jump_ixlp; 1355 1356 old_jump_ixlp = (ixl1394_jump_t *)uvp->ixloldp; 1357 new_jump_ixlp = (ixl1394_jump_t *)uvp->ixlnewp; 1358 1359 /* 1360 * set new hdr and new branch fields into last component of last 1361 * dma descriptor block of ixl xfer cmd associated with 1362 * ixl jump cmd 1363 */ 1364 hcidescp = (hci1394_desc_imm_t *) 1365 xferctlp->dma[xferctlp->cnt - 1].dma_descp; 1366 acc_hdl = xferctlp->dma[xferctlp->cnt - 1].dma_buf->bi_handle; 1367 dma_hdl = 1368 xferctlp->dma[xferctlp->cnt - 1].dma_buf->bi_dma_handle; 1369 1370 ddi_put32(acc_hdl, &hcidescp->hdr, uvp->hcihdr); 1371 ddi_put32(acc_hdl, &hcidescp->branch, uvp->jumpaddr); 1372 1373 /* 1374 * if xfer type is send and skip mode is IXL1394__SKIP_TO_NEXT 1375 * also set branch location into branch field of first 1376 * component (skip to address) of last dma descriptor block 1377 */ 1378 if (uvp->skipmode == IXL1394_SKIP_TO_NEXT) { 1379 hcidescp -= uvp->hci_offset; 1380 ddi_put32(acc_hdl, &hcidescp->branch, uvp->skipaddr); 1381 } 1382 1383 /* Sync descriptor for device (desc was modified) */ 1384 err = ddi_dma_sync(dma_hdl, (off_t)hcidescp, 1385 sizeof (hci1394_desc_imm_t), DDI_DMA_SYNC_FORDEV); 1386 if (err != DDI_SUCCESS) { 1387 uvp->upd_status = IXL1394_EINTERNAL_ERROR; 1388 1389 return (DDI_FAILURE); 1390 } 1391 1392 /* set old ixl jump cmd label from new ixl jump cmd label */ 1393 old_jump_ixlp->label = new_jump_ixlp->label; 1394 break; 1395 } 1396 case IXL1394_OP_SET_SKIPMODE_U: { 1397 ixl1394_set_skipmode_t *old_set_skipmode_ixlp; 1398 ixl1394_set_skipmode_t *new_set_skipmode_ixlp; 1399 1400 old_set_skipmode_ixlp = (ixl1394_set_skipmode_t *)uvp->ixloldp; 1401 new_set_skipmode_ixlp = (ixl1394_set_skipmode_t *)uvp->ixlnewp; 1402 1403 /* 1404 * if skip to next mode, save skip addr for last iteration 1405 * thru dma descriptor blocks for associated ixl xfer command 1406 */ 1407 if (uvp->skipmode == IXL1394_SKIP_TO_NEXT) { 1408 skipaddrlast = uvp->skipaddr; 1409 } 1410 1411 /* 1412 * iterate through set of dma descriptor blocks for associated 1413 * ixl xfer start cmd and set new skip address into first hci 1414 * descriptor of each if skip next or skip self, first determine 1415 * address in each iteration 1416 */ 1417 for (ii = 0; ii < xferctlp->cnt; ii++) { 1418 hcidescp = (hci1394_desc_imm_t *) 1419 xferctlp->dma[ii].dma_descp - uvp->hci_offset; 1420 acc_hdl = xferctlp->dma[ii].dma_buf->bi_handle; 1421 dma_hdl = xferctlp->dma[ii].dma_buf->bi_dma_handle; 1422 1423 if (uvp->skipmode == IXL1394_SKIP_TO_NEXT) { 1424 if (ii < (xferctlp->cnt - 1)) { 1425 uvp->skipaddr = 1426 xferctlp->dma[ii + 1].dma_bound; 1427 } else { 1428 uvp->skipaddr = skipaddrlast; 1429 } 1430 } else if (uvp->skipmode == IXL1394_SKIP_TO_SELF) { 1431 uvp->skipaddr = xferctlp->dma[ii].dma_bound; 1432 } 1433 1434 ddi_put32(acc_hdl, &hcidescp->branch, uvp->skipaddr); 1435 1436 /* Sync descriptor for device (desc was modified) */ 1437 err = ddi_dma_sync(dma_hdl, (off_t)hcidescp, 1438 sizeof (hci1394_desc_imm_t), DDI_DMA_SYNC_FORDEV); 1439 if (err != DDI_SUCCESS) { 1440 uvp->upd_status = IXL1394_EINTERNAL_ERROR; 1441 1442 return (DDI_FAILURE); 1443 } 1444 } 1445 1446 /* 1447 * set old ixl set skip mode cmd mode and label from new ixl cmd 1448 * set old ixl set skip mode cmd compilier_privatep to 1449 * uvp->skipxferp 1450 */ 1451 old_set_skipmode_ixlp->skipmode = uvp->skipmode; 1452 old_set_skipmode_ixlp->label = new_set_skipmode_ixlp->label; 1453 old_set_skipmode_ixlp->compiler_privatep = 1454 (ixl1394_priv_t)uvp->skipxferp; 1455 break; 1456 } 1457 case IXL1394_OP_SET_TAGSYNC_U: { 1458 ixl1394_set_tagsync_t *old_set_tagsync_ixlp; 1459 ixl1394_set_tagsync_t *new_set_tagsync_ixlp; 1460 1461 old_set_tagsync_ixlp = (ixl1394_set_tagsync_t *)uvp->ixloldp; 1462 new_set_tagsync_ixlp = (ixl1394_set_tagsync_t *)uvp->ixlnewp; 1463 1464 /* 1465 * iterate through set of descriptor blocks for associated IXL 1466 * xfer command and set new pkthdr1 value into output more/last 1467 * immediate hci descriptor (first/last hci descriptor of each 1468 * descriptor block) 1469 */ 1470 for (ii = 0; ii < xferctlp->cnt; ii++) { 1471 hcidescp = (hci1394_desc_imm_t *) 1472 xferctlp->dma[ii].dma_descp - uvp->hdr_offset; 1473 acc_hdl = xferctlp->dma[ii].dma_buf->bi_handle; 1474 dma_hdl = xferctlp->dma[ii].dma_buf->bi_dma_handle; 1475 ddi_put32(acc_hdl, &hcidescp->q1, uvp->pkthdr1); 1476 1477 /* Sync descriptor for device (desc was modified) */ 1478 err = ddi_dma_sync(dma_hdl, (off_t)hcidescp, 1479 sizeof (hci1394_desc_imm_t), DDI_DMA_SYNC_FORDEV); 1480 if (err != DDI_SUCCESS) { 1481 uvp->upd_status = IXL1394_EINTERNAL_ERROR; 1482 1483 return (DDI_FAILURE); 1484 } 1485 } 1486 1487 /* 1488 * set old ixl set tagsync cmd tag & sync from new ixl set 1489 * tagsync cmd 1490 */ 1491 old_set_tagsync_ixlp->tag = new_set_tagsync_ixlp->tag; 1492 old_set_tagsync_ixlp->sync = new_set_tagsync_ixlp->sync; 1493 break; 1494 } 1495 case IXL1394_OP_RECV_PKT_U: 1496 case IXL1394_OP_RECV_PKT_ST_U: { 1497 ixl1394_xfer_pkt_t *old_xfer_pkt_ixlp; 1498 ixl1394_xfer_pkt_t *new_xfer_pkt_ixlp; 1499 uint32_t desc_status; 1500 1501 old_xfer_pkt_ixlp = (ixl1394_xfer_pkt_t *)uvp->ixloldp; 1502 new_xfer_pkt_ixlp = (ixl1394_xfer_pkt_t *)uvp->ixlnewp; 1503 1504 /* 1505 * alter buffer address, count and rescount in ixl recv pkt cmd 1506 * related hci component in dma descriptor block 1507 */ 1508 hcidescp = (hci1394_desc_imm_t *) 1509 xferctlp->dma[0].dma_descp - uvp->hci_offset; 1510 acc_hdl = xferctlp->dma[0].dma_buf->bi_handle; 1511 dma_hdl = xferctlp->dma[0].dma_buf->bi_dma_handle; 1512 ddi_put32(acc_hdl, &hcidescp->hdr, uvp->hcihdr); 1513 ddi_put32(acc_hdl, &hcidescp->data_addr, uvp->bufaddr); 1514 1515 /* Sync the descriptor before we grab the status */ 1516 err = ddi_dma_sync(dma_hdl, (off_t)hcidescp, 1517 sizeof (hci1394_desc_imm_t), DDI_DMA_SYNC_FORCPU); 1518 if (err != DDI_SUCCESS) { 1519 uvp->upd_status = IXL1394_EINTERNAL_ERROR; 1520 1521 return (DDI_FAILURE); 1522 } 1523 1524 /* change only low 1/2 word and leave status bits unchanged */ 1525 desc_status = ddi_get32(acc_hdl, &hcidescp->status); 1526 desc_status = (desc_status & ~DESC_ST_RESCOUNT_MASK) | 1527 uvp->hcistatus; 1528 ddi_put32(acc_hdl, &hcidescp->status, desc_status); 1529 1530 /* Sync descriptor for device (desc was modified) */ 1531 err = ddi_dma_sync(dma_hdl, (off_t)hcidescp, 1532 sizeof (hci1394_desc_imm_t), DDI_DMA_SYNC_FORDEV); 1533 if (err != DDI_SUCCESS) { 1534 uvp->upd_status = IXL1394_EINTERNAL_ERROR; 1535 1536 return (DDI_FAILURE); 1537 } 1538 1539 /* 1540 * set old ixl recv pkt size and buffers from new 1541 * ixl recv pkt command 1542 */ 1543 old_xfer_pkt_ixlp->size = new_xfer_pkt_ixlp->size; 1544 old_xfer_pkt_ixlp->ixl_buf.ixldmac_addr = 1545 new_xfer_pkt_ixlp->ixl_buf.ixldmac_addr; 1546 old_xfer_pkt_ixlp->mem_bufp = new_xfer_pkt_ixlp->mem_bufp; 1547 break; 1548 } 1549 case IXL1394_OP_RECV_BUF_U: { 1550 ixl1394_xfer_buf_t *old_xfer_buf_ixlp; 1551 ixl1394_xfer_buf_t *new_xfer_buf_ixlp; 1552 uint32_t desc_hdr; 1553 uint32_t desc_status; 1554 1555 old_xfer_buf_ixlp = (ixl1394_xfer_buf_t *)uvp->ixloldp; 1556 new_xfer_buf_ixlp = (ixl1394_xfer_buf_t *)uvp->ixlnewp; 1557 1558 /* 1559 * iterate through set of descriptor blocks for this IXL xfer 1560 * command altering buffer, count and rescount in each 1561 * input more/last(the only) hci descriptor block descriptor. 1562 */ 1563 for (ii = 0; ii < xferctlp->cnt; ii++) { 1564 1565 hcidescp = (hci1394_desc_imm_t *) 1566 xferctlp->dma[ii].dma_descp - uvp->hci_offset; 1567 acc_hdl = xferctlp->dma[ii].dma_buf->bi_handle; 1568 dma_hdl = xferctlp->dma[ii].dma_buf->bi_dma_handle; 1569 1570 ddi_put32(acc_hdl, &hcidescp->data_addr, uvp->bufaddr); 1571 1572 /* 1573 * advance to next buffer segment, adjust over header 1574 * if appropriate 1575 */ 1576 uvp->bufaddr += uvp->bufsize; 1577 1578 /* Sync the descriptor before we grab the header(s) */ 1579 err = ddi_dma_sync(dma_hdl, (off_t)hcidescp, 1580 sizeof (hci1394_desc_imm_t), DDI_DMA_SYNC_FORCPU); 1581 if (err != DDI_SUCCESS) { 1582 uvp->upd_status = IXL1394_EINTERNAL_ERROR; 1583 1584 return (DDI_FAILURE); 1585 } 1586 1587 /* 1588 * this preserves interrupt enable bits, et al. in each 1589 * descriptor block header. 1590 */ 1591 desc_hdr = ddi_get32(acc_hdl, &hcidescp->hdr); 1592 desc_hdr = (desc_hdr & ~DESC_HDR_REQCOUNT_MASK) | 1593 uvp->hcihdr; 1594 ddi_put32(acc_hdl, &hcidescp->hdr, desc_hdr); 1595 1596 /* 1597 * change only low 1/2 word leaving status bits 1598 * unchanged 1599 */ 1600 desc_status = ddi_get32(acc_hdl, &hcidescp->status); 1601 desc_status = (desc_status & ~DESC_ST_RESCOUNT_MASK) | 1602 uvp->hcistatus; 1603 ddi_put32(acc_hdl, &hcidescp->status, desc_status); 1604 1605 /* Sync descriptor for device (desc was modified) */ 1606 err = ddi_dma_sync(dma_hdl, (off_t)hcidescp, 1607 sizeof (hci1394_desc_imm_t), DDI_DMA_SYNC_FORDEV); 1608 if (err != DDI_SUCCESS) { 1609 uvp->upd_status = IXL1394_EINTERNAL_ERROR; 1610 1611 return (DDI_FAILURE); 1612 } 1613 } 1614 1615 /* 1616 * set old ixl recv buf sizes and buffers from 1617 * new ixl recv pkt cmd 1618 */ 1619 old_xfer_buf_ixlp->pkt_size = new_xfer_buf_ixlp->pkt_size; 1620 old_xfer_buf_ixlp->size = new_xfer_buf_ixlp->size; 1621 old_xfer_buf_ixlp->ixl_buf.ixldmac_addr = 1622 new_xfer_buf_ixlp->ixl_buf.ixldmac_addr; 1623 old_xfer_buf_ixlp->mem_bufp = new_xfer_buf_ixlp->mem_bufp; 1624 break; 1625 } 1626 case IXL1394_OP_SEND_PKT_U: 1627 case IXL1394_OP_SEND_PKT_ST_U: 1628 case IXL1394_OP_SEND_PKT_WHDR_ST_U: { 1629 ixl1394_xfer_pkt_t *old_xfer_pkt_ixlp; 1630 ixl1394_xfer_pkt_t *new_xfer_pkt_ixlp; 1631 1632 old_xfer_pkt_ixlp = (ixl1394_xfer_pkt_t *)uvp->ixloldp; 1633 new_xfer_pkt_ixlp = (ixl1394_xfer_pkt_t *)uvp->ixlnewp; 1634 1635 /* 1636 * replace pkthdr2 in output more immediate (the first) hci 1637 * descriptor in block, then alter buffer address and count in 1638 * IXL send pkt command related output more/last hci descriptor. 1639 */ 1640 hcidescp = (hci1394_desc_imm_t *)xferctlp->dma[0].dma_descp - 1641 uvp->hdr_offset; 1642 acc_hdl = xferctlp->dma[0].dma_buf->bi_handle; 1643 dma_hdl = xferctlp->dma[0].dma_buf->bi_dma_handle; 1644 1645 ddi_put32(acc_hdl, &hcidescp->q2, uvp->pkthdr2); 1646 ddi_put32(acc_hdl, &hcidescp->hdr, uvp->hcihdr); 1647 ddi_put32(acc_hdl, &hcidescp->data_addr, uvp->bufaddr); 1648 1649 /* Sync descriptor for device (desc was modified) */ 1650 err = ddi_dma_sync(dma_hdl, (off_t)hcidescp, 1651 sizeof (hci1394_desc_imm_t), DDI_DMA_SYNC_FORDEV); 1652 if (err != DDI_SUCCESS) { 1653 uvp->upd_status = IXL1394_EINTERNAL_ERROR; 1654 1655 return (DDI_FAILURE); 1656 } 1657 1658 /* 1659 * set old ixl recv pkt size and buffers from 1660 * new ixl recv pkt cmd 1661 */ 1662 old_xfer_pkt_ixlp->size = new_xfer_pkt_ixlp->size; 1663 old_xfer_pkt_ixlp->ixl_buf.ixldmac_addr = 1664 new_xfer_pkt_ixlp->ixl_buf.ixldmac_addr; 1665 old_xfer_pkt_ixlp->mem_bufp = new_xfer_pkt_ixlp->mem_bufp; 1666 break; 1667 } 1668 case IXL1394_OP_SEND_BUF_U: { 1669 ixl1394_xfer_buf_t *old_xfer_buf_ixlp; 1670 ixl1394_xfer_buf_t *new_xfer_buf_ixlp; 1671 uint32_t desc_hdr; 1672 1673 old_xfer_buf_ixlp = (ixl1394_xfer_buf_t *)uvp->ixloldp; 1674 new_xfer_buf_ixlp = (ixl1394_xfer_buf_t *)uvp->ixlnewp; 1675 1676 /* 1677 * iterate through set of descriptor blocks for this IXL xfer 1678 * command replacing pkthdr2 in output more immediate 1679 * (the first) hci descriptor block descriptor, then altering 1680 * buffer address and count in each output last (the only other) 1681 * hci descriptor block descriptor. 1682 */ 1683 for (ii = 0; ii < xferctlp->cnt; ii++) { 1684 hcidescp = (hci1394_desc_imm_t *) 1685 xferctlp->dma[ii].dma_descp - uvp->hdr_offset; 1686 acc_hdl = xferctlp->dma[ii].dma_buf->bi_handle; 1687 dma_hdl = xferctlp->dma[ii].dma_buf->bi_dma_handle; 1688 1689 ddi_put32(acc_hdl, &hcidescp->q2, uvp->pkthdr2); 1690 ddi_put32(acc_hdl, &hcidescp->data_addr, uvp->bufaddr); 1691 1692 /* advance to next buffer segment */ 1693 uvp->bufaddr += uvp->bufsize; 1694 1695 /* Sync the descriptor before we grab the header(s) */ 1696 err = ddi_dma_sync(dma_hdl, (off_t)hcidescp, 1697 sizeof (hci1394_desc_imm_t), DDI_DMA_SYNC_FORCPU); 1698 if (err != DDI_SUCCESS) { 1699 uvp->upd_status = IXL1394_EINTERNAL_ERROR; 1700 1701 return (DDI_FAILURE); 1702 } 1703 1704 /* 1705 * this preserves interrupt enable bits, et al 1706 * in each desc block hdr 1707 */ 1708 desc_hdr = ddi_get32(acc_hdl, &hcidescp->hdr); 1709 desc_hdr = (desc_hdr & ~DESC_HDR_REQCOUNT_MASK) | 1710 uvp->hcihdr; 1711 ddi_put32(acc_hdl, &hcidescp->hdr, desc_hdr); 1712 1713 /* Sync descriptor for device (desc was modified) */ 1714 err = ddi_dma_sync(dma_hdl, (off_t)hcidescp, 1715 sizeof (hci1394_desc_imm_t), DDI_DMA_SYNC_FORDEV); 1716 if (err != DDI_SUCCESS) { 1717 uvp->upd_status = IXL1394_EINTERNAL_ERROR; 1718 1719 return (DDI_FAILURE); 1720 } 1721 } 1722 1723 /* 1724 * set old ixl recv buf sizes and buffers from 1725 * new ixl recv pkt cmd 1726 */ 1727 old_xfer_buf_ixlp->pkt_size = new_xfer_buf_ixlp->pkt_size; 1728 old_xfer_buf_ixlp->size = new_xfer_buf_ixlp->size; 1729 old_xfer_buf_ixlp->ixl_buf.ixldmac_addr = 1730 new_xfer_buf_ixlp->ixl_buf.ixldmac_addr; 1731 old_xfer_buf_ixlp->mem_bufp = new_xfer_buf_ixlp->mem_bufp; 1732 break; 1733 } 1734 default: 1735 /* ixl command being updated must be one of above, else error */ 1736 uvp->upd_status = IXL1394_EINTERNAL_ERROR; 1737 1738 return (DDI_FAILURE); 1739 } 1740 1741 /* hit the WAKE bit in the context control register */ 1742 if (ctxtp->ctxt_flags & HCI1394_ISO_CTXT_RECV) { 1743 HCI1394_IRCTXT_CTRL_SET(uvp->soft_statep, ctxtp->ctxt_index, 1744 0, 0, 0, 0, 0, 1 /* wake */); 1745 } else { 1746 HCI1394_ITCTXT_CTRL_SET(uvp->soft_statep, ctxtp->ctxt_index, 1747 0, 0, 0, 1 /* wake */); 1748 } 1749 1750 /* perform update completed successfully */ 1751 return (DDI_SUCCESS); 1752 } 1753 1754 /* 1755 * hci1394_ixl_update_evaluate() 1756 * Evaluate where the hardware is in running through the DMA descriptor 1757 * blocks. 1758 */ 1759 static int 1760 hci1394_ixl_update_evaluate(hci1394_ixl_update_vars_t *uvp) 1761 { 1762 hci1394_iso_ctxt_t *ctxtp; 1763 ixl1394_command_t *ixlp; 1764 int ixldepth; 1765 int ii; 1766 1767 ctxtp = uvp->ctxtp; 1768 1769 ixlp = NULL; 1770 ixldepth = 0xFFFFFFFF; 1771 1772 /* 1773 * repeat until IXL execution status evaluation function returns error 1774 * or until pointer to currently executing IXL command and its depth 1775 * stablize 1776 */ 1777 while ((ixlp != ctxtp->ixl_execp) || 1778 (ixldepth != ctxtp->ixl_exec_depth)) { 1779 1780 ixlp = ctxtp->ixl_execp; 1781 ixldepth = ctxtp->ixl_exec_depth; 1782 1783 /* 1784 * call IXL execution status evaluation (ixl_dma_sync) 1785 * function returning if error (HCI1394_IXL_INTR_DMALOST is 1786 * only error condition). 1787 * 1788 * Note: interrupt processing function can only return one of 1789 * the following statuses here: 1790 * HCI1394_IXL_INTR_NOERROR, HCI1394_IXL_INTR_DMASTOP, 1791 * HCI1394_IXL_INTR_DMALOST 1792 * 1793 * it can not return the following status here: 1794 * HCI1394_IXL_INTR_NOADV 1795 * 1796 * Don't need to grab the lock here... for the same reason 1797 * explained in hci1394_ixl_update_endup() above. 1798 */ 1799 ctxtp->intr_flags &= ~HCI1394_ISO_CTXT_INTRSET; 1800 if (hci1394_ixl_dma_sync(uvp->soft_statep, ctxtp) == 1801 HCI1394_IXL_INTR_DMALOST) { 1802 1803 /* return post-perform update failed status */ 1804 uvp->upd_status = IXL1394_EPOST_UPD_DMALOST; 1805 1806 return (DDI_FAILURE); 1807 } 1808 } 1809 1810 /* 1811 * if the currently executing IXL command is one of the IXL_MAX_LOCN 1812 * locations saved before update was performed, return update 1813 * successful status. 1814 */ 1815 for (ii = 0; ii < IXL_MAX_LOCN; ii++) { 1816 if ((uvp->locn_info[ii].ixlp == ixlp) && 1817 (uvp->locn_info[ii].ixldepth == ixldepth)) { 1818 1819 return (DDI_SUCCESS); 1820 } 1821 } 1822 1823 /* 1824 * else return post-perform update failed status. 1825 * note: later can make more sophisticated evaluations about where 1826 * execution processing went, and if update has really failed. 1827 */ 1828 uvp->upd_status = IXL1394_EPOST_UPD_DMALOST; 1829 1830 return (DDI_FAILURE); 1831 } 1832 1833 /* 1834 * hci1394_ixl_update_analysis() 1835 * Determine if the hardware is within the range we expected it to be. 1836 * If so the update succeeded. 1837 */ 1838 static int 1839 hci1394_ixl_update_analysis(hci1394_ixl_update_vars_t *uvp) 1840 { 1841 hci1394_iso_ctxt_t *ctxtp; 1842 ixl1394_command_t *ixlp; 1843 int ixldepth; 1844 int ii; 1845 int status; 1846 1847 ctxtp = uvp->ctxtp; 1848 1849 ixlp = NULL; 1850 ixldepth = 0xFFFFFFFF; 1851 1852 /* 1853 * repeat until ixl execution status evaluation function returns error 1854 * or until pointer to currently executing ixl command and its depth 1855 * stablize. 1856 */ 1857 while ((ixlp != ctxtp->ixl_execp) || 1858 (ixldepth != ctxtp->ixl_exec_depth)) { 1859 1860 ixlp = ctxtp->ixl_execp; 1861 ixldepth = ctxtp->ixl_exec_depth; 1862 1863 /* 1864 * call ixl execution status evaluation (interrupt processing). 1865 * set IXL1394_EIDU_PRE_UPD_DMALOST if status INTR_DMALOST and 1866 * return. 1867 * 1868 * Note: interrupt processing function can only return one of 1869 * the following statuses here: 1870 * HCI1394_IXL_INTR_NOERROR, HCI1394_IXL_INTR_DMASTOP or 1871 * HCI1394_IXL_INTR_DMALOST 1872 * 1873 * it can not return the following status here: 1874 * HCI1394_IXL_INTR_NOADV 1875 * 1876 * Don't need to grab the lock here... for the same reason 1877 * explained in hci1394_ixl_update_endup() above. 1878 */ 1879 ctxtp->intr_flags &= ~HCI1394_ISO_CTXT_INTRSET; 1880 1881 status = hci1394_ixl_dma_sync(uvp->soft_statep, ctxtp); 1882 if (status == HCI1394_IXL_INTR_DMALOST) { 1883 /* 1884 * set pre-update dma processing lost status and 1885 * return error 1886 */ 1887 uvp->upd_status = IXL1394_EPRE_UPD_DMALOST; 1888 1889 return (DDI_FAILURE); 1890 } 1891 } 1892 1893 /* 1894 * save locations of currently executing ixl command and the 1895 * 3 following it. 1896 */ 1897 hci1394_ixl_update_set_locn_info(uvp); 1898 1899 /* 1900 * if xfer_ixl_cmd associated with the IXL_command being updated is one 1901 * of the saved (currently executing) IXL commands, risk is too great to 1902 * perform update now, set IXL1394_ERISK_PROHIBITS_UPD status and 1903 * return error. 1904 * 1905 * Note: later can implement more sophisticated risk override 1906 * evaluations and processing. 1907 */ 1908 for (ii = 0; ii < IXL_MAX_LOCN; ii++) { 1909 1910 if ((uvp->locn_info[ii].ixlp == uvp->ixlxferp) && 1911 (uvp->locn_info[ii].ixldepth >= uvp->ixldepth) && 1912 (uvp->locn_info[ii].ixldepth < 1913 (uvp->ixldepth + uvp->ixlcount))) { 1914 1915 uvp->upd_status = IXL1394_ERISK_PROHIBITS_UPD; 1916 1917 return (DDI_FAILURE); 1918 } 1919 } 1920 1921 /* is save for update to be performed, return ok status */ 1922 return (DDI_SUCCESS); 1923 } 1924 1925 /* 1926 * hci1394_ixl_update_set_locn_info() 1927 * set up the local list of the IXL_MAX_LOCN next commandPtr locations we 1928 * expect the hardware to get to in the next 125 microseconds. 1929 */ 1930 static void 1931 hci1394_ixl_update_set_locn_info(hci1394_ixl_update_vars_t *uvp) 1932 { 1933 hci1394_iso_ctxt_t *ctxtp; 1934 ixl1394_command_t *ixlp; 1935 int ixldepth; 1936 int ii; 1937 1938 /* 1939 * find next xfer start ixl command, starting with current ixl command 1940 * where execution last left off 1941 */ 1942 ctxtp = uvp->ctxtp; 1943 1944 ixldepth = ctxtp->ixl_exec_depth; 1945 (void) hci1394_ixl_find_next_exec_xfer(ctxtp->ixl_execp, NULL, &ixlp); 1946 1947 /* 1948 * if the current IXL command wasn't a xfer start command, then reset 1949 * the depth to 0 for xfer command found 1950 */ 1951 if (ixlp != ctxtp->ixl_execp) 1952 ixldepth = 0; 1953 1954 /* 1955 * save xfer start IXL command & its depth and also save location and 1956 * depth of the next IXL_MAX_LOCN-1 xfer start IXL commands following 1957 * it (if any) 1958 */ 1959 for (ii = 0; ii < IXL_MAX_LOCN; ii++) { 1960 uvp->locn_info[ii].ixlp = ixlp; 1961 uvp->locn_info[ii].ixldepth = ixldepth; 1962 1963 if (ixlp) { 1964 /* 1965 * if more dma commands generated by this xfer command 1966 * still follow, use them. else, find the next xfer 1967 * start IXL command and set its depth to 0. 1968 */ 1969 if (++ixldepth >= ((hci1394_xfer_ctl_t *) 1970 ixlp->compiler_privatep)->cnt) { 1971 1972 (void) hci1394_ixl_find_next_exec_xfer( 1973 ixlp->next_ixlp, NULL, &ixlp); 1974 ixldepth = 0; 1975 } 1976 } 1977 } 1978 } 1979