📄 msd.c
字号:
MSDReadCapacityHandler();
break;
case READ_10:
MSDReadHandler();
break;
case WRITE_10:
MSDWriteHandler();
break;
case REQUEST_SENSE:
MSDRequestSenseHandler();
break;
case MODE_SENSE:
MSDModeSenseHandler();
break;
case PREVENT_ALLOW_MEDIUM_REMOVAL:
MSDMediumRemovalHandler();
break;
case TEST_UNIT_READY:
MSDTestUnitReadyHandler();
break;
case VERIFY:
MSDVerifyHandler();
break;
case STOP_START:
MSDStopStartHandler();
break;
default:
ResetSenseData();
gblSenseData.SenseKey=S_ILLEGAL_REQUEST;
gblSenseData.ASC=ASC_INVALID_COMMAND_OPCODE;
gblSenseData.ASCQ=ASCQ_INVALID_COMMAND_OPCODE;
msd_csw.bCSWStatus=0x01;
msd_csw.dCSWDataResidue=0x00;
break;
} // end switch
ptrNextData=(byte*)&msd_buffer[0];
}
/******************************************************************************
* Function: void SendCSW(void)
*
* PreCondition: None
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: This function sends the CSW and sets the State to MSD_WAIT
* It also changes MSD_BD_OUT to point to msd_csw (structure
* for reading CSW) Note that this was changed in
* MSD_DATA_OUT state to point to msd_buffer in order to
* read data from host
*
* Note: None
*****************************************************************************/
void SendCSW(void)
{
while(mMSDTxIsBusy());
MSD_BD_IN.ADR=(byte*)&msd_csw;
MSD_BD_IN.Cnt=MSD_CSW_SIZE;
mUSBBufferReady(MSD_BD_IN);
USBDriverService();
MSD_BD_OUT.Cnt=sizeof(msd_cbw);
MSD_BD_OUT.ADR=(byte*)&msd_cbw; // in MSD_DATA_OUT state the address
// was changed to point tomsd_buffer
MSD_State=MSD_WAIT;
}
/******************************************************************************
* Function: void SendData(byte* dataAddr, byte dataSize)
*
* PreCondition: None
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: This function sends "dataSize" bytes of data
* (< MSD_EP_IN_SIZE) starting at address "dataAddr".
*
* Note: None
*****************************************************************************/
void SendData(byte* dataAddr, byte dataSize)
{
while(mMSDTxIsBusy());
MSD_BD_IN.ADR=dataAddr;
MSD_BD_IN.Cnt=dataSize;
mUSBBufferReady(MSD_BD_IN);
USBDriverService();
}
/******************************************************************************
* Function: void MSDDataIn(void)
*
* PreCondition: None
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: This function sends 512B of data in msd_buffer to the
* host in 64B chunks using MSD_BD_IN.Various conditions
* when data to be sent is less than MSD_IN_EP_SIZE and
* error condition bCSWStatus = 0x01 are checked. As per
* specifications, in case of error 0 filled data of the size
* expected by the host dCBWDataTransferLength is sent.
*
* Note: None
*****************************************************************************/
void MSDDataIn(void)
{
byte i;
dword size;
/* Case (status==0) and (data to be sent > MSD_IN_EP_SIZE)*/
if ((msd_csw.bCSWStatus==0x00)&&(msd_csw.dCSWDataResidue>=MSD_IN_EP_SIZE)) {
/* Write next chunk of data to EP Buffer and send */
SendData(ptrNextData,MSD_IN_EP_SIZE);
gblCBW.dCBWDataTransferLength-= MSD_IN_EP_SIZE;
msd_csw.dCSWDataResidue-=MSD_IN_EP_SIZE;
ptrNextData+=MSD_IN_EP_SIZE;
} else {
if (msd_csw.bCSWStatus!=0x0) { // error path status!=0
size=mMin(MSD_IN_EP_SIZE,gblCBW.dCBWDataTransferLength);
for (i=0;i<size;i++) msd_buffer[i]=0; // prepare 0 data
if (gblCBW.dCBWDataTransferLength > MSD_IN_EP_SIZE) {
/* Case (status!=0) and (data to be sent > MSD_IN_EP_SIZE)*/
/* write next chunk of data to EP Buffer and send */
SendData((byte*)&msd_buffer[0],MSD_IN_EP_SIZE);
gblCBW.dCBWDataTransferLength -= MSD_IN_EP_SIZE;
msd_csw.dCSWDataResidue-=MSD_IN_EP_SIZE;
} else {
/* Case (status!=0) and (data to be sent < MSD_IN_EP_SIZE) */
/* write next chunk of data to EP Buffer and send*/
SendData((byte*)&msd_buffer[0],gblCBW.dCBWDataTransferLength);
gblCBW.dCBWDataTransferLength = 0;
/* we have sent 0s for what was expected by host*/
msd_csw.dCSWDataResidue -= gblCBW.dCBWDataTransferLength;
}
} else {
/* Case (status ==0) and (data to be sent < MSD_IN_EP_SIZE) */
/* write next chunk of data to EP Buffer and send */
SendData(ptrNextData,msd_csw.dCSWDataResidue);
/* we have sent all the data that was expected by host */
gblCBW.dCBWDataTransferLength -= msd_csw.dCSWDataResidue ;
msd_csw.dCSWDataResidue = gblCBW.dCBWDataTransferLength;
/* In case the host expected more than what we had to send */
/* Setting DataTransferLength=0 so that CSW is sent after this*/
gblCBW.dCBWDataTransferLength = 0;
}
}
}
/******************************************************************************
* Function: void IsValidCBW()
*
* PreCondition: None
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: This checks if the received CBW is valid
* According to the Mass Storage Class Specifications,
* a CSW is considered to be valid if
* 1. It was received in MS_WAIT State
* 2. CBW length is 1Fh bytes (MSD_CBW_SIZE)
* 3. dCBWSignature is equal to 0x43425355h
*
* Note: None
*****************************************************************************/
byte IsValidCBW()
{
if ((gblCBWLength!=MSD_CBW_SIZE)||(gblCBW.dCBWSignature!=0x43425355))return FALSE;
else return TRUE;
}
/******************************************************************************
* Function: void IsMeaningfulCBW()
*
* PreCondition: None
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: This checks if the received CBW is meaningful
* According to the Mass Storage Class Specifications,
* a CSW is considered to be meaningful if
* 1. No reserved bits are set
* 2. bCBWLUN contains a valid LUN supported by device
* 3. bCBWCBLength and CBWCB are in accordance with
* bInterfaceSubClass
* Note: None
*****************************************************************************/
byte IsMeaningfulCBW()
{
/* 3msb bits of CBWCBLength are reserved and must be 0,
* 4msb bits of CBWLUN are reserved and must be 0
* valid CBWCBLength is between 1 and 16B
* In bCBWFlags only msb indicates data direction rest must be 0
*/
if((gblCBW.bCBWLUN<=0x0f)&&(gblCBW.bCBWCBLength<=0x10)&&(gblCBW.bCBWCBLength>=0x01)&&(gblCBW.bCBWFlags==0x00|gblCBW.bCBWFlags==0x80))
return TRUE;
else return FALSE;
}
/******************************************************************************
* Function: void PrepareCSWData()
*
* PreCondition: None
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: This prepares the Status data of CSW by copying the
* dCSWTag from CBWTage and sets the signature
* of valid CSW=53425355h
*
* Note: None
*****************************************************************************/
void PrepareCSWData()
{
/* Residue and Status fields are set after
decoding and executing the command */
msd_csw.dCSWTag=gblCBW.dCBWTag;
msd_csw.dCSWSignature=0x53425355;
}
/******************************************************************************
* Function: void MSDInquiryHandler(void)
*
* PreCondition: None
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: This function prepares the response of the Inquiry command
* A fixed Inquiry response is copied from ROM to the
* msd_buffer and CSWStatus, CSWDataResidue values are set
*
* Note: None
*****************************************************************************/
void MSDInquiryHandler(void)
{
byte i;
byte *buffer;
memcpypgm2ram((byte *)&msd_buffer[0],(byte *)&inq_resp,sizeof(InquiryResponse));
msd_csw.dCSWDataResidue=sizeof(InquiryResponse);
msd_csw.bCSWStatus=0x00; // success
return;
}
/******************************************************************************
* Function: void ResetSenseData(void)
*
* PreCondition: None
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: This routine resets the Sense Data, initializing the
* structure RequestSenseResponse gblSenseData.
*
*
* Note: None
*****************************************************************************/
void ResetSenseData(void)
{
gblSenseData.ResponseCode=S_CURRENT;
gblSenseData.VALID=0; // no data in the information field
gblSenseData.Obsolete=0x0;
gblSenseData.SenseKey=S_NO_SENSE;
gblSenseData.Resv;
gblSenseData.ILI=0;
gblSenseData.EOM=0;
gblSenseData.FILEMARK=0;
gblSenseData.Information._dword=0x00;
gblSenseData.AddSenseLen=0x0a; // n-7 (n=17 (0..17))
gblSenseData.CmdSpecificInfo._dword=0x0;
gblSenseData.ASC=0x0;
gblSenseData.ASCQ=0x0;
gblSenseData.FRUC=0x0;
gblSenseData.SenseKeySpecific[0]=0x0;
gblSenseData.SenseKeySpecific[1]=0x0;
gblSenseData.SenseKeySpecific[2]=0x0;
}
/******************************************************************************
* Function: void MSDReadCapacityHandler()
*
* PreCondition: None
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: This function processes the data from CSD register
* (read during intiailization of sdcard)to find the number
* of blocks (gblNumBLKS) and block length (gblBLKLen)
* This data is then copied to msd_buffer and a response
* for Read Capacity Command is prepared
* Note: None
*****************************************************************************/
void MSDReadCapacityHandler()
{
dword one=0x1, C_size, C_mult, Mult, C_size_U, C_size_H, C_size_L, C_mult_H, C_mult_L;
dword C_Read_Bl_Len;
// Get the block length
C_Read_Bl_Len=gblCSDReg._byte[5]&0x0f;
gblBLKLen._dword=one<<C_Read_Bl_Len;
// Get the number of blocks using C_size and C_mult
C_size_U=gblCSDReg._byte[6]&0x03; // 2 LSB bits
C_size_H=gblCSDReg._byte[7];
C_size_L=(gblCSDReg._byte[8]&0xC0)>>6; // 2 MSB, right shift by 6places
// to get in LSB
C_size=(C_size_U<<10)|(C_size_H<<2)|(C_size_L);
C_mult_H=gblCSDReg._byte[9]&0x03;
C_mult_L=(gblCSDReg._byte[10]&0x80)>>7;
C_mult=(C_mult_H<<1)|C_mult_L;
Mult = one<<(C_mult+2);
gblNumBLKS._dword=Mult*(C_size+1)-1; // last LBA is noLBAs-1
// prepare the data response
msd_buffer[0]=gblNumBLKS.v[3];
msd_buffer[1]=gblNumBLKS.v[2];
msd_buffer[2]=gblNumBLKS.v[1];
msd_buffer[3]=gblNumBLKS.v[0];
msd_buffer[4]=gblBLKLen.v[3];
msd_buffer[5]=gblBLKLen.v[2];
msd_buffer[6]=gblBLKLen.v[1];
msd_buffer[7]=gblBLKLen.v[0];
msd_csw.dCSWDataResidue=0x08; // size of response
msd_csw.bCSWStatus=0x00; // success
}
/******************************************************************************
* Function: void MSDReadHandler(void)
*
* PreCondition: None
*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -