📄 atl_mix.c
字号:
***************************************
**
** Buffer maintenance for transfer done and timeout
**
***************************************
***************************************/
void handle_transfer_done( transfer_instance_ptr tip )
{
unsigned char ptd_header_buffer_ptr[ PTD_HEADER_SIZE ];
PTD_header_param ph;
unsigned short transferred_bytes;
if ( tip->data_ptr_start == NULL )
return;
g_processing_block = tip;
read_direct_access( tip->target_address, ptd_header_buffer_ptr, PTD_HEADER_SIZE );
get_PTD_header( &ph, ptd_header_buffer_ptr );
tip->fatal_error <<= 1;
(tip->epi_ptr)->toggle = ph.Toggle;
transferred_bytes = ph.ActualBytes;
if ( tip->direction == IN )
read_direct_access( tip->target_address + PTD_HEADER_SIZE, tip->data_ptr_start, transferred_bytes );
tip->data_ptr_start += transferred_bytes;
tip->transferred_size += transferred_bytes;
tip->completion_code = ph.CompletionCode;
tip->retry_count = 0;
gp_cc_logger[ ph.CompletionCode ]++;
switch ( ph.CompletionCode )
{
case 0x0 : // No error
break;
case 0x4 : // Stall - Fatal error
case 0x9 : // DataUnderrun - Non-fatal error
break;
case 0x3 : // DataToggleMismatch - Fatal error
#ifdef AUTO_TRANSFER_RETRY_ENABLE
{
if ( tip->transfer_type == INTERRUPT_TRANSFER )
atlmix_re_enable_interrupt_transfer( tip );
else
re_enable_atl_transfer( tip );
return;
}
#else
break;
#endif
case 0x5 : // DeviceNotResponding - Fatal error
case 0x6 : // PIDCheckFailure - Fatal error
tip->fatal_error |= 0x1;
#ifdef AUTO_TRANSFER_RETRY_ENABLE
if ( (tip->fatal_error) != 0x7 )
{
if ( tip->transfer_type == INTERRUPT_TRANSFER )
atlmix_re_enable_interrupt_transfer( tip );
else
re_enable_atl_transfer( tip );
return;
}
#else
break;
#endif
case 0x1 : // CRC - Fatal error
case 0x2 : // BitStuffing - Fatal error
case 0x7 : // UnexpectedPID - Fatal error
case 0x8 : // DataOverrun - Non-fatal error
case 0xC : // BufferOverrun - Non-fatal error
case 0xD : // BufferUnderrun - Non-fatal error
break;
default : // Other errors
// un-documented error, never be happened.
break;
}
free_transfer_block( tip );
tip->data_ptr_start = NULL;
// if ( tip->epi_ptr != NULL )
(*(tip->callback))( tip->epi_ptr );
}
/***************************************
***************************************
**
** Utility routines
**
***************************************
***************************************/
static 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 + 1)) = (*(ph + 1)) | (0xE << 4);
*(ph + 2) = php->MaxPacketSize & 0xFF;
*(ph + 3) = (php->EndpointNumber << 4)
| (0 << 3)
| (php->Speed << 2)
| (php->MaxPacketSize >> 8);
*(ph + 4) = php->TotalBytes & 0xFF;
// *(ph + 5) = (php->DirectionPID << 2)
// | (php->TotalBytes >> 8);
*(ph + 5) = (php->Paired << 7)
| (php->PingPong << 6)
| (php->DirectionPID << 2)
| (php->TotalBytes >> 8);
*(ph + 6) = (php->Format << 7)
| (php->FunctionAddress & 0x7F);
*(ph + 7) = (php->PollingRate << 5)
| (php->StartingFrame & 0x1F);
}
static 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 atlmix_is_fatal_error( transfer_instance *tr_inst_ptr )
{
unsigned char completion_code;
completion_code = tr_inst_ptr->completion_code;
return ( (completion_code & 0x8) ? 0 : completion_code );
}
#define DEBUG_CODE
#ifdef DEBUG_CODE
#if 0
void atlmix_show_ptd_header( unsigned char transfer_type, unsigned char index )
{
unsigned short p[4];
unsigned short target_address;
target_address = g_buffer_parameter[ transfer_type ].base_address + (g_buffer_parameter[ transfer_type ].payload_size + PTD_HEADER_SIZE) * index;
read_direct_access( target_address, (unsigned char *)p, 8 );
mprintf( WHITE, CONTINUE, "%d-%d : PTD-h 0x %04X %04X %04X %04X \r\n", transfer_type, index, *(p + 0), *(p + 1), *(p + 2), *(p + 3) );
}
#else
void atlmix_show_ptd_header( unsigned char transfer_type, unsigned char index )
{
unsigned short p[6];
unsigned short target_address;
target_address = g_buffer_parameter[ transfer_type ].base_address + (g_buffer_parameter[ transfer_type ].payload_size + PTD_HEADER_SIZE) * index;
read_direct_access( target_address, (unsigned char *)p, 12 );
mprintf( WHITE, CONTINUE, "%d-%d : PTD-h 0x %04X %04X %04X %04X %04X %04X \r\n", transfer_type, index, *(p + 0), *(p + 1), *(p + 2), *(p + 3), *(p + 4), *(p + 5) );
}
#endif
void atlmix_view_PTD( unsigned char index )
{
atlmix_show_ptd_header( CTRL_BULK_TRANSFER, index );
}
void atlmix_display_open_slot( void )
{
unsigned char i;
for ( i = 0; i < g_buffer_parameter[ CTRL_BULK_TRANSFER ].number_of_blocks; i++ )
mprintf( YELLOW, CONTINUE, "%c", (g_atl_transfer_slot[ i ].lock == LOCK) ? 'L' : 'O' );
mprintf( YELLOW, CONTINUE, "\r\n" );
}
#endif // DEBUG_CODE
void atlmix_buffer_parameter_initialize( buffer_info *bip )
{
unsigned char i;
unsigned short next_base_address;
// ISTL parameters
next_base_address = 0;
g_buffer_parameter[ ISOCHRONOUS_TRANSFER ].base_address = 0x0000;
g_buffer_parameter[ ISOCHRONOUS_TRANSFER ].total_buffer_size = ((bip->isochr).single_buffer_size) << 1;
g_buffer_parameter[ ISOCHRONOUS_TRANSFER ].payload_size = 0;
g_buffer_parameter[ ISOCHRONOUS_TRANSFER ].number_of_blocks = 0;
next_base_address += g_buffer_parameter[ ISOCHRONOUS_TRANSFER ].total_buffer_size;
// INTL parameters
g_buffer_parameter[ INTERRUPT_TRANSFER ].base_address = next_base_address;
g_buffer_parameter[ INTERRUPT_TRANSFER ].total_buffer_size = (PTD_HEADER_SIZE + (bip->interr).payload_size) * (bip->interr).n_of_blocks;
g_buffer_parameter[ INTERRUPT_TRANSFER ].payload_size = (bip->interr).payload_size;
g_buffer_parameter[ INTERRUPT_TRANSFER ].number_of_blocks = (bip->interr).n_of_blocks;
next_base_address += g_buffer_parameter[ INTERRUPT_TRANSFER ].total_buffer_size;
// ATL parameters
#ifdef USE_PAIRED_PTD
{
unsigned char c = 0;
for ( i = 0; i < 10; i++ )
c += (((bip->aperio).payload_size >> i) & 0x1) ? 1 : 0;
if (c != 1)
mprintf( LIGHTRED, CONTINUE, "\r\n*** WARNING! ***\r\nFor the paired-PTD, the ATL payload size is needed to be \"(2^N) && (>=128)\".\r\n\r\n" );
}
#else
#endif
g_buffer_parameter[ CTRL_BULK_TRANSFER ].base_address = next_base_address;
g_buffer_parameter[ CTRL_BULK_TRANSFER ].total_buffer_size = 4096 - next_base_address;
g_buffer_parameter[ CTRL_BULK_TRANSFER ].payload_size = (bip->aperio).payload_size;
g_buffer_parameter[ CTRL_BULK_TRANSFER ].number_of_blocks = (4096 - next_base_address) / (PTD_HEADER_SIZE + (bip->aperio).payload_size);
// First block is reserved for ControlTransfer in this program
g_buffer_parameter[ CONTROL_TRANSFER ].base_address = g_buffer_parameter[ CTRL_BULK_TRANSFER ].base_address;
g_buffer_parameter[ CONTROL_TRANSFER ].total_buffer_size = g_buffer_parameter[ CTRL_BULK_TRANSFER ].payload_size + PTD_HEADER_SIZE;
g_buffer_parameter[ CONTROL_TRANSFER ].payload_size = g_buffer_parameter[ CTRL_BULK_TRANSFER ].payload_size;
g_buffer_parameter[ CONTROL_TRANSFER ].number_of_blocks = 1;
g_buffer_parameter[ BULK_TRANSFER ].base_address = g_buffer_parameter[ CTRL_BULK_TRANSFER ].base_address + g_buffer_parameter[ CONTROL_TRANSFER ].payload_size + PTD_HEADER_SIZE;
g_buffer_parameter[ BULK_TRANSFER ].total_buffer_size = g_buffer_parameter[ CTRL_BULK_TRANSFER ].total_buffer_size - g_buffer_parameter[ CONTROL_TRANSFER ].total_buffer_size;
g_buffer_parameter[ BULK_TRANSFER ].payload_size = g_buffer_parameter[ CTRL_BULK_TRANSFER ].payload_size;
g_buffer_parameter[ BULK_TRANSFER ].number_of_blocks = g_buffer_parameter[ CTRL_BULK_TRANSFER ].number_of_blocks - 1;
// Buffer general
write_register16( Com16_HcBufferStatus, 0 );
// Buffer sizes
write_register16( Com16_HcATLBufferSize, g_buffer_parameter[ CTRL_BULK_TRANSFER ].total_buffer_size );
write_register16( Com16_HcINTLBufferSize, g_buffer_parameter[ INTERRUPT_TRANSFER ].total_buffer_size );
write_register16( Com16_HcISTLBufferSize, (g_buffer_parameter[ ISOCHRONOUS_TRANSFER ].total_buffer_size) >> 1 ); // Set size of single buffer
// ISTL settings
write_register16( Com16_HcISTLToggleRate, 0 );
// INTL settings
write_register16( Com16_HcINTLBlkSize, g_buffer_parameter[ INTERRUPT_TRANSFER ].payload_size );
write_register32( Com32_HcINTLPTDSkipMap, 0xFFFFFFFF );
write_register32( Com32_HcINTLLastPTD, 0x1 << (g_buffer_parameter[ INTERRUPT_TRANSFER ].number_of_blocks - 1) );
// ATL settings
write_register16( Com16_HcATLBlkSize, g_buffer_parameter[ CTRL_BULK_TRANSFER ].payload_size );
write_register32( Com32_HcATLPTDSkipMap, 0xFFFFFFFF );
write_register32( Com32_HcATLLastPTD, 0x1 << (g_buffer_parameter[ CTRL_BULK_TRANSFER ].number_of_blocks - 1) );
write_register16( Com16_HcATLPTDDoneThresholdCount, InitVal_HcATLPTDDoneThresholdCount );
write_register16( Com16_HcATLPTDDoneThresholdTimeOut, InitVal_HcATLPTDDoneThresholdTimeOut );
if ( NULL == (g_atl_transfer_slot = (transfer_instance *)malloc( sizeof( transfer_instance ) * g_buffer_parameter[ CTRL_BULK_TRANSFER ].number_of_blocks )) )
mprintf( LIGHTRED, ABORT, "failed to make transfer instances for ATL slots for %u blocks", g_buffer_parameter[ BULK_TRANSFER ].number_of_blocks);
if ( NULL == (g_intl_transfer_slot = (transfer_instance *)malloc( sizeof( transfer_instance ) * g_buffer_parameter[ INTERRUPT_TRANSFER ].number_of_blocks )) )
mprintf( LIGHTRED, ABORT, "failed to make transfer instances for INTL slots for %u blocks", g_buffer_parameter[ BULK_TRANSFER ].number_of_blocks);
for ( i = 0; i < g_buffer_parameter[ CTRL_BULK_TRANSFER ].number_of_blocks; i++ )
{
atlmix_free_transfer_index( CTRL_BULK_TRANSFER, i );
g_atl_transfer_slot[ i ].index = i;
g_atl_transfer_slot[ i ].transfer_type = CTRL_BULK_TRANSFER;
}
for ( i = 0; i < g_buffer_parameter[ INTERRUPT_TRANSFER ].number_of_blocks; i++ )
{
atlmix_free_transfer_index( INTERRUPT_TRANSFER, i );
g_intl_transfer_slot[ i ].index = i;
g_intl_transfer_slot[ i ].transfer_type = INTERRUPT_TRANSFER;
}
for ( i = 0; i < 32; i++ )
g_atl_slot_number_by_block[ i ] = 0xFF;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -