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_write_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_write_initialize(UX_HOST_CLASS_STORAGE * storage,ULONG sector_start,ULONG sector_count)41 _ux_host_class_storage_write_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 Write 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_WRITE_COMMAND_LENGTH_UFI;
57     else
58         command_length =  UX_HOST_CLASS_STORAGE_WRITE_COMMAND_LENGTH_SBC;
59 #else
60     command_length =  UX_HOST_CLASS_STORAGE_WRITE_COMMAND_LENGTH_SBC;
61 #endif
62 
63     /* Initialize the CBW for this command.  */
64     _ux_host_class_storage_cbw_initialize(storage, UX_HOST_CLASS_STORAGE_DATA_OUT,
65                                     sector_count * storage -> ux_host_class_storage_sector_size,
66                                     command_length);
67 
68     /* Prepare the MEDIA WRITE command block.  */
69     *(cbw_cb + UX_HOST_CLASS_STORAGE_WRITE_OPERATION) =  UX_HOST_CLASS_STORAGE_SCSI_WRITE16;
70 
71     /* Store the sector start (LBA field).  */
72     _ux_utility_long_put_big_endian(cbw_cb + UX_HOST_CLASS_STORAGE_WRITE_LBA, sector_start);
73 
74     /* Store the number of sectors to write.  */
75     _ux_utility_short_put_big_endian(cbw_cb + UX_HOST_CLASS_STORAGE_WRITE_TRANSFER_LENGTH, (USHORT) sector_count);
76 }
77 
78 
79 /**************************************************************************/
80 /*                                                                        */
81 /*  FUNCTION                                               RELEASE        */
82 /*                                                                        */
83 /*    _ux_host_class_storage_media_write                  PORTABLE C      */
84 /*                                                           6.2.1        */
85 /*  AUTHOR                                                                */
86 /*                                                                        */
87 /*    Chaoqiong Xiao, Microsoft Corporation                               */
88 /*                                                                        */
89 /*  DESCRIPTION                                                           */
90 /*                                                                        */
91 /*    This function will write one or more logical sector to the media.   */
92 /*                                                                        */
93 /*  INPUT                                                                 */
94 /*                                                                        */
95 /*    storage                               Pointer to storage class      */
96 /*    sector_start                          Starting sector               */
97 /*    sector_count                          Number of sectors to write    */
98 /*    data_pointer                          Pointer to data to write      */
99 /*                                                                        */
100 /*  OUTPUT                                                                */
101 /*                                                                        */
102 /*    Completion Status                                                   */
103 /*                                                                        */
104 /*  CALLS                                                                 */
105 /*                                                                        */
106 /*    _ux_host_class_storage_cbw_initialize Initialize the CBW            */
107 /*    _ux_host_class_storage_transport      Send command                  */
108 /*    _ux_utility_long_put_big_endian       Put 32-bit word               */
109 /*    _ux_utility_short_put_big_endian      Put 16-bit word               */
110 /*                                                                        */
111 /*  CALLED BY                                                             */
112 /*                                                                        */
113 /*    Storage Class                                                       */
114 /*                                                                        */
115 /*  RELEASE HISTORY                                                       */
116 /*                                                                        */
117 /*    DATE              NAME                      DESCRIPTION             */
118 /*                                                                        */
119 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
120 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
121 /*                                            resulting in version 6.1    */
122 /*  01-31-2022     Chaoqiong Xiao           Modified comment(s),          */
123 /*                                            added standalone support,   */
124 /*                                            resulting in version 6.1.10 */
125 /*  03-08-2023     Chaoqiong Xiao           Modified comment(s),          */
126 /*                                            checked device removal,     */
127 /*                                            resulting in version 6.2.1  */
128 /*                                                                        */
129 /**************************************************************************/
_ux_host_class_storage_media_write(UX_HOST_CLASS_STORAGE * storage,ULONG sector_start,ULONG sector_count,UCHAR * data_pointer)130 UINT  _ux_host_class_storage_media_write(UX_HOST_CLASS_STORAGE *storage, ULONG sector_start,
131                                         ULONG sector_count, UCHAR *data_pointer)
132 {
133 #if defined(UX_HOST_STANDALONE)
134 UINT            status;
135     do {
136         status = _ux_host_class_storage_read_write_run(storage, UX_FALSE,
137                                     sector_start, sector_count, data_pointer);
138     } while(status == UX_STATE_WAIT);
139     if (status < UX_STATE_IDLE)
140         return(UX_HOST_CLASS_INSTANCE_UNKNOWN);
141     return(storage -> ux_host_class_storage_status);
142 #else
143 UINT            status;
144 UINT            media_retry;
145 
146     /* If trace is enabled, insert this event into the trace buffer.  */
147     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)
148 
149     /* Initialize CBW.  */
150     _ux_host_class_storage_write_initialize(storage, sector_start, sector_count);
151 
152     /* Reset the retry count.  */
153     media_retry =  UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RETRY;
154 
155     /* We may need several attempts.  */
156     while (media_retry-- != 0)
157     {
158 
159         /* Send the command to transport layer.  */
160         status =  _ux_host_class_storage_transport(storage, data_pointer);
161         if (status != UX_SUCCESS)
162             return(status);
163 
164         /* Check the sense code */
165         if (storage -> ux_host_class_storage_sense_code == UX_SUCCESS)
166             return(UX_SUCCESS);
167     }
168 
169     /* Return sense error.  */
170     return(UX_HOST_CLASS_STORAGE_SENSE_ERROR);
171 #endif
172 }
173 
174