📄 scsi.c
字号:
/*----------------------------------------------------------------------------------
*
* COPYRIGHT (c) 2001 by Singing Electrons, Inc. All rights reserved.
*
*
* Module Name : C:\se\adi\msclass\vdsp\scsi.c
*
* Description : The SCSI implementation
*
*
* Revision History : At bottom of the file.
*
*---------------------------------------------------------------------------------*/
/** include files **/
#include <defBF535.h>
#include "dtype.h"
#include "register.h"
#include "scsi.h"
#include "dprintf.h"
#include "formatted_16MB.h"
//#include "formatted_8MB.h"
/** local definitions **/
#define SCSI_SENSE_DATA_VALID 0x80
#define SCSI_SENSE_DATA_CURRENT_ERROR 0x70
#define EndianSwap(someVal) \
(ULONG)(((someVal & 0xff000000) >> 24) | ((someVal & 0x00ff0000) >> 8) | ((someVal & 0x0000ff00) << 8) | ((someVal & 0x000000ff) << 24))
//Let's do a 2048 x 512 bytes device = 1 MB
#define MAX_BLOCKS (ULONG)32768
#define BLOCK_SIZE (ULONG)512
#define SCSI_INQUIRY_REPORT_SIZE 36
#define SCSI_READ_CAPACITY_REPORT_SIZE 8
#define SCSI_REQUEST_SENSE_REPORT_SIZE 18
#define SCSI_MODE_SENSE_REPORT_SIZE 0xc0
const UCHAR VID[] = "ADI\0";
const UCHAR PID[] = "MSClass\0";
const UCHAR REV[] = "1.0\0";
/* default settings */
/** external functions **/
/** external data **/
/** internal functions **/
/** public data **/
/** private data **/
UCHAR *gpDataBlock;
UCHAR gInquiryReport[SCSI_INQUIRY_REPORT_SIZE];
UCHAR gpDataSaveLocation;
UCHAR gReadCapacityReport[SCSI_READ_CAPACITY_REPORT_SIZE];
UCHAR gRequestSenseReport[SCSI_REQUEST_SENSE_REPORT_SIZE];
UCHAR gModeSenseReport[SCSI_MODE_SENSE_REPORT_SIZE];
ULONG gCurrentDataWriteLocation;
/** public functions **/
/** private functions **/
static void initExtL2SDRAM(void);
/*------------------------------------------------------------
* SCSI_Init
*
* Parameters:
* None.
*
* Globals Used:
* gpDataBlock, gInquiryReport, gReadCapacityReport,
*
*
* Description:
* Initializes SDRAM access, and also initializes other
* globals. It also initializes the data block to contain
* an initialized copy of a FAT formatted disk!
*
* Returns:
* Nothing.
*
*------------------------------------------------------------*/
void SCSI_Init (void)
{
initExtL2SDRAM ();
gpDataBlock = (PUCHAR)START_EXT_L2SDRAM;
memset (&gInquiryReport[0], 0, SCSI_INQUIRY_REPORT_SIZE);
memset (gpDataBlock, 0, MAX_BLOCKS * BLOCK_SIZE);
//The following will make this look like a FAT formatted disk
memcpy (gpDataBlock, &gInitialData[0], sizeof (gInitialData));
gInquiryReport[0] = SCSI_DEVICE_DIRECT_ACCESS; // Direct-access device
gInquiryReport[1] = 0x80; //Removable
// Vendor ID string
strcpy(&gInquiryReport[8], &VID[0]);
// Product ID string
strcpy(&gInquiryReport[16], &PID[0]);
// Rev string
strcpy(&gInquiryReport[32], &REV[0]);
*(PULONG)(&gReadCapacityReport[0]) = EndianSwap ((MAX_BLOCKS-1));
*(PULONG)(&gReadCapacityReport[4]) = EndianSwap (BLOCK_SIZE);
gCurrentDataWriteLocation = 0;
}
/*------------------------------------------------------------
* initExtL2SDRAM
*
* Parameters:
*
* Globals Used:
* None
*
* Description:
* Initializes the SDRAM registers for access to SDRAM
*
* Returns:
* nothing.
*
*------------------------------------------------------------*/
static void initExtL2SDRAM(void) {
// set up SDRAM registers
*(volatile USHORT *)EBIU_SDRRC = kSDRRC;
asm("ssync;");
*(volatile ULONG *)EBIU_SDBCTL = kSDBCTL;
asm("ssync;");
*(volatile ULONG *)EBIU_SDGCTL = kSDGCTL;
asm("ssync;");
}
/*------------------------------------------------------------
* IsValidCommandBlock
*
* Parameters:
* pCommandBlock - pointer to the CDB.
* len - length of the CDB
*
* Globals Used:
* gRequestSenseReport
*
* Description:
* Determines if the command data block received is
* vaild or not. Accordinly it updates the request sense data.
*
* Returns:
*
*
*------------------------------------------------------------*/
bool SCSI_IsValidCommandBlock (PUCHAR pCommandBlock, UCHAR len)
{
switch (pCommandBlock[0])
{
case SCSI_INQUIRY:
case SCSI_READ_CAPACITY:
case SCSI_READ10:
case SCSI_WRITE10:
case SCSI_REQUEST_SENSE:
case SCSI_MODE_SENSE6:
case SCSI_TEST_UNIT_READY:
case SCSI_START_STOP:
case SCSI_MEDIUM_REMOVAL:
case SCSI_VERIFY:
memset (&gRequestSenseReport[0], 0, SCSI_REQUEST_SENSE_REPORT_SIZE);
gRequestSenseReport[0] = SCSI_SENSE_DATA_VALID | SCSI_SENSE_DATA_CURRENT_ERROR;
gRequestSenseReport[2] = SENSE_NONE; //Sense key
return (true);
default:
memset (&gRequestSenseReport[0], 0, SCSI_REQUEST_SENSE_REPORT_SIZE);
gRequestSenseReport[0] = SCSI_SENSE_DATA_VALID | SCSI_SENSE_DATA_CURRENT_ERROR;
gRequestSenseReport[2] = SENSE_ILLEGAL_REQUEST; //Sense key
gRequestSenseReport[12] = ASC_INVALID_COMMAND;//Additional Sense Code
return(false);
}
}
/*------------------------------------------------------------
* SCSI_ProcessCDB
*
* Parameters:
*
* Globals Used:
* gModeSenseReport, gpDataBlock, gCurrentDataWriteLocation
* gInquiryReport, gReadCapacityReport, gRequestSenseReport
*
* Description:
* This routine processes the SCSI command data block received by
* the Mass storage protocol handler.
*
* Returns:
* True if the commnad was handled successfully, false otherwise.
*
*------------------------------------------------------------*/
bool SCSI_ProcessCDB (PUCHAR pCommandBlock, UCHAR len, ULONG datalen, void **ppBuffer, ULONG *pActualBytesToReturn)
{
//By default return the same number of bytes as requested
*pActualBytesToReturn = datalen;
switch (pCommandBlock[0])
{
case SCSI_INQUIRY:
if (datalen == sizeof (gInquiryReport))
{
*ppBuffer = &gInquiryReport;
return (true);
}
break;
case SCSI_READ_CAPACITY:
if (datalen == sizeof (gReadCapacityReport))
{
*ppBuffer = &gReadCapacityReport;
return (true);
}
break;
case SCSI_REQUEST_SENSE:
if (datalen == sizeof (gRequestSenseReport))
{
*ppBuffer = &gRequestSenseReport;
return (true);
}
break;
case SCSI_TEST_UNIT_READY:
return (true);
case SCSI_START_STOP:
return (true);
case SCSI_MEDIUM_REMOVAL:
return (true);
case SCSI_VERIFY:
return (true);
case SCSI_MODE_SENSE6:
Dprintf1 ("Mode Sense, Code Page: %02x", pCommandBlock[2]);
if (datalen >= 4)
{
memset (&gModeSenseReport[0], 0, SCSI_MODE_SENSE_REPORT_SIZE);
gModeSenseReport[0] = 4; // mode data length
gModeSenseReport[1] = 0; // medium type (current)
gModeSenseReport[2] = 0; // device-specific
gModeSenseReport[3] = 0; // block descriptor length
*ppBuffer = &gModeSenseReport;
*pActualBytesToReturn = 4;
return(true);
}
break;
case SCSI_READ10:
{
ULONG startingBlock, blocksToRead;
startingBlock = (pCommandBlock[2] << 24) + (pCommandBlock[3] << 16) + (pCommandBlock[4] << 8) + pCommandBlock[5];
blocksToRead = (pCommandBlock[7] << 8) + pCommandBlock[8];
Dprintf2 ("Read: offset: %04x, len: %04x", startingBlock, blocksToRead);
*ppBuffer = gpDataBlock + (startingBlock * BLOCK_SIZE);
return (true);
}
case SCSI_WRITE10:
{
ULONG startingBlock, blocksToWrite;
startingBlock = (pCommandBlock[2] << 24) + (pCommandBlock[3] << 16) + (pCommandBlock[4] << 8) + pCommandBlock[5];
blocksToWrite = (pCommandBlock[7] << 8) + pCommandBlock[8];
gCurrentDataWriteLocation = startingBlock * BLOCK_SIZE;
Dprintf2 ("Write: offset: %04x, len: %04x", startingBlock, blocksToWrite);
return (true);
}
}
memset (&gRequestSenseReport[0], 0, SCSI_REQUEST_SENSE_REPORT_SIZE);
gRequestSenseReport[0] = SCSI_SENSE_DATA_VALID | SCSI_SENSE_DATA_CURRENT_ERROR;
gRequestSenseReport[2] = SENSE_ILLEGAL_REQUEST; //Sense key
gRequestSenseReport[12] = ASC_INVALID_COMMAND;//Additional Sense Code
return(false);
}
/*------------------------------------------------------------
* SCSI_ProcessData
*
* Parameters:
* pBuffer -pointer to the data to process.
* len - total number of bytes to process.
*
* Globals Used:
* gpDataBlock, gCurrentDataWriteLocation
*
* Description:
* Processes data associated with a SCSI_WRITE operation.
*
* Returns:
* Nothing
*
*------------------------------------------------------------*/
void SCSI_ProcessData (void *pBuffer, ULONG len)
{
//Need to save the data, somewhere?
memcpy (gpDataBlock + gCurrentDataWriteLocation, pBuffer, len);
gCurrentDataWriteLocation += len;
}
/*----------------------------------------------------------------------------------
* $Log: scsi.c,v $
* Revision 1.3 2003/03/03 22:37:10 Devendra
* - Added documentation.
* - Some code cleanup.
*
* Revision 1.2 2003/03/03 21:26:41 Devendra
* - BugFix: Writes were not working correctly.
* - Changed to using the SDRAM for disk data storage.
* - Increased the disk capacity to 16MB.
* - Added disk init. routine to make it look like a FAT formatted 16MB disk.
*
* Revision 1.1 2003/03/03 18:13:47 Devendra
* First Rev, the device enumerates as Mass Storage Class
*
*
*---------------------------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -