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

📄 scsi.h

📁 爱特梅尔的mp3解码模块源代码之5
💻 H
字号:
//传输方向
#define SCSI_CBW_IN				0x80
#define SCSI_CBW_OUT			0x00

//命令块状态
#define SCSI_CSW_PASSED			0x00
#define SCSI_CSW_FILED			0x01
#define SCSI_CSW_ERROR			0x02

//LUN相关参数
#define SCSI_MAX_LUN			0x00
#define SCSI_HDD1_LUN			0x00
#define SCSI_HDD2_LUN			0x01
#define SCSI_FLASH_LUN			0x02

//SCSI命令
#define SCSI_CMD_INQUIRY						0x12
#define SCSI_CMD_READ10							0x28
#define SCSI_CMD_WRITE10						0x2a
#define SCSI_CMD_READ_LONG						0x23
#define SCSI_CMD_READ_CAPACITY					0x25
#define SCSI_CMD_TEST_UNIT_READY				0x00
#define SCSI_CMD_REQUEST_SENSE					0x03
#define SCSI_CMD_MODE_SENSE6					0x1a

#define SCSI_CMD_EXTENDED_COPY					0x83
#define SCSI_CMD_LOG_SELECT						0x4c
#define SCSI_CMD_LOG_SENSE						0x4d
#define SCSI_CMD_MODE_SELECT6					0x15
#define SCSI_CMD_MODE_SELECT10					0x55
#define SCSI_CMD_MODE_SENSE10					0x5a
#define SCSI_CMD_PERSISTENT_RESERVE_IN			0x5e
#define SCSI_CMD_PERSISTENT_RESERVE_OUT			0x5f
#define SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL	0x12

struct SCSICBWStr					//命令块包结构
{
	DWORD	dSignature;				//包标识符 USBC
	DWORD	dTag;					//包识别符
	DWORD	dDataLength;			//期望传输的数据
	BYTE	bmFlag;					//方向标志
	BYTE	bLUN;					//LUN
	BYTE	bCBLength;				//命令块大小
	BYTE	CBWCB[16];				//命令块
};

struct SCSICSWStr					//命令状态包
{
	DWORD	dSignature;				//包标识符 USBS
	DWORD	dTag;					//包识别符
	DWORD	dDataResidue;			//实际处理的长度
	BYTE	bStatus;				//命令状态
};

struct SCSIRead10Str				//Read10命令数据结构
{
	BYTE	OperateCode;			//命令代码
	BYTE	Attribute;				//位属性
	DWORD	LBA;					//LBA地址
	BYTE	Reserved;				//保留
	WORD	Length;					//返回长度
	BYTE	Control;				//控制
};

struct SCSIWrite10Str				//Read10命令数据结构
{
	BYTE	OperateCode;			//命令代码
	BYTE	Attribute;				//位属性
	DWORD	LBA;					//LBA地址
	BYTE	Reserved;				//保留
	WORD	Length;					//返回长度
	BYTE	Control;				//控制
};

code BYTE temp1[]=
{
	0x00,0x00,0x00,0x10,0x00,0x01,0xf4,0x00,0x02,0x00,0x02,0x00,0x00,0x01,0xf4,0x00
};
code BYTE temp2[]=
{
	0x03,0x00,0x00,0x00
};

code BYTE SCSIStandardInquiry[]=
{
	0x00,
	0x00,				//removiable
	0x02,				//version
	0x02,				//response data format
	0x1f,				//additional length
	0x00,0x00,0x00,
	'M','a','s','h','i','m','a','r','o',' ','M','P','3',
	' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
	'1','.','0','0'
};

code BYTE SCSICapacity[]=
{
	0x00,0xc1,0xe2,0xa6,0x00,0x00,0x02,0x00
};

extern struct USBEP1BufferStr USBEP1Buffer;
xdata struct SCSICBWStr *SCSICBW=USBEP1Buffer.In;
xdata struct SCSICSWStr *SCSICSW=USBEP1Buffer.In;

extern void USBEP1ReadPacket(void);
extern void USBEP1WritePacket(void);

void SCSICBWProcess(void);
void SCSICSWProcess(BYTE Status,BYTE DataResidue);

void SCSIInquiry(void);
void SCSIRead10(void);
void SCSIWrite10(void);
void SCSIReadLong(void);
void SCSIReadCapacity(void);
void SCSITestUnitReady(void);
void SCSIRequestSense(void);
void SCSIModeSense6(void);


