Dependencies:   mbed

Committer:
joe
Date:
Fri Aug 20 15:38:52 2010 +0000
Revision:
2:a079de4fd5b9
Parent:
0:960b355eaa84

        

Who changed what in which revision?

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