📄 tr_gene.c
字号:
/*
** Kenobi2 version 1.3
**
** ** This code has been made to check/learn the 1161 functionalities **
** ** Release 25-Feb-2002 **
**
** OKANO, Akifumi
**
** Computing Segment, Semisonductors Div, Philips Japan Ltd.
** akifumi.okano@philips.com
** +81-3-3740-4668
*/
// 06Nov2001 redundant code removed
// 06Nov2001 CC=0x5/0x6 handling is moved here
#include <stdio.h>
#include "hc_comm.h"
#include "hw_acces.h"
#include "tr_gene.h"
#include "data_tr.h"
#include "ui.h"
#include "general.h"
#define SETUP_NAK_RETRY_COUNT_LIMIT 10
#define IN_NAK_RETRY_COUNT_LIMIT 10
#define OUT_NAK_RETRY_COUNT_LIMIT 10
unsigned char raw_transaction( unsigned char direction, unsigned char *data_ptr, unsigned short *size_ptr, endpoint_info *epi_ptr );
unsigned short control_transfer( USB_Device_Request *dev_req, device_instance *dvi_ptr, unsigned char *data_ptr )
{
/*
** returns
**
** error @ SETUP 0x-0--
** error @ DataStage 0x-1--
** error @ StatusStage 0x-2--
** error @ CC 0x--CC (CC=value 0x01-0x0D)
** retry over 0x--FF
** data short 0xF-DD (DD=received data length)
*/
endpoint_info *epi_ptr;
unsigned short err;
unsigned char device_to_host_transfer;
unsigned char *ds_data_ptr;
unsigned short ds_size;
unsigned short total_ds_size;
unsigned char ss_data_ptr[ 1 ]; // dummy
unsigned short ss_size;
unsigned short transfer_size;
epi_ptr = dvi_ptr->epi_ptr[ 0 ];
device_to_host_transfer = dev_req->bmRequestType >> 7;
transfer_size = dev_req->wLength;
/********* SETUP STAGE *********/
ds_size = 8; // SETUP payload size is always 8
if ( 0 != (err = transaction( SETUP, (unsigned char *)dev_req, &ds_size, epi_ptr )) )
{
// mprintf( RED, CONTINUE, " control transfer terminated (SETUP failed). err = 0x%04X\r\n", err );
return ( err | 0x0000 );
}
testprint( YELLOW, "*" );
/********* DATA STAGE *********/
if ( transfer_size )
{
epi_ptr->toggle = 1; // force DT <- 1 (defined in standard)
ds_data_ptr = data_ptr;
total_ds_size = 0;
do
{
ds_size = transfer_size - total_ds_size;
err = transaction( (device_to_host_transfer ? IN : OUT), ds_data_ptr, &ds_size, epi_ptr );
if ( isCCFatalError( err ) ) // If "err" is fatal error
{
mprintf( RED, CONTINUE, " control transfer terminated (IN failed). err = 0x%04X\r\n", err );
return ( err | 0x0100 );
}
total_ds_size += ds_size;
ds_data_ptr += ds_size;
if ( err == 0x9 ) // It is short packet
{
err = 0xF000 | total_ds_size;
break;
}
testprint( WHITE, "*" );
}
while ( total_ds_size < transfer_size );
}
/********* STAUS STAGE *********/
epi_ptr->toggle = 1; // force DT <- 1 (defined in standard)
ss_size = 0; // must be 0
err = transaction( (device_to_host_transfer ? OUT : IN), ss_data_ptr, &ss_size, epi_ptr );
if ( err )
{
// mprintf( RED, CONTINUE, " control transfer terminated (OUT failed). err = 0x%04X\r\n", err );
return ( err | 0x0200 );
}
testprint( CYAN, "*" );
return ( 0 );
}
unsigned char transaction( unsigned char direction, unsigned char *data_ptr, unsigned short *size_ptr, endpoint_info *epi_ptr )
{
/*
* This function has been made for CompletionCode 0x5, 0x6 handling.
* Sometime 1161 gives 0x6 or 0x5 error code when a device continues to send NAKs.
* In the OHCI specification, the HC should retry to transfer data when this error
* has been occured.
* This function is a wrapper function for "raw_transaction()".
* The "raw_transaction()" will do the actual USB trasaction.
*
* This function will try with rest data which has been given by this function caller.
* The speed tuning/optimization will not be required. Because this process is needed by
* slow data receiving devices.
*/
unsigned short size;
unsigned short transfered_size;
unsigned char completion_code;
int i;
transfered_size = 0;
for ( i = 0; i < 3; i++ ) // try 3 times (for fatal (CC=0x5, 0x6) handling )
{
size = *size_ptr - transfered_size;
completion_code = raw_transaction( direction, data_ptr + transfered_size, &size, epi_ptr );
transfered_size += size;
if ( !isCCFatalError( completion_code ) )
break;
// mprintf( RED, CONTINUE, "### fatal error encountered %02X \r\n", completion_code );
}
*size_ptr = transfered_size;
return ( completion_code );
}
static unsigned char raw_transaction( unsigned char direction, unsigned char *data_ptr, unsigned short *size_ptr, endpoint_info *epi_ptr )
{
ATLD *ATLD_Ptr;
PTD_header_param php,
result;
php.ActualBytes = 0;
php.CompletionCode = 0;
php.Active = 1;
php.Toggle = epi_ptr->toggle;
php.MaxPacketSize = epi_ptr->max_packet_size;
php.EndpointNumber = epi_ptr->ep_num;
php.Last = 1;
php.Speed = epi_ptr->speed;
php.TotalBytes = *size_ptr;
php.DirectionPID = direction;
php.Format = epi_ptr->tr_type;
php.FunctionAddress = epi_ptr->dev_addr;
if ( NULL == (ATLD_Ptr = open_single_PTD_ATLD( &php, data_ptr )) )
mprintf( RED, ABORT, "ATLD memory allocation error\r\n" );
set_ATLD_base_ptr( ATLD_Ptr ); // Set start ATLD
enable_transfer(); // Start the transfer
// After this function call, ISR takes care the
// ATL buffer interactions.
//
// I this function, it will waits the USB
// transaction complete.
if ( wait_ATLD_done( ATLD_Ptr, 1000 ) ) // wait 1000-SOF period
{
mprintf( RED, CONTINUE, " ATL mechanism is not working (1161 buffer status = 0x%04X)\r\n", read_register16( Com16_HcBufferStatus ) );
status_monitor();
mprintf( RED, CONTINUE, "\r\n" );
}
completion_check_ATLD( &result, ATLD_Ptr );
if ( direction == IN )
readout_ATLD( data_ptr, result.ActualBytes, ATLD_Ptr );
close_ATLD( ATLD_Ptr );
*size_ptr = result.ActualBytes;
epi_ptr->toggle = result.Toggle;
if ( result.CompletionCode )
epi_ptr->toggle = result.Toggle ? 0 : 1;
return ( result.CompletionCode );
}
// mprintf( LIGHTGREEN, CONTINUE, " -->readout data body 0x %02X %02X %02X %02X %02X %02X %02X %02X\r\n", d[0]&0xFF, d[1]&0xFF, d[2]&0xFF, d[3]&0xFF, d[4]&0xFF, d[5]&0xFF, d[6]&0xFF, d[7]&0xFF );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -