etd.c

来自「winNT技术操作系统,国外开放的原代码和LIUX一样」· C语言 代码 · 共 644 行 · 第 1/2 页

C
644
字号
/**
 * etd.c - USB driver stack project for Windows NT 4.0
 *
 * Copyright (c) 2002-2004 Zhiming  mypublic99@yahoo.com
 *
 * This program/include file is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as published
 * by the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program/include file is distributed in the hope that it will be
 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program (in the main directory of the distribution, the file
 * COPYING); if not, write to the Free Software Foundation,Inc., 59 Temple
 * Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <usbdriver.h>
#include "ehci.h"

#define init_elem( ptr, type, ehci_elem_type ) \
{\
	PEHCI_ELEM_LINKS tmp;\
	ptr = ( type* )( plist->phys_bufs[ i ] + sizeof( type ) * j );\
	ptr->hw_next = ehci_elem_type << 1;\
	if( ehci_elem_type == INIT_LIST_FLAG_QTD )\
		ptr->hw_next = 0;\
	tmp = ptr->elem_head_link = &plist->elem_head_buf[ i * elms_per_page + j ];\
	InitializeListHead( &tmp->elem_link );\
	InitializeListHead( &tmp->sched_link );\
	InsertTailList( &plist->free_list, &tmp->elem_link );\
	tmp->list_link = plist;\
	tmp->pool_link = pinit_ctx->pool;\
	tmp->phys_part = ( PVOID )( ( ULONG )ptr | ( ehci_elem_type << 1 ) );\
	if( ehci_elem_type != INIT_LIST_FLAG_QTD )\
		ptr->phys_addr = ( plist->phys_addrs[ i ].LowPart + sizeof( type ) * j ) | ( ehci_elem_type << 1 );\
	else \
		ptr->phys_addr = plist->phys_addrs[ i ].LowPart + sizeof( type ) * j ;\
}

// get the actual max list count of the pool, two limit, max_elem_pool and max_lists_pool
#define get_max_lists_count( pOOL, max_liSTS ) \
{\
	LONG ii1=0;\
	switch( elem_pool_get_type( pOOL ) )\
	{\
	case INIT_LIST_FLAG_QTD:\
		ii1 = EHCI_MAX_QTDS_LIST;\
		break;\
	case INIT_LIST_FLAG_FSTN:\
		ii1 = EHCI_MAX_QHS_LIST;\
		break;\
	case INIT_LIST_FLAG_SITD:\
		ii1 = EHCI_MAX_ITDS_LIST;\
		break;\
	case INIT_LIST_FLAG_QH:  \
		ii1 = EHCI_MAX_SITDS_LIST;\
		break;\
	case INIT_LIST_FLAG_ITD: \
		ii1 = EHCI_MAX_FSTNS_LIST;\
		break;\
	}\
	max_liSTS = ( EHCI_MAX_ELEMS_POOL / ii1 ) > EHCI_MAX_LISTS_POOL ? EHCI_MAX_LISTS_POOL : ( EHCI_MAX_ELEMS_POOL / ii1 );\
}

VOID elem_list_destroy_elem_list(PEHCI_ELEM_LIST plist);

PLIST_ENTRY elem_list_get_list_head(PEHCI_ELEM_LIST plist);

LONG elem_list_get_total_count(PEHCI_ELEM_LIST plist);

LONG elem_list_get_elem_size(PEHCI_ELEM_LIST plist);

LONG elem_list_get_link_offset(PEHCI_ELEM_LIST plist);

LONG elem_list_add_ref(PEHCI_ELEM_LIST plist);

LONG elem_list_release_ref(PEHCI_ELEM_LIST plist);

LONG elem_list_get_ref(PEHCI_ELEM_LIST plist);

BOOLEAN
elem_pool_lock(PEHCI_ELEM_POOL pool, BOOLEAN at_dpc)
{
    UNREFERENCED_PARAMETER(pool);
    UNREFERENCED_PARAMETER(at_dpc);

    return TRUE;
}

BOOLEAN
elem_pool_unlock(PEHCI_ELEM_POOL pool, BOOLEAN at_dpc)
{
    UNREFERENCED_PARAMETER(pool);
    UNREFERENCED_PARAMETER(at_dpc);

    return TRUE;
}

LONG
get_elem_phys_part_size(ULONG type)
{
    // type is INIT_LIST_FLAG_XXX
    LONG size;

    size = 0;
    switch (type)
    {
        case INIT_LIST_FLAG_ITD:
            size = 64;
            break;
        case INIT_LIST_FLAG_SITD:
            size = 28;
            break;
        case INIT_LIST_FLAG_QTD:
            size = 32;
            break;
        case INIT_LIST_FLAG_QH:
            size = 48;
            break;
        case INIT_LIST_FLAG_FSTN:
            size = 8;
            break;
    }
    return size;
}

BOOLEAN
elem_list_init_elem_list(PEHCI_ELEM_LIST plist, LONG init_flags, PVOID context, LONG count)
{
    LONG pages, i, j, elms_per_page;
    PEHCI_QH pqh;
    PEHCI_ITD pitd;
    PEHCI_SITD psitd;
    PEHCI_QTD pqtd;
    PEHCI_FSTN pfstn;
    PINIT_ELEM_LIST_CONTEXT pinit_ctx;

    UNREFERENCED_PARAMETER(count);

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

    RtlZeroMemory(plist, sizeof(EHCI_ELEM_LIST));

    pinit_ctx = context;

    plist->destroy_list = elem_list_destroy_elem_list;
    plist->get_list_head = elem_list_get_list_head;
    plist->get_total_count = elem_list_get_total_count;
    plist->get_elem_size = elem_list_get_elem_size;
    plist->get_link_offset = elem_list_get_link_offset;
    plist->add_ref = elem_list_add_ref;
    plist->release_ref = elem_list_release_ref;
    plist->get_ref = elem_list_get_ref;

    InitializeListHead(&plist->free_list);

    switch (init_flags & 0x0f)
    {
        case INIT_LIST_FLAG_ITD:
            plist->total_count = EHCI_MAX_ITDS_LIST;
            plist->elem_size = sizeof(EHCI_ITD);
            break;
        case INIT_LIST_FLAG_QH:
            plist->total_count = EHCI_MAX_QHS_LIST;
            plist->elem_size = sizeof(EHCI_QH);
            break;
        case INIT_LIST_FLAG_SITD:
            plist->total_count = EHCI_MAX_SITDS_LIST;
            plist->elem_size = sizeof(EHCI_SITD);
            break;
        case INIT_LIST_FLAG_FSTN:
            plist->total_count = EHCI_MAX_FSTNS_LIST;
            plist->elem_size = sizeof(EHCI_FSTN);
            break;
        case INIT_LIST_FLAG_QTD:
            plist->total_count = EHCI_MAX_QTDS_LIST;
            plist->elem_size = sizeof(EHCI_QTD);
            break;
        default:
            goto ERROR_OUT;
    }
    if (plist->elem_size & 0x1f)
    {
        plist->total_count = 0;
        goto ERROR_OUT;
    }

    plist->flags = init_flags;
    plist->parent_pool = pinit_ctx->pool;
    plist->padapter = pinit_ctx->padapter;
    pages = ((plist->elem_size * plist->total_count) + (PAGE_SIZE - 1)) / PAGE_SIZE;
    elms_per_page = PAGE_SIZE / plist->elem_size;

    plist->phys_addrs = usb_alloc_mem(NonPagedPool,
                                      (sizeof(PHYSICAL_ADDRESS) + sizeof(PBYTE)) * pages +
                                      sizeof(EHCI_ELEM_LINKS) * plist->total_count);

    if (plist->phys_addrs == NULL)
    {
        plist->total_count = 0;
        goto ERROR_OUT;
    }

    plist->phys_bufs = (PBYTE *) & plist->phys_addrs[pages];
    plist->elem_head_buf = (PEHCI_ELEM_LINKS) & plist->phys_bufs[pages];
    RtlZeroMemory(plist->phys_addrs,
                  (sizeof(PHYSICAL_ADDRESS) + sizeof(PBYTE)) * pages +
                  sizeof(EHCI_ELEM_LINKS) * plist->total_count);

    for(i = 0; i < pages; i++)
    {
        plist->phys_bufs[i] = HalAllocateCommonBuffer(plist->padapter,
                                                      PAGE_SIZE, &plist->phys_addrs[i], FALSE);

        if (plist->phys_bufs[i] == NULL)
        {
            // failed, roll back
            for(j = i - 1; j >= 0; j--)
                HalFreeCommonBuffer(plist->padapter,
                                    PAGE_SIZE, plist->phys_addrs[j], plist->phys_bufs[j], FALSE);
            goto ERROR_OUT;
        }
        RtlZeroMemory(plist->phys_bufs[i], PAGE_SIZE);
        for(j = 0; j < elms_per_page; j++)
        {
            switch (init_flags & 0xf)
            {
                case INIT_LIST_FLAG_QH:
                {
                    init_elem(pqh, EHCI_QH, INIT_LIST_FLAG_QH);
                    break;
                }
                case INIT_LIST_FLAG_ITD:
                {
                    init_elem(pitd, EHCI_ITD, INIT_LIST_FLAG_ITD);
                    break;
                }
                case INIT_LIST_FLAG_QTD:
                {
                    init_elem(pqtd, EHCI_QTD, INIT_LIST_FLAG_QTD);
                    break;
                }
                case INIT_LIST_FLAG_SITD:
                {
                    init_elem(psitd, EHCI_SITD, INIT_LIST_FLAG_SITD);
                    break;
                }
                case INIT_LIST_FLAG_FSTN:
                {
                    init_elem(pfstn, EHCI_FSTN, INIT_LIST_FLAG_FSTN);
                    break;
                }
                default:
                    TRAP();
            }
        }
    }
    return TRUE;

ERROR_OUT:
    if (plist->phys_addrs != NULL)
        usb_free_mem(plist->phys_addrs);

    RtlZeroMemory(plist, sizeof(EHCI_ELEM_LIST));
    return FALSE;
}

VOID
elem_list_destroy_elem_list(PEHCI_ELEM_LIST plist)
{
    LONG i, pages;

    if (plist == NULL)
        return;

    pages = (plist->total_count * plist->elem_size + PAGE_SIZE - 1) / PAGE_SIZE;
    for(i = 0; i < pages; i++)
        HalFreeCommonBuffer(plist->padapter, PAGE_SIZE, plist->phys_addrs[i], plist->phys_bufs[i], FALSE);

    usb_free_mem(plist->phys_addrs);
    RtlZeroMemory(plist, sizeof(EHCI_ELEM_LIST));
}

PLIST_ENTRY
elem_list_get_list_head(PEHCI_ELEM_LIST plist)
{
    if (plist == NULL)
        return NULL;
    return &plist->free_list;
}

LONG
elem_list_get_total_count(PEHCI_ELEM_LIST plist)
{
    if (plist == NULL)
        return 0;
    return plist->total_count;;
}

LONG
elem_list_get_elem_size(PEHCI_ELEM_LIST plist)
{
    if (plist == NULL)
        return 0;
    return plist->elem_size;
}

LONG
elem_list_get_link_offset(PEHCI_ELEM_LIST plist)
{
    if (plist == NULL)
        return 0;

    return get_elem_phys_part_size(plist->flags & 0xf);
}

⌨️ 快捷键说明

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