📄 port_ctl.c
字号:
/*
** WASABI-Hot! version 1.2c
**
**
** -- copyright (c) 2001-2004 by Philips Japan, Ltd. -- All rights reserved --
**
**
** ** This code has been made to check/learn **
** ** the ISP1362/ISP1363 functionalities **
** ** Release 06-Aug-2004 **
**
** OKANO, Akifumi
**
** Application Laboratory, Mobile and Connectivity
** Semiconductors Div, Philips Japan Ltd.
** akifumi.okano@philips.com
** +81-3-3740-4668
*/
// 2002 02 27 Port connection disconnection process improved
// 2002 04 08 Device speed reading timing corrected
/****************************************************************************/
/* includes */
/****************************************************************************/
#include <dos.h>
#include <stdio.h>
#include <conio.h>
#include "_hc_core/atl_mix.h"
#include "_hc_core/dev_ep.h"
#include "_hc_core/isr.h"
#include "_hc_core/port_ctl.h"
#include "_hc_hw/hc_comm.h"
#include "_hc_hw/hw_acces.h"
#include "_hc_cls/cls_hndl.h"
#include "_otg/otg.h"
#include "class_dr/hub/hub.h"
#include "general.h"
#include "beep.h"
#include "ui.h"
/****************************************************************************/
/* constants */
/****************************************************************************/
#define ENUM_RETRY 3
#define ENUM_RETRY_INTERVAL 1000L
#define RESET_SECOVERY_TIME 100L // In the standard, it is 10mS. But some devices need more time to start enum.
// See section 7.1.7.3 in USB2.0 spec.
#define LONGER_RESET // This is required for USB2.0 specification
// BusReset from root hub must have 50ms duration.
#define ENUMERATION_DONE_BLINKING_INTERVAL 350L
#define ROOT_HUB_ADDRESS 1
/****************************************************************************/
/* global vars */
/****************************************************************************/
device_instance *device_at_root_hub[ NUMBER_OF_ROOT_HUB_PORT ] = {
NULL,
NULL
};
hub_instance gp_root_hub_instance = {
NULL, // Pointer to device instance
{ 0x09, 0x29, 0x02, 0x09, 0x00, 0x32, 0x00, 0x00, 0x00 }, // Dummy hub descriptor
2, // Number of downstream ports
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL }, // Pointer to device attached on downstream ports
0xFF, // Transfer index for interrupt transfer
NULL, // Pointer to transfer instance
0 // Hub and Port Statua Change Bitmap
};
hub_event_flag gp_hub_event = {
0,
0x00
};
unsigned short HcRhPortStatusComm[2] = {
Com32_HcRhPortStatus1,
Com32_HcRhPortStatus2
};
unsigned char gp_fast_enumeration = Disabled;
unsigned char gp_silent_enumeration = Disabled;
unsigned char gp_warning_message = Disabled;
/****************************************************************************/
/* function prototypes */
/****************************************************************************/
void isr_flag_handler( void );
void root_hub_event( hub_instance *hi_ptr );
void hub_event_handler( hub_event_flag *h_ev_ptr );
unsigned long read_hub_port_status( unsigned char address, unsigned char port );
void clear_status_change_bits( unsigned char address, unsigned char port, unsigned long status_bits );
device_instance *connect_a_device( unsigned char address, unsigned char port, unsigned char topology_layer );
void disconnect_a_device( device_instance **dvi_ptr_ptr );
unsigned char port_reset( unsigned char address, unsigned char port, unsigned short reset_recovery_time );
device_instance *start_a_device( unsigned char speed, unsigned char topology_layer );
void message_of_enum_done( device_instance *dvi_ptr );
/****************************************************************************/
/* function definitions */
/****************************************************************************/
void portctl_isr_flag_routine_dspatch( void )
{
isr_flag_handler();
hub_event_handler( &gp_hub_event );
}
void isr_flag_handler( void )
{
unsigned short flag_mask; /* this mask shold be set to */
flag_mask = SOFISTLInt | ATL_IRQ | AllEOTInterrupt;
if ( !(gp_isr_flag & ~flag_mask) )
return;
root_hub_event( &gp_root_hub_instance );
}
void root_hub_event( hub_instance *dummy_for_func_compatibility )
{
static unsigned char rh_Vbus_status[ 2 ] = { 0, 0 }; // ## version1.2c
unsigned long rh_status; // ## version1.2c
unsigned char i; // ## version1.2c
dummy_for_func_compatibility = dummy_for_func_compatibility; // This line for erase warning
if ( gp_isr_flag & RHSC )
gp_isr_flag &= ~RHSC;
else
return;
gp_hub_event.port_status_change_bit_map = 0x0;
for ( i = 0; i < 2; i++ )
{
rh_status = read_register32( HcRhPortStatusComm[ i ] );
#ifdef PORT1_AS_HOST_ONLY
#else
if ( i == 0 )
{
if ( !OTG_host_operation_enabled() )
continue;
else if ( (rh_status & 0x1) && (gp_root_hub_instance.portctl_device_on_port)[ 0 ] )
continue;
}
#endif
// ## version1.2c (from here)
if ( (rh_status & 0x001F0000) || (rh_Vbus_status[ i ] && (~rh_status & 0x100)) ) // ## version1.2c
{
// If this event is happened root-hub, over-ride the any hub events.
// Root-hub event has highest priority
if ( rh_status & 0x00080000 )
ui_over_current_detected_message( i );
gp_hub_event.hub_address = 1;
gp_hub_event.port_status_change_bit_map |= (0x1 << (i + 1));
gp_hub_event.topology_layer = 0;
}
rh_Vbus_status[ i ] = (rh_status & 0x100) ? True : False; // ## version1.2c
// ## version1.2c (to here)
}
}
void hub_event_handler( hub_event_flag *h_ev_ptr )
{
device_instance *dvi_ptr;
hub_instance *hi_ptr;
unsigned long h_status;
unsigned char port_num;
int i;
if ( h_ev_ptr->hub_address == 0 )
return;
if ( NULL == (dvi_ptr = devep_find_device( h_ev_ptr->hub_address )) )
return;
// Set target HUB
if ( h_ev_ptr->hub_address == ROOT_HUB_ADDRESS )
{
hi_ptr = &gp_root_hub_instance; // If the target is a root HUB
}
else
{
hi_ptr = hub_instance_ptr( dvi_ptr ); // If the target is a device HUB
}
// Port processing for target HUB
for ( i = 0; i < hi_ptr->number_of_ports; i++ )
{
port_num = i + 1;
if ( !(h_ev_ptr->port_status_change_bit_map & (0x1 << port_num)) )
continue;
h_status = read_hub_port_status( h_ev_ptr->hub_address, port_num );
if ( h_status & 0x001F0000 )
{
// This function clears register bits for hub.
// It clears interrupt transfer data body from device-hub
clear_status_change_bits( h_ev_ptr->hub_address, port_num, h_status & 0x001F0000 );
}
// ## version1.2c (from here)
if ( (h_status & 0x00010000) && ( h_status & 0x00000001) ) // Device connected!
{
if ( NULL == hi_ptr->portctl_device_on_port[ i ] )
hi_ptr->portctl_device_on_port[ i ] = connect_a_device( h_ev_ptr->hub_address, i + 1, h_ev_ptr->topology_layer + 1 );
}
else if ( ((h_status & 0x00010000) && (~h_status & 0x00000001)) || ((hi_ptr->portctl_device_on_port[ i ] != NULL) && (~h_status & 0x00000001)) )
// Device disconnected! or Vbus turned-off while the device instance exist
{
disconnect_a_device( &(hi_ptr->portctl_device_on_port[ i ]) );
}
// ## version1.2c (from here)
}
h_ev_ptr->hub_address = 0;
#if 0
if ( h_status & 0x00010000 )
ui_show_topology();
#endif
}
unsigned long read_hub_port_status( unsigned char address, unsigned char port )
{
if ( address == ROOT_HUB_ADDRESS )
return ( read_register32( HcRhPortStatusComm[ port - 1 ] ) );
else
return ( hub_read_hub_device_port_status( devep_find_device( address ), port ) );
}
void clear_status_change_bits( unsigned char address, unsigned char port, unsigned long status_bits )
{
int i;
if ( address == ROOT_HUB_ADDRESS )
write_register32( HcRhPortStatusComm[ port - 1 ], status_bits );
else
{
for ( i = 16; i <=20; i++ )
{
if ( status_bits & (0x1L << i) )
hub_clear_status_change_bits_in_hub( devep_find_device( address ), port, i );
}
}
}
device_instance *connect_a_device( unsigned char address, unsigned char port, unsigned char topology_layer )
{
device_instance *dvi_ptr;
unsigned char speed;
unsigned char retry;
unsigned char i;
unsigned char fast_enumeration_flag_to_remember;
dvi_ptr = NULL;
#if 0
if ( address == ROOT_HUB_ADDRESS )
mprintf( LIGHTGRAY, CONTINUE, "\r\ndetected a connection @root_hub" );
else
mprintf( LIGHTGRAY, CONTINUE, "\r\ndetected a connection @hub(addr=%d)", address );
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -