/*
LUFA Library
Copyright (C) Dean Camera, 2010.
-
+
dean [at] fourwalledcubicle [dot] com
- www.fourwalledcubicle.com
+ www.lufa-lib.org
*/
/*
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
- Permission to use, copy, modify, distribute, and sell this
+ Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
- without fee, provided that the above copyright notice appear in
+ without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
- permission notice and warranty disclaimer appear in supporting
- documentation, and that the name of the author not be used in
- advertising or publicity pertaining to distribution of the
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaim all warranties with regard to this
* devices use a thin "Bulk-Only Transport" protocol for issuing commands and status information,
* which wrap around standard SCSI device commands for controlling the actual storage medium.
*/
-
+
#define INCLUDE_FROM_SCSI_C
#include "SCSI.h"
/** Structure to hold the SCSI response data to a SCSI INQUIRY command. This gives information about the device's
* features and capabilities.
*/
-SCSI_Inquiry_Response_t InquiryData =
+SCSI_Inquiry_Response_t InquiryData =
{
.DeviceType = DEVICE_TYPE_BLOCK,
.PeripheralQualifier = 0,
-
+
.Removable = true,
-
+
.Version = 0,
-
+
.ResponseDataFormat = 2,
.NormACA = false,
.TrmTsk = false,
.AERC = false,
.AdditionalLength = 0x1F,
-
+
.SoftReset = false,
.CmdQue = false,
.Linked = false,
.WideBus16Bit = false,
.WideBus32Bit = false,
.RelAddr = false,
-
+
.VendorID = "LUFA",
.ProductID = "Dataflash Disk",
.RevisionID = {'0','.','0','0'},
switch (MSInterfaceInfo->State.CommandBlock.SCSICommandData[0])
{
case SCSI_CMD_INQUIRY:
- CommandSuccess = SCSI_Command_Inquiry(MSInterfaceInfo);
+ CommandSuccess = SCSI_Command_Inquiry(MSInterfaceInfo);
break;
case SCSI_CMD_REQUEST_SENSE:
CommandSuccess = SCSI_Command_Request_Sense(MSInterfaceInfo);
break;
case SCSI_CMD_READ_CAPACITY_10:
- CommandSuccess = SCSI_Command_Read_Capacity_10(MSInterfaceInfo);
+ CommandSuccess = SCSI_Command_Read_Capacity_10(MSInterfaceInfo);
break;
case SCSI_CMD_SEND_DIAGNOSTIC:
CommandSuccess = SCSI_Command_Send_Diagnostic(MSInterfaceInfo);
SCSI_SET_SENSE(SCSI_SENSE_KEY_GOOD,
SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,
SCSI_ASENSEQ_NO_QUALIFIER);
-
+
return true;
}
return false;
}
-
+
Endpoint_Write_Stream_LE(&InquiryData, BytesTransferred, NO_STREAM_CALLBACK);
uint8_t PadBytes[AllocationLength - BytesTransferred];
-
+
/* Pad out remaining bytes with 0x00 */
Endpoint_Write_Stream_LE(&PadBytes, sizeof(PadBytes), NO_STREAM_CALLBACK);
/* Succeed the command and update the bytes transferred counter */
MSInterfaceInfo->State.CommandBlock.DataTransferLength -= BytesTransferred;
-
+
return true;
}
{
uint8_t AllocationLength = MSInterfaceInfo->State.CommandBlock.SCSICommandData[4];
uint8_t BytesTransferred = (AllocationLength < sizeof(SenseData))? AllocationLength : sizeof(SenseData);
-
+
uint8_t PadBytes[AllocationLength - BytesTransferred];
Endpoint_Write_Stream_LE(&SenseData, BytesTransferred, NO_STREAM_CALLBACK);
Endpoint_Write_Stream_BE(&LastBlockAddressInLUN, sizeof(LastBlockAddressInLUN), NO_STREAM_CALLBACK);
Endpoint_Write_Stream_BE(&MediaBlockSize, sizeof(MediaBlockSize), NO_STREAM_CALLBACK);
Endpoint_ClearIN();
-
+
/* Succeed the command and update the bytes transferred counter */
MSInterfaceInfo->State.CommandBlock.DataTransferLength -= 8;
-
+
return true;
}
return false;
}
-
+
/* Check to see if all attached Dataflash ICs are functional */
if (!(DataflashManager_CheckDataflashOperation()))
{
/* Update SENSE key with a hardware error condition and return command fail */
SCSI_SET_SENSE(SCSI_SENSE_KEY_HARDWARE_ERROR,
SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,
- SCSI_ASENSEQ_NO_QUALIFIER);
-
+ SCSI_ASENSEQ_NO_QUALIFIER);
+
return false;
}
-
+
/* Succeed the command and update the bytes transferred counter */
MSInterfaceInfo->State.CommandBlock.DataTransferLength = 0;
-
+
return true;
}
{
uint32_t BlockAddress;
uint16_t TotalBlocks;
-
+
/* Load in the 32-bit block address (SCSI uses big-endian, so have to reverse the byte order) */
BlockAddress = SwapEndian_32(*(uint32_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[2]);
/* Load in the 16-bit total blocks (SCSI uses big-endian, so have to reverse the byte order) */
TotalBlocks = SwapEndian_16(*(uint16_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[7]);
-
+
/* Check if the block address is outside the maximum allowable value for the LUN */
if (BlockAddress >= VIRTUAL_MEMORY_BLOCKS)
{
return false;
}
-
+
/* Determine if the packet is a READ (10) or WRITE (10) command, call appropriate function */
if (IsDataRead == DATA_READ)
DataflashManager_ReadBlocks(MSInterfaceInfo, BlockAddress, TotalBlocks);
/* Update the bytes transferred counter and succeed the command */
MSInterfaceInfo->State.CommandBlock.DataTransferLength -= ((uint32_t)TotalBlocks * VIRTUAL_MEMORY_BLOCK_SIZE);
-
+
return true;
}
#endif
+