etd.c

来自「这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统」· C语言 代码 · 共 644 行 · 第 1/2 页

C
644
字号
LONG
elem_list_add_ref(PEHCI_ELEM_LIST plist)
{
    plist->reference++;
    return plist->reference;
}

LONG
elem_list_release_ref(PEHCI_ELEM_LIST plist)
{
    plist->reference--;
    return plist->reference;
}

LONG
elem_list_get_ref(PEHCI_ELEM_LIST plist)
{
    return plist->reference;
}

//
// pool methods
//

BOOLEAN
elem_pool_init_pool(PEHCI_ELEM_POOL pool, LONG flags, PVOID context)
{
    INIT_ELEM_LIST_CONTEXT init_ctx;

    if (pool == NULL || context == NULL)
        return FALSE;

    RtlZeroMemory(pool, sizeof(EHCI_ELEM_POOL));

    init_ctx.pool = pool;
    init_ctx.padapter = context;

    pool->elem_lists[0] = usb_alloc_mem(NonPagedPool, sizeof(EHCI_ELEM_LIST));

    if (pool->elem_lists[0] == NULL)
        return FALSE;

    if (elem_list_init_elem_list(pool->elem_lists[0], flags, &init_ctx, 0) == FALSE)
    {
        usb_free_mem(pool->elem_lists[0]);
        return FALSE;
    }
    pool->link_offset = pool->elem_lists[0]->get_link_offset(pool->elem_lists[0]);
    pool->free_count = pool->elem_lists[0]->get_total_count(pool->elem_lists[0]);
    pool->list_count = 1;
    pool->flags = flags;

    return TRUE;
}

LONG
elem_pool_get_link_offset(PEHCI_ELEM_POOL elem_pool)
{
    return elem_pool->link_offset;
}

LONG
elem_pool_get_total_count(PEHCI_ELEM_POOL elem_pool)
{
    return elem_pool->elem_lists[0]->get_total_count(elem_pool->elem_lists[0]) * elem_pool->list_count;
}

VOID
elem_pool_destroy_pool(PEHCI_ELEM_POOL pool)
{
    LONG i;
    if (pool == NULL)
        return;
    for(i = pool->list_count - 1; i >= 0; i--)
    {
        pool->elem_lists[i]->destroy_list(pool->elem_lists[i]);
        usb_free_mem(pool->elem_lists[i]);
        pool->elem_lists[i] = NULL;
    }
    RtlZeroMemory(pool, sizeof(EHCI_ELEM_POOL));
    return;
}

PEHCI_ELEM_LINKS
elem_pool_alloc_elem(PEHCI_ELEM_POOL pool)
{
    LONG i;
    PEHCI_ELEM_LIST pel = NULL;
    PLIST_HEAD lh;
    PEHCI_ELEM_LINKS elnk;

    if (pool == NULL)
        return NULL;

    for(i = 0; i < pool->list_count; i++)
    {
        pel = pool->elem_lists[i];
        if (pel->get_ref(pel) == pel->get_total_count(pel))
            continue;
        break;
    }
    if (i == pool->list_count)
    {
        if (elem_pool_expand_pool(pool, pel->get_total_count(pel)) == FALSE)
            return NULL;
        pel = pool->elem_lists[i];
    }

    lh = pel->get_list_head(pel);
    elnk = (PEHCI_ELEM_LINKS) RemoveHeadList(lh);
    InitializeListHead(&elnk->elem_link);
    InitializeListHead(&elnk->sched_link);

    pel->add_ref(pel);
    pool->free_count--;

    return elnk;
}

VOID
elem_pool_free_elem(PEHCI_ELEM_LINKS elem_link)
{
    PLIST_HEAD lh;
    LONG ref;
    PEHCI_ELEM_POOL pool;
    if (elem_link == NULL)
        return;
    pool = elem_link->pool_link;
    lh = elem_link->list_link->get_list_head(elem_link->list_link);
    if (lh == NULL)
        return;
    InsertHeadList(lh, (PLIST_ENTRY) elem_link);
    ref = elem_link->list_link->release_ref(elem_link->list_link);
    pool->free_count++;
    if (ref == 0)
        elem_pool_collect_garbage(pool);
    return;
}

BOOLEAN
elem_pool_is_empty(PEHCI_ELEM_POOL pool)
{
    PEHCI_ELEM_LIST pel;

    if (pool == NULL)
        return TRUE;
    pel = pool->elem_lists[0];
    return (BOOLEAN) (pool->list_count == 1 && pool->free_count == pel->get_total_count(pel));
}

LONG
elem_pool_get_free_count(PEHCI_ELEM_POOL pool)
{
    if (pool == NULL)
        return 0;
    return pool->free_count;
}

PEHCI_ELEM_LINKS
elem_pool_alloc_elems(PEHCI_ELEM_POOL pool, LONG count)
{
    LIST_HEAD lh;
    PLIST_ENTRY pthis;
    LONG i, alloc_count, max_pool_lists;
    PEHCI_ELEM_LIST pel;
    PEHCI_ELEM_LINKS elnk;
    // calculate to see if the count is affordable

    if (pool == NULL || count <= 0)
        return NULL;

    get_max_lists_count(pool, max_pool_lists);
    InitializeListHead(&lh);
    pel = pool->elem_lists[0];
    if (count <= pool->free_count)
        alloc_count = 0;
    else
        alloc_count = count - pool->free_count;

    if (alloc_count > pel->get_total_count(pel) * (max_pool_lists - pool->list_count))
        return NULL;

    for(i = 0; i < count; i++)
    {
        if ((elnk = elem_pool_alloc_elem(pool)) == NULL)
        {
            // undo what we have done
            while (IsListEmpty(&lh) == FALSE)
            {
                pthis = RemoveHeadList(&lh);
                elnk = struct_ptr(pthis, EHCI_ELEM_LINKS, elem_link);
                elem_pool_free_elem(elnk);
            }
            return NULL;
        }
        InsertTailList(&lh, &elnk->elem_link);
    }
    ListFirst(&lh, pthis);
    elnk = struct_ptr(pthis, EHCI_ELEM_LINKS, elem_link);
    RemoveEntryList(&lh);
    return elnk;
}

BOOLEAN
elem_pool_free_elems(PEHCI_ELEM_LINKS elem_chains)
{
    // note: no list head exists.
    LIST_HEAD lh;
    PEHCI_ELEM_LINKS elnk;

    InsertTailList(&elem_chains->elem_link, &lh);
    while (IsListEmpty(&lh) == FALSE)
    {
        elnk = (PEHCI_ELEM_LINKS) RemoveHeadList(&lh);
        elem_pool_free_elem(elnk);
    }
    return TRUE;
}

LONG
elem_pool_get_type(PEHCI_ELEM_POOL pool)
{
    if (pool == NULL)
        return -1;
    return (pool->flags & 0xf);
}

BOOLEAN
elem_pool_expand_pool(PEHCI_ELEM_POOL pool, LONG elem_count)
{
    LONG elem_cnt_list, list_count, i, j;
    INIT_ELEM_LIST_CONTEXT init_ctx;

    if (pool == NULL || elem_count <= 0 || elem_count > EHCI_MAX_ELEMS_POOL)
        return FALSE;

    init_ctx.pool = pool;
    init_ctx.padapter = pool->elem_lists[0]->padapter;

    elem_cnt_list = pool->elem_lists[0]->get_total_count(pool->elem_lists[0]);
    list_count = (elem_count + elem_cnt_list - 1) / elem_cnt_list;
    get_max_lists_count(pool, i);

    if (list_count + pool->list_count > i)
        return FALSE;

    for(i = pool->list_count; i < list_count + pool->list_count; i++)
    {
        pool->elem_lists[i] = usb_alloc_mem(NonPagedPool, sizeof(EHCI_ELEM_LIST));
        if (elem_list_init_elem_list(pool->elem_lists[i], pool->flags, &init_ctx, 0) == FALSE)
            break;
    }

    if (i < list_count + pool->list_count)
    {
        // undo all we have done
        for(j = pool->list_count; j < pool->list_count + i; j++)
        {
            pool->elem_lists[j]->destroy_list(pool->elem_lists[j]);
            usb_free_mem(pool->elem_lists[j]);
            pool->elem_lists[j] = NULL;
        }
        return FALSE;
    }

    // update pool
    pool->free_count += elem_cnt_list * list_count;
    pool->list_count += list_count;
    return TRUE;
}

BOOLEAN
elem_pool_collect_garbage(PEHCI_ELEM_POOL pool)
{
    LONG i, j, k, fl;
    LONG free_elem_lists[EHCI_MAX_LISTS_POOL - 1];
    PEHCI_ELEM_LIST pel;

    if (pool == NULL)
        return FALSE;

    for(i = 1, fl = 0; i < pool->list_count; i++)
    {
        if (pool->elem_lists[i]->get_ref(pool->elem_lists[i]) == 0)
        {
            free_elem_lists[fl++] = i;
        }
    }
    for(j = fl - 1; j >= 0; j--)
    {
        pel = pool->elem_lists[free_elem_lists[j]];
        pel->destroy_list(pel);
        usb_free_mem(pel);

        for(k = free_elem_lists[j] + 1; k < pool->list_count; k++)
        {
            // shrink the elem_lists
            pool->elem_lists[k - 1] = pool->elem_lists[k];
        }
        pool->elem_lists[k] = NULL;
        pel = pool->elem_lists[0];
        pool->free_count -= pel->get_total_count(pel);
        pool->list_count--;
    }
    return TRUE;
}

BOOLEAN
elem_pool_can_transfer(PEHCI_ELEM_POOL pool, LONG td_count)
{
    LONG i;
    if (pool == NULL || td_count <= 0)
        return FALSE;
    get_max_lists_count(pool, i);
    if ((i - pool->list_count)
        * pool->elem_lists[0]->get_total_count(pool->elem_lists[0]) + pool->free_count < td_count)
        return FALSE;
    return TRUE;
}

//----------------------------------------------------------

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?