📄 bulkonly.c
字号:
/*********************************************************************
********************
* Module History
********************
*2007-6-20 10:10 Created by Oli
*********************************************************************/
/*********************************************************************
* Support the SCSI command
*********************************************************************/
#include "hw_include.h"
#include "usb.h"
#include "hw_memmap.h"
#include "hw_common.h"
#include "BulkOnly.h"
#include "hwapi_cache.h"
#include "usbblock.h"
#include "include.h"
#define USB_WRITE_BUF_EN 1
USB_MSDC_CBW *pCBW;
UINT8 SCSIDATA_RequestSense[18];
UINT8 *pBulkOutDataBuff;
UINT8 volatile UsbStatus;
UINT8 G_ucBulkStausPhase;
INT32 dCSWDataResidueVal;
USB_MSDC_CSW gCSW;
UINT8 *pBulkInDataBuff ;
UINT16 BulkEndpSize;
UINT8 G_ucBulkPhase; //BULK命令阶段状态字
extern UINT8 Bulk_buf[4096];
UINT32 SCSI_BulkOutDataLen;
extern UINT8 volatile SCSI_MediaReady; //BULK命令阶段状态字
static uint8 MediaChange[4]; //add by lxs @2008.02.22
__align(4) UINT8 SCSIDATA_RequestSense[] =
{
0x70, //information filed is invalid=0x70,information filed is valid=0xf0,
0x00, //reserve
0x05, //Sense Key[3...0]
0x00, 0x00, 0x00, 0x00, //information
0x0a, //Addition Sense Length
0x00, 0x00, 0x00, 0x00, //reserve
0x20, //Additional Sense Code(ASC)
0x00, //Additional Sense Code Qualifier(ASCQ)
0x00, //reserve
0x00, 0x00, 0x00, //reserve
};
__align(4) UINT8 InquirySupportedData[] =
{
0x00,
SUPPORTED_PAGES,
0x00,
0x03,
SERIAL_NUMBER_PAGE,
DEVICE_INDENIFICATION_PAGE
};
__align(4) UINT8 InquirySnData[] =
{
0x00,
SERIAL_NUMBER_PAGE,
0x00,
20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20
};
__align(4) UINT8 InquiryDeviceData[] =
{
0x00,
DEVICE_INDENIFICATION_PAGE,
0x00,
26,
0x02,
0x01,
0x00,
22,
'R', 'o', 'c', 'k', 'c', 'h', 'i', 'p', ' ',
'U', 's', 'b', ' ', 'M', 'p', '3', ' ',
' ', ' ', ' ', ' '
};
__align(4) UINT8 SCSIDATA_Sense[] =
{
#if (CD_ROM==1)
0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x0a,
0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
// 0x01, 0x00, 0x04, 0x80, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00,
// 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00
#else
0x03, 0x00, 0x00, 0x00, //第3字节为0x80表示写保护
0x01, 0x0a, 0x00, 0x10,
0x00, 0x00, 0x00, 0x00
#endif
#if 0
0x02, 0x00, 0x00, 0x00, //page 1
0x05, 0x1e, 0x0f, 0xa0, //page 2
0x04, 0x10, 0x02, 0x00,
0x00, 0xfa, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
#endif
};
void SCSICMD_Read12(void);
/***************************************************************************
16位数据大小端转换
***************************************************************************/
UINT16 Swap16(UINT16 input)
{
return ((input >> 8) | (input << 8));
}
/***************************************************************************
32位数据大小端转换
***************************************************************************/
UINT32 Swap32(UINT32 input)
{
return ((input >> 24) | (input << 24) | (input >> 8&0xff00) | (input << 8&0xff0000));
}
/********************************************************************
Routine : UsbBulkInPacket
Input : None
Output : None
Function : ...
*********************************************************************/
extern MSC_DEVICE gUsbMscDevice[4];
void BulkInIoDoneCallback(void);
extern UINT32 uCurrentBulklPacketSize;
void UsbBulkInPacket(void)
{
UINT32 TX_Status;
//TX_Status = TX2_STATUS;
return;
if (TX_Status & (/*TxVOID|*/TxERR))
{
return;
}
else
{
TX_Status &= 0x7ff;
}
if (G_ucBulkStausPhase == K_InDataPhase)
{
pBulkInDataBuff = UsbBlkBulkInDataPack(BulkEndpSize);
if (pBulkInDataBuff)
{
UsbWriteDataEP(BulkEndpSize, pBulkInDataBuff);
}
}
}
void BulkInIoDoneCallback(void)
{
SendCSW();
G_ucBulkStausPhase = K_CommandPhase;
G_ucBulkPhase = K_CommandPhase;
}
/***************************************************************************
批量数据传输BulkOnly命令解释
***************************************************************************/
void BulkOutIoDoneCallback(void);
void UsbBulkOutPacket(void) //NOT OK
{
#if (USB_WRITE_BUF_EN==0)
MSC_DEVICE *pMscDev;
#endif
UINT32 len;
len = RX1_STATUS;//2007-8-31 10:47
if (len & (RxOVF | RxERR | RxVOID))
{
len = 0;
return;
}
else
len &= 0x7ff;
if (len == 0) //无数据返回
{
return;
}
//接收命令
if (G_ucBulkPhase == K_CommandPhase)
{
Cache_FlushDataLine((UINT32)(Bulk_buf), 64);
(UINT8 *)pCBW = (Bulk_buf);
pCBW->LBA = Swap32(pCBW->LBA);
pCBW->Len = Swap16(pCBW->Len);
if (CBWValidVerify() == OK)
{
BulkOnlyCmd();
}
else
{
CSWHandler(CASECBW, 0);
}
}
//接收数据
else if (G_ucBulkPhase == K_OutDataPhase)
{
#if (USB_WRITE_BUF_EN)
//printf("out while %x %x %x\n",pBulkOutDataBuff,dCSWDataResidueVal,SCSI_BulkOutDataLen);
pBulkOutDataBuff = UsbBlkBulkOutDataPack(len);
UsbReadyToReadDataEP(pBulkOutDataBuff);
//printf("write ep2 \n");
#endif
#if 0//(USB_WRITE_BUF_EN)
do
{
//printf("out \n");
//printf("out while %x %x %x\n",pBulkOutDataBuff,dCSWDataResidueVal,SCSI_BulkOutDataLen);
if (dCSWDataResidueVal == SCSI_BulkOutDataLen)
{
//printf("break \n");
break;
}
pBulkOutDataBuff = UsbBlkBulkOutDataPack(len);
UsbReadyToReadDataEP(pBulkOutDataBuff);
SCSI_BulkOutDataLen = SCSI_BulkOutDataLen + len;
//printf("write ep2 \n");
}
while (ReadReg32(UDC_RX1STAT) & RxFULL);
#endif
///////////////
}
}
void BulkOutIoDoneCallback(void)
{
SendCSW();
G_ucBulkPhase = K_CommandPhase;
UsbStatus = USB_XFER_IDLE;
}
/***************************************************************************
批量数据传输BulkOnly命令解释
***************************************************************************/
void BulkOnlyCmd(void)
{
switch (pCBW->Code)
{
//6-byte command
case K_SCSICMD_TEST_UNIT_READY: //0x00
SCSICMD_TestUnitReady();
break;
case K_SCSICMD_REQUEST_SENSE: //0x03
SCSICMD_RequestSense();
break;
case K_SCSICMD_INQUIRY: //0x12
SCSICMD_Inquiry();
break;
case K_SCSICMD_MODE_SENSE_06: //0x1a
SCSICMD_ModeSense06();
break;
case K_SCSICMD_PREVENT_ALLOW_MEDIUM_REMOVAL: //0x1e
SCSICMD_PreventAllowMediumRemoval();
break;
case K_SCSICMD_START_STOP_UNIT: //0x1b
SCSICMD_StartStopUnit();
break;
//10-byte command
case K_SCSICMD_READ_CAPACITY: //0x25
SCSICMD_ReadCapacity();
break;
case K_SCSICMD_READ_10: //0x28
SCSICMD_Read10();
break;
case K_SCSICMD_WRITE_10: //0x2a
G_ucBulkPhase = K_OutDataPhase;
SCSICMD_Write10();
break;
case K_SCSICMD_VERIFY_10: //0x2f
SCSICMD_Verify10();
break;
case K_SCSICMD_MODE_SENSE_10: //0x5a
SCSICMD_ModeSense10();
break;
//12-byte command
case K_SCSICMD_READ_FORMAT_CAPACITIES: //0x23
SCSICMD_ReadFormatCapacities();
break;
case K_SCSICMD_READ_12:
SCSICMD_Read12();
break;
default:
CSWHandler(CASECBW, 0);
BuildSenseData(SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ADSENSE_ILLEGAL_COMMAND, 0);
break;
}
}
/***************************************************************************
功能:命令块有效校验
入口:无
出口:OK=命令块格式正确,ERROR=命令块格式出错
***************************************************************************/
BOOL CBWValidVerify(void) //ok
{
if (pCBW->dCBWSignature == 0x43425355 //CBW_SIGNATURE校对
&& pCBW->bCBWLUN < 10/*MAX_LUN*/ && pCBW->bCBWCBLength <= MAX_CDBLEN) //LUN和命令块长度校对
return(OK); //有效返回
else
return(ERROR); //无效返回
}
/***************************************************************************
功能:CSW处理
入口:HostDevCase=状态,DeviceTrDataLen=设备要发送的数据长度
出口:无
***************************************************************************/
void CSWHandler(UINT8 HostDevCase, UINT16 DeviceTrDataLen)
{
gCSW.dCSWSignature = 0x53425355;
gCSW.dCSWTag = pCBW->dCBWTag;
gCSW.dCSWDataResidue = (pCBW->dCBWDataTransferLength - DeviceTrDataLen);
switch (HostDevCase)
{
case CASEOK:
case CASE1: /* Hn=Dn*/
case CASE6: /* Hi=Di*/
case CASE12: /* Ho=Do*/
gCSW.bCSWStatus = CSW_GOOD;
break;
case CASE4: /* Hi>Dn*/
case CASE5: /* Hi>Di*/
case CASE9: /* Ho>Dn*/
case CASE11: /* Ho>Do*/
gCSW.bCSWStatus = CSW_GOOD; //CSW_GOOD or CSW_FAIL
break;
case CASE2: /* Hn<Di*/
case CASE3: /* Hn<Do*/
case CASE7: /* Hi<Di*/
case CASE8: /* Hi<>Do */
case CASECMDFAIL:
//2007-6-13 23:42MUSBHSFC_SetEndpointStatus(3, 1); //stall IN endpoint
//?将out ep置stall
gCSW.bCSWStatus = CSW_PHASE_ERROR;
break;
case CASE13: /* Ho<Do*/
//2007-6-13 23:42MUSBHSFC_SetEndpointStatus(2, 1);
//?将in ep置stall
gCSW.bCSWStatus = CSW_FAIL;
break;
case CASE10: /* Ho<>Di */
case CASECBW: /* invalid CBW */
WriteReg32(UDC_TX2CON, ReadReg32(UDC_TX2CON) | (1 << 13));
gCSW.bCSWStatus = CSW_FAIL;
break;
default:
break;
}
}
/***************************************************************************
功能:拷贝FLASH的后面PAGE
入口:无
出口:无
***************************************************************************/
void CopyFlashReside(void)
{
//serial_printf(" CopyFlashReside\n");
}
/***************************************************************************
功能:回送CSW
入口:无
出口:无
***************************************************************************/
void SendCSW(void)//ok
{
UsbWriteDataEP(13, (UINT8*)&gCSW);
UsbReadyToReadDataEP(Bulk_buf);
G_ucBulkPhase = K_CommandPhase;
G_ucBulkStausPhase = K_CommandPhase;
}
/***************************************************************************
功能:建立 sense
入口:
出口:无
***************************************************************************/
void BuildSenseData(UINT8 SenseKey, UINT8 ASC, UINT8 ASCQ)//ok
{
SCSIDATA_RequestSense[0] = 0x70; //information filed is invalid=0x70,information filed is valid=0xf0,
SCSIDATA_RequestSense[1] = 0x00; //reserve
SCSIDATA_RequestSense[2] = SenseKey;
SCSIDATA_RequestSense[3] = 0x00; //information
SCSIDATA_RequestSense[4] = 0x00;
SCSIDATA_RequestSense[5] = 0x00;
SCSIDATA_RequestSense[6] = 0x00;
SCSIDATA_RequestSense[7] = 0x0a; //Addition Sense Length
SCSIDATA_RequestSense[8] = 0x00; //reserve
SCSIDATA_RequestSense[9] = 0x00;
SCSIDATA_RequestSense[10] = 0x00;
SCSIDATA_RequestSense[11] = 0x00;
SCSIDATA_RequestSense[12] = ASC;
SCSIDATA_RequestSense[13] = ASCQ;
SCSIDATA_RequestSense[14] = 0x00; //reserve
SCSIDATA_RequestSense[15] = 0x00;
SCSIDATA_RequestSense[16] = 0x00;
SCSIDATA_RequestSense[17] = 0x00;
}
extern UINT8 g_pmid[16];
/***************************************************************************
函数描述:修改DRM9 ID值
入口参数:
出口参数:
调用函数:
***************************************************************************/
void Modify_DRM9ID()
{
UINT32 i;
InquirySnData[3] = 16;
for (i = 0;i < 16; i++)
{
InquirySnData[i+4] = g_pmid[i];
}
}
/********************************************************************
SCSI COMMAND
********************************************************************/
/***************************************************************************
命令:查询0x12
***************************************************************************/
void SCSICMD_Inquiry(void)
{
UINT8 t;
MSC_PROPERTIES p;
MSC_STATUS MediaStatus;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -