231 lines
9.8 KiB
C
231 lines
9.8 KiB
C
/******************** (C) COPYRIGHT 2015 e-Design Co., Ltd. ********************
|
|
File Name : USB_scsi.c
|
|
Version : STM32 USB Disk Ver 3.4 Author : MCD Application Team & bure
|
|
*******************************************************************************/
|
|
#include "USB_scsi.h"
|
|
#include "USB_bot.h"
|
|
#include "USB_regs.h"
|
|
#include "usb_lib.h"
|
|
#include "Disk.h"
|
|
|
|
u8 Page00_Inquiry_Data[] ={ 0, 0, 0, 0, 0};
|
|
u8 Mode_Sense6_data[] ={0x03, 0x00, 0x00, 0x00};
|
|
u8 Mode_Sense10_data[] ={0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
u8 Scsi_Sense_Data[] ={0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
u8 ReadCapacity10_Data[] ={ 0, 0, 0, 0, 0, 0, 0, 0};
|
|
u8 ReadFormatCapacity[] ={ 0, 0, 0, 8, 0, 0, 0, 0, 2, 0, 0, 0};
|
|
|
|
#ifdef DFU_MODE
|
|
uc8 Disk_Inquiry_Str[] ={0x00, 0x80, 0x02, 0x02, 36-4, 0x00, 0x00, 0x00,
|
|
'V', 'i', 'r', 't', 'u', 'a', 'l', ' ',
|
|
'D', 'F', 'U', ' ', 'D', 'i', 's', 'k',
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
|
|
' ', ' ', ' ', ' ', };
|
|
#else
|
|
uc8 Disk_Inquiry_Str[] ={0x00, 0x80, 0x02, 0x02, 36-4, 0x00, 0x00, 0x00,
|
|
'M', 'i', 'n', 'i', ' ', 'D', 'S', 'O',
|
|
'D', 'i', 's', 'k', ' ', ' ', ' ', ' ',
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
|
|
' ', ' ', ' ', ' ', };
|
|
#endif
|
|
|
|
/*******************************************************************************
|
|
SCSI_Inquiry_Cmd: SCSI Inquiry Command routine.
|
|
*******************************************************************************/
|
|
void SCSI_Inquiry_Cmd(void)
|
|
{
|
|
u8* Inquiry_Data;
|
|
u16 Inquiry_Data_Length;
|
|
|
|
if (CBW.CB[1] & 0x01){ // Evpd is set
|
|
Inquiry_Data = Page00_Inquiry_Data;
|
|
Inquiry_Data_Length = 5;
|
|
} else {
|
|
Inquiry_Data = (u8*)Disk_Inquiry_Str;
|
|
if (CBW.CB[4] <= STANDARD_INQUIRY_DATA_LEN) Inquiry_Data_Length = CBW.CB[4];
|
|
else Inquiry_Data_Length = STANDARD_INQUIRY_DATA_LEN;
|
|
}
|
|
Transfer_Data_Request(Inquiry_Data, Inquiry_Data_Length);
|
|
}
|
|
/*******************************************************************************
|
|
SCSI_ReadFormatCapacity_Cmd: SCSI ReadFormatCapacity Command routine.
|
|
*******************************************************************************/
|
|
void SCSI_ReadFormatCapacity_Cmd(void)
|
|
{
|
|
ReadFormatCapacity[ 4] = (u8)(SECTOR_SIZE >> 24);
|
|
ReadFormatCapacity[ 5] = (u8)(SECTOR_SIZE >> 16);
|
|
ReadFormatCapacity[ 6] = (u8)(SECTOR_SIZE >> 8);
|
|
ReadFormatCapacity[ 7] = (u8)(SECTOR_SIZE);
|
|
|
|
ReadFormatCapacity[ 9] = (u8)(SECTOR_SIZE >> 16);
|
|
ReadFormatCapacity[10] = (u8)(SECTOR_SIZE >> 8);
|
|
ReadFormatCapacity[11] = (u8)(SECTOR_SIZE);
|
|
|
|
Transfer_Data_Request(ReadFormatCapacity, READ_FORMAT_CAPACITY_DATA_LEN);
|
|
}
|
|
/*******************************************************************************
|
|
SCSI_ReadCapacity10_Cmd: SCSI ReadCapacity10 Command routine.
|
|
*******************************************************************************/
|
|
void SCSI_ReadCapacity10_Cmd(void)
|
|
{
|
|
ReadCapacity10_Data[0] = (u8)(SECTOR_CNT - 1 >> 24);
|
|
ReadCapacity10_Data[1] = (u8)(SECTOR_CNT - 1 >> 16);
|
|
ReadCapacity10_Data[2] = (u8)(SECTOR_CNT - 1 >> 8);
|
|
ReadCapacity10_Data[3] = (u8)(SECTOR_CNT - 1);
|
|
|
|
ReadCapacity10_Data[4] = (u8)(SECTOR_SIZE >> 24);
|
|
ReadCapacity10_Data[5] = (u8)(SECTOR_SIZE >> 16);
|
|
ReadCapacity10_Data[6] = (u8)(SECTOR_SIZE >> 8);
|
|
ReadCapacity10_Data[7] = (u8)(SECTOR_SIZE);
|
|
|
|
Transfer_Data_Request(ReadCapacity10_Data, READ_CAPACITY10_DATA_LEN);
|
|
}
|
|
/*******************************************************************************
|
|
SCSI_ModeSense6_Cmd: SCSI ModeSense6 Command routine.
|
|
*******************************************************************************/
|
|
void SCSI_ModeSense6_Cmd (void)
|
|
{
|
|
Transfer_Data_Request(Mode_Sense6_data, MODE_SENSE6_DATA_LEN);
|
|
}
|
|
/*******************************************************************************
|
|
SCSI_ModeSense10_Cmd: SCSI ModeSense10 Command routine.
|
|
*******************************************************************************/
|
|
void SCSI_ModeSense10_Cmd (void)
|
|
{
|
|
Transfer_Data_Request(Mode_Sense10_data, MODE_SENSE10_DATA_LEN);
|
|
}
|
|
/*******************************************************************************
|
|
SCSI_RequestSense_Cmd: SCSI RequestSense Command routine.
|
|
*******************************************************************************/
|
|
void SCSI_RequestSense_Cmd (void)
|
|
{
|
|
u8 Request_Sense_data_Length;
|
|
|
|
if (CBW.CB[4] <= REQUEST_SENSE_DATA_LEN) Request_Sense_data_Length = CBW.CB[4];
|
|
else Request_Sense_data_Length = REQUEST_SENSE_DATA_LEN;
|
|
|
|
Transfer_Data_Request(Scsi_Sense_Data, Request_Sense_data_Length);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
Set_Scsi_Sense_Data: Set Scsi Sense Data routine.
|
|
*******************************************************************************/
|
|
void Set_Scsi_Sense_Data(u8 Sens_Key, u8 Asc)
|
|
{
|
|
Scsi_Sense_Data[2] = Sens_Key;
|
|
Scsi_Sense_Data[12] = Asc;
|
|
}
|
|
/*******************************************************************************
|
|
SCSI_Start_Stop_Unit_Cmd: SCSI Start_Stop_Unit Command routine.
|
|
*******************************************************************************/
|
|
void SCSI_Start_Stop_Unit_Cmd(void)
|
|
{
|
|
Set_CSW (CSW_CMD_PASSED, SEND_CSW_ENABLE);
|
|
}
|
|
/*******************************************************************************
|
|
SCSI_Read10_Cmd: SCSI Read10 Command routine.
|
|
*******************************************************************************/
|
|
void SCSI_Read10_Cmd(u32 LBA , u32 BlockNbr)
|
|
{
|
|
if (Bot_State == BOT_IDLE){
|
|
if (!(SCSI_Address_Management(SCSI_READ10, LBA, BlockNbr))) return;//address out of range
|
|
if ((CBW.bmFlags & 0x80) != 0){
|
|
Bot_State = BOT_DATA_IN;
|
|
Read_Memory(LBA , BlockNbr);
|
|
} else {
|
|
Bot_Abort(BOTH_DIR);
|
|
Set_Scsi_Sense_Data(ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND);
|
|
Set_CSW (CSW_CMD_FAILED, SEND_CSW_ENABLE);
|
|
}
|
|
return;
|
|
} else if (Bot_State == BOT_DATA_IN) Read_Memory(LBA , BlockNbr);
|
|
}
|
|
/*******************************************************************************
|
|
SCSI_Write10_Cmd: SCSI Write10 Command routine.
|
|
*******************************************************************************/
|
|
void SCSI_Write10_Cmd(u32 LBA , u32 BlockNbr)
|
|
{
|
|
if (Bot_State == BOT_IDLE){
|
|
if (!(SCSI_Address_Management(SCSI_WRITE10 , LBA, BlockNbr))) return;//address out of range
|
|
if ((CBW.bmFlags & 0x80) == 0){
|
|
Bot_State = BOT_DATA_OUT;
|
|
SetEPRxStatus(ENDP2, EP_RX_VALID);
|
|
} else {
|
|
Bot_Abort(DIR_IN);
|
|
Set_Scsi_Sense_Data(ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND);
|
|
Set_CSW (CSW_CMD_FAILED, SEND_CSW_DISABLE);
|
|
}
|
|
return;
|
|
} else if (Bot_State == BOT_DATA_OUT) Write_Memory(LBA , BlockNbr);
|
|
}
|
|
/*******************************************************************************
|
|
SCSI_Verify10_Cmd: SCSI Verify10 Command routine.
|
|
*******************************************************************************/
|
|
void SCSI_Verify10_Cmd(void)
|
|
{
|
|
if ((CBW.dDataLength == 0) && !(CBW.CB[1] & BLKVFY)){ // BLKVFY not set
|
|
Set_CSW (CSW_CMD_PASSED, SEND_CSW_ENABLE);
|
|
} else {
|
|
Bot_Abort(BOTH_DIR);
|
|
Set_Scsi_Sense_Data(ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND);
|
|
Set_CSW (CSW_CMD_FAILED, SEND_CSW_DISABLE);
|
|
}
|
|
}
|
|
/*******************************************************************************
|
|
SCSI_Valid_Cmd: Valid Commands routine.
|
|
*******************************************************************************/
|
|
void SCSI_Valid_Cmd(void)
|
|
{
|
|
if (CBW.dDataLength != 0){
|
|
Bot_Abort(BOTH_DIR);
|
|
Set_Scsi_Sense_Data(ILLEGAL_REQUEST, INVALID_COMMAND);
|
|
Set_CSW (CSW_CMD_FAILED, SEND_CSW_DISABLE);
|
|
} else Set_CSW (CSW_CMD_PASSED, SEND_CSW_ENABLE);
|
|
}
|
|
/*******************************************************************************
|
|
SCSI_Valid_Cmd: Valid Commands routine.
|
|
*******************************************************************************/
|
|
void SCSI_TestUnitReady_Cmd(void)
|
|
{
|
|
Set_CSW (CSW_CMD_PASSED, SEND_CSW_ENABLE);
|
|
}
|
|
/*******************************************************************************
|
|
SCSI_Invalid_Cmd: Invalid Commands routine
|
|
*******************************************************************************/
|
|
void SCSI_Invalid_Cmd(void)
|
|
{
|
|
if (CBW.dDataLength == 0) Bot_Abort(DIR_IN);
|
|
else{
|
|
if ((CBW.bmFlags & 0x80) != 0) Bot_Abort(DIR_IN);
|
|
else Bot_Abort(BOTH_DIR);
|
|
}
|
|
Set_Scsi_Sense_Data(ILLEGAL_REQUEST, INVALID_COMMAND);
|
|
Set_CSW (CSW_CMD_FAILED, SEND_CSW_DISABLE);
|
|
}
|
|
/*******************************************************************************
|
|
SCSI_Address_Management: Test the received address.
|
|
Input: Cmd the command can be SCSI_READ10 or SCSI_WRITE10.
|
|
Return: Read\Write status (bool).
|
|
*******************************************************************************/
|
|
u8 SCSI_Address_Management(u8 Cmd , u32 LBA , u32 BlockNbr)
|
|
{
|
|
|
|
if ((LBA + BlockNbr) > SECTOR_CNT){
|
|
if (Cmd == SCSI_WRITE10) Bot_Abort(BOTH_DIR);
|
|
Bot_Abort(DIR_IN);
|
|
Set_Scsi_Sense_Data(ILLEGAL_REQUEST, ADDRESS_OUT_OF_RANGE);
|
|
Set_CSW (CSW_CMD_FAILED, SEND_CSW_DISABLE);
|
|
return (FALSE);
|
|
}
|
|
if (CBW.dDataLength != BlockNbr * SECTOR_SIZE){
|
|
if (Cmd == SCSI_WRITE10) Bot_Abort(BOTH_DIR);
|
|
else Bot_Abort(DIR_IN);
|
|
Set_Scsi_Sense_Data(ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND);
|
|
Set_CSW (CSW_CMD_FAILED, SEND_CSW_DISABLE);
|
|
return (FALSE);
|
|
}
|
|
return (TRUE);
|
|
}
|
|
/********************************* END OF FILE ******************************/
|