📄 scsi.c
字号:
INT8U *u8ModeSenseData;
u8ModeSenseData = (INT8U*)malloc(DATA_LENGTH_MODE_SENSE);
Mass_stor_us->srb = (struct scsi_cmnd *)malloc(sizeof(struct scsi_cmnd ));
for(u8j =0; u8j< ScsiCmd_Fail_Retry ;u8j++)
{
memset(Mass_stor_us->srb, 0, sizeof(struct scsi_cmnd ));
// Build SCSI command.
vSCSICmd_MODE_SENSE(Mass_stor_us, Mass_stor_us->srb,0x3F, u8ModeSenseData);
// call mass storage function to send CBW
// and get Mode Sense Data. Return CSW to check status.
Host20_MSCD_usb_stor_control_thread(Mass_stor_us);
if(Mass_stor_us->srb->result == SAM_STAT_GOOD)
{
// save all Mode Sense(page code=0x3F) data
// Now we only use u8ModeSenseData[2], this byte save device
// write protection information
Mass_stor_us->Mass_stor_device[u8Drive].bWriteProtect = (u8ModeSenseData[2]==0x80)?
TRUE:FALSE;
free(u8ModeSenseData);
if(Mass_stor_us->srb != NULL)
free(Mass_stor_us->srb);
return TRUE;
}
}
free(u8ModeSenseData);
if(Mass_stor_us->srb != NULL)
free(Mass_stor_us->srb);
return FALSE;
}
//***************************************************************************************
// Function Name:bSCSI_READ_CAPACITY
// Description:To get the CAPACITY
// Input:
// Output:
// Status:S
//***************************************************************************************
///////////////////////////////////////////////////////////////////////////////
// bSCSI_READ_CAPACITY()
// Description:
// 1. scsi READ_CAPACITY command.
// input: none
// output: TRUE or FALSE (BOOLEAN)
///////////////////////////////////////////////////////////////////////////////
BOOLEAN bSCSI_READ_CAPACITY(void)
{
INT8U u8j;
INT8U *u8ReadCapacityData;
for(u8j =0; u8j< ScsiCmd_Fail_Retry ;u8j++)
{
u8ReadCapacityData = (INT8U*)malloc(DATA_LENGTH_READ_CAPACITY);
Mass_stor_us->srb = (struct scsi_cmnd *)malloc(sizeof(struct scsi_cmnd ));
memset(Mass_stor_us->srb, 0, sizeof(struct scsi_cmnd ));
// Build SCSI command.
vSCSICmd_READ_CAPACITY(Mass_stor_us, Mass_stor_us->srb, u8ReadCapacityData);
// call mass storage function to send CBW
// and get CAPACITY Data. Return CSW to check status.
Host20_MSCD_usb_stor_control_thread(Mass_stor_us);
if(Mass_stor_us->srb->result == SAM_STAT_GOOD)
{
// save all CAPACITY data
Mass_stor_us->Mass_stor_device[u8Drive].u32BlockTotalNum = ((INT32U)u8ReadCapacityData[0] << 24) |
((INT32U)u8ReadCapacityData[1] << 16) |
((INT32U)u8ReadCapacityData[2] << 8) |
((INT32U)u8ReadCapacityData[3] ) ;
Mass_stor_us->Mass_stor_device[u8Drive].u32BlockSize = ((INT32U)u8ReadCapacityData[4] << 24) |
((INT32U)u8ReadCapacityData[5] << 16) |
((INT32U)u8ReadCapacityData[6] << 8) |
((INT32U)u8ReadCapacityData[7] ) ;
if ( Mass_stor_us->Mass_stor_device[u8Drive].u32BlockSize > 1024)
{
printk("Block size over 1024, is %X\n",Mass_stor_us->Mass_stor_device[u8Drive].u32BlockSize);
while(1);
}
SCSI_DbgPrint("SCSI CAPACITY : SCSI Device total block <0x%x%x>\n",
(INT16U)(Mass_stor_us->Mass_stor_device[u8Drive].u32BlockTotalNum >> 16),
(INT16U)Mass_stor_us->Mass_stor_device[u8Drive].u32BlockTotalNum);
SCSI_DbgPrint("SCSI CAPACITY : SCSI Product block size <0x%x bytes>\n",(INT16U)Mass_stor_us->Mass_stor_device[u8Drive].u32BlockSize);
free(u8ReadCapacityData);
if(Mass_stor_us->srb != NULL)
free(Mass_stor_us->srb);
return TRUE;
}
else
{
free(u8ReadCapacityData);
if(Mass_stor_us->srb != NULL)
free(Mass_stor_us->srb);
}
}
return FALSE;
}
//***************************************************************************************
// Function Name:bSCSI_TEST_UNIT_READY
// Description: To know that "device is ready ?"
// Input:
// Output:
// Status:
//***************************************************************************************
///////////////////////////////////////////////////////////////////////////////
// bSCSI_TEST_UNIT_READY()
// Description:
// 1. scsi TEST_UNIT_READY command.
// input: none
// output: TRUE or FALSE (BOOLEAN)
///////////////////////////////////////////////////////////////////////////////
BOOLEAN bSCSI_TEST_UNIT_READY(void)
{
INT8U u8j;
for(u8j =0; u8j< ScsiCmd_Fail_Retry ;u8j++)
{
Mass_stor_us->srb = (struct scsi_cmnd *)malloc(sizeof(struct scsi_cmnd ));
memset(Mass_stor_us->srb, 0, sizeof(struct scsi_cmnd ));
// Build SCSI command.
vSCSICmd_TEST_UNIT_READY(Mass_stor_us, Mass_stor_us->srb);
// call mass storage function to send CBW
// and get CAPACITY Data. Return CSW to check status.
Host20_MSCD_usb_stor_control_thread(Mass_stor_us);
if(Mass_stor_us->srb->result == SAM_STAT_GOOD)
{
Mass_stor_us->Mass_stor_device[u8Drive].bDeviceReady = TRUE;
SCSI_DbgPrint("SCSI TEST UNIT READY (Lun=%d): Succeed\n",u8Drive);
if(Mass_stor_us->srb != NULL)
free(Mass_stor_us->srb);
return TRUE;
}
else
{
if(Mass_stor_us->srb != NULL)
free(Mass_stor_us->srb);
}
//Bruce #if 0
//Bruce if(iCardSuddenlyRemove == TRUE)
//Bruce {
//Bruce fLib_RemoveFileSystem((u8Drive+'A'));
//Bruce Mass_stor_us->Mass_stor_device[u8Drive].bDeviceReady = FALSE;
//Bruce iCardSuddenlyRemove = FALSE;
//Bruce SCSI_DbgPrint("**Media already be removed.%s","\n");
//Bruce }
//Bruce if(iCardReplace == TRUE)
//Bruce {
//Bruce SCSI_DbgPrint("**Media has been replaced.%s","\n");
//Bruce fLib_RemoveFileSystem((u8Drive+'A'));
//Bruce
//Bruce Drive = 'A'+u8Drive;
//Bruce fLib_InsertFileSystem(Drive, &(Mass_stor_us->Mass_stor_device[u8Drive].FileSys));
//Bruce fLib_InitFATFileSystemRoutines(&(Mass_stor_us->Mass_stor_device[u8Drive].FileSys),
//Bruce &(Mass_stor_us->Mass_stor_device[u8Drive]),
//Bruce (INIT_CARD)bSCSI_Initial,
//Bruce (READ_SECTOR)bSCSI_READ_10,
//Bruce (WRITE_SECTOR)bSCSI_Write_10,
//Bruce (ERASE_SECTOR)bSCSI_ERASE);
//Bruce // Get FAT, John add
//Bruce SplitDrivePath(&Drive, &DriveName, Path);
//Bruce GetFileSystem(DriveName);
//Bruce iCardReplace = FALSE;
//Bruce }
//Bruce #endif
}
SCSI_DbgPrint("SCSI TEST UNIT READY : Failed%s","\n");
return FALSE;
}
//***************************************************************************************
// Function Name:bSCSI_Initial
// Description:
// Input:
// Output:
// Status:P-OK
//***************************************************************************************
BOOLEAN bSCSI_Initial(struct LUN_Device* LunDevice)
{
//INT8U i=0;
//iCardSuddenlyRemove = FALSE;
//iCardReplace = FALSE;
if(!bSCSI_TEST_UNIT_READY())
{
SCSI_DbgPrint("Scsi Device not ready (Lun=%d).\n",u8Drive);
return FALSE;
}
bSCSI_INQUIRY();
if(!bSCSI_READ_CAPACITY())
{
SCSI_DbgPrint("Read CAPACITY failed.%s","\n");
return FALSE;
}
if(!bSCSI_TEST_UNIT_READY())
{
SCSI_DbgPrint("Scsi Device not ready (Lun=%d).\n",u8Drive);
return FALSE;
}
return TRUE;
}
//***************************************************************************************
// Function Name:bUSBDisk_FileSystem_Initial
// Description:
// Input:
// Output:
// Status:P-OK
//***************************************************************************************
BOOLEAN bUSBDisk_FileSystem_Initial(void)
{
UINT32 DriveName;
INT8 Path[MAX_DIRECTORY_PATH_SIZE];
INT8U Drive,i,DriveTmp[2];
// fLib_InitFileSystem();
/* register a file system to file system control */
for(i=0; i<=Mass_stor_us->max_lun; i++)
{
if(!Mass_stor_us->Mass_stor_device[i].bDeviceReady)
{
Mass_stor_us->Mass_stor_device[i].u8LunNum = i;
u8Drive = i;
Drive = 'A'+i;//'C'+
fLib_InsertFileSystem(Drive, &(Mass_stor_us->Mass_stor_device[i].FileSys));
fLib_InitFATFileSystemRoutines(&(Mass_stor_us->Mass_stor_device[i].FileSys),
&(Mass_stor_us->Mass_stor_device[i]),
(INIT_CARD)bSCSI_Initial,
(READ_SECTOR)bSCSI_READ_10,
(WRITE_SECTOR)bSCSI_Write_10,
(ERASE_SECTOR)bSCSI_ERASE);
// Get FAT, John add
SplitDrivePath(&Drive, &DriveName, Path);
GetFileSystem(DriveName);
// Show Drive status..
DriveTmp[0] = Drive;
DriveTmp[1] = 0;
if(Mass_stor_us->Mass_stor_device[i].bDeviceReady == TRUE)
{
printk("Drive '%01s' ready to wrok..\n",DriveTmp);
}
else
{
printk("Drive '%01s' already registered, but can't work now..\n",DriveTmp);
}
}
}
u8Drive = Mass_stor_us->max_lun;
return TRUE;
}
//***************************************************************************************
// Function Name:
// Description:
// Input:
// Output:
// Status:
//***************************************************************************************
void vUSBDisk_FileSystem_Remove(void)
{
INT8U Drive ,i;
for(i=0; i<=Mass_stor_us->max_lun; i++)
{
Drive = 'A'+i;
fLib_RemoveFileSystem(Drive);
}
}
//***************************************************************************************
// Function Name:
// Description:
// Input:
// Output:
// Status:
//***************************************************************************************
BOOLEAN bSCSI_ERASE( struct LUN_Device* LunDevice, INT32U u32BlockAddr, INT32U u32BlockNum,
INT32U u32SectorSize)
{
return TRUE;
}
//***************************************************************************************
// Function Name:
// Description:
// Input:
// Output:
// Status:
//***************************************************************************************
BOOLEAN bSCSI_READ_10( struct LUN_Device* LunDevice, INT32U u32BlockAddr, INT32U u32BlockNum,
INT32U u32SectorSize, INT8U *u8Buffer)
{
#if 1
INT32U u32DataLeft = (Mass_stor_us->Mass_stor_device[LunDevice->u8LunNum].u32BlockSize)*u32BlockNum;
INT32U u32TransBlockTmp, u32TransSizeTmp,u32BlockOfSet = 0, u32TransOfSet = 0;
Mass_stor_us->srb = (struct scsi_cmnd *)malloc(sizeof(struct scsi_cmnd ));
memset(Mass_stor_us->srb, 0, sizeof(struct scsi_cmnd ));
while(u32DataLeft > 0)
{
if(u32DataLeft > Scsi_Max_Transfer_Len)
{
u32TransBlockTmp = Scsi_Max_Transfer_Len / Mass_stor_us->Mass_stor_device[LunDevice->u8LunNum].u32BlockSize;
u32TransSizeTmp = u32TransBlockTmp * Mass_stor_us->Mass_stor_device[LunDevice->u8LunNum].u32BlockSize;
u32DataLeft -= u32TransSizeTmp;
}
else
{
u32TransBlockTmp = u32DataLeft/Mass_stor_us->Mass_stor_device[LunDevice->u8LunNum].u32BlockSize;
u32TransSizeTmp = u32DataLeft;
u32DataLeft = 0;
}
// Build SCSI command.
vSCSICmd_READ_10(Mass_stor_us, Mass_stor_us->srb, LunDevice->u8LunNum,
u32BlockAddr + u32BlockOfSet, (INT16U)u32TransBlockTmp, u8Buffer + u32TransOfSet);
// call mass storage function to send scsi command
Host20_MSCD_usb_stor_control_thread(Mass_stor_us);
if(Mass_stor_us->srb->result != SAM_STAT_GOOD)
{
SCSI_DbgPrint("Scsi READ_10 command failed.%s","\n");
if(Mass_stor_us->srb != NULL)
free(Mass_stor_us->srb);
return FALSE;
}
u32BlockOfSet += u32TransBlockTmp;
u32TransOfSet += u32TransSizeTmp;
}
if(Mass_stor_us->srb != NULL)
free(Mass_stor_us->srb);
printk("#");
return TRUE;
#else
Mass_stor_us->srb = (struct scsi_cmnd *)malloc(sizeof(struct scsi_cmnd ));
memset(Mass_stor_us->srb, 0, sizeof(struct scsi_cmnd ));
// Build SCSI command.
vSCSICmd_READ_10(Mass_stor_us, Mass_stor_us->srb, LunDevice->u8LunNum,
u32BlockAddr, (INT16U)u32BlockNum, u8Buffer);
// call mass storage function to send scsi command
Host20_MSCD_usb_stor_control_thread(Mass_stor_us);
if(Mass_stor_us->srb->result != SAM_STAT_GOOD)
{
SCSI_DbgPrint("Scsi READ_10 command failed.%s","\n");
if(Mass_stor_us->srb != NULL)
free(Mass_stor_us->srb);
return FALSE;
}
if(Mass_stor_us->srb != NULL)
free(Mass_stor_us->srb);
printk("#");
return TRUE;
#endif
}
//***************************************************************************************
// Function Name:
// Description:
// Input:
// Output:
// Status:
//***************************************************************************************
BOOLEAN bSCSI_Write_10( struct LUN_Device* LunDevice, INT32U u32BlockAddr, INT32U u32BlockNum,
INT32U u32SectorSize, INT8U *u8Buffer)
{
#if 1
INT32U u32DataLeft = (Mass_stor_us->Mass_stor_device[LunDevice->u8LunNum].u32BlockSize)*u32BlockNum;
INT32U u32TransBlockTmp, u32TransSizeTmp,u32BlockOfSet = 0, u32TransOfSet = 0;
if(!Mass_stor_us->Mass_stor_device[u8Drive].bWriteProtect)
{
Mass_stor_us->srb = (struct scsi_cmnd *)malloc(sizeof(struct scsi_cmnd ));
memset(Mass_stor_us->srb, 0, sizeof(struct scsi_cmnd ));
while(u32DataLeft > 0)
{
if(u32DataLeft > Scsi_Max_Transfer_Len)
{
u32TransBlockTmp = Scsi_Max_Transfer_Len / Mass_stor_us->Mass_stor_device[LunDevice->u8LunNum].u32BlockSize;
u32TransSizeTmp = u32TransBlockTmp * Mass_stor_us->Mass_stor_device[LunDevice->u8LunNum].u32BlockSize;
u32DataLeft -= u32TransSizeTmp;
}
else
{
u32TransBlockTmp = u32DataLeft/Mass_stor_us->Mass_stor_device[LunDevice->u8LunNum].u32BlockSize;
u32TransSizeTmp = u32DataLeft;
u32DataLeft = 0;
}
// Build SCSI command.
vSCSICmd_WRITE_10(Mass_stor_us, Mass_stor_us->srb, LunDevice->u8LunNum,
u32BlockAddr + u32BlockOfSet, (INT16U)u32TransBlockTmp, u8Buffer + u32TransOfSet);
// call mass storage function to send scsi command
Host20_MSCD_usb_stor_control_thread(Mass_stor_us);
if(Mass_stor_us->srb->result != SAM_STAT_GOOD)
{
SCSI_DbgPrint("Scsi WRITE_10 command failed.%s","\n");
if(Mass_stor_us->srb != NULL)
free(Mass_stor_us->srb);
return FALSE;
}
u32BlockOfSet += u32TransBlockTmp;
u32TransOfSet += u32TransSizeTmp;
}
if(Mass_stor_us->srb != NULL)
free(Mass_stor_us->srb);
printk("*");
return TRUE;
}
else
{
printk("This device is write protect now\n");
return FALSE;
}
#else
if(!Mass_stor_us->Mass_stor_device[u8Drive].bWriteProtect)
{
Mass_stor_us->srb = (struct scsi_cmnd *)malloc(sizeof(struct scsi_cmnd ));
memset(Mass_stor_us->srb, 0, sizeof(struct scsi_cmnd ));
// Build SCSI command.
vSCSICmd_WRITE_10(Mass_stor_us, Mass_stor_us->srb, LunDevice->u8LunNum,
u32BlockAddr, (INT16U)u32BlockNum, u8Buffer);
// call mass storage function to send scsi command
Host20_MSCD_usb_stor_control_thread(Mass_stor_us);
if(Mass_stor_us->srb->result != SAM_STAT_GOOD)
{
SCSI_DbgPrint("Scsi WRITE_10 command failed.%s","\n");
if(Mass_stor_us->srb != NULL)
free(Mass_stor_us->srb);
return FALSE;
}
if(Mass_stor_us->srb != NULL)
free(Mass_stor_us->srb);
printk("*");
return TRUE;
}
else
{
printk("This device is write protect now\n");
return FALSE;
}
#endif
}
//***************************************************************************************
// Function Name:vScsi_SendCmd_Done
// Description:
// Input:
// Output:
// Status:
//***************************************************************************************
static void vScsi_SendCmd_Done(struct scsi_cmnd *srb)
{
SCSI_DbgPrint("Send SCSI command (0x%x) Done (LUN=%d), result = 0x%x\n", srb->cmnd[0],u8Drive, srb->result);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -