Writing data to and from a USB stick

Dependencies:   mbed

Committer:
ms523
Date:
Sun Nov 06 15:45:12 2011 +0000
Revision:
0:5934350323b2
Working with a USB stick

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ms523 0:5934350323b2 1 /*
ms523 0:5934350323b2 2 **************************************************************************************************************
ms523 0:5934350323b2 3 * NXP USB Host Stack
ms523 0:5934350323b2 4 *
ms523 0:5934350323b2 5 * (c) Copyright 2008, NXP SemiConductors
ms523 0:5934350323b2 6 * (c) Copyright 2008, OnChip Technologies LLC
ms523 0:5934350323b2 7 * All Rights Reserved
ms523 0:5934350323b2 8 *
ms523 0:5934350323b2 9 * www.nxp.com
ms523 0:5934350323b2 10 * www.onchiptech.com
ms523 0:5934350323b2 11 *
ms523 0:5934350323b2 12 * File : usbhost_ms.c
ms523 0:5934350323b2 13 * Programmer(s) : Ravikanth.P
ms523 0:5934350323b2 14 * Version :
ms523 0:5934350323b2 15 *
ms523 0:5934350323b2 16 **************************************************************************************************************
ms523 0:5934350323b2 17 */
ms523 0:5934350323b2 18
ms523 0:5934350323b2 19 /*
ms523 0:5934350323b2 20 **************************************************************************************************************
ms523 0:5934350323b2 21 * INCLUDE HEADER FILES
ms523 0:5934350323b2 22 **************************************************************************************************************
ms523 0:5934350323b2 23 */
ms523 0:5934350323b2 24
ms523 0:5934350323b2 25 #include "usbhost_ms.h"
ms523 0:5934350323b2 26
ms523 0:5934350323b2 27 /*
ms523 0:5934350323b2 28 **************************************************************************************************************
ms523 0:5934350323b2 29 * GLOBAL VARIABLES
ms523 0:5934350323b2 30 **************************************************************************************************************
ms523 0:5934350323b2 31 */
ms523 0:5934350323b2 32
ms523 0:5934350323b2 33 USB_INT32U MS_BlkSize;
ms523 0:5934350323b2 34
ms523 0:5934350323b2 35 /*
ms523 0:5934350323b2 36 **************************************************************************************************************
ms523 0:5934350323b2 37 * INITIALIZE MASS STORAGE INTERFACE
ms523 0:5934350323b2 38 *
ms523 0:5934350323b2 39 * Description: This function initializes the mass storage interface
ms523 0:5934350323b2 40 *
ms523 0:5934350323b2 41 * Arguments : None
ms523 0:5934350323b2 42 *
ms523 0:5934350323b2 43 * Returns : OK if Success
ms523 0:5934350323b2 44 * ERR_INVALID_BOOTSIG if Failed
ms523 0:5934350323b2 45 *
ms523 0:5934350323b2 46 **************************************************************************************************************
ms523 0:5934350323b2 47 */
ms523 0:5934350323b2 48
ms523 0:5934350323b2 49 USB_INT32S MS_Init (USB_INT32U *blkSize, USB_INT32U *numBlks, USB_INT08U *inquiryResult)
ms523 0:5934350323b2 50 {
ms523 0:5934350323b2 51 USB_INT08U retry;
ms523 0:5934350323b2 52 USB_INT32S rc;
ms523 0:5934350323b2 53
ms523 0:5934350323b2 54 MS_GetMaxLUN(); /* Get maximum logical unit number */
ms523 0:5934350323b2 55 retry = 80;
ms523 0:5934350323b2 56 while(retry) {
ms523 0:5934350323b2 57 rc = MS_TestUnitReady(); /* Test whether the unit is ready */
ms523 0:5934350323b2 58 if (rc == OK) {
ms523 0:5934350323b2 59 break;
ms523 0:5934350323b2 60 }
ms523 0:5934350323b2 61 MS_GetSenseInfo(); /* Get sense information */
ms523 0:5934350323b2 62 retry--;
ms523 0:5934350323b2 63 }
ms523 0:5934350323b2 64 if (rc != OK) {
ms523 0:5934350323b2 65 PRINT_Err(rc);
ms523 0:5934350323b2 66 return (rc);
ms523 0:5934350323b2 67 }
ms523 0:5934350323b2 68 rc = MS_ReadCapacity(numBlks, blkSize); /* Read capacity of the disk */
ms523 0:5934350323b2 69 MS_BlkSize = *blkSize; // Set global
ms523 0:5934350323b2 70 rc = MS_Inquire (inquiryResult);
ms523 0:5934350323b2 71 return (rc);
ms523 0:5934350323b2 72 }
ms523 0:5934350323b2 73 /*
ms523 0:5934350323b2 74 **************************************************************************************************************
ms523 0:5934350323b2 75 * PARSE THE CONFIGURATION
ms523 0:5934350323b2 76 *
ms523 0:5934350323b2 77 * Description: This function is used to parse the configuration
ms523 0:5934350323b2 78 *
ms523 0:5934350323b2 79 * Arguments : None
ms523 0:5934350323b2 80 *
ms523 0:5934350323b2 81 * Returns : OK if Success
ms523 0:5934350323b2 82 * ERR_INVALID_BOOTSIG if Failed
ms523 0:5934350323b2 83 *
ms523 0:5934350323b2 84 **************************************************************************************************************
ms523 0:5934350323b2 85 */
ms523 0:5934350323b2 86
ms523 0:5934350323b2 87 USB_INT32S MS_ParseConfiguration (void)
ms523 0:5934350323b2 88 {
ms523 0:5934350323b2 89 volatile USB_INT08U *desc_ptr;
ms523 0:5934350323b2 90 USB_INT08U ms_int_found;
ms523 0:5934350323b2 91
ms523 0:5934350323b2 92
ms523 0:5934350323b2 93 desc_ptr = TDBuffer;
ms523 0:5934350323b2 94 ms_int_found = 0;
ms523 0:5934350323b2 95
ms523 0:5934350323b2 96 if (desc_ptr[1] != USB_DESCRIPTOR_TYPE_CONFIGURATION) {
ms523 0:5934350323b2 97 return (ERR_BAD_CONFIGURATION);
ms523 0:5934350323b2 98 }
ms523 0:5934350323b2 99 desc_ptr += desc_ptr[0];
ms523 0:5934350323b2 100
ms523 0:5934350323b2 101 while (desc_ptr != TDBuffer + ReadLE16U(&TDBuffer[2])) {
ms523 0:5934350323b2 102
ms523 0:5934350323b2 103 switch (desc_ptr[1]) {
ms523 0:5934350323b2 104
ms523 0:5934350323b2 105 case USB_DESCRIPTOR_TYPE_INTERFACE: /* If it is an interface descriptor */
ms523 0:5934350323b2 106 if (desc_ptr[5] == MASS_STORAGE_CLASS && /* check if the class is mass storage */
ms523 0:5934350323b2 107 desc_ptr[6] == MASS_STORAGE_SUBCLASS_SCSI && /* check if the subclass is SCSI */
ms523 0:5934350323b2 108 desc_ptr[7] == MASS_STORAGE_PROTOCOL_BO) { /* check if the protocol is Bulk only */
ms523 0:5934350323b2 109 ms_int_found = 1;
ms523 0:5934350323b2 110 desc_ptr += desc_ptr[0]; /* Move to next descriptor start */
ms523 0:5934350323b2 111 }
ms523 0:5934350323b2 112 break;
ms523 0:5934350323b2 113
ms523 0:5934350323b2 114 case USB_DESCRIPTOR_TYPE_ENDPOINT: /* If it is an endpoint descriptor */
ms523 0:5934350323b2 115 if ((desc_ptr[3] & 0x03) == 0x02) { /* If it is Bulk endpoint */
ms523 0:5934350323b2 116 if (desc_ptr[2] & 0x80) { /* If it is In endpoint */
ms523 0:5934350323b2 117 EDBulkIn->Control = 1 | /* USB address */
ms523 0:5934350323b2 118 ((desc_ptr[2] & 0x7F) << 7) | /* Endpoint address */
ms523 0:5934350323b2 119 (2 << 11) | /* direction */
ms523 0:5934350323b2 120 (ReadLE16U(&desc_ptr[4]) << 16); /* MaxPkt Size */
ms523 0:5934350323b2 121 desc_ptr += desc_ptr[0]; /* Move to next descriptor start */
ms523 0:5934350323b2 122 } else { /* If it is Out endpoint */
ms523 0:5934350323b2 123 EDBulkOut->Control = 1 | /* USB address */
ms523 0:5934350323b2 124 ((desc_ptr[2] & 0x7F) << 7) | /* Endpoint address */
ms523 0:5934350323b2 125 (1 << 11) | /* direction */
ms523 0:5934350323b2 126 (ReadLE16U(&desc_ptr[4]) << 16); /* MaxPkt Size */
ms523 0:5934350323b2 127 desc_ptr += desc_ptr[0]; /* Move to next descriptor start */
ms523 0:5934350323b2 128 }
ms523 0:5934350323b2 129 } else { /* If it is not bulk end point */
ms523 0:5934350323b2 130 desc_ptr += desc_ptr[0]; /* Move to next descriptor start */
ms523 0:5934350323b2 131 }
ms523 0:5934350323b2 132 break;
ms523 0:5934350323b2 133
ms523 0:5934350323b2 134 default: /* If the descriptor is neither interface nor endpoint */
ms523 0:5934350323b2 135 desc_ptr += desc_ptr[0]; /* Move to next descriptor start */
ms523 0:5934350323b2 136 break;
ms523 0:5934350323b2 137 }
ms523 0:5934350323b2 138 }
ms523 0:5934350323b2 139 if (ms_int_found) {
ms523 0:5934350323b2 140 PRINT_Log("Mass Storage device connected\n");
ms523 0:5934350323b2 141 return (OK);
ms523 0:5934350323b2 142 } else {
ms523 0:5934350323b2 143 PRINT_Log("Not a Mass Storage device\n");
ms523 0:5934350323b2 144 return (ERR_NO_MS_INTERFACE);
ms523 0:5934350323b2 145 }
ms523 0:5934350323b2 146 }
ms523 0:5934350323b2 147
ms523 0:5934350323b2 148 /*
ms523 0:5934350323b2 149 **************************************************************************************************************
ms523 0:5934350323b2 150 * GET MAXIMUM LOGICAL UNIT
ms523 0:5934350323b2 151 *
ms523 0:5934350323b2 152 * Description: This function returns the maximum logical unit from the device
ms523 0:5934350323b2 153 *
ms523 0:5934350323b2 154 * Arguments : None
ms523 0:5934350323b2 155 *
ms523 0:5934350323b2 156 * Returns : OK if Success
ms523 0:5934350323b2 157 * ERR_INVALID_BOOTSIG if Failed
ms523 0:5934350323b2 158 *
ms523 0:5934350323b2 159 **************************************************************************************************************
ms523 0:5934350323b2 160 */
ms523 0:5934350323b2 161
ms523 0:5934350323b2 162 USB_INT32S MS_GetMaxLUN (void)
ms523 0:5934350323b2 163 {
ms523 0:5934350323b2 164 USB_INT32S rc;
ms523 0:5934350323b2 165
ms523 0:5934350323b2 166
ms523 0:5934350323b2 167 rc = Host_CtrlRecv(USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE,
ms523 0:5934350323b2 168 MS_GET_MAX_LUN_REQ,
ms523 0:5934350323b2 169 0,
ms523 0:5934350323b2 170 0,
ms523 0:5934350323b2 171 1,
ms523 0:5934350323b2 172 TDBuffer);
ms523 0:5934350323b2 173 return (rc);
ms523 0:5934350323b2 174 }
ms523 0:5934350323b2 175
ms523 0:5934350323b2 176 /*
ms523 0:5934350323b2 177 **************************************************************************************************************
ms523 0:5934350323b2 178 * GET SENSE INFORMATION
ms523 0:5934350323b2 179 *
ms523 0:5934350323b2 180 * Description: This function is used to get sense information from the device
ms523 0:5934350323b2 181 *
ms523 0:5934350323b2 182 * Arguments : None
ms523 0:5934350323b2 183 *
ms523 0:5934350323b2 184 * Returns : OK if Success
ms523 0:5934350323b2 185 * ERROR if Failed
ms523 0:5934350323b2 186 *
ms523 0:5934350323b2 187 **************************************************************************************************************
ms523 0:5934350323b2 188 */
ms523 0:5934350323b2 189
ms523 0:5934350323b2 190 USB_INT32S MS_GetSenseInfo (void)
ms523 0:5934350323b2 191 {
ms523 0:5934350323b2 192 USB_INT32S rc;
ms523 0:5934350323b2 193
ms523 0:5934350323b2 194
ms523 0:5934350323b2 195 Fill_MSCommand(0, 0, 0, MS_DATA_DIR_IN, SCSI_CMD_REQUEST_SENSE, 6);
ms523 0:5934350323b2 196 rc = Host_ProcessTD(EDBulkOut, TD_OUT, TDBuffer, CBW_SIZE);
ms523 0:5934350323b2 197 if (rc == OK) {
ms523 0:5934350323b2 198 rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, 18);
ms523 0:5934350323b2 199 if (rc == OK) {
ms523 0:5934350323b2 200 rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, CSW_SIZE);
ms523 0:5934350323b2 201 if (rc == OK) {
ms523 0:5934350323b2 202 if (TDBuffer[12] != 0) {
ms523 0:5934350323b2 203 rc = ERR_MS_CMD_FAILED;
ms523 0:5934350323b2 204 }
ms523 0:5934350323b2 205 }
ms523 0:5934350323b2 206 }
ms523 0:5934350323b2 207 }
ms523 0:5934350323b2 208 return (rc);
ms523 0:5934350323b2 209 }
ms523 0:5934350323b2 210
ms523 0:5934350323b2 211 /*
ms523 0:5934350323b2 212 **************************************************************************************************************
ms523 0:5934350323b2 213 * TEST UNIT READY
ms523 0:5934350323b2 214 *
ms523 0:5934350323b2 215 * Description: This function is used to test whether the unit is ready or not
ms523 0:5934350323b2 216 *
ms523 0:5934350323b2 217 * Arguments : None
ms523 0:5934350323b2 218 *
ms523 0:5934350323b2 219 * Returns : OK if Success
ms523 0:5934350323b2 220 * ERROR if Failed
ms523 0:5934350323b2 221 *
ms523 0:5934350323b2 222 **************************************************************************************************************
ms523 0:5934350323b2 223 */
ms523 0:5934350323b2 224
ms523 0:5934350323b2 225 USB_INT32S MS_TestUnitReady (void)
ms523 0:5934350323b2 226 {
ms523 0:5934350323b2 227 USB_INT32S rc;
ms523 0:5934350323b2 228
ms523 0:5934350323b2 229
ms523 0:5934350323b2 230 Fill_MSCommand(0, 0, 0, MS_DATA_DIR_NONE, SCSI_CMD_TEST_UNIT_READY, 6);
ms523 0:5934350323b2 231 rc = Host_ProcessTD(EDBulkOut, TD_OUT, TDBuffer, CBW_SIZE);
ms523 0:5934350323b2 232 if (rc == OK) {
ms523 0:5934350323b2 233 rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, CSW_SIZE);
ms523 0:5934350323b2 234 if (rc == OK) {
ms523 0:5934350323b2 235 if (TDBuffer[12] != 0) {
ms523 0:5934350323b2 236 rc = ERR_MS_CMD_FAILED;
ms523 0:5934350323b2 237 }
ms523 0:5934350323b2 238 }
ms523 0:5934350323b2 239 }
ms523 0:5934350323b2 240 return (rc);
ms523 0:5934350323b2 241 }
ms523 0:5934350323b2 242
ms523 0:5934350323b2 243 /*
ms523 0:5934350323b2 244 **************************************************************************************************************
ms523 0:5934350323b2 245 * READ CAPACITY
ms523 0:5934350323b2 246 *
ms523 0:5934350323b2 247 * Description: This function is used to read the capacity of the mass storage device
ms523 0:5934350323b2 248 *
ms523 0:5934350323b2 249 * Arguments : None
ms523 0:5934350323b2 250 *
ms523 0:5934350323b2 251 * Returns : OK if Success
ms523 0:5934350323b2 252 * ERROR if Failed
ms523 0:5934350323b2 253 *
ms523 0:5934350323b2 254 **************************************************************************************************************
ms523 0:5934350323b2 255 */
ms523 0:5934350323b2 256
ms523 0:5934350323b2 257 USB_INT32S MS_ReadCapacity (USB_INT32U *numBlks, USB_INT32U *blkSize)
ms523 0:5934350323b2 258 {
ms523 0:5934350323b2 259 USB_INT32S rc;
ms523 0:5934350323b2 260
ms523 0:5934350323b2 261
ms523 0:5934350323b2 262 Fill_MSCommand(0, 0, 0, MS_DATA_DIR_IN, SCSI_CMD_READ_CAPACITY, 10);
ms523 0:5934350323b2 263 rc = Host_ProcessTD(EDBulkOut, TD_OUT, TDBuffer, CBW_SIZE);
ms523 0:5934350323b2 264 if (rc == OK) {
ms523 0:5934350323b2 265 rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, 8);
ms523 0:5934350323b2 266 if (rc == OK) {
ms523 0:5934350323b2 267 if (numBlks)
ms523 0:5934350323b2 268 *numBlks = ReadBE32U(&TDBuffer[0]);
ms523 0:5934350323b2 269 if (blkSize)
ms523 0:5934350323b2 270 *blkSize = ReadBE32U(&TDBuffer[4]);
ms523 0:5934350323b2 271 rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, CSW_SIZE);
ms523 0:5934350323b2 272 if (rc == OK) {
ms523 0:5934350323b2 273 if (TDBuffer[12] != 0) {
ms523 0:5934350323b2 274 rc = ERR_MS_CMD_FAILED;
ms523 0:5934350323b2 275 }
ms523 0:5934350323b2 276 }
ms523 0:5934350323b2 277 }
ms523 0:5934350323b2 278 }
ms523 0:5934350323b2 279 return (rc);
ms523 0:5934350323b2 280 }
ms523 0:5934350323b2 281
ms523 0:5934350323b2 282
ms523 0:5934350323b2 283
ms523 0:5934350323b2 284 USB_INT32S MS_Inquire (USB_INT08U *response)
ms523 0:5934350323b2 285 {
ms523 0:5934350323b2 286 USB_INT32S rc;
ms523 0:5934350323b2 287 USB_INT32U i;
ms523 0:5934350323b2 288
ms523 0:5934350323b2 289 Fill_MSCommand(0, 0, 0, MS_DATA_DIR_IN, SCSI_CMD_INQUIRY, 6);
ms523 0:5934350323b2 290 rc = Host_ProcessTD(EDBulkOut, TD_OUT, TDBuffer, CBW_SIZE);
ms523 0:5934350323b2 291 if (rc == OK) {
ms523 0:5934350323b2 292 rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, INQUIRY_LENGTH);
ms523 0:5934350323b2 293 if (rc == OK) {
ms523 0:5934350323b2 294 if (response) {
ms523 0:5934350323b2 295 for ( i = 0; i < INQUIRY_LENGTH; i++ )
ms523 0:5934350323b2 296 *response++ = *TDBuffer++;
ms523 0:5934350323b2 297 #if 0
ms523 0:5934350323b2 298 MemCpy (response, TDBuffer, INQUIRY_LENGTH);
ms523 0:5934350323b2 299 StrNullTrailingSpace (response->vendorID, SCSI_INQUIRY_VENDORCHARS);
ms523 0:5934350323b2 300 StrNullTrailingSpace (response->productID, SCSI_INQUIRY_PRODUCTCHARS);
ms523 0:5934350323b2 301 StrNullTrailingSpace (response->productRev, SCSI_INQUIRY_REVCHARS);
ms523 0:5934350323b2 302 #endif
ms523 0:5934350323b2 303 }
ms523 0:5934350323b2 304 rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, CSW_SIZE);
ms523 0:5934350323b2 305 if (rc == OK) {
ms523 0:5934350323b2 306 if (TDBuffer[12] != 0) { // bCSWStatus byte
ms523 0:5934350323b2 307 rc = ERR_MS_CMD_FAILED;
ms523 0:5934350323b2 308 }
ms523 0:5934350323b2 309 }
ms523 0:5934350323b2 310 }
ms523 0:5934350323b2 311 }
ms523 0:5934350323b2 312 return (rc);
ms523 0:5934350323b2 313 }
ms523 0:5934350323b2 314
ms523 0:5934350323b2 315 /*
ms523 0:5934350323b2 316 **************************************************************************************************************
ms523 0:5934350323b2 317 * RECEIVE THE BULK DATA
ms523 0:5934350323b2 318 *
ms523 0:5934350323b2 319 * Description: This function is used to receive the bulk data
ms523 0:5934350323b2 320 *
ms523 0:5934350323b2 321 * Arguments : None
ms523 0:5934350323b2 322 *
ms523 0:5934350323b2 323 * Returns : OK if Success
ms523 0:5934350323b2 324 * ERR_INVALID_BOOTSIG if Failed
ms523 0:5934350323b2 325 *
ms523 0:5934350323b2 326 **************************************************************************************************************
ms523 0:5934350323b2 327 */
ms523 0:5934350323b2 328
ms523 0:5934350323b2 329 USB_INT32S MS_BulkRecv ( USB_INT32U block_number,
ms523 0:5934350323b2 330 USB_INT16U num_blocks,
ms523 0:5934350323b2 331 volatile USB_INT08U *user_buffer)
ms523 0:5934350323b2 332 {
ms523 0:5934350323b2 333 USB_INT32S rc;
ms523 0:5934350323b2 334 int i;
ms523 0:5934350323b2 335 volatile USB_INT08U *c = user_buffer;
ms523 0:5934350323b2 336 for (i=0;i<MS_BlkSize*num_blocks;i++)
ms523 0:5934350323b2 337 *c++ = 0;
ms523 0:5934350323b2 338
ms523 0:5934350323b2 339
ms523 0:5934350323b2 340 Fill_MSCommand(block_number, MS_BlkSize, num_blocks, MS_DATA_DIR_IN, SCSI_CMD_READ_10, 10);
ms523 0:5934350323b2 341
ms523 0:5934350323b2 342 rc = Host_ProcessTD(EDBulkOut, TD_OUT, TDBuffer, CBW_SIZE);
ms523 0:5934350323b2 343 if (rc == OK) {
ms523 0:5934350323b2 344 rc = Host_ProcessTD(EDBulkIn, TD_IN, user_buffer, MS_BlkSize * num_blocks);
ms523 0:5934350323b2 345 if (rc == OK) {
ms523 0:5934350323b2 346 rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, CSW_SIZE);
ms523 0:5934350323b2 347 if (rc == OK) {
ms523 0:5934350323b2 348 if (TDBuffer[12] != 0) {
ms523 0:5934350323b2 349 rc = ERR_MS_CMD_FAILED;
ms523 0:5934350323b2 350 }
ms523 0:5934350323b2 351 }
ms523 0:5934350323b2 352 }
ms523 0:5934350323b2 353 }
ms523 0:5934350323b2 354 return (rc);
ms523 0:5934350323b2 355 }
ms523 0:5934350323b2 356
ms523 0:5934350323b2 357 /*
ms523 0:5934350323b2 358 **************************************************************************************************************
ms523 0:5934350323b2 359 * SEND BULK DATA
ms523 0:5934350323b2 360 *
ms523 0:5934350323b2 361 * Description: This function is used to send the bulk data
ms523 0:5934350323b2 362 *
ms523 0:5934350323b2 363 * Arguments : None
ms523 0:5934350323b2 364 *
ms523 0:5934350323b2 365 * Returns : OK if Success
ms523 0:5934350323b2 366 * ERR_INVALID_BOOTSIG if Failed
ms523 0:5934350323b2 367 *
ms523 0:5934350323b2 368 **************************************************************************************************************
ms523 0:5934350323b2 369 */
ms523 0:5934350323b2 370
ms523 0:5934350323b2 371 USB_INT32S MS_BulkSend ( USB_INT32U block_number,
ms523 0:5934350323b2 372 USB_INT16U num_blocks,
ms523 0:5934350323b2 373 volatile USB_INT08U *user_buffer)
ms523 0:5934350323b2 374 {
ms523 0:5934350323b2 375 USB_INT32S rc;
ms523 0:5934350323b2 376
ms523 0:5934350323b2 377
ms523 0:5934350323b2 378 Fill_MSCommand(block_number, MS_BlkSize, num_blocks, MS_DATA_DIR_OUT, SCSI_CMD_WRITE_10, 10);
ms523 0:5934350323b2 379
ms523 0:5934350323b2 380 rc = Host_ProcessTD(EDBulkOut, TD_OUT, TDBuffer, CBW_SIZE);
ms523 0:5934350323b2 381 if (rc == OK) {
ms523 0:5934350323b2 382 rc = Host_ProcessTD(EDBulkOut, TD_OUT, user_buffer, MS_BlkSize * num_blocks);
ms523 0:5934350323b2 383 if (rc == OK) {
ms523 0:5934350323b2 384 rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, CSW_SIZE);
ms523 0:5934350323b2 385 if (rc == OK) {
ms523 0:5934350323b2 386 if (TDBuffer[12] != 0) {
ms523 0:5934350323b2 387 rc = ERR_MS_CMD_FAILED;
ms523 0:5934350323b2 388 }
ms523 0:5934350323b2 389 }
ms523 0:5934350323b2 390 }
ms523 0:5934350323b2 391 }
ms523 0:5934350323b2 392 return (rc);
ms523 0:5934350323b2 393 }
ms523 0:5934350323b2 394
ms523 0:5934350323b2 395 /*
ms523 0:5934350323b2 396 **************************************************************************************************************
ms523 0:5934350323b2 397 * FILL MASS STORAGE COMMAND
ms523 0:5934350323b2 398 *
ms523 0:5934350323b2 399 * Description: This function is used to fill the mass storage command
ms523 0:5934350323b2 400 *
ms523 0:5934350323b2 401 * Arguments : None
ms523 0:5934350323b2 402 *
ms523 0:5934350323b2 403 * Returns : OK if Success
ms523 0:5934350323b2 404 * ERR_INVALID_BOOTSIG if Failed
ms523 0:5934350323b2 405 *
ms523 0:5934350323b2 406 **************************************************************************************************************
ms523 0:5934350323b2 407 */
ms523 0:5934350323b2 408
ms523 0:5934350323b2 409 void Fill_MSCommand (USB_INT32U block_number,
ms523 0:5934350323b2 410 USB_INT32U block_size,
ms523 0:5934350323b2 411 USB_INT16U num_blocks,
ms523 0:5934350323b2 412 MS_DATA_DIR direction,
ms523 0:5934350323b2 413 USB_INT08U scsi_cmd,
ms523 0:5934350323b2 414 USB_INT08U scsi_cmd_len)
ms523 0:5934350323b2 415 {
ms523 0:5934350323b2 416 USB_INT32U data_len;
ms523 0:5934350323b2 417 static USB_INT32U tag_cnt = 0;
ms523 0:5934350323b2 418 USB_INT32U cnt;
ms523 0:5934350323b2 419
ms523 0:5934350323b2 420
ms523 0:5934350323b2 421 for (cnt = 0; cnt < CBW_SIZE; cnt++) {
ms523 0:5934350323b2 422 TDBuffer[cnt] = 0;
ms523 0:5934350323b2 423 }
ms523 0:5934350323b2 424 switch(scsi_cmd) {
ms523 0:5934350323b2 425
ms523 0:5934350323b2 426 case SCSI_CMD_TEST_UNIT_READY:
ms523 0:5934350323b2 427 data_len = 0;
ms523 0:5934350323b2 428 break;
ms523 0:5934350323b2 429 case SCSI_CMD_READ_CAPACITY:
ms523 0:5934350323b2 430 data_len = 8;
ms523 0:5934350323b2 431 break;
ms523 0:5934350323b2 432 case SCSI_CMD_REQUEST_SENSE:
ms523 0:5934350323b2 433 data_len = 18;
ms523 0:5934350323b2 434 break;
ms523 0:5934350323b2 435 case SCSI_CMD_INQUIRY:
ms523 0:5934350323b2 436 data_len = 36;
ms523 0:5934350323b2 437 break;
ms523 0:5934350323b2 438 default:
ms523 0:5934350323b2 439 data_len = block_size * num_blocks;
ms523 0:5934350323b2 440 break;
ms523 0:5934350323b2 441 }
ms523 0:5934350323b2 442 WriteLE32U(TDBuffer, CBW_SIGNATURE);
ms523 0:5934350323b2 443 WriteLE32U(&TDBuffer[4], tag_cnt);
ms523 0:5934350323b2 444 WriteLE32U(&TDBuffer[8], data_len);
ms523 0:5934350323b2 445 TDBuffer[12] = (direction == MS_DATA_DIR_NONE) ? 0 : direction;
ms523 0:5934350323b2 446 TDBuffer[14] = scsi_cmd_len; /* Length of the CBW */
ms523 0:5934350323b2 447 TDBuffer[15] = scsi_cmd;
ms523 0:5934350323b2 448 if ((scsi_cmd == SCSI_CMD_REQUEST_SENSE)
ms523 0:5934350323b2 449 || (scsi_cmd == SCSI_CMD_INQUIRY)) {
ms523 0:5934350323b2 450 TDBuffer[19] = (USB_INT08U)data_len;
ms523 0:5934350323b2 451 } else {
ms523 0:5934350323b2 452 WriteBE32U(&TDBuffer[17], block_number);
ms523 0:5934350323b2 453 }
ms523 0:5934350323b2 454 WriteBE16U(&TDBuffer[22], num_blocks);
ms523 0:5934350323b2 455 }