etd.c
来自「这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统」· 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 + -
显示快捷键?