GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usbx_device_classes/src/ux_device_class_storage_synchronize_cache.c Lines: 25 25 100.0 %
Date: 2024-12-12 17:16:36 Branches: 10 10 100.0 %

Line Branch Exec Source
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
/**   Device 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_device_class_storage.h"
29
#include "ux_device_stack.h"
30
31
32
/**************************************************************************/
33
/*                                                                        */
34
/*  FUNCTION                                               RELEASE        */
35
/*                                                                        */
36
/*    _ux_device_class_storage_synchronize_cache          PORTABLE C      */
37
/*                                                           6.1.10       */
38
/*  AUTHOR                                                                */
39
/*                                                                        */
40
/*    Chaoqiong Xiao, Microsoft Corporation                               */
41
/*                                                                        */
42
/*  DESCRIPTION                                                           */
43
/*                                                                        */
44
/*    This function performs a SYNCHRONIZE_CACHE command in 32 or 16      */
45
/*    bits.                                                               */
46
/*                                                                        */
47
/*  INPUT                                                                 */
48
/*                                                                        */
49
/*    storage                               Pointer to storage class      */
50
/*    endpoint_in                           Pointer to IN endpoint        */
51
/*    endpoint_out                          Pointer to OUT endpoint       */
52
/*    cbwcb                                 Pointer to the CBWCB          */
53
/*    scsi_command                          SCSI command                  */
54
/*                                                                        */
55
/*  OUTPUT                                                                */
56
/*                                                                        */
57
/*    Completion Status                                                   */
58
/*                                                                        */
59
/*  CALLS                                                                 */
60
/*                                                                        */
61
/*    (ux_slave_class_storage_media_status) Get media status              */
62
/*    (ux_slave_class_storage_media_flush)  Flush media                   */
63
/*    _ux_device_class_storage_csw_send     Send CSW                      */
64
/*    _ux_device_stack_endpoint_stall       Stall endpoint                */
65
/*    _ux_utility_long_get_big_endian       Get 32-bit big endian         */
66
/*    _ux_utility_short_get_big_endian      Get 16-bit big endian         */
67
/*                                                                        */
68
/*  CALLED BY                                                             */
69
/*                                                                        */
70
/*    Device Storage Class                                                */
71
/*                                                                        */
72
/*  RELEASE HISTORY                                                       */
73
/*                                                                        */
74
/*    DATE              NAME                      DESCRIPTION             */
75
/*                                                                        */
76
/*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
77
/*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
78
/*                                            optimized command logic,    */
79
/*                                            resulting in version 6.1    */
80
/*  01-31-2022     Chaoqiong Xiao           Modified comment(s),          */
81
/*                                            added standalone support,   */
82
/*                                            resulting in version 6.1.10 */
83
/*                                                                        */
84
/**************************************************************************/
85
11
UINT  _ux_device_class_storage_synchronize_cache(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun,
86
                                                 UX_SLAVE_ENDPOINT *endpoint_in,
87
                                                 UX_SLAVE_ENDPOINT *endpoint_out, UCHAR *cbwcb, UCHAR scsi_command)
88
{
89
90
UINT                    status;
91
ULONG                   lba;
92
USHORT                  number_blocks;
93
ULONG                   media_status;
94
95
#if !defined(UX_DEVICE_STANDALONE)
96
UCHAR                   flags;
97
#endif
98
99
100
    UX_PARAMETER_NOT_USED(endpoint_out);
101
    UX_PARAMETER_NOT_USED(scsi_command);
102
103
    /* By default status is passed.  */
104
11
    storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PASSED;
105
106
    /* Is there not an implementation?  */
107
11
    if (storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_flush == UX_NULL)
108
    {
109
110
        /* This means the application is not using a cache.  */
111
112
        /* Return success.  */
113
1
        return(UX_SUCCESS);
114
    }
115
116
    /* Get the LBA and number of blocks from the CBWCB in 16 bits.  */
117
10
    lba           =         _ux_utility_long_get_big_endian(cbwcb + UX_SLAVE_CLASS_STORAGE_SYNCHRONIZE_CACHE_LBA);
118
10
    number_blocks = (USHORT)_ux_utility_short_get_big_endian(cbwcb + UX_SLAVE_CLASS_STORAGE_SYNCHRONIZE_CACHE_NUMBER_OF_BLOCKS);
119
120
    /* If trace is enabled, insert this event into the trace buffer.  */
121
    UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_STORAGE_SYNCHRONIZE_CACHE, storage, lun, lba, number_blocks, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0)
