EA BaseBoard, playing wav, PC see\'s SD-card through USB port.

Dependencies:   mbed

Committer:
Lerche
Date:
Tue Nov 22 05:45:58 2011 +0000
Revision:
0:fef366d2ed20
Thanks to those who provided EA_WavPlayer and USB_MSC

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Lerche 0:fef366d2ed20 1 /*
Lerche 0:fef366d2ed20 2 LPCUSB, an USB device driver for LPC microcontrollers
Lerche 0:fef366d2ed20 3 Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
Lerche 0:fef366d2ed20 4
Lerche 0:fef366d2ed20 5 Redistribution and use in source and binary forms, with or without
Lerche 0:fef366d2ed20 6 modification, are permitted provided that the following conditions are met:
Lerche 0:fef366d2ed20 7
Lerche 0:fef366d2ed20 8 1. Redistributions of source code must retain the above copyright
Lerche 0:fef366d2ed20 9 notice, this list of conditions and the following disclaimer.
Lerche 0:fef366d2ed20 10 2. Redistributions in binary form must reproduce the above copyright
Lerche 0:fef366d2ed20 11 notice, this list of conditions and the following disclaimer in the
Lerche 0:fef366d2ed20 12 documentation and/or other materials provided with the distribution.
Lerche 0:fef366d2ed20 13 3. The name of the author may not be used to endorse or promote products
Lerche 0:fef366d2ed20 14 derived from this software without specific prior written permission.
Lerche 0:fef366d2ed20 15
Lerche 0:fef366d2ed20 16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
Lerche 0:fef366d2ed20 17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
Lerche 0:fef366d2ed20 18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
Lerche 0:fef366d2ed20 19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
Lerche 0:fef366d2ed20 20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
Lerche 0:fef366d2ed20 21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Lerche 0:fef366d2ed20 22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Lerche 0:fef366d2ed20 23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Lerche 0:fef366d2ed20 24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
Lerche 0:fef366d2ed20 25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Lerche 0:fef366d2ed20 26 */
Lerche 0:fef366d2ed20 27
Lerche 0:fef366d2ed20 28 /**
Lerche 0:fef366d2ed20 29 @file
Lerche 0:fef366d2ed20 30
Lerche 0:fef366d2ed20 31 This is the SCSI layer of the USB mass storage application example.
Lerche 0:fef366d2ed20 32 This layer depends directly on the blockdev layer.
Lerche 0:fef366d2ed20 33
Lerche 0:fef366d2ed20 34 Windows peculiarities:
Lerche 0:fef366d2ed20 35 * Size of REQUEST SENSE CDB is 12 bytes instead of expected 6
Lerche 0:fef366d2ed20 36 * Windows requires VERIFY(10) command to do a format.
Lerche 0:fef366d2ed20 37 This command is not mandatory in the SBC/SBC-2 specification.
Lerche 0:fef366d2ed20 38 */
Lerche 0:fef366d2ed20 39 /*
Lerche 0:fef366d2ed20 40 * Modified for mbed NXP LPC1768 & LPCXpresso board
Lerche 0:fef366d2ed20 41 * original LPC214x USB stack beta by bertrik
Lerche 0:fef366d2ed20 42 * target-20070727.tar.gr (119.5KB)
Lerche 0:fef366d2ed20 43 * http://sourceforge.net/projects/lpcusb/
Lerche 0:fef366d2ed20 44 * By Kenji Arai / JH1PJL on September 25th, 2010
Lerche 0:fef366d2ed20 45 * October 3rd, 2010
Lerche 0:fef366d2ed20 46 */
Lerche 0:fef366d2ed20 47 #define FATFS
Lerche 0:fef366d2ed20 48
Lerche 0:fef366d2ed20 49 //#define DEBUG
Lerche 0:fef366d2ed20 50 #include "dbg.h"
Lerche 0:fef366d2ed20 51 #include "mbed.h"
Lerche 0:fef366d2ed20 52 #include <string.h> // memcpy
Lerche 0:fef366d2ed20 53
Lerche 0:fef366d2ed20 54 #include "blockdev.h"
Lerche 0:fef366d2ed20 55 #include "msc_scsi.h"
Lerche 0:fef366d2ed20 56
Lerche 0:fef366d2ed20 57 //#include "SDFileSystem.h"
Lerche 0:fef366d2ed20 58 //extern SDFileSystem sd;
Lerche 0:fef366d2ed20 59
Lerche 0:fef366d2ed20 60 #define BLOCKSIZE 512
Lerche 0:fef366d2ed20 61
Lerche 0:fef366d2ed20 62 // SBC2 mandatory SCSI commands
Lerche 0:fef366d2ed20 63 #define SCSI_CMD_TEST_UNIT_READY 0x00
Lerche 0:fef366d2ed20 64 #define SCSI_CMD_REQUEST_SENSE 0x03
Lerche 0:fef366d2ed20 65 #define SCSI_CMD_FORMAT_UNIT 0x04
Lerche 0:fef366d2ed20 66 #define SCSI_CMD_READ_6 0x08 /* not implemented yet */
Lerche 0:fef366d2ed20 67 #define SCSI_CMD_INQUIRY 0x12
Lerche 0:fef366d2ed20 68 #define SCSI_CMD_SEND_DIAGNOSTIC 0x1D /* not implemented yet */
Lerche 0:fef366d2ed20 69 #define SCSI_CMD_READ_CAPACITY_10 0x25
Lerche 0:fef366d2ed20 70 #define SCSI_CMD_READ_10 0x28
Lerche 0:fef366d2ed20 71 #define SCSI_CMD_REPORT_LUNS 0xA0 /* not implemented yet */
Lerche 0:fef366d2ed20 72
Lerche 0:fef366d2ed20 73 // SBC2 optional SCSI commands
Lerche 0:fef366d2ed20 74 #define SCSI_CMD_WRITE_6 0x0A /* not implemented yet */
Lerche 0:fef366d2ed20 75 #define SCSI_CMD_WRITE_10 0x2A
Lerche 0:fef366d2ed20 76 #define SCSI_CMD_VERIFY_10 0x2F /* required for windows format */
Lerche 0:fef366d2ed20 77
Lerche 0:fef366d2ed20 78 // sense codes
Lerche 0:fef366d2ed20 79 #define WRITE_ERROR 0x030C00
Lerche 0:fef366d2ed20 80 #define READ_ERROR 0x031100
Lerche 0:fef366d2ed20 81 #define INVALID_CMD_OPCODE 0x052000
Lerche 0:fef366d2ed20 82 #define INVALID_FIELD_IN_CDB 0x052400
Lerche 0:fef366d2ed20 83
Lerche 0:fef366d2ed20 84 // Sense code, which is set on error conditions
Lerche 0:fef366d2ed20 85 static uint32_t dwSense; // hex: 00aabbcc, where aa=KEY, bb=ASC, cc=ASCQ
Lerche 0:fef366d2ed20 86
Lerche 0:fef366d2ed20 87 static const uint8_t abInquiry[] = {
Lerche 0:fef366d2ed20 88 0x00, // PDT = direct-access device
Lerche 0:fef366d2ed20 89 0x80, // removeable medium bit = set
Lerche 0:fef366d2ed20 90 0x05, // version = complies to SPC3
Lerche 0:fef366d2ed20 91 0x02, // response data format = SPC3
Lerche 0:fef366d2ed20 92 0x1F, // additional length
Lerche 0:fef366d2ed20 93 0x00,
Lerche 0:fef366d2ed20 94 0x00,
Lerche 0:fef366d2ed20 95 0x00,
Lerche 0:fef366d2ed20 96 'L','P','C','U','S','B',' ',' ', // vendor
Lerche 0:fef366d2ed20 97 'M','a','s','s',' ','s','t','o', // product
Lerche 0:fef366d2ed20 98 'r','a','g','e',' ',' ',' ',' ',
Lerche 0:fef366d2ed20 99 '0','.','1',' ' // revision
Lerche 0:fef366d2ed20 100 };
Lerche 0:fef366d2ed20 101
Lerche 0:fef366d2ed20 102 // Data for "request sense" command. The 0xFF are filled in later
Lerche 0:fef366d2ed20 103 static const uint8_t abSense[] = { 0x70, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0A,
Lerche 0:fef366d2ed20 104 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00,
Lerche 0:fef366d2ed20 105 0x00, 0x00 };
Lerche 0:fef366d2ed20 106
Lerche 0:fef366d2ed20 107 // Buffer for holding one block of disk data
Lerche 0:fef366d2ed20 108 static uint8_t abBlockBuf[512];
Lerche 0:fef366d2ed20 109
Lerche 0:fef366d2ed20 110
Lerche 0:fef366d2ed20 111 struct TCDB6 {
Lerche 0:fef366d2ed20 112 uint8_t bOperationCode;
Lerche 0:fef366d2ed20 113 uint8_t abLBA[3];
Lerche 0:fef366d2ed20 114 uint8_t bLength;
Lerche 0:fef366d2ed20 115 uint8_t bControl;
Lerche 0:fef366d2ed20 116 } __attribute__((packed));
Lerche 0:fef366d2ed20 117
Lerche 0:fef366d2ed20 118
Lerche 0:fef366d2ed20 119 /*************************************************************************
Lerche 0:fef366d2ed20 120 SCSIReset
Lerche 0:fef366d2ed20 121 =========
Lerche 0:fef366d2ed20 122 Resets any SCSI state
Lerche 0:fef366d2ed20 123
Lerche 0:fef366d2ed20 124 **************************************************************************/
Lerche 0:fef366d2ed20 125 void SCSIReset(void)
Lerche 0:fef366d2ed20 126 {
Lerche 0:fef366d2ed20 127 dwSense = 0;
Lerche 0:fef366d2ed20 128 }
Lerche 0:fef366d2ed20 129
Lerche 0:fef366d2ed20 130
Lerche 0:fef366d2ed20 131 /*************************************************************************
Lerche 0:fef366d2ed20 132 SCSIHandleCmd
Lerche 0:fef366d2ed20 133 =============
Lerche 0:fef366d2ed20 134 Verifies a SCSI CDB and indicates the direction and amount of data
Lerche 0:fef366d2ed20 135 that the device wants to transfer.
Lerche 0:fef366d2ed20 136
Lerche 0:fef366d2ed20 137 If this call fails, a sense code is set in dwSense.
Lerche 0:fef366d2ed20 138
Lerche 0:fef366d2ed20 139 IN pbCDB Command data block
Lerche 0:fef366d2ed20 140 iCDBLen Command data block len
Lerche 0:fef366d2ed20 141 OUT *piRspLen Length of intended response data:
Lerche 0:fef366d2ed20 142 *pfDevIn true if data is transferred from device-to-host
Lerche 0:fef366d2ed20 143
Lerche 0:fef366d2ed20 144 Returns a pointer to the data exchange buffer if successful,
Lerche 0:fef366d2ed20 145 return NULL otherwise.
Lerche 0:fef366d2ed20 146 **************************************************************************/
Lerche 0:fef366d2ed20 147 uint8_t * SCSIHandleCmd(uint8_t *pbCDB, uint8_t iCDBLen, int *piRspLen, bool *pfDevIn)
Lerche 0:fef366d2ed20 148 {
Lerche 0:fef366d2ed20 149 static const uint8_t aiCDBLen[] = {6, 10, 10, 0, 16, 12, 0, 0};
Lerche 0:fef366d2ed20 150 int i;
Lerche 0:fef366d2ed20 151 TCDB6 *pCDB;
Lerche 0:fef366d2ed20 152 uint32_t dwLen, dwLBA;
Lerche 0:fef366d2ed20 153 uint8_t bGroupCode;
Lerche 0:fef366d2ed20 154
Lerche 0:fef366d2ed20 155 pCDB = (TCDB6 *)pbCDB;
Lerche 0:fef366d2ed20 156
Lerche 0:fef366d2ed20 157 // default direction is from device to host
Lerche 0:fef366d2ed20 158 *pfDevIn = true;
Lerche 0:fef366d2ed20 159
Lerche 0:fef366d2ed20 160 // check CDB length
Lerche 0:fef366d2ed20 161 bGroupCode = (pCDB->bOperationCode >> 5) & 0x7;
Lerche 0:fef366d2ed20 162 if (iCDBLen < aiCDBLen[bGroupCode]) {
Lerche 0:fef366d2ed20 163 DBG("Invalid CBD len (expected %d)!\n", aiCDBLen[bGroupCode]);
Lerche 0:fef366d2ed20 164 return NULL;
Lerche 0:fef366d2ed20 165 }
Lerche 0:fef366d2ed20 166
Lerche 0:fef366d2ed20 167 switch (pCDB->bOperationCode) {
Lerche 0:fef366d2ed20 168
Lerche 0:fef366d2ed20 169 // test unit ready (6)
Lerche 0:fef366d2ed20 170 case SCSI_CMD_TEST_UNIT_READY:
Lerche 0:fef366d2ed20 171 DBG("TEST UNIT READY\n");
Lerche 0:fef366d2ed20 172 *piRspLen = 0;
Lerche 0:fef366d2ed20 173 break;
Lerche 0:fef366d2ed20 174
Lerche 0:fef366d2ed20 175 // request sense (6)
Lerche 0:fef366d2ed20 176 case SCSI_CMD_REQUEST_SENSE:
Lerche 0:fef366d2ed20 177 DBG("REQUEST SENSE (%06X)\n", dwSense);
Lerche 0:fef366d2ed20 178 // check params
Lerche 0:fef366d2ed20 179 *piRspLen = MIN(18, pCDB->bLength);
Lerche 0:fef366d2ed20 180 break;
Lerche 0:fef366d2ed20 181
Lerche 0:fef366d2ed20 182 case SCSI_CMD_FORMAT_UNIT:
Lerche 0:fef366d2ed20 183 DBG("FORMAT UNIT %02X\n", pbCDB[1]);
Lerche 0:fef366d2ed20 184 *piRspLen = 0;
Lerche 0:fef366d2ed20 185 break;
Lerche 0:fef366d2ed20 186
Lerche 0:fef366d2ed20 187 // inquiry (6)
Lerche 0:fef366d2ed20 188 case SCSI_CMD_INQUIRY:
Lerche 0:fef366d2ed20 189 DBG("INQUIRY\n");
Lerche 0:fef366d2ed20 190 // see SPC3r23, 4.3.4.6
Lerche 0:fef366d2ed20 191 *piRspLen = MIN(36, pCDB->bLength);
Lerche 0:fef366d2ed20 192 break;
Lerche 0:fef366d2ed20 193
Lerche 0:fef366d2ed20 194 // read capacity (10)
Lerche 0:fef366d2ed20 195 case SCSI_CMD_READ_CAPACITY_10:
Lerche 0:fef366d2ed20 196 DBG("READ CAPACITY\n");
Lerche 0:fef366d2ed20 197 *piRspLen = 8;
Lerche 0:fef366d2ed20 198 break;
Lerche 0:fef366d2ed20 199
Lerche 0:fef366d2ed20 200 // read (10)
Lerche 0:fef366d2ed20 201 case SCSI_CMD_READ_10:
Lerche 0:fef366d2ed20 202 dwLBA = (pbCDB[2] << 24) | (pbCDB[3] << 16) | (pbCDB[4] << 8) | (pbCDB[5]);
Lerche 0:fef366d2ed20 203 dwLen = (pbCDB[7] << 8) | pbCDB[8];
Lerche 0:fef366d2ed20 204 DBG("READ10, LBA=%d, len=%d\n", dwLBA, dwLen);
Lerche 0:fef366d2ed20 205 *piRspLen = dwLen * BLOCKSIZE;
Lerche 0:fef366d2ed20 206 break;
Lerche 0:fef366d2ed20 207
Lerche 0:fef366d2ed20 208 // write (10)
Lerche 0:fef366d2ed20 209 case SCSI_CMD_WRITE_10:
Lerche 0:fef366d2ed20 210 dwLBA = (pbCDB[2] << 24) | (pbCDB[3] << 16) | (pbCDB[4] << 8) | (pbCDB[5]);
Lerche 0:fef366d2ed20 211 dwLen = (pbCDB[7] << 8) | pbCDB[8];
Lerche 0:fef366d2ed20 212 DBG("WRITE10, LBA=%d, len=%d\n", dwLBA, dwLen);
Lerche 0:fef366d2ed20 213 *piRspLen = dwLen * BLOCKSIZE;
Lerche 0:fef366d2ed20 214 *pfDevIn = false;
Lerche 0:fef366d2ed20 215 break;
Lerche 0:fef366d2ed20 216
Lerche 0:fef366d2ed20 217 case SCSI_CMD_VERIFY_10:
Lerche 0:fef366d2ed20 218 DBG("VERIFY10\n");
Lerche 0:fef366d2ed20 219 if ((pbCDB[1] & (1 << 1)) != 0) {
Lerche 0:fef366d2ed20 220 // we don't support BYTCHK
Lerche 0:fef366d2ed20 221 DBG("BYTCHK not supported\n");
Lerche 0:fef366d2ed20 222 return NULL;
Lerche 0:fef366d2ed20 223 }
Lerche 0:fef366d2ed20 224 *piRspLen = 0;
Lerche 0:fef366d2ed20 225 break;
Lerche 0:fef366d2ed20 226
Lerche 0:fef366d2ed20 227 default:
Lerche 0:fef366d2ed20 228 DBG("Unhandled SCSI: ");
Lerche 0:fef366d2ed20 229 for (i = 0; i < iCDBLen; i++) {
Lerche 0:fef366d2ed20 230 DBG(" %02X", pbCDB[i]);
Lerche 0:fef366d2ed20 231 }
Lerche 0:fef366d2ed20 232 DBG("\n");
Lerche 0:fef366d2ed20 233 // unsupported command
Lerche 0:fef366d2ed20 234 dwSense = INVALID_CMD_OPCODE;
Lerche 0:fef366d2ed20 235 *piRspLen = 0;
Lerche 0:fef366d2ed20 236 return NULL;
Lerche 0:fef366d2ed20 237 }
Lerche 0:fef366d2ed20 238
Lerche 0:fef366d2ed20 239
Lerche 0:fef366d2ed20 240 return abBlockBuf;
Lerche 0:fef366d2ed20 241 }
Lerche 0:fef366d2ed20 242
Lerche 0:fef366d2ed20 243
Lerche 0:fef366d2ed20 244 /*************************************************************************
Lerche 0:fef366d2ed20 245 SCSIHandleData
Lerche 0:fef366d2ed20 246 ==============
Lerche 0:fef366d2ed20 247 Handles a block of SCSI data.
Lerche 0:fef366d2ed20 248
Lerche 0:fef366d2ed20 249 IN pbCDB Command data block
Lerche 0:fef366d2ed20 250 iCDBLen Command data block len
Lerche 0:fef366d2ed20 251 IN/OUT pbData Data buffer
Lerche 0:fef366d2ed20 252 IN dwOffset Offset in data
Lerche 0:fef366d2ed20 253
Lerche 0:fef366d2ed20 254 Returns a pointer to the next data to be exchanged if successful,
Lerche 0:fef366d2ed20 255 returns NULL otherwise.
Lerche 0:fef366d2ed20 256 **************************************************************************/
Lerche 0:fef366d2ed20 257 uint8_t * SCSIHandleData(uint8_t *pbCDB, uint8_t iCDBLen, uint8_t *pbData, uint32_t dwOffset)
Lerche 0:fef366d2ed20 258 {
Lerche 0:fef366d2ed20 259 TCDB6 *pCDB;
Lerche 0:fef366d2ed20 260 uint32_t dwLBA;
Lerche 0:fef366d2ed20 261 uint32_t dwBufPos, dwBlockNr;
Lerche 0:fef366d2ed20 262 uint32_t dwDevSize, dwMaxBlock;
Lerche 0:fef366d2ed20 263
Lerche 0:fef366d2ed20 264 pCDB = (TCDB6 *)pbCDB;
Lerche 0:fef366d2ed20 265
Lerche 0:fef366d2ed20 266 switch (pCDB->bOperationCode) {
Lerche 0:fef366d2ed20 267
Lerche 0:fef366d2ed20 268 // test unit ready
Lerche 0:fef366d2ed20 269 case SCSI_CMD_TEST_UNIT_READY:
Lerche 0:fef366d2ed20 270 if (dwSense != 0) {
Lerche 0:fef366d2ed20 271 return NULL;
Lerche 0:fef366d2ed20 272 }
Lerche 0:fef366d2ed20 273 break;
Lerche 0:fef366d2ed20 274
Lerche 0:fef366d2ed20 275 // request sense
Lerche 0:fef366d2ed20 276 case SCSI_CMD_REQUEST_SENSE:
Lerche 0:fef366d2ed20 277 memcpy(pbData, abSense, 18);
Lerche 0:fef366d2ed20 278 // fill in KEY/ASC/ASCQ
Lerche 0:fef366d2ed20 279 pbData[2] = (dwSense >> 16) & 0xFF;
Lerche 0:fef366d2ed20 280 pbData[12] = (dwSense >> 8) & 0xFF;
Lerche 0:fef366d2ed20 281 pbData[13] = (dwSense >> 0) & 0xFF;
Lerche 0:fef366d2ed20 282 // reset sense data
Lerche 0:fef366d2ed20 283 dwSense = 0;
Lerche 0:fef366d2ed20 284 break;
Lerche 0:fef366d2ed20 285
Lerche 0:fef366d2ed20 286 case SCSI_CMD_FORMAT_UNIT:
Lerche 0:fef366d2ed20 287 // nothing to do, ignore this command
Lerche 0:fef366d2ed20 288 break;
Lerche 0:fef366d2ed20 289
Lerche 0:fef366d2ed20 290 // inquiry
Lerche 0:fef366d2ed20 291 case SCSI_CMD_INQUIRY:
Lerche 0:fef366d2ed20 292 memcpy(pbData, abInquiry, sizeof(abInquiry));
Lerche 0:fef366d2ed20 293 break;
Lerche 0:fef366d2ed20 294
Lerche 0:fef366d2ed20 295 // read capacity
Lerche 0:fef366d2ed20 296 case SCSI_CMD_READ_CAPACITY_10:
Lerche 0:fef366d2ed20 297 #ifdef FATFS
Lerche 0:fef366d2ed20 298 // get size of drive (bytes)
Lerche 0:fef366d2ed20 299 dwDevSize = BlockDevGetSize();
Lerche 0:fef366d2ed20 300 // dwDevSize = sd.disk_sectors() * 512;
Lerche 0:fef366d2ed20 301 #else
Lerche 0:fef366d2ed20 302 // get size of drive (bytes)
Lerche 0:fef366d2ed20 303 BlockDevGetSize(&dwDevSize);
Lerche 0:fef366d2ed20 304 #endif
Lerche 0:fef366d2ed20 305 // calculate highest LBA
Lerche 0:fef366d2ed20 306 dwMaxBlock = (dwDevSize - 1) / 512;
Lerche 0:fef366d2ed20 307
Lerche 0:fef366d2ed20 308 pbData[0] = (dwMaxBlock >> 24) & 0xFF;
Lerche 0:fef366d2ed20 309 pbData[1] = (dwMaxBlock >> 16) & 0xFF;
Lerche 0:fef366d2ed20 310 pbData[2] = (dwMaxBlock >> 8) & 0xFF;
Lerche 0:fef366d2ed20 311 pbData[3] = (dwMaxBlock >> 0) & 0xFF;
Lerche 0:fef366d2ed20 312 pbData[4] = (BLOCKSIZE >> 24) & 0xFF;
Lerche 0:fef366d2ed20 313 pbData[5] = (BLOCKSIZE >> 16) & 0xFF;
Lerche 0:fef366d2ed20 314 pbData[6] = (BLOCKSIZE >> 8) & 0xFF;
Lerche 0:fef366d2ed20 315 pbData[7] = (BLOCKSIZE >> 0) & 0xFF;
Lerche 0:fef366d2ed20 316 break;
Lerche 0:fef366d2ed20 317
Lerche 0:fef366d2ed20 318 // read10
Lerche 0:fef366d2ed20 319 case SCSI_CMD_READ_10:
Lerche 0:fef366d2ed20 320 dwLBA = (pbCDB[2] << 24) | (pbCDB[3] << 16) | (pbCDB[4] << 8) | (pbCDB[5]);
Lerche 0:fef366d2ed20 321
Lerche 0:fef366d2ed20 322 // copy data from block buffer
Lerche 0:fef366d2ed20 323 dwBufPos = (dwOffset & (BLOCKSIZE - 1));
Lerche 0:fef366d2ed20 324 if (dwBufPos == 0) {
Lerche 0:fef366d2ed20 325 // read new block
Lerche 0:fef366d2ed20 326 dwBlockNr = dwLBA + (dwOffset / BLOCKSIZE);
Lerche 0:fef366d2ed20 327 DBG("R");
Lerche 0:fef366d2ed20 328 if (BlockDevRead(dwBlockNr, abBlockBuf)) {
Lerche 0:fef366d2ed20 329 // if (sd.disk_read((char*)abBlockBuf, dwBlockNr)) {
Lerche 0:fef366d2ed20 330 dwSense = READ_ERROR;
Lerche 0:fef366d2ed20 331 DBG("BlockDevRead failed\n");
Lerche 0:fef366d2ed20 332 return NULL;
Lerche 0:fef366d2ed20 333 }
Lerche 0:fef366d2ed20 334 }
Lerche 0:fef366d2ed20 335 // return pointer to data
Lerche 0:fef366d2ed20 336 return abBlockBuf + dwBufPos;
Lerche 0:fef366d2ed20 337
Lerche 0:fef366d2ed20 338 // write10
Lerche 0:fef366d2ed20 339 case SCSI_CMD_WRITE_10:
Lerche 0:fef366d2ed20 340 dwLBA = (pbCDB[2] << 24) | (pbCDB[3] << 16) | (pbCDB[4] << 8) | (pbCDB[5]);
Lerche 0:fef366d2ed20 341
Lerche 0:fef366d2ed20 342 // copy data to block buffer
Lerche 0:fef366d2ed20 343 dwBufPos = ((dwOffset + 64) & (BLOCKSIZE - 1));
Lerche 0:fef366d2ed20 344 if (dwBufPos == 0) {
Lerche 0:fef366d2ed20 345 // write new block
Lerche 0:fef366d2ed20 346 dwBlockNr = dwLBA + (dwOffset / BLOCKSIZE);
Lerche 0:fef366d2ed20 347 DBG("W");
Lerche 0:fef366d2ed20 348 if (BlockDevWrite(dwBlockNr, abBlockBuf)) {
Lerche 0:fef366d2ed20 349 // if (sd.disk_write((char*)abBlockBuf, dwBlockNr)) {
Lerche 0:fef366d2ed20 350 dwSense = WRITE_ERROR;
Lerche 0:fef366d2ed20 351 DBG("BlockDevWrite failed\n");
Lerche 0:fef366d2ed20 352 return NULL;
Lerche 0:fef366d2ed20 353 }
Lerche 0:fef366d2ed20 354 }
Lerche 0:fef366d2ed20 355 // return pointer to next data
Lerche 0:fef366d2ed20 356 return abBlockBuf + dwBufPos;
Lerche 0:fef366d2ed20 357
Lerche 0:fef366d2ed20 358 case SCSI_CMD_VERIFY_10:
Lerche 0:fef366d2ed20 359 // dummy implementation
Lerche 0:fef366d2ed20 360 break;
Lerche 0:fef366d2ed20 361
Lerche 0:fef366d2ed20 362 default:
Lerche 0:fef366d2ed20 363 // unsupported command
Lerche 0:fef366d2ed20 364 dwSense = INVALID_CMD_OPCODE;
Lerche 0:fef366d2ed20 365 return NULL;
Lerche 0:fef366d2ed20 366 }
Lerche 0:fef366d2ed20 367
Lerche 0:fef366d2ed20 368 // default: return pointer to start of block buffer
Lerche 0:fef366d2ed20 369 return abBlockBuf;
Lerche 0:fef366d2ed20 370 }