1 /**************************************************************************/
2 /*                                                                        */
3 /*       Copyright (c) Microsoft Corporation. All rights reserved.        */
4 /*                                                                        */
5 /*       This software is licensed under the Microsoft Software License   */
6 /*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
7 /*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
8 /*       and in the root directory of this software.                      */
9 /*                                                                        */
10 /**************************************************************************/
11 
12 
13 /**************************************************************************/
14 /**************************************************************************/
15 /**                                                                       */
16 /** USBX Component                                                        */
17 /**                                                                       */
18 /**   Storage Class                                                       */
19 /**                                                                       */
20 /**************************************************************************/
21 /**************************************************************************/
22 
23 
24 /* Include necessary system files.  */
25 
26 #define UX_SOURCE_CODE
27 
28 #include "ux_api.h"
29 #include "ux_host_class_storage.h"
30 #include "ux_host_stack.h"
31 
32 
33 #if defined(UX_HOST_STANDALONE)
34 VOID _ux_host_class_storage_read_initialize(UX_HOST_CLASS_STORAGE *storage,
35                 ULONG sector_start, ULONG sector_count);
36 
37 VOID
38 #else
39 static inline VOID
40 #endif
_ux_host_class_storage_read_initialize(UX_HOST_CLASS_STORAGE * storage,ULONG sector_start,ULONG sector_count)41 _ux_host_class_storage_read_initialize(UX_HOST_CLASS_STORAGE *storage,
42                 ULONG sector_start, ULONG sector_count)
43 {
44 UCHAR       *cbw;
45 UCHAR       *cbw_cb;
46 ULONG       command_length;
47 
48     /* Use a pointer for the cbw, easier to manipulate.  */
49     cbw = (UCHAR *)storage -> ux_host_class_storage_cbw;
50     cbw_cb = cbw + UX_HOST_CLASS_STORAGE_CBW_CB;
51 
52     /* Get the Read Command Length.  */
53 #ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT
54     if (storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceSubClass ==
55         UX_HOST_CLASS_STORAGE_SUBCLASS_UFI)
56         command_length =  UX_HOST_CLASS_STORAGE_READ_COMMAND_LENGTH_UFI;
57     else
58         command_length =  UX_HOST_CLASS_STORAGE_READ_COMMAND_LENGTH_SBC;
59 #else
60     command_length =  UX_HOST_CLASS_STORAGE_READ_COMMAND_LENGTH_SBC;
61 #endif
62 
63     /* Initialize the CBW for this command.  */
64     _ux_host_class_storage_cbw_initialize(storage,
65                     UX_HOST_CLASS_STORAGE_DATA_IN,
66                     sector_count * storage -> ux_host_class_storage_sector_size,
67                     command_length);
68 
69     /* Prepare the MEDIA READ command block.  */
70     *(cbw_cb + UX_HOST_CLASS_STORAGE_READ_OPERATION) =  UX_HOST_CLASS_STORAGE_SCSI_READ16;
71 
72     /* Store the sector start (LBA field).  */
73     _ux_utility_long_put_big_endian(cbw_cb + UX_HOST_CLASS_STORAGE_READ_LBA, sector_start);
74 
75     /* Store the number of sectors to read.  */
76     _ux_utility_short_put_big_endian(cbw_cb + UX_HOST_CLASS_STORAGE_READ_TRANSFER_LENGTH, (USHORT) sector_count);
77 }
78 
79 
80 /**************************************************************************/
81 /*                                                                        */
82 /*  FUNCTION                                               RELEASE        */
83 /*                                                                        */
84 /*    _ux_host_class_storage_media_read                   PORTABLE C      */
85 /*                                                           6.2.1        */
86 /*  AUTHOR                                                                */
87 /*                                                                        */
88 /*    Chaoqiong Xiao, Microsoft Corporation                               */
89 /*                                                                        */
90 /*  DESCRIPTION                                                           */
91 /*                                                                        */
92 /*    This function will read one or more logical sector from the media.  */
93 /*                                                                        */
94 /*  INPUT                                                                 */
95 /*                                                                        */
96 /*    storage                               Pointer to storage class      */
97 /*    sector_start                          Starting sector               */
98 /*    sector_count                          Number of sectors to read     */
99 /*    data_pointer                          Pointer to data to read       */
100 /*                                                                        */
101 /*  OUTPUT                                                                */
102 /*                                                                        */
103 /*    Completion Status                                                   */
104 /*                                                                        */
105 /*  CALLS                                                                 */
106 /*                                                                        */
107 /*    _ux_host_class_storage_cbw_initialize Initialize the CBW            */
108 /*    _ux_host_class_storage_transport      Send command                  */
109 /*    _ux_utility_long_put_big_endian       Put 32-bit word               */
110 /*    _ux_utility_short_put_big_endian      Put 16-bit word               */
111 /*                                                                        */
112 /*  CALLED BY                                                             */
113 /*                                                                        */
114 /*    Storage Class                                                       */
115 /*                                                                        */
116 /*  RELEASE HISTORY                                                       */
117 /*                                                                        */
118 /*    DATE              NAME                      DESCRIPTION             */
119 /*                                                                        */
120 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
121 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
122 /*                                            resulting in version 6.1    */
123 /*  01-31-2022     Chaoqiong Xiao           Modified comment(s),          */
124 /*                                            added standalone support,   */
125 /*                                            resulting in version 6.1.10 */
126 /*  03-08-2023     Chaoqiong Xiao           Modified comment(s),          */
127 /*                                            checked device removal,     */
128 /*                                            resulting in version 6.2.1  */
129 /*                                                                        */
130 /**************************************************************************/
_ux_host_class_storage_media_read(UX_HOST_CLASS_STORAGE * storage,ULONG sector_start,ULONG sector_count,UCHAR * data_pointer)131 UINT  _ux_host_class_storage_media_read(UX_HOST_CLASS_STORAGE *storage, ULONG sector_start,
132                                     ULONG sector_count, UCHAR *data_pointer)
133 {
134 #if defined(UX_HOST_STANDALONE)
135 UINT            status;
136     do {
137         status = _ux_host_class_storage_read_write_run(storage, UX_TRUE,
138                                     sector_start, sector_count, data_pointer);
139     } while(status == UX_STATE_WAIT);
140     if (status < UX_STATE_IDLE)
141         return(UX_HOST_CLASS_INSTANCE_UNKNOWN);
142     return(storage -> ux_host_class_storage_status);
143 #else
144 UINT            status;
145 UINT            media_retry;
146 
147     /* If trace is enabled, insert this event into the trace buffer.  */
148     UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_STORAGE_MEDIA_READ, storage, sector_start, sector_count, data_pointer, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
149 
150     /* Reset the retry count.  */
151     media_retry =  UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RETRY;
152 
153     /* We may need several attempts.  */
154     while (media_retry-- != 0)
155     {
156 
157         /* Initialize CBW.  */
158         _ux_host_class_storage_read_initialize(storage, sector_start, sector_count);
159 
160         /* Send the command to transport layer.  */
161         status =  _ux_host_class_storage_transport(storage, data_pointer);
162         if (status != UX_SUCCESS)
163             return(status);
164 
165         /* Did the command succeed?  */
166         if (storage -> ux_host_class_storage_sense_code == UX_SUCCESS)
167         {
168 
169             /* Check for completeness of sector read.  */
170             if (storage -> ux_host_class_storage_data_phase_length != sector_count * storage -> ux_host_class_storage_sector_size)
171             {
172 
173                 /* This can happen if the device sent less data than the host
174                    requested. This does not fit our definition of success and
175                    retrying shouldn't change the outcome, so we return an error.  */
176 
177                 /* We got an error during read. Packet not complete.  */
178                 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_DATA_LESS_THAN_EXPECTED);
179 
180                 /* Return to UX_MEDIA (default FileX).  */
181                 return(UX_ERROR);
182             }
183 
184             /* The read succeeded.  */
185             return(UX_SUCCESS);
186         }
187 
188         /* The command did not succeed. Retry.  */
189     }
190 
191     /* Check if the media in the device has been removed. If so
192        we have to tell UX_MEDIA (default FileX) that the media is closed.  */
193     return(UX_HOST_CLASS_STORAGE_SENSE_ERROR);
194 #endif
195 }
196