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