⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 otgsvc.c

📁 此為philip 1362 USB DOS下的驅動程式包, 已經共測試並內含有說明文件
💻 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 + -