/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Isochronous IXL miscellaneous routines.
* Contains common routines used by the ixl compiler, interrupt handler and
* dynamic update.
*/
#include <sys/tnf_probe.h>
/* local routines */
static void hci1394_delete_xfer_ctl(hci1394_xfer_ctl_t *);
/*
* hci1394_ixl_set_start()
* Set up the context structure with the first ixl command to process
* and the first hci descriptor to execute.
*
* This function assumes the current context is stopped!
*
* If ixlstp IS NOT null AND is not the first compiled ixl command and
* is not an ixl label command, returns an error.
* If ixlstp IS null, uses the first compiled ixl command (ixl_firstp)
* in place of ixlstp.
*
* If no executeable xfer found along exec path from ixlstp, returns error.
*/
int
{
/* if ixl start command is null, use first compiled ixl command */
}
/*
* if ixl start command is not first ixl compiled and is not a label,
* error
*/
IXL1394_OP_LABEL)) {
return (-1);
}
/* follow exec path to find first ixl command that's an xfer command */
/*
* if there was one, then in it's compiler private, its
* hci1394_xfer_ctl structure has the appropriate bound address
*/
if (ixl_exec_startp != NULL) {
/* set up for start of context and return done */
ctxtp->dma_last_time = 0;
ctxtp->ixl_exec_depth = 0;
return (0);
}
/* else no executeable xfer command found, return error */
return (1);
}
#ifdef _KERNEL
/*
* hci1394_ixl_reset_status()
* Reset all statuses in all hci descriptor blocks associated with the
* current linked list of compiled ixl commands.
*
* This function assumes the current context is stopped!
*/
void
{
/*
* Scan for next ixl xfer start command along ixl link path.
* Once xfer command found, clear its hci descriptor block's
* status. If is composite ixl xfer command, clear statuses
* in each of its hci descriptor blocks.
*/
/* set current and next ixl command */
/* skip to examine next if this is not xfer start ixl command */
continue;
}
/* get control struct for this xfer start ixl command */
/* clear status in each hci descriptor block for this ixl cmd */
ixldepth = 0;
(void) hci1394_ixl_check_status(
ixldepth++;
}
}
}
#endif
/*
* hci1394_ixl_find_next_exec_xfer()
* Follows execution path of ixl linked list until finds next xfer start IXL
* command, including the current IXL command or finds end of IXL linked
* list. Counts callback commands found along the way. (Previously, counted
* store timestamp commands, as well.)
*
* To detect an infinite loop of label<->jump without an intervening xfer,
* a tolerance level of HCI1394_IXL_MAX_SEQ_JUMPS is used. Once this
* number of jumps is traversed, the IXL prog is assumed to have a loop.
*
* Returns DDI_SUCCESS or DDI_FAILURE. DDI_FAILURE, indicates an infinite
* loop of labels & jumps was detected without any intervening xfers.
* DDI_SUCCESS indicates the next_exec_ixlpp contains the next xfer ixlp
* address, or NULL indicating the end of the list was reached. Note that
* DDI_FAILURE can only be returned during the IXL compilation phase, and
* not during ixl_update processing.
*/
int
{
int ii;
if (callback_cnt != NULL) {
*callback_cnt = 0;
}
/* continue until xfer start ixl cmd or end of ixl list found */
/* get current ixl cmd opcode without update flag */
/* if found an xfer start ixl command, are done */
if (((ixlopcode & IXL1394_OPF_ISXFER) != 0) &&
((ixlopcode & IXL1394_OPTY_MASK) != 0)) {
continue;
}
/* if found jump command, adjust to follow its path */
if (ixlopcode == IXL1394_OP_JUMP) {
ixlp = (ixl1394_command_t *)
ii--;
/* if exceeded tolerance, give up */
if (ii == 0) {
return (DDI_FAILURE);
}
continue;
}
/* if current ixl command is a callback, count it */
if ((ixlopcode == IXL1394_OP_CALLBACK) &&
(callback_cnt != NULL)) {
(*callback_cnt)++;
}
/* advance to next linked ixl command */
}
/* return ixl xfer start command found, if any */
*next_exec_ixlpp = ixlp;
return (DDI_SUCCESS);
}
#ifdef _KERNEL
/*
* hci1394_ixl_check_status()
* Read the descriptor status and hdrs, clear as appropriate.
*/
{
int err;
/* last dma descriptor in descriptor block from dma structure */
/* if current ixl command opcode is xmit */
if ((ixlopcode & IXL1394_OPF_ONXMIT) != 0) {
/* Sync the descriptor before we get the status */
sizeof (hci1394_desc_t), DDI_DMA_SYNC_FORCPU);
if (err != DDI_SUCCESS) {
"dma_sync() failed");
}
/* check if status is set in last dma descriptor in block */
if ((desc_status & DESC_XFER_ACTIVE_MASK) != 0) {
/*
* dma descriptor status set - I/O done.
* if not to reset status, just return; else extract
* timestamp, reset desc status and return dma
* descriptor block status set
*/
if (do_status_reset == B_FALSE) {
return (1);
}
((desc_status & DESC_ST_TIMESTAMP_MASK) >>
/* Sync descriptor for device (status was cleared) */
sizeof (hci1394_desc_t), DDI_DMA_SYNC_FORDEV);
if (err != DDI_SUCCESS) {
errmsg, "dma_sync() failed");
}
return (1);
}
/* else, return dma descriptor block status not set */
return (0);
}
/* else current ixl opcode is recv */
hcirecvcnt = 0;
/* get count of descriptors in current dma descriptor block */
/* iterate fwd through hci descriptors until end or find status set */
while (hcicnt-- != 0) {
/* Sync the descriptor before we get the status */
if (err != DDI_SUCCESS) {
"dma_sync() failed");
}
/* get cur buffer size & accumulate potential buffr usage */
hcirecvcnt += bufsiz;
/* check if status set on this descriptor block descriptor */
if ((desc_status & DESC_XFER_ACTIVE_MASK) != 0) {
/*
* dma descriptor status set - I/O done.
* if not to reset status, just return; else extract
* buffer space used, reset desc status and return dma
* descriptor block status set
*/
if (do_status_reset == B_FALSE) {
return (1);
}
*timestamp = hcirecvcnt;
/* Sync descriptor for device (status was cleared) */
sizeof (hci1394_desc_t), DDI_DMA_SYNC_FORDEV);
if (err != DDI_SUCCESS) {
errmsg, "dma_sync() failed");
}
return (1);
} else {
/* else, set to evaluate next descriptor. */
hcidescp++;
}
}
/* return input not complete status */
return (0);
}
#endif
/*
* hci1394_ixl_cleanup()
* Delete all memory that has earlier been allocated for a context's IXL prog
*/
void
{
}
/*
* hci1394_delete_dma_desc_mem()
* Iterate through linked list of dma memory descriptors, deleting
* allocated dma memory blocks, then deleting the dma memory
* descriptor after advancing to next one
*/
static void
/* ARGSUSED */
{
while (dma_firstp != NULL) {
#ifdef _KERNEL
/*
* if this dma descriptor memory block has the handles, then
* free the memory. (Note that valid handles are kept only with
* the most recently acquired cookie, and that each cookie is in
* it's own idma_desc_mem_t struct.)
*/
}
/* free current dma memory descriptor */
#else
/* user mode free */
/* free dma memory block and current dma mem descriptor */
#endif
/* advance to next dma memory descriptor */
}
}
/*
* hci1394_delete_xfer_ctl()
* Iterate thru linked list of xfer_ctl structs, deleting allocated memory.
*/
void
{
/* advance ptr to next xfer_ctl struct */
/*
* delete current xfer_ctl struct and included
* xfer_ctl_dma structs
*/
#ifdef _KERNEL
sizeof (hci1394_xfer_ctl_t) +
#else
#endif
}
}