dd

Dependencies:   C12832 mbed

Committer:
pfe
Date:
Wed Apr 08 08:27:55 2015 +0000
Revision:
0:caecb0d1e7d3
ddd

Who changed what in which revision?

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