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