void SCSICBWProcess(void)
{
	//验证CBW有效性
	if (USBEP1Buffer.InLength!=0x1f) return;		//31字节
	if (SCSICBW->dSignature!=0x55534243) return;	//包标记  USBC
	//验证CBW有意义
	if (SCSICBW->bLUN>SCSI_MAX_LUN) return;			//错误的LUN
	if (SCSICBW->bCBLength>0x10) return;				//CBWCB长度错误
	switch (SCSICBW->CBWCB[0])
	{
		case SCSI_CMD_INQUIRY			:
			SCSIInquiry();
			USBEP2WritePacket();
			SCSICSWProcess(SCSI_CSW_PASSED,0);
			break;
		case SCSI_CMD_READ10			:
			SCSIRead10();
			SCSICSWProcess(SCSI_CSW_PASSED,0);
			break;
		case SCSI_CMD_WRITE10			:
			SCSIWrite10();
			SCSICSWProcess(SCSI_CSW_PASSED,0);
			break;
		case SCSI_CMD_READ_LONG			:
			SCSIReadLong();
			USBEP2WritePacket();
			SCSICSWProcess(SCSI_CSW_PASSED,SCSICBW->dDataLength - USBEP1Buffer.OutLength);
			break;
		case SCSI_CMD_READ_CAPACITY		:
//			printf("request CAPACITY\n");
			SCSIReadCapacity();
			USBEP2WritePacket();
			SCSICSWProcess(SCSI_CSW_PASSED,0);
			break;
		case SCSI_CMD_TEST_UNIT_READY	:
			SCSICSWProcess(SCSI_CSW_PASSED,0);
			break;
		case SCSI_CMD_REQUEST_SENSE		:
			printf("request sense\n");
			SCSIRequestSense();
			break;
		case SCSI_CMD_MODE_SENSE6		:
			SCSIModeSense6();
			USBEP2WritePacket();
//			UEPNUM=0x02;
//			USB_SEND_STALL_PACKET;
			SCSICSWProcess(SCSI_CSW_PASSED,0xbc);
			break;
	}

}

void SCSICSWProcess(BYTE Status,BYTE DataResidue)
{
	SCSICSW->dSignature=0x55534253;
	SCSICSW->dDataResidue=DataResidue;
	SCSICSW->bStatus=Status;
	USBEP1Buffer.Out=(BYTE *)SCSICSW;
	USBEP1Buffer.OutLength=13;
	USBEP2WritePacket();
}

void SCSIInquiry(void)
{
	if (SCSICBW->CBWCB[1]==0x00&&SCSICBW->CBWCB[2]==0)		//EVPD=0 CMDDT=0 PAGECODE=0
	{//STANDARD
		USBEP1Buffer.Out=SCSIStandardInquiry;
		USBEP1Buffer.OutLength=sizeof(SCSIStandardInquiry);
	}
	else if (SCSICBW->CBWCB[1]==0x00&&SCSICBW->CBWCB[2]!=0)	//EVPD=0 CMDDT=0 PAGECODE!=0
	{//CHECK CONDITION

	}
	else if (SCSICBW->CBWCB[1]==0x01)		//EVPD=0 CMDDT=1
	{//CHECK CONDITION

	}
	else if (SCSICBW->CBWCB[1]==0x02)		//EVPD=1 CMDDT=0
	{

	}
	else									//EVPD=1	CMDDT=1
	{

	}
}

void SCSIRead10(void)
{
	data WORD i;
	data BYTE m,n;
	xdata BYTE *sector;

	xdata struct SCSIRead10Str *SCSICmdRead10=SCSICBW->CBWCB;

	while (!IDEStatus(IDE_STATUS_BSY,IDE_WAIT,FALSE,255));
	while (!IDEStatus(IDE_STATUS_DRDY,IDE_WAIT,TRUE,255));
	sector=(BYTE *)&SCSICmdRead10->LBA;
//	printf("read sector:%08lx,%02bx...",*(DWORD *)sector,(BYTE)SCSICmdRead10->Length);
	IDE_WRITE_LSB(IDE_ADDR_CMD_LBA0,sector[3]);
	IDE_WRITE_LSB(IDE_ADDR_CMD_LBA1,sector[2]);
	IDE_WRITE_LSB(IDE_ADDR_CMD_LBA2,sector[1]);
	IDE_WRITE_LSB(IDE_ADDR_CMD_LBA3,0xe0|(sector[0]&0x0f));
	IDE_WRITE_LSB(IDE_ADDR_CMD_SECCNT,(BYTE)(SCSICmdRead10->Length));
	IDE_WRITE_LSB(IDE_ADDR_CMD_COMMAND,IDE_CMD_READ);

	UEPNUM=0x02;
	for(i=0;i<SCSICmdRead10->Length;i++)
	{
		while (!IDEStatus(IDE_STATUS_BSY,IDE_WAIT,FALSE,255));
		while (!IDEStatus(IDE_STATUS_DRDY,IDE_WAIT,TRUE,255));
		for(m=0;m<8;m++)
		{
			SET_BIT_7(UEPSTAX);						//设置DIR
			for(n=0;n<32;n++)
			{
				
				IDE_READ_WORD(IDE_ADDR_CMD_DATA,UEPDATX,UEPDATX);
			}
			SET_BIT_4(UEPSTAX);						//设置TXRDY
			while(!( UEPSTAX & 0x01 ));				//等待TXCMP
			CLEAR_BIT_0(UEPSTAX);					//清除TXCMP
		}
	}
}