122
123
    /* Obtain the status of the device.  */
124
10
    status =  storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_status(storage,
125
                            lun, storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_id, &media_status);
126
127
    /* Update the request sense.  */
128
10
    storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_status = media_status;
129
130
    /* If there is a problem, return a failed command.  */
131
10
    if (status != UX_SUCCESS)
132
    {
133
134
        /* We have a problem, media status error. Return a bad completion and wait for the
135
           REQUEST_SENSE command.  */
136
#if !defined(UX_DEVICE_STANDALONE)
137
1
        _ux_device_stack_endpoint_stall(endpoint_in);
138
#else
139
        UX_PARAMETER_NOT_USED(endpoint_in);
140
        storage -> ux_device_class_storage_cmd_state = UX_DEVICE_CLASS_STORAGE_CMD_ERR;
141
#endif
142
143
1
        storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_FAILED;
144
145
        /* We are done here.  */
146
1
        return(UX_ERROR);
147
    }
148
149
    /* Now it's OK to perform synchronize cache.  */
150
151
#if defined(UX_DEVICE_STANDALONE)
152
153
    /* Next: Disk (SYNC).  */
154
    storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_DISK_WAIT;
155
    storage -> ux_device_class_storage_disk_state = UX_DEVICE_CLASS_STORAGE_DISK_OP_START;
156
    storage -> ux_device_class_storage_cmd_state = UX_DEVICE_CLASS_STORAGE_CMD_DISK_OP;
157
158
    storage -> ux_device_class_storage_cmd_lba = lba;
159
    storage -> ux_device_class_storage_cmd_n_lb = number_blocks;
160
161
#else
162
163
    /* Get the flags.  */
164
9
    flags =  *(cbwcb + UX_SLAVE_CLASS_STORAGE_SYNCHRONIZE_CACHE_FLAGS);
165
166
    /* If the immediate bit is set, we return a CSW before flush.  */
167
9
    if ((flags & UX_SLAVE_CLASS_STORAGE_SYNCHRONIZE_CACHE_FLAGS_IMMED) != 0)
168
1
        _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_PASSED);
169
170
    /* Send the flush command to the local media.  */
171
9
    status =  storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_flush(storage, lun, number_blocks, lba, &media_status);
172
173
    /* Update the request sense.  */
174
9
    storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_status = media_status;
175
176
    /* If the immediate bit is set, we are already done, no matter what local operation status is.  */
177
9
    if ((flags & UX_SLAVE_CLASS_STORAGE_SYNCHRONIZE_CACHE_FLAGS_IMMED) != 0)
178
    {
179
180
        /* CSW skipped since already sent in this function.  */
181
1
        UX_DEVICE_CLASS_STORAGE_CSW_SKIP(&storage -> ux_slave_class_storage_csw_status) = UX_TRUE;
182
1
        return(status);
183
    }
184
185
    /* If there is a problem, return a failed command.  */
186
8
    if (status != UX_SUCCESS)
187
    {
188
189
        /* We have a problem, request error. Return a bad completion and wait for the
190
           REQUEST_SENSE command.  */
191
1
        _ux_device_stack_endpoint_stall(endpoint_in);
192
193
1
        storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_FAILED;
194
195
        /* Return an error.  */
196
1
        return(UX_ERROR);
197
    }
198
#endif
199
200
    /* Return completion status.  */
201
7
    return(status);
202
}