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