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
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)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
hci1394_ixl_update_enable(hci1394_ixl_update_vars_t * uvp)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
hci1394_ixl_update_endup(hci1394_ixl_update_vars_t * uvp)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
hci1394_ixl_update_prepare(hci1394_ixl_update_vars_t * uvp)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
hci1394_ixl_update_prep_jump(hci1394_ixl_update_vars_t * uvp)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
hci1394_ixl_update_prep_set_skipmode(hci1394_ixl_update_vars_t * uvp)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
hci1394_ixl_update_prep_set_tagsync(hci1394_ixl_update_vars_t * uvp)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
hci1394_ixl_update_prep_recv_pkt(hci1394_ixl_update_vars_t * uvp)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
hci1394_ixl_update_prep_recv_buf(hci1394_ixl_update_vars_t * uvp)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
hci1394_ixl_update_prep_send_pkt(hci1394_ixl_update_vars_t * uvp)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
hci1394_ixl_update_prep_send_buf(hci1394_ixl_update_vars_t * uvp)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
hci1394_ixl_update_perform(hci1394_ixl_update_vars_t * uvp)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
hci1394_ixl_update_evaluate(hci1394_ixl_update_vars_t * uvp)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
hci1394_ixl_update_analysis(hci1394_ixl_update_vars_t * uvp)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
hci1394_ixl_update_set_locn_info(hci1394_ixl_update_vars_t * uvp)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