📄 tr_scheduler.c
字号:
if ( ph.ActualBytes )
{
if ( i == BULK_TRANSFER)
tr_inst_ptr->readout_position = NULL;
if ( tr_inst_ptr->direction == IN )
memcpy( tr_inst_ptr->data_ptr_start, ptd_start + PTD_HEADER_LENGTH, ph.ActualBytes );
tr_inst_ptr->data_ptr_start += ph.ActualBytes;
tr_inst_ptr->transferred_size += ph.ActualBytes;
}
tr_inst_ptr->readout_position = NULL;
//
tr_inst_ptr->fatal_error = (tr_inst_ptr->fatal_error << 1) | (( (!ph.CompletionCode) || (ph.CompletionCode & 0x8) ) ? 0 : 1);
tr_inst_ptr->completion_code = ph.CompletionCode;
if ( !((!ph.CompletionCode) || (ph.CompletionCode & 0x8)) ) /* 2005-2-24 updata */
{
(tr_inst_ptr->epi_ptr)->toggle = !ph.Toggle;
}
else
{
if ( (i == INTERRUPT_TRANSFER) && (ph.DirectionPID == IN) && !ph.Active && !ph.ActualBytes )
ph.Toggle = !ph.Toggle;
else
(tr_inst_ptr->epi_ptr)->toggle = ph.Toggle;
}
if ( ((!ph.Active)&&(!(tr_inst_ptr->data_ptr_start < tr_inst_ptr->data_ptr_end)))
|| (tr_inst_ptr->fatal_error == 0x7)
|| (tr_inst_ptr->completion_code == CompletionCode_DataUnderrun)
|| (tr_inst_ptr->completion_code == CompletionCode_Stall))
{
tr_inst_ptr->data_ptr_start = NULL;
(*(tr_inst_ptr->callback))( tr_inst_ptr );
}
}
}
}
void atl_schedule( unsigned char *bp, unsigned short length, unsigned short *atl_buffer_access_length )
{
transfer_instance_ptr tr_inst_ptr;
PTD_header_param ph;
unsigned char *ptd_start;
unsigned char *ptd_end;
unsigned char *last_ptd_start;
unsigned short required_transfer_size;
unsigned short transfer_size;
unsigned short transfer_size_limit;
unsigned short size_may_be_written;
unsigned short packet_size;
int i;
ptd_start = bp;
ptd_end = bp + length;
last_ptd_start = ptd_start;
for(i=0;i<NUMBER_OF_TRANSFER_TYPES;i++)
for(tr_inst_ptr = g_tr_list_ptr[i];
tr_inst_ptr!=NULL;
tr_inst_ptr = tr_inst_ptr->tr_list_for_tr.Blink)
{
if(tr_inst_ptr->lock == DELETE)
{
tr_inst_ptr->lock = UNLOCK;
remove_tr_list(&g_tr_list_ptr[i],tr_inst_ptr);
remove_tr_from_ep(tr_inst_ptr);
continue;
}
if ( tr_inst_ptr->data_ptr_start == NULL )
continue;
if ( tr_inst_ptr->readout_position != NULL )
continue;
if ( tr_inst_ptr->direction == HOLD )
continue;
if ( i == INTERRUPT_TRANSFER )
{
if ( g_sof_counter < (tr_inst_ptr->poll_timing_timer) )
continue;
else
tr_inst_ptr->poll_timing_timer = g_sof_counter + tr_inst_ptr->schedule_rate;
}
size_may_be_written = ptd_end - ptd_start;
packet_size = (tr_inst_ptr->epi_ptr)->max_packet_size;
transfer_size_limit = (size_may_be_written < MAX_DATA_SIZE_IN_A_FRAME) ? ((size_may_be_written / packet_size) * packet_size) : MAX_DATA_SIZE_IN_A_FRAME;
required_transfer_size = (unsigned short)((unsigned long)(tr_inst_ptr->data_ptr_end) - (unsigned long)(tr_inst_ptr->data_ptr_start));
transfer_size = (required_transfer_size < transfer_size_limit) ? required_transfer_size : transfer_size_limit;
if ( required_transfer_size && !transfer_size )
continue;
if ( !((ptd_start + PTD_HEADER_LENGTH + transfer_size) < ptd_end) )
continue;
tr_inst_ptr->readout_position = ptd_start;
last_ptd_start = ptd_start;
ph.ActualBytes = 0;
ph.CompletionCode = 0;
ph.Active = 1;
ph.Toggle = (tr_inst_ptr->epi_ptr)->toggle;
ph.MaxPacketSize = packet_size;
ph.EndpointNumber = (tr_inst_ptr->epi_ptr)->ep_num;
ph.Last = 0;
ph.Speed = (tr_inst_ptr->epi_ptr)->speed;
ph.TotalBytes = transfer_size;
ph.DirectionPID = tr_inst_ptr->direction;
ph.Format = 0x03&(tr_inst_ptr->epi_ptr)->tr_type;
ph.FunctionAddress = (tr_inst_ptr->epi_ptr)->dev_addr;
if ( i == BULK_TRANSFER)
ph.FunctionAddress = (tr_inst_ptr->epi_ptr)->dev_addr;
#define A_BIT_FOR_INTERRUPT_TR 0x2
ph.test = (i == INTERRUPT_TRANSFER) ? A_BIT_FOR_INTERRUPT_TR : 0x0;
set_PTD_header( ptd_start, &ph );
if ( tr_inst_ptr->direction != IN )
memcpy( ptd_start + PTD_HEADER_LENGTH, tr_inst_ptr->data_ptr_start, transfer_size );
ptd_start = ptd_start + PTD_HEADER_LENGTH + transfer_size;
ptd_start = mem_align( ptd_start ); //
}
set_LAST_PTD_flag( last_ptd_start );
*atl_buffer_access_length = ptd_start - bp;
}
unsigned char atl_buffer_state( unsigned short pattern )
{
return ( read_register16( Com16_HcBufferStatus ) & pattern );
}
void PTD_image_create( PTD_header_param *php, unsigned char *data, unsigned char *atl_buffer )
{
int i;
set_PTD_header( atl_buffer, php );
atl_buffer += 8;
for ( i = 0; i < php->TotalBytes; i++ )
*atl_buffer++ = *data++;
}
void set_PTD_header( unsigned char *ph, PTD_header_param *php )
{
*(ph + 0) = php->ActualBytes & 0x0FF;
*(ph + 1) = (php->CompletionCode << 4)
| (php->Active << 3)
| (php->Toggle << 2)
| (php->ActualBytes >> 8);
*(ph + 2) = php->MaxPacketSize & 0xFF;
*(ph + 3) = (php->EndpointNumber << 4)
| (php->Last << 3)
| (php->Speed << 2)
| (php->MaxPacketSize >> 8);
*(ph + 4) = php->TotalBytes & 0xFF;
*(ph + 5) = (php->DirectionPID << 2)
| (php->TotalBytes >> 8);
*(ph + 6) = (php->Format << 7)
| (php->FunctionAddress & 0x7F);
*(ph + 5) |= (php->test << 4);
}
void set_LAST_PTD_flag( unsigned char *p )
{
*(p + 3) = *(p + 3) | (0x01 << 3);
}
void get_PTD_header( PTD_header_param *php, unsigned char *ph )
{
php->ActualBytes = *(ph + 0) | ((*(ph + 1) & 0x3) << 8);
php->CompletionCode = *(ph + 1) >> 4;
php->Active = (*(ph + 1) >> 3) & 0x01;
php->Toggle = (*(ph + 1) >> 2) & 0x01;
php->MaxPacketSize = *(ph + 2) | ((*(ph + 3) & 0x3) << 8);
php->EndpointNumber = *(ph + 3) >> 4;
php->Last = (*(ph + 3) >> 3) & 0x01;
php->Speed = (*(ph + 3) >> 2) & 0x01;
php->TotalBytes = *(ph + 4) | ((*(ph + 5) & 0x3) << 8);
php->DirectionPID = (*(ph + 5) >> 2) & 0x03;
php->Format = *(ph + 6) >> 7;
php->FunctionAddress = *(ph + 6) & 0x7F;
}
unsigned char is_fatal_error( transfer_instance *tr_inst_ptr )
{
unsigned char completion_code;
completion_code = tr_inst_ptr->completion_code;
if ( !completion_code )
return ( FALSE );
else if ( completion_code & 0x8 )
return ( FALSE );
else
return ( TRUE );
}
void insert_tr_to_ep_list(transfer_instance **to_this_list, transfer_instance *list )
{
disable();
if(list->epi_ptr->ep_num==0x2)
to_this_list = to_this_list;
if(*to_this_list!=NULL)
list->tr_list_for_ep.Flink = (*to_this_list)->tr_list_for_ep.Flink;
else
list->tr_list_for_ep.Flink = list;
list->tr_list_for_ep.Blink = *to_this_list;
if(*to_this_list!=NULL)
(*to_this_list)->tr_list_for_ep.Flink = list;
*to_this_list = list;
enable();
}
void remove_tr_list(transfer_instance **from_this_list, transfer_instance *list )
{
transfer_instance * last_tr_inst_ptr;
transfer_instance * next_tr_inst_ptr;
if(((*from_this_list)->tr_list_for_tr.Flink==list)&&(*from_this_list)==list)
(*from_this_list) = NULL ;
else
if((*from_this_list)->tr_list_for_tr.Flink==list)
{
(*from_this_list)->tr_list_for_tr.Flink = list->tr_list_for_tr.Flink;
last_tr_inst_ptr = list->tr_list_for_tr.Flink;
last_tr_inst_ptr->tr_list_for_tr.Blink= NULL;
}
else
if((*from_this_list)==list)
{
next_tr_inst_ptr = list->tr_list_for_tr.Blink;
next_tr_inst_ptr->tr_list_for_tr.Flink = list->tr_list_for_tr.Flink;
*from_this_list = next_tr_inst_ptr;
}
else
{
last_tr_inst_ptr = list->tr_list_for_tr.Flink;
next_tr_inst_ptr = list->tr_list_for_tr.Blink;
last_tr_inst_ptr->tr_list_for_tr.Blink = next_tr_inst_ptr;
next_tr_inst_ptr->tr_list_for_tr.Flink = last_tr_inst_ptr;
}
list->tr_list_for_tr.Flink = NULL;
list->tr_list_for_tr.Blink = NULL;
}
void remove_tr_from_ep(transfer_instance *list )
{
transfer_instance **from_this_list;
transfer_instance * last_tr_inst_ptr;
transfer_instance * next_tr_inst_ptr;
if(NULL==list->epi_ptr->tr_instance_ptr) // UPDATA 2005-3-16
return;
from_this_list = &list->epi_ptr->tr_instance_ptr;
if(((*from_this_list)->tr_list_for_ep.Flink==list)&&(*from_this_list)==list)
(*from_this_list) = NULL ;
else
if((*from_this_list)->tr_list_for_ep.Flink==list)
{
(*from_this_list)->tr_list_for_ep.Flink = list->tr_list_for_ep.Flink;
last_tr_inst_ptr = list->tr_list_for_ep.Flink;
last_tr_inst_ptr->tr_list_for_ep.Blink= NULL;
}
else
if((*from_this_list)==list)
{
next_tr_inst_ptr = list->tr_list_for_ep.Blink;
next_tr_inst_ptr->tr_list_for_ep.Flink = list->tr_list_for_ep.Flink;
*from_this_list = next_tr_inst_ptr;
}
else
{
last_tr_inst_ptr = list->tr_list_for_ep.Flink;
next_tr_inst_ptr = list->tr_list_for_ep.Blink;
last_tr_inst_ptr->tr_list_for_ep.Blink = next_tr_inst_ptr;
next_tr_inst_ptr->tr_list_for_ep.Flink = last_tr_inst_ptr;
}
list->tr_list_for_ep.Flink = NULL;
list->tr_list_for_ep.Blink = NULL;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -