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

📄 usbhost.c.c

📁 主机端控制C程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* 2005.05.20
****************************************
**  Copyright  (C)  W.ch  1999-2003   **
**  Web:  http://www.winchiphead.com  **
****************************************
**  USB HOST software interface       **
**  C, TC2.0                          **
****************************************

 UHCI的BIOS/DOS接口库  V1.0
 南京沁恒电子有限公司  作者: W.ch 2005.05
 运行环境: BIOS, DOS
*/

/*
\TC\TCC -ms -O -r -Z -c USBHOST.C
\TC\TLIB USBHOST +USBHOST.OBJ
*/

/*#define		DEBUG*/

#include	<dos.h>
#ifdef	DEBUG
#include	<stdio.h>
#endif

#define		THIS_VERSION		0x10

#include	"USBHOST.H"

#define		UHCI_NULL_DATA_SIZE	0x07FF	/* for UHCI controller TD */

#define		UHCI_PTR_BITS		0x000F
#define		UHCI_PTR_TERM		0x0001
#define		UHCI_PTR_QH			0x0002
#define		UHCI_PTR_DEPTH		0x0004

typedef struct	UHCI_TD {
	unsigned short	Terminate	:1;
	unsigned short	QHS			:1;
	unsigned short	Depth		:1;
	unsigned short	reserved1	:1;
	unsigned short	pLinkL		:12;
	unsigned short	pLinkH;
	unsigned short	ActLen		:11;
	unsigned short	reserved2	:5;
/*	unsigned short	reserved3	:1;
	unsigned short	BitstuErr	:1;
	unsigned short	Crc_Tout	:1;
	unsigned short	NAK			:1;
	unsigned short	BabbleDetc	:1;
	unsigned short	BufferErr	:1;
	unsigned short	Stalled		:1;*/
	unsigned short	Status		:7;
	unsigned short	Active		:1;
	unsigned short	IOC			:1;
	unsigned short	IOS			:1;
	unsigned short	LS			:1;
	unsigned short	C_ERR		:2;
	unsigned short	SPD			:1;
	unsigned short	reserved4	:2;
	unsigned short	PID			:8;
	unsigned short	DevAddr		:7;
	unsigned short	EndPt		:4;
	unsigned short	DataTog		:1;
	unsigned short	reserved5	:1;
	unsigned short	MaxLen		:11;
	unsigned long	pBuffer;			/* 指向数据缓冲区地址 */
	unsigned long	reserved9[4];
	unsigned char	Buffer[ USB_ENDP_MAX_SIZE ];	/* 数据缓冲区 */
} mUHCI_TD;

typedef struct	UHCI_QH {
	unsigned short	Terminate	:1;
	unsigned short	QHS			:1;
	unsigned short	reserved1	:2;
	unsigned short	QHLPL		:12;	/* 水平连接,指向下一个QH */
	unsigned short	QHLPH;
	unsigned short	QE_Term		:1;
	unsigned short	QE_QHS		:1;
	unsigned short	reserved2	:2;
	unsigned short	QELPL		:12;	/* 垂直连接,指向一个TD */
	unsigned short	QELPH;
	unsigned long	reserved9[2];
} mUHCI_QH;

#define		UHCI_NUM_FRAMES		1024	/* in the frame list [array] */

typedef struct	FRAME_LIST {
	unsigned long	FLP[ UHCI_NUM_FRAMES ];	/* 指向一个QH */
} mFRAME_LIST;


void	USB_DelayuS( USHORT delay );  /* 以微秒为单位延时 */

mPUHCI_IO_REG	USB_CheckUHCI(  /* 读取配置空间判断是否UHCI, 是则返回I/O基址, 否则返回0 */
	USHORT		iPciAddr );  /* PCI地址 */

void	USB_SetupQH(  /* 设置帧列表及QH */
	mPUSB_DEVICE	UsbDevice );  /* 指向USB设备信息 */

void	USB_SetupTD(  /* 设置事务传输中的TD */
	mPUSB_DEVICE	UsbDevice,  /* 指向USB设备信息 */
	mPUSB_TRANS		UsbTrans );  /* 指向USB传输信息 */

void	USB_EnableTD(  /* 允许TD运行 */
	mPUSB_DEVICE	UsbDevice );  /* 指向USB设备信息 */

void	USB_DisableTD(  /* 禁止TD运行 */
	mPUSB_DEVICE	UsbDevice );  /* 指向USB设备信息 */

UCHAR	USB_WaitTrans(  /* 等待USB事务完成, 返回状态, 为0则成功, 为ERR_TRANS_TOUT则超时 */
	mPUSB_DEVICE	UsbDevice,  /* 指向USB设备信息 */
	mPUSB_TRANS		UsbTrans );  /* 指向USB传输信息 */

UCHAR	USB_GetVersion(  /* 获取库的版本号 */
	UCHAR	what )  /* 参数0 */
{
	if ( what ) return( THIS_VERSION );
	return( THIS_VERSION );
}

void	USB_DelayuS(  /* 以微秒为单位延时 */
	USHORT delay )
{
	int	i;
	while( delay -- ) for ( i = 0; i < 4; i++ ) inportb(0x70);
}

void	USB_DelaymS(  /* 以毫秒为单位延时 */
	USHORT delay )
{
	int	i;
	while( delay -- ) for ( i = 0; i < 4000; i++ ) inportb(0x70);
}

USHORT			PCI_ReadCfgWord(  /* 从配置空间读取一个字数据,返回读取的字数据 */
	USHORT		iPciAddr,  /* PCI地址 */
	USHORT		iOffset )  /* 指定偏移地址 */
{
	X86REG	mReg;
	mReg.x.bx = iPciAddr;
	mReg.x.ax = 0xB109;
	mReg.x.di = iOffset;
	mReg.x.cx = 0;
	int86 ( 0x1A, &mReg, &mReg );  /* 调用PCI的BIOS */
	return( mReg.x.cx );  /* 返回数据 */
}

mPUHCI_IO_REG	USB_CheckUHCI(  /* 读取配置空间判断是否UHCI, 是则返回I/O基址, 否则返回0 */
	USHORT		iPciAddr )  /* PCI地址 */
{
	USHORT	data;
	data = PCI_ReadCfgWord( iPciAddr, mOFFSET( mPCI_CONFIG, mPcSubClass ) );  /* 检查设备类 */
	if ( data == 0x0C03 ) {
		data = PCI_ReadCfgWord( iPciAddr, mOFFSET( mPCI_CONFIG, mPcRevisionId ) );  /* 检查设备类 */
		if ( ( data & 0xFF00 ) == 0x0000 ) {  /* UHCI */
			data = PCI_ReadCfgWord( iPciAddr, mOFFSET( mPCI_CONFIG, mPcBaseAddr4 ) );  /* 获取基址 */
			return( (mPUHCI_IO_REG)( data & 0xFFFE ) );
		}
	}
	return( (mPUHCI_IO_REG)0 );
}

void	USB_SetupQH(  /* 设置帧列表及QH */
	mPUSB_DEVICE	UsbDevice )  /* 指向USB设备信息 */
{
	USHORT			i;
	ULONG			mLineAddr;
	mFRAME_LIST	far	*pFrameList;
	mUHCI_QH	far	*pQH0;
	mUHCI_TD	far	*pTD0;
	pFrameList = GET_SEG_OFS( UsbDevice -> FrameBaseAddr );  /* 帧列表基址,远指针 */
	mLineAddr = UsbDevice -> FrameBaseAddr + sizeof( mFRAME_LIST );  /* QH的线性地址 */
	for ( i = 0; i < UHCI_NUM_FRAMES; i++ ) pFrameList -> FLP[ i ] = mLineAddr | UHCI_PTR_QH;
	pQH0 = GET_SEG_OFS( mLineAddr );  /* 队列头 */
	for ( i = 0; i < sizeof( mUHCI_QH )/2; i++ ) *( (FPUSHORT)pQH0 + i ) = 0;
	pQH0 -> Terminate = 0;  /* 继续 */
	pQH0 -> QHS = 1;  /* 指向下一个QH */
	pQH0 -> QHLPL = mLineAddr >> 4;  /* 水平连接,指向下一个QH */
	pQH0 -> QHLPH = mLineAddr >> 16;
	mLineAddr = UsbDevice -> FrameBaseAddr + sizeof( mFRAME_LIST ) + sizeof( mUHCI_QH ) * 8;  /* TD的线性地址 */
	pQH0 -> QE_Term = 1;  /* TD队列无效 */
	pQH0 -> QE_QHS = 0;  /* 指向TD */
	pQH0 -> QELPL = mLineAddr >> 4;  /* 垂直连接,指向一个TD */
	pQH0 -> QELPH = mLineAddr >> 16;
	pTD0 = GET_SEG_OFS( mLineAddr );  /* 传输描述符 */
	for ( i = 0; i < mOFFSET( mUHCI_TD, Buffer )/2; i++ ) *( (FPUSHORT)pTD0 + i ) = 0;
	pTD0 -> Terminate = 1;
}

void	USB_SetupTD(  /* 设置事务传输中的TD */
	mPUSB_DEVICE	UsbDevice,  /* 指向USB设备信息 */
	mPUSB_TRANS		UsbTrans )  /* 指向USB传输信息 */
{
	UCHAR		i;
	ULONG		mLineAddr;
	mUHCI_TD	far	*pTD0;
	mLineAddr = UsbDevice -> FrameBaseAddr + sizeof( mFRAME_LIST ) + sizeof( mUHCI_QH ) * 8;  /* TD的线性地址 */
	pTD0 = GET_SEG_OFS( mLineAddr );  /* 传输描述符 */
	for ( i = 0; i < mOFFSET( mUHCI_TD, Buffer )/2; i++ ) *( (FPUSHORT)pTD0 + i ) = 0;
	pTD0 -> Terminate = 1;
	pTD0 -> C_ERR = 3;  /* 设置错误重试次数 */
	pTD0 -> SPD = 1;  /* 设置短包有效 */
	pTD0 -> PID = UsbTrans -> PID;  /* 设置传输PID */
	pTD0 -> DevAddr = UsbDevice -> DevAddr;  /* 设置设备地址 */
	pTD0 -> EndPt = UsbDevice -> EndpInfo[ UsbTrans -> EndpIndex ].EndpAddr & USB_ENDP_ADDR_MASK;  /* 设置端点号 */
	pTD0 -> DataTog = UsbDevice -> EndpInfo[ UsbTrans -> EndpIndex ].DataTog;  /* 数据同步控制位 */
	pTD0 -> MaxLen = ( UsbTrans -> Len - 1 ) & UHCI_NULL_DATA_SIZE;  /* 设置数据长度 */
	mLineAddr += mOFFSET( mUHCI_TD, Buffer );
	pTD0 -> pBuffer = mLineAddr;  /* 指向数据缓冲区地址 */
	if ( UsbTrans -> PID != DEF_USB_PID_IN ) {  /* 不是IN */
		for ( i = 0; i != UsbTrans -> Len; i++ ) pTD0 -> Buffer[ i ] = UsbTrans -> Buffer[ i ];  /* 将输出数据复制到缓冲区 */
	}
#ifdef	DEBUG
	printf( "TD: Endp=%02XH, Len=%02XH, PID=%s\n", (USHORT)( UsbDevice -> EndpInfo[ UsbTrans -> EndpIndex ].EndpAddr ), (USHORT)( UsbTrans -> Len ), \
	( UsbTrans -> PID == DEF_USB_PID_IN ? "IN" : ( UsbTrans -> PID == DEF_USB_PID_OUT ? "OUT" : ( UsbTrans -> PID == DEF_USB_PID_SETUP ? "SETUP" : "OTHER" ) ) ) );
#endif
	pTD0 -> Active = 1;  /* 设置活动标志 */
}

void	USB_EnableTD(  /* 允许TD运行 */
	mPUSB_DEVICE	UsbDevice )  /* 指向USB设备信息 */
{
	ULONG		mLineAddr;
	mUHCI_QH	far	*pQH0;
	mLineAddr = UsbDevice -> FrameBaseAddr + sizeof( mFRAME_LIST );
	pQH0 = GET_SEG_OFS( mLineAddr );  /* 队列头 */
	mLineAddr = UsbDevice -> FrameBaseAddr + sizeof( mFRAME_LIST ) + sizeof( mUHCI_QH ) * 8;  /* TD的线性地址 */
	pQH0 -> QE_QHS = 0;  /* 指向TD */
	pQH0 -> QELPL = mLineAddr >> 4;  /* 垂直连接,指向一个TD */
	pQH0 -> QELPH = mLineAddr >> 16;
	pQH0 -> QE_Term = 0;  /* TD队列有效 */
}

void	USB_DisableTD(  /* 禁止TD运行 */
	mPUSB_DEVICE	UsbDevice )  /* 指向USB设备信息 */
{
	ULONG		mLineAddr;
	mUHCI_QH	far	*pQH0;
	mLineAddr = UsbDevice -> FrameBaseAddr + sizeof( mFRAME_LIST );
	pQH0 = GET_SEG_OFS( mLineAddr );  /* 队列头 */
	pQH0 -> QE_Term = 1;  /* TD队列无效 */
}

UCHAR	USB_WaitTrans(  /* 等待USB事务完成, 返回状态, 为0则成功, 为ERR_TRANS_TOUT则超时 */
	mPUSB_DEVICE	UsbDevice,  /* 指向USB设备信息 */
	mPUSB_TRANS		UsbTrans )  /* 指向USB传输信息 */
{
	UCHAR			i;
	USHORT			Timeout;
	ULONG			mLineAddr;
	mPUHCI_IO_REG	IoBaseAddr;
	mUHCI_TD		far	*pTD0;
	mLineAddr = UsbDevice -> FrameBaseAddr + sizeof( mFRAME_LIST ) + sizeof( mUHCI_QH ) * 8;  /* TD的线性地址 */
	pTD0 = GET_SEG_OFS( mLineAddr );  /* 传输描述符 */
	for ( Timeout = ( UsbTrans -> Timeout << 2 ) + 1; Timeout != 0 || UsbTrans -> Timeout == 0; Timeout-- ) {
		USB_DelayuS( 250 );
		IoBaseAddr = UsbDevice -> IoBaseAddr;
		if ( PortInWord( & ( IoBaseAddr -> mUSBSTS ) ) ) break;  /* 如果状态不为0跳出 */
		if ( ( PortInWord( & ( IoBaseAddr -> mUSBCMD ) ) & USBCMD_RS ) == 0 ) break;  /* 如果停机跳出 */
		if ( pTD0 -> Active == 0 ) break;  /* 事务处理结束跳出 */
	}
#ifdef	DEBUG
	printf( "CMD=%04XH, STS=%04XH, TD->Status=%02XH, TD->ActLen=%02XH, Timeout=%d\n", \
	PortInWord( & ( UsbDevice -> IoBaseAddr -> mUSBCMD ) ), PortInWord( & ( UsbDevice -> IoBaseAddr -> mUSBSTS ) ), \
	(USHORT)( pTD0 -> Status ), (USHORT)( pTD0 -> ActLen ), ( UsbTrans -> Timeout << 2 ) + 1 - Timeout );
#endif
	if ( Timeout == 0 ) return( ERR_TRANS_TOUT );
	if ( ( pTD0 -> Status & 0x7E ) == 0x00 ) {
		if ( UsbTrans -> PID == DEF_USB_PID_IN ) {  /* 是IN */
			for ( i = 0; i != UsbTrans -> Len; i++ ) UsbTrans -> Buffer[ i ] = pTD0 -> Buffer[ i ];  /* 从缓冲区复制输入数据 */
		}
		UsbTrans -> Len = (UCHAR)( pTD0 -> ActLen + 1 );
	}
	return( pTD0 -> Status & 0x7E );
}

UCHAR	USB_CheckDevice(  /* 检测有无USB设备连接 */
	mPUSB_DEVICE	UsbDevice )  /* 指向USB设备信息, 成员PortIndex指定端口序号, 0FFH则搜索第一个 */
{
	UCHAR			Index;
	USHORT			PciAddr, HubStatus;
	mPUHCI_IO_REG	IoBaseAddr;
	Index = 0;
	for ( PciAddr = 0; PciAddr <= 0x0400; PciAddr++ ) {
		IoBaseAddr = USB_CheckUHCI( PciAddr );  /* 读取配置空间判断是否UHCI */
		if ( IoBaseAddr ) {
			if ( UsbDevice -> PortIndex == 0xFF || UsbDevice -> PortIndex == Index ) {
				HubStatus = PortInWord( & ( IoBaseAddr -> mPORTSC1 ) );
				if ( ( HubStatus & USBPORTSC_CCS ) && ( HubStatus & USBPORTSC_LSDA ) == 0 ) break;  /* 全速设备存在 */
			}
			Index++;
			if ( UsbDevice -> PortIndex == 0xFF || UsbDevice -> PortIndex == Index ) {
				HubStatus = PortInWord( & ( IoBaseAddr -> mPORTSC2 ) );
				if ( ( HubStatus & USBPORTSC_CCS ) && ( HubStatus & USBPORTSC_LSDA ) == 0 ) break;  /* 全速设备存在 */
			}
			Index++;
		}
	}
	if ( PciAddr >= 0x0400 ) {
		if ( UsbDevice -> PortIndex < Index ) return( ERR_NO_DEVICE );
		return( ERR_NO_HOST );
	}
#ifdef	DEBUG
	printf( "PCI=%04XH, Base=%04XH, Index=%02XH, Hub=%04XH\n", PciAddr, IoBaseAddr, (USHORT)Index, HubStatus );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -