root/usr/src/uts/common/sys/1394/adapters/hci1394_tlist.h
/*
 * 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
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright (c) 1999-2000 by Sun Microsystems, Inc.
 * All rights reserved.
 */

#ifndef _SYS_1394_ADAPTERS_HCI1394_TLIST_H
#define _SYS_1394_ADAPTERS_HCI1394_TLIST_H

/*
 * hci1394_tlist.h
 *   This implements a timed double linked list.
 *   This list supports:
 *      - addition of node to the end of the list
 *      - atomic deletion of node anywhere in list
 *      - get and remove node from head of list
 *      - enable/disable of timeout feature
 *      - timeout feature, if enabled, will remove each node on the list which
 *        has been on the list for > timeout.  The callback provided will be
 *        called for each node removed. The worst case time is around
 *        timer_resolution after the timeout has occurred (i.e. if you set the
 *        timer resolution to 50uS and the timeout to 100uS, you could get the
 *        callback anywhere from 100uS to 150uS from when you added the node to
 *        the list.  This is a general statement and ignores things like
 *        interrupt latency, context switching, etc.  So if you see a time
 *        around 155uS, don't complain :-)
 *      - The timer is only used when something is on the list
 */

#ifdef __cplusplus
extern "C" {
#endif

#include <sys/types.h>
#include <sys/conf.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
#include <sys/time.h>
#include <sys/note.h>

/*
 * Node Information
 *   This structure is used to track the information for a given node in the
 *   linked list.  The node is added to the end of the linked list be calling
 *   tlist_add().
 */
typedef struct hci1394_tlist_node_s {
        /*
         * Public Members
         *  addr
         *    generic address pointer.  This should be set to point to
         *    whatever information you are using this node to track.
         */
        void    *tln_addr;

        /*
         * Private Members
         *   These are private.  They are only to be used in the tlist
         *   implementation.  They are included in the header file so that we
         *   do not have to alloc/free memory when something is added/deleted
         *   from the tlist.
         */
        boolean_t                       tln_on_list;
        hrtime_t                        tln_expire_time;
        struct hci1394_tlist_node_s     *tln_prev;
        struct hci1394_tlist_node_s     *tln_next;
} hci1394_tlist_node_t;


/*
 * callback used in hci1394_tlist_timer_t.  This will be called when a node on
 * the list expires.
 */
typedef
    void (*hci1394_tlist_callback_t)(hci1394_tlist_node_t *node, void *arg);


/*
 * This structure is used if you are using the timeout feature of the linked
 * list.
 *   timeout
 *      time in nS when a node should be considered to haved timed out.
 *
 *   timer_resolution
 *      time in nS when the list should be checked for timeouts. It can be
 *      varied from timeout to reduce the jitter in the callback.
 *
 *   callback
 *      function to call on timeout.
 *
 *   callback_arg
 *      user specified argument passed in callback
 *
 */
typedef struct hci1394_tlist_timer_s {
        hrtime_t                        tlt_timeout;
        hrtime_t                        tlt_timer_resolution;
        hci1394_tlist_callback_t        tlt_callback;
        void                            *tlt_callback_arg;
} hci1394_tlist_timer_t;


/* State to determine if timeout is scheduled or not */
typedef enum {
        HCI1394_TLIST_TIMEOUT_OFF,
        HCI1394_TLIST_TIMEOUT_ON
} hci1394_tlist_timeout_state_t;


/* private structure used to keep track of the tlist */
typedef struct hci1394_tlist_s {
        /* head and tail of linked list */
        hci1394_tlist_node_t            *tl_head;
        hci1394_tlist_node_t            *tl_tail;

        /* are we using timeout feature */
        boolean_t                       tl_timer_enabled;

        /* has timeout() been called */
        hci1394_tlist_timeout_state_t   tl_state;

        /* id returned from timeout() */
        timeout_id_t                    tl_timeout_id;

        /* local copy of timer_info */
        hci1394_tlist_timer_t           tl_timer_info;

        hci1394_drvinfo_t               *tl_drvinfo;
        kmutex_t                        tl_mutex;
} hci1394_tlist_t;

_NOTE(SCHEME_PROTECTS_DATA("Single thread modifies", \
        hci1394_tlist_s::tl_state \
        hci1394_tlist_s::tl_timeout_id \
        hci1394_tlist_s::tl_timer_info.tlt_timeout))

/* handle passed back from init() and used for rest of functions */
typedef struct hci1394_tlist_s  *hci1394_tlist_handle_t;



void hci1394_tlist_init(hci1394_drvinfo_t *drvinfo,
    hci1394_tlist_timer_t *timer, hci1394_tlist_handle_t *tlist_handle);
void hci1394_tlist_fini(hci1394_tlist_handle_t *tlist_handle);


void hci1394_tlist_add(hci1394_tlist_handle_t tlist_handle,
    hci1394_tlist_node_t *node);
int hci1394_tlist_delete(hci1394_tlist_handle_t tlist_handle,
    hci1394_tlist_node_t *node);
void hci1394_tlist_get(hci1394_tlist_handle_t tlist_handle,
    hci1394_tlist_node_t **node);
void hci1394_tlist_peek(hci1394_tlist_handle_t tlist_handle,
    hci1394_tlist_node_t **node);

void hci1394_tlist_timeout_update(hci1394_tlist_handle_t tlist_handle,
    hrtime_t timeout);
void hci1394_tlist_timeout_cancel(hci1394_tlist_handle_t tlist_handle);


#ifdef  __cplusplus
}
#endif

#endif  /* _SYS_1394_ADAPTERS_HCI1394_TLIST_H */