1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** USBX Component */
16 /** */
17 /** Storage Class */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22
23 /* Include necessary system files. */
24
25 #define UX_SOURCE_CODE
26
27 #include "ux_api.h"
28 #include "ux_host_class_storage.h"
29 #include "ux_host_stack.h"
30
31
32 #if defined(UX_HOST_STANDALONE)
33 VOID _ux_host_class_storage_write_initialize(UX_HOST_CLASS_STORAGE *storage,
34 ULONG sector_start, ULONG sector_count);
35
36 VOID
37 #else
38 static inline VOID
39 #endif
_ux_host_class_storage_write_initialize(UX_HOST_CLASS_STORAGE * storage,ULONG sector_start,ULONG sector_count)40 _ux_host_class_storage_write_initialize(UX_HOST_CLASS_STORAGE *storage,
41 ULONG sector_start, ULONG sector_count)
42 {
43 UCHAR *cbw;
44 UCHAR *cbw_cb;
45 ULONG command_length;
46
47 /* Use a pointer for the cbw, easier to manipulate. */
48 cbw = (UCHAR *)storage -> ux_host_class_storage_cbw;
49 cbw_cb = cbw + UX_HOST_CLASS_STORAGE_CBW_CB;
50
51 /* Get the Write Command Length. */
52 #ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT
53 if (storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceSubClass ==
54 UX_HOST_CLASS_STORAGE_SUBCLASS_UFI)
55 command_length = UX_HOST_CLASS_STORAGE_WRITE_COMMAND_LENGTH_UFI;
56 else
57 command_length = UX_HOST_CLASS_STORAGE_WRITE_COMMAND_LENGTH_SBC;
58 #else
59 command_length = UX_HOST_CLASS_STORAGE_WRITE_COMMAND_LENGTH_SBC;
60 #endif
61
62 /* Initialize the CBW for this command. */
63 _ux_host_class_storage_cbw_initialize(storage, UX_HOST_CLASS_STORAGE_DATA_OUT,
64 sector_count * storage -> ux_host_class_storage_sector_size,
65 command_length);
66
67 /* Prepare the MEDIA WRITE command block. */
68 *(cbw_cb + UX_HOST_CLASS_STORAGE_WRITE_OPERATION) = UX_HOST_CLASS_STORAGE_SCSI_WRITE16;
69
70 /* Store the sector start (LBA field). */
71 _ux_utility_long_put_big_endian(cbw_cb + UX_HOST_CLASS_STORAGE_WRITE_LBA, sector_start);
72
73 /* Store the number of sectors to write. */
74 _ux_utility_short_put_big_endian(cbw_cb + UX_HOST_CLASS_STORAGE_WRITE_TRANSFER_LENGTH, (USHORT) sector_count);
75 }
76
77
78 /**************************************************************************/
79 /* */
80 /* FUNCTION RELEASE */
81 /* */
82 /* _ux_host_class_storage_media_write PORTABLE C */
83 /* 6.2.1 */
84 /* AUTHOR */
85 /* */
86 /* Chaoqiong Xiao, Microsoft Corporation */
87 /* */
88 /* DESCRIPTION */
89 /* */
90 /* This function will write one or more logical sector to the media. */
91 /* */
92 /* INPUT */
93 /* */
94 /* storage Pointer to storage class */
95 /* sector_start Starting sector */
96 /* sector_count Number of sectors to write */
97 /* data_pointer Pointer to data to write */
98 /* */
99 /* OUTPUT */
100 /* */
101 /* Completion Status */
102 /* */
103 /* CALLS */
104 /* */
105 /* _ux_host_class_storage_cbw_initialize Initialize the CBW */
106 /* _ux_host_class_storage_transport Send command */
107 /* _ux_utility_long_put_big_endian Put 32-bit word */
108 /* _ux_utility_short_put_big_endian Put 16-bit word */
109 /* */
110 /* CALLED BY */
111 /* */
112 /* Storage Class */
113 /* */
114 /* RELEASE HISTORY */
115 /* */
116 /* DATE NAME DESCRIPTION */
117 /* */
118 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
119 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
120 /* resulting in version 6.1 */
121 /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */
122 /* added standalone support, */
123 /* resulting in version 6.1.10 */
124 /* 03-08-2023 Chaoqiong Xiao Modified comment(s), */
125 /* checked device removal, */
126 /* resulting in version 6.2.1 */
127 /* */
128 /**************************************************************************/
_ux_host_class_storage_media_write(UX_HOST_CLASS_STORAGE * storage,ULONG sector_start,ULONG sector_count,UCHAR * data_pointer)129 UINT _ux_host_class_storage_media_write(UX_HOST_CLASS_STORAGE *storage, ULONG sector_start,
130 ULONG sector_count, UCHAR *data_pointer)
131 {
132 #if defined(UX_HOST_STANDALONE)
133 UINT status;
134 do {
135 status = _ux_host_class_storage_read_write_run(storage, UX_FALSE,
136 sector_start, sector_count, data_pointer);
137 } while(status == UX_STATE_WAIT);
138 if (status < UX_STATE_IDLE)
139 return(UX_HOST_CLASS_INSTANCE_UNKNOWN);
140 return(storage -> ux_host_class_storage_status);
141 #else
142 UINT status;
143 UINT media_retry;
144
145 /* If trace is enabled, insert this event into the trace buffer. */
146 UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_STORAGE_MEDIA_WRITE, storage, sector_start, sector_count, data_pointer, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
147
148 /* Initialize CBW. */
149 _ux_host_class_storage_write_initialize(storage, sector_start, sector_count);
150
151 /* Reset the retry count. */
152 media_retry = UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RETRY;
153
154 /* We may need several attempts. */
155 while (media_retry-- != 0)
156 {
157
158 /* Send the command to transport layer. */
159 status = _ux_host_class_storage_transport(storage, data_pointer);
160 if (status != UX_SUCCESS)
161 return(status);
162
163 /* Check the sense code */
164 if (storage -> ux_host_class_storage_sense_code == UX_SUCCESS)
165 return(UX_SUCCESS);
166 }
167
168 /* Return sense error. */
169 return(UX_HOST_CLASS_STORAGE_SENSE_ERROR);
170 #endif
171 }
172
173
174 /**************************************************************************/
175 /* */
176 /* FUNCTION RELEASE */
177 /* */
178 /* _ux_host_class_storage_media_write PORTABLE C */
179 /* 6.3.0 */
180 /* AUTHOR */
181 /* */
182 /* Chaoqiong Xiao, Microsoft Corporation */
183 /* */
184 /* DESCRIPTION */
185 /* */
186 /* This function checks errors in storage media write function call. */
187 /* */
188 /* INPUT */
189 /* */
190 /* storage Pointer to storage class */
191 /* sector_start Starting sector */
192 /* sector_count Number of sectors to write */
193 /* data_pointer Pointer to data to write */
194 /* */
195 /* OUTPUT */
196 /* */
197 /* Status */
198 /* */
199 /* CALLS */
200 /* */
201 /* _ux_host_class_storage_media_write write storage media */
202 /* */
203 /* CALLED BY */
204 /* */
205 /* Application */
206 /* */
207 /* RELEASE HISTORY */
208 /* */
209 /* DATE NAME DESCRIPTION */
210 /* */
211 /* 10-31-2023 Chaoqiong Xiao Initial Version 6.3.0 */
212 /* */
213 /**************************************************************************/
_uxe_host_class_storage_media_write(UX_HOST_CLASS_STORAGE * storage,ULONG sector_start,ULONG sector_count,UCHAR * data_pointer)214 UINT _uxe_host_class_storage_media_write(UX_HOST_CLASS_STORAGE *storage, ULONG sector_start,
215 ULONG sector_count, UCHAR *data_pointer)
216 {
217
218 /* Sanity check. */
219 if (storage == UX_NULL)
220 return(UX_INVALID_PARAMETER);
221
222 /* Invoke storage media write function. */
223 return(_ux_host_class_storage_media_write(storage, sector_start, sector_count, data_pointer));
224 }
225