⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scsi.c

📁 基于ADSP-BF535 USB驱动应用程序
💻 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 + -