void SCSIWrite10(void)
{
	register WORD i;
	register BYTE m,n,hi;
	xdata BYTE *sector;
	bit k;
	xdata struct SCSIWrite10Str *SCSICmdWrite10=SCSICBW->CBWCB;

	sector=(BYTE *)&SCSICmdWrite10->LBA;
//	printf("write sector:%08lx,%02bx...",*(DWORD *)sector,(BYTE)SCSICmdWrite10->Length);
	while (!IDEStatus(IDE_STATUS_BSY,IDE_WAIT,FALSE,255));
//	printf("BSY ok ");
	while (!IDEStatus(IDE_STATUS_DRDY,IDE_WAIT,TRUE,255));
//	printf("DRDY ok ");
	IDE_WRITE_LSB(IDE_ADDR_CMD_LBA0,sector[3]);
	IDE_WRITE_LSB(IDE_ADDR_CMD_LBA1,sector[2]);
	IDE_WRITE_LSB(IDE_ADDR_CMD_LBA2,sector[1]);
	IDE_WRITE_LSB(IDE_ADDR_CMD_LBA3,0xe0|(sector[0]&0x0f));
	IDE_WRITE_LSB(IDE_ADDR_CMD_SECCNT,(BYTE)(SCSICmdWrite10->Length));
	IDE_WRITE_LSB(IDE_ADDR_CMD_COMMAND,IDE_CMD_WRITE);
	while (!IDEStatus(IDE_STATUS_BSY,IDE_WAIT,FALSE,255));
//	printf("BSY ok ");
	while(!IDEStatus(IDE_STATUS_DRQ,IDE_WAIT,TRUE,255));
//	printf("DRQ ok \n");
	UEPNUM=0x01;
		while((UEPSTAX&(USB_INT_RXOUTB0|USB_INT_RXOUTB1))!=0x42);
		if (UEP_BIT_DTGL) k=1; else k=0;
	for(i=0;i<SCSICmdWrite10->Length;i++)
	{
		for(m=0;m<8;m++)
		{
//			if (UEP_BIT_DTGL)
			{
				while(!(UEPSTAX&(USB_INT_RXOUTB0|USB_INT_RXOUTB1)));
//				printf("RX%bd--%02bx-%02bx-%02bx ",k,UBYCTX,UEPSTAX,UEPCONX);
				for(n=0;n<UBYCTX;n+=2)
				{
					hi=UEPDATX;
//					lo=UEPDATX;
//					printf("%02bx %02bx ",hi,lo);
					IDE_WRITE_WORD(IDE_ADDR_CMD_DATA,hi,UEPDATX);
				}
//				printf("\n");
				if (k) CLEAR_BIT_6(UEPSTAX); else CLEAR_BIT_1(UEPSTAX);			//清RXOUTB0
				k=!k;
//				printf("RB0 CLEARED %04d,%02bd\n",k++,m);
			}
/*			else
			{
//			while(!UEPSTAX&USB_INT_RXOUTB1);
				printf("RX1--%02bx-%02bx-%02bx \n",UBYCTX,UEPSTAX,UEPCONX);
				for(n=0;n<UBYCTX;n+=2)
				{
					hi=UEPDATX;
					lo=UEPDATX;
//					printf("%02bx %02bx ",hi,lo);
//					IDE_WRITE_WORD(IDE_ADDR_CMD_DATA,hi,lo);
				}
				m++;
				CLEAR_BIT_1(UEPSTAX);				//清RXOUTB1
//				printf("RB1 CLEARED %04d,%02bd\n",k++,m);
			}*/
		}
	}
//	printf("write ok\n");
}
								
void SCSIReadLong(void)
{
	USBEP1Buffer.Out=temp1;
	USBEP1Buffer.OutLength=sizeof(temp1);
}

void SCSIReadCapacity(void)
{
	USBEP1Buffer.Out=SCSICapacity;
	USBEP1Buffer.OutLength=sizeof(SCSICapacity);
}

void SCSIRequestSense(void)
{

}

void SCSIModeSense6(void)
{
	USBEP1Buffer.Out=temp2;
	USBEP1Buffer.OutLength=sizeof(temp2);
}


⌨️ 快捷键说明

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