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 #if defined(UX_HOST_STANDALONE)
32 
33 extern VOID _ux_host_class_storage_read_initialize(UX_HOST_CLASS_STORAGE *storage,
34             ULONG sector_start, ULONG sector_count);
35 
36 extern VOID _ux_host_class_storage_write_initialize(UX_HOST_CLASS_STORAGE *storage,
37             ULONG sector_start, ULONG sector_count);
38 
39 
40 /**************************************************************************/
41 /*                                                                        */
42 /*  FUNCTION                                               RELEASE        */
43 /*                                                                        */
44 /*    _ux_host_class_storage_read_write_run               PORTABLE C      */
45 /*                                                           6.2.1        */
46 /*  AUTHOR                                                                */
47 /*                                                                        */
48 /*    Chaoqiong Xiao, Microsoft Corporation                               */
49 /*                                                                        */
50 /*  DESCRIPTION                                                           */
51 /*                                                                        */
52 /*    This function runs state machine to read or write one or more       */
53 /*    logical sector on a selected media of a storage function.           */
54 /*                                                                        */
55 /*    It's valid only in standalone mode.                                 */
56 /*                                                                        */
57 /*    Note it must be used in case following conditions are true:         */
58 /*    - storage insstance is live                                         */
59 /*    - storage is locked for specific LUN                                */
60 /*    - the main storage state must be idle                               */
61 /*                                                                        */
62 /*  INPUT                                                                 */
63 /*                                                                        */
64 /*    storage                               Pointer to storage class      */
65 /*    read_write                            Set to UX_TRUE to read        */
66 /*    sector_start                          Starting sector               */
67 /*    sector_count                          Number of sectors to read     */
68 /*    data_pointer                          Pointer to data to read       */
69 /*                                                                        */
70 /*  OUTPUT                                                                */
71 /*                                                                        */
72 /*    Completion Status                                                   */
73 /*    UX_STATE_WAIT                         States started/in progress    */
74 /*    UX_STATE_NEXT                         Read/write is done, next call */
75 /*                                          starts read/write again.      */
76 /*                                                                        */
77 /*  CALLS                                                                 */
78 /*                                                                        */
79 /*    _ux_host_class_storage_read_initialize                              */
80 /*                                          Initialize the CBW            */
81 /*    _ux_host_class_storage_write_initialize                              */
82 /*                                          Initialize the CBW            */
83 /*    _ux_system_error_handler              The error trap                */
84 /*    _ux_system_tasks_run                  Run USB system tasks          */
85 /*                                                                        */
86 /*  CALLED BY                                                             */
87 /*                                                                        */
88 /*    Storage Class                                                       */
89 /*                                                                        */
90 /*  RELEASE HISTORY                                                       */
91 /*                                                                        */
92 /*    DATE              NAME                      DESCRIPTION             */
93 /*                                                                        */
94 /*  01-31-2022     Chaoqiong Xiao           Initial Version 6.1.10        */
95 /*  03-08-2023     Chaoqiong Xiao           Modified comment(s),          */
96 /*                                            checked device state,       */
97 /*                                            resulting in version 6.2.1  */
98 /*                                                                        */
99 /**************************************************************************/
_ux_host_class_storage_read_write_run(UX_HOST_CLASS_STORAGE * storage,ULONG read_write,ULONG sector_start,ULONG sector_count,UCHAR * data_pointer)100 UINT  _ux_host_class_storage_read_write_run(UX_HOST_CLASS_STORAGE *storage,
101                 ULONG read_write,
102                 ULONG sector_start, ULONG sector_count, UCHAR *data_pointer)
103 {
104 
105 UX_DEVICE           *device;
106 
107 #if defined UX_HOST_CLASS_STORAGE_STATE_CHECK_ENABLE
108 UX_INTERRUPT_SAVE_AREA
109 
110     /* Check states - storage must be live, locked and main state machine idle.  */
111     UX_DISABLE
112     if (storage -> ux_host_class_storage_state != UX_HOST_CLASS_INSTANCE_LIVE ||
113         (storage -> ux_host_class_storage_flags & UX_HOST_CLASS_STORAGE_FLAG_LOCK) == 0 ||
114         storage -> ux_host_class_storage_state_state != UX_STATE_IDLE)
115     {
116         UX_RESTORE
117 
118         /* Error trap.  */
119         _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_NOT_READY);
120 
121         /* The state is not ready for read.  */
122         storage -> ux_host_class_storage_status = UX_TRANSFER_NOT_READY;
123         storage -> ux_host_class_storage_op_state = UX_STATE_RESET;
124         return(UX_STATE_ERROR);
125     }
126     UX_RESTORE
127 #endif
128 
129     /* If trace is enabled, insert this event into the trace buffer.  */
130     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)
131 
132     /* Get device.  */
133     device = storage -> ux_host_class_storage_device;
134 
135     switch(storage -> ux_host_class_storage_op_state)
136     {
137     case UX_STATE_IDLE:     /* Fall through.  */
138     case UX_STATE_ERROR:    /* Fall through.  */
139     case UX_STATE_RESET:
140 
141         /* Initialize CBW.  */
142         if (read_write)
143             _ux_host_class_storage_read_initialize(storage, sector_start, sector_count);
144         else
145             _ux_host_class_storage_write_initialize(storage, sector_start, sector_count);
146 
147         /* Initialize for transport.  */
148         UX_HOST_CLASS_STORAGE_TRANS_STATE_RESET(storage);
149         storage -> ux_host_class_storage_trans_data = data_pointer;
150 
151         /* Next : wait  */
152         storage -> ux_host_class_storage_op_state = UX_STATE_WAIT;
153 
154         /* Fall through.  */
155     case UX_STATE_WAIT:
156 
157         /* Run tasks, including transport task.  */
158         _ux_system_host_tasks_run();
159 
160         /* Check if device is still available.  */
161         if (device -> ux_device_state != UX_DEVICE_CONFIGURED)
162         {
163 
164             /* Instance should have been destroyed, just return.  */
165             return(UX_STATE_EXIT);
166         }
167 
168         /* Fatal error.  */
169         if (storage -> ux_host_class_storage_op_state < UX_STATE_IDLE)
170             return(UX_STATE_EXIT);
171 
172         /* It's done with/without error.  */
173         if (storage -> ux_host_class_storage_op_state <= UX_STATE_NEXT)
174             return(UX_STATE_NEXT);
175 
176         /* Wait.  */
177         return(UX_STATE_WAIT);
178 
179     /* Unexpected states.  */
180     default:
181         storage -> ux_host_class_storage_op_state = UX_STATE_RESET;
182         break;
183     }
184 
185     /* Return fatal exit state status.  */
186     return(UX_STATE_EXIT);
187 }
188 #endif
189