Implementation of USB Host for mbed 1768 which can access USB flash drives. See notebook page for details.

Dependencies:   FatFileSystemCpp mbed

Committer:
igorsk
Date:
Mon Jul 30 13:49:56 2012 +0000
Revision:
3:95e55809ecdb
Parent:
1:ad941ffd64cb
Switched to FatFileSystemCpp

Who changed what in which revision?

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