?? otgsvc.c
字號:
/*
//*************************************************************************
//
// P H I L I P S P R O P R I E T A R Y
//
// COPYRIGHT (c) 2000-2002 BY PHILIPS SINGAPORE.
// -- ALL RIGHTS RESERVED --
//
// File Name: OTGSVC.C
// Created: Feb. 1, 2000
// Modified: Jun. 6, 2002 by wang.zhong.wei@philips.com
// Revision: 1.0
//
//*************************************************************************
// Abstract:
//
//*************************************************************************
*/
#include <stdio.h>
#include <string.h>
#include <bios.h>
#include <dos.h>
#include <malloc.h>
#include "BasicTyp.h"
#include "common.h"
#include "SysCnfg.h"
#include "HAL4Sys.h"
#include "HAL4ISA.h"
#include "HAL4IKit.h"
#include "HAL4D13.h"
#include "HAL4HC.h"
#include "D13_Reg.h"
#include "D13_Dcs.h"
#include "DcCommon.h"
#include "DCISR.h"
#include "PHC_Reg.h"
#include "USB100.h"
#include "USBstd.h"
#include "Hal4OTG.h"
#include "OTGSvc.h"
//*************************************************************************
// Public/Global static data
//*************************************************************************
extern OTG_REG OtgReg;
OTG_TCB OtgTcb;
//*************************************************************************
// OTG Functions
//*************************************************************************
void OTGCtrl_LocalVBus(BOOL bOn)
{
if(1 == OtgTcb.id)
Hal4OTG_VBUS_SessionReq(bOn);
else
Hal4OTG_VBUS_PowerUp(bOn);
}
void OTGCtrl_LocalPullup(BOOL bOn)
{
Hal4OTG_PULLUP_CTRL(bOn);
}
void OTGCtrl_LocalPulldown(BOOL bOn)
{
Hal4OTG_PULLDOWN_CTRL(bOn);
}
void OTGCtrl_LocalSOF(BOOL bOn)
{
#if 1
if(bOn)
{
PHC_Control(0x00000080); // HOST Controller in Operation Mode
}
else
{
PHC_Control(0x000000C0); // HOST Controller in Suspend Mode
}
#else
Hal4OTG_SuspendOTGPort(bOn);
#endif
}
void OTGStatus_Probe(void)
{
SLH_REG_ULONG SlhReg;
ULONG IR;
Hal4OTG_Status();
// printf("Debug: OTG status/int reigsters are: %x / %x\n", OtgReg.StatusPort.Word, OtgReg.StatusChangePort.Word);
OtgTcb.id = OtgReg.StatusPort.bitmap.ID;
OtgTcb.a_vbus_vld = OtgReg.StatusPort.bitmap.a_vbus_vld;
OtgTcb.a_sess_vld = OtgReg.StatusPort.bitmap.a_sess_vld;
OtgTcb.b_sess_end = OtgReg.StatusPort.bitmap.b_sess_end;
OtgTcb.b_sess_vld = OtgReg.StatusPort.bitmap.b_sess_vld;
OtgTcb.b_se0_srp = OtgReg.StatusPort.bitmap.b_se0_srp;
if(OtgReg.StatusChangePort.bitmap.otg_tmr_tmout)
OtgTcb.TimeOut = 1;
if(OtgTcb.id == 0) //A-device
{
OtgTcb.b_conn = OtgReg.StatusPort.bitmap.rmt_conn;
if(OtgReg.StatusChangePort.bitmap.bus_resume)
OtgTcb.b_bus_resume = 1;
if(OtgReg.StatusChangePort.bitmap.a_srp_det)
OtgTcb.a_srp_det = 1;
}
else //B-device
{
OtgTcb.a_conn = OtgReg.StatusPort.bitmap.rmt_conn;
if(OtgReg.StatusChangePort.bitmap.bus_resume)
OtgTcb.a_bus_resume = 1;
}
}
void OTG_StartTimer(ULONG uTime, USHORT uTimerID )
{
OtgTcb.TimerID = uTimerID;
OtgTcb.TimeOut = 0;
Hal4OTG_StartTimer(uTime*100); //OTG HW timer base is 0.01ms
}
void OTG_StopTimer(void)
{
OtgTcb.TimeOut = 0;
Hal4OTG_StopTimer();
// OtgTcb.TimerRunning = FALSE;
}
void OTG_FSM4DeviceB()
{
switch (OtgTcb.FSM)
{
// B StateMachine
case B_IDLE:
OTGCtrl_LocalVBus(FALSE);
OTGCtrl_LocalPullup(FALSE);
OTGCtrl_LocalPulldown(TRUE);
OTGCtrl_LocalSOF(FALSE);
Hal4OTG_HC_DC_Sel(TRUE); //default is DC
if( 0 == OtgTcb.id )
{
OTGsup_SetVarible();
OtgTcb.err_code = OTG_ERR_PLUGA_INSERTED;
Hal4OTG_SRP_Det_En(TRUE); //enable SRP detection
OtgTcb.FSM = A_IDLE;
}
else if ( 1 == OtgTcb.bus_req && \
1 == OtgTcb.b_sess_end && \
1 == OtgTcb.b_se0_srp && \
0 == OtgTcb.b_srp_done) \
{
OtgTcb.FSM = B_SRP_INIT;
}
else if ( 1 == OtgTcb.b_sess_vld )
{
DcS_EnableIRQ();
OtgTcb.FSM = B_PERIPHERAL;
}
else if ( 1 == OtgTcb.TimeOut )
{
OtgTcb.TimeOut = 0;
OtgTcb.err_code = OTG_ERR_SRP_FAIL;
}
break;
case B_SRP_INIT:
if( 0 == OtgTcb.id || 1 == OtgTcb.b_srp_done )
{
if(1==OtgTcb.b_srp_done )
OTG_StartTimer(B_BUS_REQ_TIMER,B_BUS_REQ_TIMER_ID); //Allow 5s for A-device responding SRP
OtgTcb.FSM = B_IDLE;
}
break;
case B_PERIPHERAL:
OTGCtrl_LocalPullup(TRUE);
OTGCtrl_LocalSOF(FALSE);
Hal4OTG_HC_DC_Sel(TRUE);
if( 0 == OtgTcb.b_sess_vld \
|| 0 == OtgTcb.id ) \
{
DcS_DisableIRQ();
OTGsup_SetVarible();
OtgTcb.FSM = B_IDLE;
}
else if ( 1 == OtgTcb.bus_req \
&& 1 == OtgTcb.b_hnp_en \
&& (1 == OtgTcb.a_bus_suspend) \
)
{
DcS_DisableIRQ();
Hal4OTG_RconLse0_En(TRUE); //to meet the 1ms tight requirement
OTGCtrl_LocalPullup(FALSE);
Hal4Sys_WaitinUS(100);
Hal4OTG_HC_DC_Sel(FALSE);
OTG_StartTimer(B_ASE0_BRST_TIMER,B_ASE0_BRST_TIMER_ID);
OtgTcb.FSM = B_WAIT_ACON;
}
break;
case B_WAIT_ACON:
OTGCtrl_LocalPullup(FALSE);
OTGCtrl_LocalSOF(FALSE);
Hal4OTG_HC_DC_Sel(FALSE);
if( 0 == OtgTcb.b_sess_vld || 0 == OtgTcb.id )
{
OTG_StopTimer();
Hal4OTG_RconLse0_En(FALSE);
OTGsup_SetVarible();
OtgTcb.FSM = B_IDLE;
}
else if( 1 == OtgTcb.a_conn )
{
OTG_StopTimer();
Hal4OTG_RconLse0_En(FALSE);
OtgTcb.FSM = B_HOST;
}
else if( 1 == OtgTcb.TimeOut || 1 == OtgTcb.a_bus_resume/* || 1 == OtgTcb.a_bus_reset*/ )
{
if( 1 == OtgTcb.TimeOut)
{
OtgTcb.TimeOut = 0;
OtgTcb.a_bus_reset = 1; //SE0 >3.125ms should be taken as bus reset
OtgTcb.a_alt_hnp_support = 0;
OtgTcb.a_hnp_support = 0;
OtgTcb.b_hnp_en = 0;
OtgTcb.err_code = OTG_ERR_B_ASE0_BRST_TMOUT;
}
else
{
OtgTcb.a_bus_resume = 0;
}
Hal4OTG_RconLse0_En(FALSE);
DcS_EnableIRQ();
OtgTcb.FSM = B_PERIPHERAL;
}
break;
case B_HOST:
OTGCtrl_LocalPullup(FALSE);
OTGCtrl_LocalSOF(TRUE);
Hal4OTG_HC_DC_Sel(FALSE);
if( 0 == OtgTcb.b_sess_vld || 0 == OtgTcb.id )
{
OTGsup_SetVarible();
OtgTcb.FSM = B_IDLE;
}
else if( (0 == OtgTcb.a_conn || 0 == OtgTcb.bus_req))
{
DcS_EnableIRQ();
OtgTcb.FSM = B_PERIPHERAL;
}
break;
default:
break;
}
}
void OTG_FSM4DeviceA()
{
USHORT wTemp;
switch (OtgTcb.FSM)
{
// A_device statemachine
case A_IDLE:
OTGCtrl_LocalVBus(FALSE);
OTGCtrl_LocalPullup(FALSE);
OTGCtrl_LocalPulldown(TRUE);
OTGCtrl_LocalSOF(FALSE);
Hal4OTG_HC_DC_Sel(FALSE); //default HC
if( 1 == OtgTcb.id )
{
Hal4OTG_SRP_Det_En(FALSE); //Disable SRP detection
OTGsup_SetVarible();
OtgTcb.err_code = OTG_ERR_PLUGA_REMOVED;
OtgTcb.FSM = B_IDLE;
}
else if( (1 == OtgTcb.bus_req || 1 == OtgTcb.a_srp_det) \
&& 0 == OtgTcb.bus_drop )
{
Hal4OTG_SRP_Det_En(FALSE);
if(1 == OtgTcb.a_srp_det)
{
OtgTcb.a_srp_det = 0;
Hal4Sys_WaitinMS(100); //don't respond to SRP too fast
}
OTG_StartTimer(A_WAIT_VRISE_TIMER,A_WAIT_VRISE_TIMER_ID);
OtgTcb.FSM = A_WAIT_VRISE;
}
break;
case A_WAIT_VRISE:
OTGCtrl_LocalVBus(TRUE);
OTGCtrl_LocalPullup(FALSE);
OTGCtrl_LocalSOF(FALSE);
Hal4OTG_HC_DC_Sel(FALSE);
if ( (1 == OtgTcb.a_vbus_vld && 1 == OtgTcb.b_sess_vld) \
|| (1 == OtgTcb.TimeOut && A_WAIT_VRISE_TIMER_ID == OtgTcb.TimerID) \
)
{
OtgTcb.TimeOut = 0;
Hal4Sys_WaitinMS(3);
OTG_StartTimer(A_WAIT_BCON_TIMER,A_WAIT_BCON_TIMER_ID);
OtgTcb.FSM = A_WAIT_BCON;
}
break;
case A_WAIT_BCON:
OTGCtrl_LocalVBus(TRUE);
OTGCtrl_LocalPullup(FALSE);
OTGCtrl_LocalSOF(FALSE);
Hal4OTG_HC_DC_Sel(FALSE);
if( 1 == OtgTcb.id || \
1 == OtgTcb.bus_drop || \
(1 == OtgTcb.TimeOut && A_WAIT_BCON_TIMER_ID == OtgTcb.TimerID))
{
if ( 1 == OtgTcb.TimeOut)
{
OtgTcb.TimeOut = 0;
OtgTcb.err_code = OTG_ERR_A_WAIT_BCON_TMOUT;
}
OtgTcb.bus_req = 0; //this bit should be cleared by application
OTG_StopTimer();
OtgTcb.FSM = A_WAIT_VFALL;
}
else if ( 0 == OtgTcb.a_vbus_vld )
{
OtgTcb.FSM = A_VBUS_ERR;
OtgTcb.err_code = OTG_ERR_A_OVERCURRENT;
}
else if (1 == OtgTcb.b_conn)
{
if(A_BCON_LDBC_TIMER_ID != OtgTcb.TimerID)
OTG_StartTimer(A_BCON_LDBC_TIMER,A_BCON_LDBC_TIMER_ID);
else if (1 == OtgTcb.TimeOut)
{
OtgTcb.TimeOut = 0;
OtgTcb.a_host_done = 0; //A_HOST starts to use the bus
OtgTcb.FSM = A_HOST;
}
}
break;
case A_HOST:
OTGCtrl_LocalVBus(TRUE);
OTGCtrl_LocalPullup(FALSE);
OTGCtrl_LocalSOF(TRUE);
Hal4OTG_HC_DC_Sel(FALSE);
if(1==OtgTcb.id || 1==OtgTcb.bus_drop || 0==OtgTcb.b_conn)
{
OTG_StartTimer(A_WAIT_BCON_TIMER,A_WAIT_BCON_TIMER_ID);
OtgTcb.FSM = A_WAIT_BCON;
}
else if(0==OtgTcb.a_vbus_vld)
{
OtgTcb.FSM = A_VBUS_ERR;
OtgTcb.err_code = OTG_ERR_A_OVERCURRENT;
}
else if( 0==OtgTcb.bus_req && 1==OtgTcb.a_host_done)
{
if(1 == OtgTcb.a_set_b_hnp_en)
Hal4OTG_RdisLcon_En(TRUE); // if B-device disconnected, then A-device assert pull-up immediately
OTG_StartTimer(A_AIDL_BDIS_TIMER,A_AIDL_BDIS_TIMER_ID);
OtgTcb.FSM = A_SUSPEND;
}
break;
case A_SUSPEND:
OTGCtrl_LocalVBus(TRUE);
OTGCtrl_LocalPullup(FALSE);
OTGCtrl_LocalSOF(FALSE);
Hal4OTG_HC_DC_Sel(FALSE);
if( 1 == OtgTcb.id || 1 == OtgTcb.bus_drop || 1 == OtgTcb.TimeOut)
{
if ( 1 == OtgTcb.TimeOut)
{
OtgTcb.TimeOut = 0;
OtgTcb.err_code = OTG_ERR_A_AIDL_BDIS_TMOUT;
}
OTG_StopTimer();
Hal4OTG_RdisLcon_En(FALSE);
OtgTcb.FSM = A_WAIT_VFALL;
}
else if (0 == OtgTcb.a_vbus_vld )
{
OtgTcb.FSM = A_VBUS_ERR;
OtgTcb.err_code = OTG_ERR_A_OVERCURRENT;
}
else if ( 0 == OtgTcb.b_conn && 1 == OtgTcb.a_set_b_hnp_en)
{
OTGCtrl_LocalPullup(TRUE);
Hal4OTG_RdisLcon_En(FALSE);
DcS_EnableIRQ();
OtgTcb.FSM = A_PERIPHERAL;
}
else if ( 0 == OtgTcb.b_conn && 0 == OtgTcb.a_set_b_hnp_en)
{
Hal4OTG_RdisLcon_En(FALSE);
OTG_StartTimer(A_WAIT_BCON_TIMER,A_WAIT_BCON_TIMER_ID);
OtgTcb.FSM = A_WAIT_BCON;
}
else if(1 == OtgTcb.bus_req \
|| 1 == OtgTcb.b_bus_resume)
{
Hal4OTG_RdisLcon_En(FALSE);
OtgTcb.FSM = A_HOST;
}
break;
case A_PERIPHERAL:
OTGCtrl_LocalVBus(TRUE);
OTGCtrl_LocalPullup(TRUE);
OTGCtrl_LocalSOF(FALSE);
Hal4Sys_WaitinUS(10);
Hal4OTG_HC_DC_Sel(TRUE);
if(
1 == OtgTcb.id || \
1 == OtgTcb.bus_drop )
{
OtgTcb.FSM = A_WAIT_VFALL;
}
else if (0 == OtgTcb.a_vbus_vld )
{
OtgTcb.FSM = A_VBUS_ERR;
OtgTcb.err_code = OTG_ERR_A_OVERCURRENT;
}
else if (1 == OtgTcb.b_bus_suspend)
{
OtgTcb.b_bus_suspend = 0;
DcS_DisableIRQ();
OTG_StartTimer(A_WAIT_BCON_TIMER,A_WAIT_BCON_TIMER_ID);
OtgTcb.FSM = A_WAIT_BCON;
}
break;
case A_WAIT_VFALL:
OTGCtrl_LocalVBus(FALSE);
OTGCtrl_LocalPullup(FALSE);
OTGCtrl_LocalSOF(FALSE);
Hal4OTG_HC_DC_Sel(FALSE);
if(
1 == OtgTcb.id || \
1 == OtgTcb.bus_req || \
(0 == OtgTcb.a_sess_vld && 0 == OtgTcb.b_conn))
{
OTGsup_SetVarible();
Hal4OTG_SRP_Det_En(TRUE); //enable SRP detection
OtgTcb.FSM = A_IDLE;
}
break;
case A_VBUS_ERR:
OTGCtrl_LocalVBus(FALSE);
OTGCtrl_LocalPullup(FALSE);
OTGCtrl_LocalSOF(FALSE);
Hal4OTG_HC_DC_Sel(FALSE);
// if(1 == OtgTcb.a_clr_err)
if(1 == OtgTcb.id || 1 == OtgTcb.bus_drop)
{
// OtgTcb.a_clr_err = 0;
OtgTcb.FSM = A_WAIT_VFALL;
}
break;
default:
break;
}
}
void OTG_FSM(void)
{
if(OtgTcb.FSM >= A_IDLE) //device is in A state machine
{
OTG_FSM4DeviceA();
}
else //device is in B state machine
{
OTG_FSM4DeviceB();
}
}
void OTG_HW_emulator(void)
{
// Input of FSM
OTGStatus_Probe();
// FSM
OTG_FSM();
// Timer Routine
/* if( 1 == OtgTcb.TimerRunning)
{
if(0 == OtgTcb.TimerTick)
{
OtgTcb.TimerRunning = 0;
OtgTcb.TimeOut = 1;
}
else
{
OtgTcb.TimerTick --;
}
}*/
}
void OTGsup_SetVarible(void)
{
RaiseIRQL();
// OtgTcb.UsageBased = 1;
OtgTcb.a_bus_resume = 0;
OtgTcb.a_bus_suspend = 0;
OtgTcb.a_bus_reset = 0;
OtgTcb.b_bus_resume = 0;
OtgTcb.b_bus_suspend = 0;
OtgTcb.b_hnp_en = 0;
OtgTcb.a_set_b_hnp_en = 0;
OtgTcb.a_hnp_support = 0;
OtgTcb.a_alt_hnp_support = 0;
OtgTcb.TimerRunning = 0;
OtgTcb.TimeOut = 0;
OtgTcb.TimerTick = 0;
OtgTcb.TimerID = 0;
//these variables should be initialized by application
// OtgTcb.bus_req = 0;
// OtgTcb.bus_drop = 0;
// OtgTcb.a_suspend_req = 0;
OtgTcb.err_code = 0;
OtgTcb.VendorID = 0;
OtgTcb.ProductID = 0;
OtgTcb.DevAddr = 0;
LowerIRQL();
}
void OTG_Init(void )
{
OTGsup_SetVarible();
OTGStatus_Probe();
//Select on-chip charge-pump or external 5v for OTG VBUS.
//on-chip charge-pump supports up to 8mA, on-board 5v supports up to 500mA
Hal4OTG_Sel_Vbus();
switch(OtgTcb.id)
{
case 0:
OtgTcb.FSM = A_IDLE;
Hal4OTG_HC_DC_Sel(FALSE); //default HC
Hal4OTG_SRP_Det_En(TRUE); //enable SRP detection
break;
case 1:
OtgTcb.FSM = B_IDLE;
Hal4OTG_HC_DC_Sel(TRUE); //default DC
break;
default:
break;
}
}
void OTG_Acquire(void)
{
OTG_Init();
Hal4ISA_AcquireIRQ4Timer();
}
void OTG_Release(void)
{
Hal4ISA_ReleaseIRQ4Timer();
}
BOOLEAN OTGSup_ADevGiveupMastership(void)
{
if( TRUE == UsbStd_SetFeature(
OtgTcb.DevAddr, //DevAddr,
0,//Speed,
8,//RmtDev.PktSize,
0,//byRecipient,
USB_FEATURE_B_HNP_ENABLE,//wFeatureSelector,
0//wIndex
)
)
{
RaiseIRQL();
OtgTcb.a_set_b_hnp_en = 1;
LowerIRQL();
return TRUE;
}
else
{
RaiseIRQL();
OtgTcb.a_set_b_hnp_en = 0;
LowerIRQL();
return FALSE;
}
}
void OTG_do_srp(void)
{
// Data line Pulsing
OTGCtrl_LocalPullup(TRUE);
Hal4Sys_WaitinMS(B_DATA_PLS_TIMER); // DATA LINE HIGH FOR 5-10MS
OTGCtrl_LocalPullup(FALSE);
// VBUS Pulsing
OTGCtrl_LocalVBus(TRUE);
Hal4Sys_WaitinMS(B_VBUS_PLS_TIMER);
OTGCtrl_LocalVBus(FALSE);
// VBUS discharge
Hal4OTG_VBUS_DisChrg(TRUE);
Hal4Sys_WaitinMS(VBUS_DISCHRG_TIMER);
Hal4OTG_VBUS_DisChrg(FALSE);
OtgTcb.b_srp_done = 1;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -