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

📄 usbmass.c

📁 ubi9021的51驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "reg51.h"
#include "read_reg.h"
#include "usbmass.h"

#define	TRY_WAIT	100	//100
#define	ERROR_WAIT	500
#define	READCAP_STALL_CNT_MAX	5

int		gLunSet = 0;			//"LUN" for USB_XXX routines
XD	U8	gCBW[31];		//SCSI CBW 31byte or
XD	U8		gMaxLun;		//gMaxLun = ??á??· LUN


XD	U8		gLunFlag;		//bitmap for LUN presence
XD	U8		gLunMask;		//bit=0: allow, bit=1: disable(CD or ...)
XD	U32		gLastSec;		//last PHYSICAL sector

extern XD	U8		gDevAddr;

U32 gUsbReadUnit;

extern XD	U8		gEPOUT;			//out-endpoint
extern XD	U8		gEPIN;			//in-endpoint
extern XD	U8		volatile gEP;
extern XD	U8		gIrqEn;
extern XD	U8		gLun;			//"LUN" for USB_XXX routines
extern XD	U8		gMxPkSz;		//maximum packet size (bulk)
extern XD	U8		gIFSC;			//interface sub-class
extern XD	U8		gUsbVer;		//USB Version


extern U8	gStallMark;

extern int gSecCnt;
extern int gSecAddr;
extern XD	U16 	gVID;
extern XD	U16		gPID;

U32	gUsbTrgCnt; //1=when to get CSW,0=no active read

XD	U32 	gTotSecCnt;		//total sector including all system area (for current partition)

/******************************************************************************
 *	RETURN:
 *		RES_ERR/RES_OK
 *	NOTE:
 * 		gCBW俊 31 byte CBW data甫 固府 盲款 饶 妮!
 ******************************************************************************/

U8 SCSI_SendCBW(void)
{
    UH_SET_FIFO_SZ_EACH(0,31);
    UH_FIFO_ROLLBACK_OUT();
    UH_IRQ_EN(UH_IRQ_USB_PKT_DONE);
    DEV_WriteRegMulti(RH_USB_HOST_BASE_ADDR, 31, (U8*)gCBW);
    UH_Trigger(gEPOUT);
	//if(DEV_WaitForIrq(UH_IRQ_USB_PKT_DONE)==0) return RES_ERR_SCSI_CBW;
	return RES_OK;
}


/******************************************************************************
 *	INPUT:
 *		- totBytCnt	: total byte count of DATA-IN
 *		- buf		: pointer to a data buffer
 *					  NULL if you want to discard the data
 *	RETURN:
 *		RES_ERR: timeout or CSW error
 *		RES_ERR+1: CSW error --> require REQUEST_SENSE
 *		RES_OK:  success
 *		RES_OK+1:  incomplete DATA-IN
 *		RES_OK+UH_IRQ_FAKE_STALL: stalled --> require CSW-IN
 *
 ******************************************************************************/

U8 SCSI_GetDataIn(U16 totBytCnt, U8* buf)
{
	U8	res;
	U16 bytCnt;
	res=RES_OK;

	while(totBytCnt>0)
	{
		bytCnt = (totBytCnt>64)?64:totBytCnt;
		res = DEV_SafeTriggerAndWaitForInPacket(gEPIN,bytCnt,2000);
		if(UH_IRQ_FAKE_STALL==res) return (RES_OK+UH_IRQ_FAKE_STALL); // --> continue on CSW stage
		if(0==res) return RES_ERR; //timeout
		UH_FIFO_ROLLBACK_IN();
		if(buf!=TxNULL){ DEV_ReadRegMulti(RH_USB_HOST_BASE_ADDR,bytCnt,buf); }
		else{ DEV_ReadRegMultiAndDiscard(RH_USB_HOST_BASE_ADDR,bytCnt); }
		if(!(UH_IRQ_READ_READY&res))//incomplete data-in
		{
			if((bytCnt<13)||(buf==TxNULL)) return RES_ERR; 		//we can't see CSW error flag
			if(buf[0]==0&&buf[1]==0){							//ZERO packet arrived!
				if(buf[2]==0x42&&buf[3]==0x43) return RES_OK+1;	// only ZERO packet --> continue on CSW
				if(buf[2]==0x55&&buf[3]==0x53){					//CSW followed ZERO packet
					if(bytCnt>=15&&buf[4]==0x42&&buf[5]==0x53&&buf[14]==1) return RES_ERR+1;
					return RES_ERR;
				}
			}
			else if(buf[0]==0x55&&buf[1]==0x53&&buf[2]==0x42&&buf[3]==0x53){ //CSW arrived without DATA-IN
				if(bytCnt>=13&&buf[12]==1) //SCSI_RequestSense();  //LIU TEST 11-29
				return RES_ERR; //CSW
			}
		}
		totBytCnt -=bytCnt;
		if(buf!=TxNULL) buf += bytCnt;
	}
	return res;
}



U8 SCSI_RequestSense(void)
{
	U8	res;

	MemFill(gCBW+8,0,31-8);
	DEV_WriteReg(RH_USB_HOST_BASE_LEN,gMxPkSz);
	gCBW[13]=gLun;
    SET_CBW_BULKIN();
	SET_CBW_CMD(SCSI_CMD_REQUESTSENSE);
	gCBW[14]=0x0C;
	gCBW[8]=gCBW[19]=18;
	SCSI_SendCBW();
    if(DEV_WaitForIrq(UH_IRQ_USB_PKT_DONE)==0) return RES_ERR_SCSI_CBW;

	res = SCSI_GetDataIn(18,(U8*)TxNULL);
	if(ISERR(res)) return RES_ERR; //timeout or earlier CSW (no measure for CSW-error)

	res = SCSI_SafeCSW();
	if(ISERR(res)) return RES_ERR; //timeout or earlier CSW (no measure for CSW-error)
	return RES_OK;
}



/******************************************************************************
 *	INPUT:
 *
 *	RETURN:
 *		RES_ERR: timeout or CSW error
 *		RES_ERR+1: CSW error --> require REQUEST_SENSE
 *		RES_OK:  success
 *		RES_OK+UH_IRQ_FAKE_STALL: stalled --> no measure
 *
 ******************************************************************************/

U8 SCSI_SafeCSW(void)
{
	U8 res;
	res = DEV_SafeTriggerAndWaitForInPacket(gEPIN,13,2000);
	if(res==0) return RES_ERR;	//timeout --> no measure
	if(UH_IRQ_FAKE_STALL==res) return UH_IRQ_FAKE_STALL;

	UH_FIFO_ROLLBACK_IN();
	res = DEV_ReadRegMultiAndDiscard(RH_USB_HOST_BASE_ADDR,13);
	return (res==0)?RES_OK:RES_ERR+1;
}



/******************************************************************************
 *	IMPLICIT INPUT:
 *		- gLun : LUN number
 *
 *	NOTE:
 *
 *		Mode-Sense: subclass=6(SCSI-2) 捞搁 SCSI_CMD_MODESENSE6,
 *					酒聪搁 SCSI_CMD_MODESENSE10
 *					* 林狼: 固府 buf[0] 俊 pageCode甫 持阑巴!!
 *
 *		Prevent-Allow: buf=0(NULL) 捞搁 Allow,
 *					弊寇绰 Prevent
 *
 *	RETURN:
 *		RES_ERR_SCSI_CBW
 *		RES_ERR_SCSI_CMD_IGNORED
 *		RES_ERR_SCSI_DATA
 *		RES_ERR
 *		RES_OK
 ******************************************************************************/

U8 SCSI_CMD(IN U8 cmd, OUT U8* buf)
{
	U8	res1,res2,bytCnt;
	res1=res2=RES_OK;


	bytCnt=0;
	MemFill(gCBW+8,0,31-8);
	gCBW[13]=gLun;
    SET_CBW_CMD(cmd);
    SET_CBW_BULKIN();
    if(gIFSC==6) gCBW[14]=0x06;	//CBW Length for subclass-6: non-fixed!!
    else gCBW[14]=0x0C;			//CBW Length for non-subclass-6: fixed to 0x0C

	switch(cmd)
	{
		case SCSI_CMD_TESTUNITREADY:	SET_CBW_BULKOUT();
						break;

		case SCSI_CMD_INQUIRY:		bytCnt=0x24;
						gCBW[8]=gCBW[19]=bytCnt;
						break;

		case SCSI_CMD_PREVENTALLOW:	SET_CBW_BULKOUT();
						gCBW[19]=(buf==NULL)?0:1; //1=prevent(disable removal)
						break;


		case SCSI_CMD_READFORMATCAP:	bytCnt=12;
						gCBW[8]=gCBW[23]=bytCnt;//0xFC;
						if(gIFSC==6)gCBW[14]=0x0A;
						break;

		case SCSI_CMD_READCAPACITY:	bytCnt=0x08;
						gCBW[8]=bytCnt;
						if(gIFSC==6)gCBW[14]=0x0A;
						break;

		case SCSI_CMD_TO_STALL_EPIN:	bytCnt=1;
						gCBW[8]=1;
						break;
		default:
			return RES_ERR;
	}

	SCSI_SendCBW();
    if(DEV_WaitForIrq(UH_IRQ_USB_PKT_DONE)==0) return RES_ERR_SCSI_CBW;


    DEV_WaitMS(10);


	res1 = SCSI_GetDataIn(bytCnt,buf);
	if(res1==RES_ERR) return RES_ERR; //timeout
	else if(res1==RES_ERR+1){ //earlier CSW(with error flag)
		SCSI_RequestSense();
		return RES_ERR;
	}


	res2 = SCSI_SafeCSW();
	if(res2==RES_ERR+1){ //earlier CSW(with error flag)
		SCSI_RequestSense();
		return RES_ERR;
	}
	if((res1|res2)&UH_IRQ_FAKE_STALL) return RES_ERR+1;
	if(ISERR(res2)) return RES_ERR;
	return RES_OK;
}


U8 UM_SetLun(U8 bLun, U8* tBUF)
{
	if(gLunMask&(1<<bLun)) return RES_ERR; //skip non-generic storage
	//#if (UMO_EXACT_SECTOR_READ==0)
	//	if(gSecCnt>0){ UBI9021_FlushSectorRead(); }
	//#endif

	if(bLun<=gMaxLun)
	{
	    gLun = bLun;
	    if(ISERR(SCSI_ReadCapacity(tBUF))){
		    DEV_WaitMS(1);
		    gLastSec = nOK32-1; //unknown size
		}else{
			gLastSec = (((U32)tBUF[0])<<24)+(((U32)tBUF[1])<<16)+(((U32)tBUF[2])<<8)+((U32)tBUF[3]);
	    }
	    gTotSecCnt = gLastSec+1;
	    return RES_OK;
	}
	return RES_ERR;
}



/******************************************************************************
 *
 *	get lun count and initialize each LUN
 *
 *	INPUT:
 *		- tBUF: tiny buffer for SCSI data-in
 *
 *	OUTPUT:
 *		- gLunFlag = bitmap for LUN presence (each bit indicate presence of each LUN)
 *		- gMaxLun
 *
 *	RETURN:
 *		return max LUN
 *		return RES_ERR(=0x80)
 *
 ******************************************************************************/



U8	UM_InitMultiLun(U8* tBUF)
{
	int i;
	U8 res,rcscnt=0; //read-capacity stall count
	U8 maxTryCnt=3;

	///GET-MAX-LUN:
	gMaxLun = 0;
	gLunMask = 0;
	if(ISOK(USB_ControlTransfer(USB_SETUP_GET_MAX_LUN,0,tBUF))){ gMaxLun = tBUF[0]; }
	DEV_WriteReg(RH_USB_HOST_BASE_LEN,gMxPkSz);

	if(gMaxLun>=16) gMaxLun=0;
	if(gMaxLun>0) DEV_WaitMS(3000);//wait 3second for multi-card reader
	else DEV_WaitMS(500);

	for(gLun=0;gLun<=gMaxLun;gLun++)
	{
		DEV_WaitMS(TRY_WAIT); //100msec
		if(ISERR(SCSI_Inquiry(tBUF))){
			if(gDevAddr!=DEV_ReadReg(RH_DEV_ADDR)||0x5A!=DEV_ReadReg(RH_MASS_ADDR2)) return RES_ERR;
			DEV_WaitMS(ERROR_WAIT);
			continue;
		}
		else{
			if(tBUF[0]!=0){ //check if generic Flash or HDD drive (0x05=CD)
				gLunMask |= (1<<gLun);
				continue;
			}
		}
	//	DEV_WaitMS(TRY_WAIT);
	//	if(ISERR(SCSI_ReadFormatCapacity(tBUF))){
	//		DEV_WaitMS(ERROR_WAIT);
	//	}
		DEV_WaitMS(TRY_WAIT);
		if(ISERR(SCSI_TestUnit())){
			if(gDevAddr!=DEV_ReadReg(RH_DEV_ADDR)||0x5A!=DEV_ReadReg(RH_MASS_ADDR2)) return RES_ERR;
			DEV_WaitMS(ERROR_WAIT);
		}
	}

IML_RETRY:
	rcscnt=0;

	for(gLun=0,gLunFlag=0;gLun<=gMaxLun;gLun++)
	{
		if(gLunMask&(1<<gLun))continue; //skip non-generic storage
		DEV_WaitMS(TRY_WAIT);
		if(rcscnt<READCAP_STALL_CNT_MAX){
			res = SCSI_ReadCapacity(tBUF);
			if(res==RES_ERR+1)rcscnt++;
			if(ISERR(res)){
				if(gDevAddr!=DEV_ReadReg(RH_DEV_ADDR)||0x5A!=DEV_ReadReg(RH_MASS_ADDR2)) return RES_ERR;

⌨️ 快捷键说明

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