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 /**************************************************************************/
33 /*                                                                        */
34 /*  FUNCTION                                               RELEASE        */
35 /*                                                                        */
36 /*    _ux_host_class_storage_start_stop                   PORTABLE C      */
37 /*                                                           6.1          */
38 /*  AUTHOR                                                                */
39 /*                                                                        */
40 /*    Chaoqiong Xiao, Microsoft Corporation                               */
41 /*                                                                        */
42 /*  DESCRIPTION                                                           */
43 /*                                                                        */
44 /*    This function starts or stops the UFI device.                       */
45 /*                                                                        */
46 /*  INPUT                                                                 */
47 /*                                                                        */
48 /*    storage                               Pointer to storage class      */
49 /*    start_stop_flag                       1 or 0 if start/stop          */
50 /*                                                                        */
51 /*  OUTPUT                                                                */
52 /*                                                                        */
53 /*    Completion Status                                                   */
54 /*                                                                        */
55 /*  CALLS                                                                 */
56 /*                                                                        */
57 /*    _ux_host_class_storage_cbw_initialize Initialize the CBW            */
58 /*    _ux_host_class_storage_transport      Send transport layer command  */
59 /*                                                                        */
60 /*  CALLED BY                                                             */
61 /*                                                                        */
62 /*    Storage Class                                                       */
63 /*                                                                        */
64 /*  RELEASE HISTORY                                                       */
65 /*                                                                        */
66 /*    DATE              NAME                      DESCRIPTION             */
67 /*                                                                        */
68 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
69 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
70 /*                                            resulting in version 6.1    */
71 /*                                                                        */
72 /**************************************************************************/
_ux_host_class_storage_start_stop(UX_HOST_CLASS_STORAGE * storage,ULONG start_stop_signal)73 UINT  _ux_host_class_storage_start_stop(UX_HOST_CLASS_STORAGE *storage,
74                                             ULONG start_stop_signal)
75 {
76 
77 UINT            status;
78 UCHAR             *cbw;
79 UINT            command_length;
80 ULONG           command_retry;
81 
82     /* If trace is enabled, insert this event into the trace buffer.  */
83     UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_STORAGE_START_STOP, storage, start_stop_signal, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
84 
85     /* Use a pointer for the CBW, easier to manipulate.  */
86     cbw =  (UCHAR *) storage -> ux_host_class_storage_cbw;
87 
88     /* Get the START_STOP Command Length.  */
89 #ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT
90     if (storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceSubClass == UX_HOST_CLASS_STORAGE_SUBCLASS_UFI)
91         command_length =  UX_HOST_CLASS_STORAGE_START_STOP_COMMAND_LENGTH_UFI;
92     else
93         command_length =  UX_HOST_CLASS_STORAGE_START_STOP_COMMAND_LENGTH_SBC;
94 #else
95     command_length =  UX_HOST_CLASS_STORAGE_START_STOP_COMMAND_LENGTH_SBC;
96 #endif
97 
98     /* Initialize the CBW for this command.  */
99     _ux_host_class_storage_cbw_initialize(storage, 0, 0, command_length);
100 
101     /* Prepare the START STOP command block.  */
102     *(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_START_STOP_OPERATION) =  UX_HOST_CLASS_STORAGE_SCSI_START_STOP;
103 
104     /* Set the required signal.  */
105     *(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_START_STOP_START_BIT) =  (UCHAR) start_stop_signal;
106 
107     /* On floppies, this operation tends to fail a few times. So we try harder.  */
108     for (command_retry = 0; command_retry < 50; command_retry++)
109     {
110 
111         /* Send the command to transport layer.  */
112         status =  _ux_host_class_storage_transport(storage, UX_NULL);
113 
114         /* If we have a transport error give up. */
115         if(status != UX_SUCCESS)
116 
117             /* Return completion status.  */
118             return(status);
119 
120         /* Check the CSW. We may learn something there about the state of the device.  */
121         if (storage -> ux_host_class_storage_sense_code == 0)
122             return(UX_SUCCESS);
123     }
124 
125     /* The start/Stop did not work.  */
126     return(UX_ERROR);
127 }
128 
129