root/usr/src/uts/intel/io/dktp/hba/ghd/ghd_queue.c
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (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 1999 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#include <sys/types.h>
#include <sys/param.h>
#include <sys/debug.h>
#include "ghd_queue.h"



void
L1_add(L1_t *lp, L1el_t *lep, void *datap)
{
        /* init the list element */
        lep->le_nextp = NULL;
        lep->le_datap = datap;

        if (!lp->l1_tailp) {
                /* list is empty */
                lp->l1_headp = lep;
        } else {
                /* add it to the tailend */
                lp->l1_tailp->le_nextp = lep;
        }

        lp->l1_tailp = lep;
}


/*
 * L1Delete()
 *
 *      Remove a specific entry from a singly-linked list.
 *
 */

void
L1_delete(L1_t *lp, L1el_t *lep)
{
        L1el_t  *prevp;

        if (lp->l1_headp == lep) {
                /* it's the first entry in the list */
                if ((lp->l1_headp = lep->le_nextp) == NULL) {
                        /* the list is now empty */
                        lp->l1_tailp = NULL;
                }
                return;
        }

        for (prevp = lp->l1_headp; prevp != NULL; prevp = prevp->le_nextp) {
                if (prevp->le_nextp == lep) {
                        if ((prevp->le_nextp = lep->le_nextp) == NULL)
                                lp->l1_tailp = prevp;
                        return;
                }
        }
        /* its not on this list */
}


/*
 * L1_remove()
 *
 *      Remove the entry at the head of the list (if any).
 *
 */

void *
L1_remove(L1_t *lp)
{
        L1el_t  *lep;

        /* pop the first one off the list head */
        if ((lep = lp->l1_headp) == NULL) {
                return (NULL);
        }

        /* if the list is now empty fix the tail pointer */
        if ((lp->l1_headp = lep->le_nextp) == NULL)
                lp->l1_tailp = NULL;

        lep->le_nextp = NULL;

        return (lep->le_datap);
}


void
L2_add(L2el_t *headp, L2el_t *elementp, void *private)
{

        ASSERT(headp != NULL && elementp != NULL);
        ASSERT(headp->l2_nextp != NULL);
        ASSERT(headp->l2_prevp != NULL);

        elementp->l2_private = private;

        elementp->l2_nextp = headp;
        elementp->l2_prevp = headp->l2_prevp;
        headp->l2_prevp->l2_nextp = elementp;
        headp->l2_prevp = elementp;
}

void
L2_delete(L2el_t *elementp)
{

        ASSERT(elementp != NULL);
        ASSERT(elementp->l2_nextp != NULL);
        ASSERT(elementp->l2_prevp != NULL);
        ASSERT(elementp->l2_nextp->l2_prevp == elementp);
        ASSERT(elementp->l2_prevp->l2_nextp == elementp);

        elementp->l2_prevp->l2_nextp = elementp->l2_nextp;
        elementp->l2_nextp->l2_prevp = elementp->l2_prevp;

        /* link it to itself in case someone does a double delete */
        elementp->l2_nextp = elementp;
        elementp->l2_prevp = elementp;
}


void
L2_add_head(L2el_t *headp, L2el_t *elementp, void *private)
{

        ASSERT(headp != NULL && elementp != NULL);
        ASSERT(headp->l2_nextp != NULL);
        ASSERT(headp->l2_prevp != NULL);

        elementp->l2_private = private;

        elementp->l2_prevp = headp;
        elementp->l2_nextp = headp->l2_nextp;
        headp->l2_nextp->l2_prevp = elementp;
        headp->l2_nextp = elementp;
}



/*
 * L2_remove()
 *
 *      Remove the entry from the head of the list (if any).
 *
 */

void *
L2_remove_head(L2el_t *headp)
{
        L2el_t *elementp;

        ASSERT(headp != NULL);

        if (L2_EMPTY(headp))
                return (NULL);

        elementp = headp->l2_nextp;

        headp->l2_nextp = elementp->l2_nextp;
        elementp->l2_nextp->l2_prevp = headp;

        /* link it to itself in case someone does a double delete */
        elementp->l2_nextp = elementp;
        elementp->l2_prevp = elementp;

        return (elementp->l2_private);
}

void *
L2_next(L2el_t *elementp)
{

        ASSERT(elementp != NULL);

        if (L2_EMPTY(elementp))
                return (NULL);
        return (elementp->l2_nextp->l2_private);
}