ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_usb_pmsc_scsi.c
Go to the documentation of this file.
1
22
23#include <stdint.h>
24
25#include "ra8_attributes.h"
26#include "ra8_err.h"
27#include "ra8_usb.h"
28#include "ra8_usb_pmsc.h"
30
31/* =============================================================================
32 * Internal constants
33 * =============================================================================
34 */
35
53
69
89
99
115
120typedef enum : uint8_t {
123
124/* =============================================================================
125 * Internal helpers
126 * =============================================================================
127 */
128
143static void internal_pack_u32_be(uint32_t value, uint8_t* dst)
144{
145 dst[0] = (uint8_t)((value >> k_ra8_pmsc_shift_byte3) & k_ra8_pmsc_byte_mask);
146 dst[1] = (uint8_t)((value >> k_ra8_pmsc_shift_byte2) & k_ra8_pmsc_byte_mask);
147 dst[2] = (uint8_t)((value >> k_ra8_pmsc_shift_byte1) & k_ra8_pmsc_byte_mask);
148 dst[3] = (uint8_t)((value >> k_ra8_pmsc_shift_byte0) & k_ra8_pmsc_byte_mask);
149}
150
165static void internal_pad_space(uint8_t* dst, uint32_t len)
166{
167 for (uint32_t i = 0U; i < len; ++i) {
168 dst[i] = k_ra8_pmsc_ascii_space;
169 }
170}
171
172/* =============================================================================
173 * SCSI handler internals
174 * =============================================================================
175 */
176
192static void internal_decode_rw10(const uint8_t* cdb, uint32_t* out_lba, uint32_t* out_block_count)
193{
194 *out_lba = ((uint32_t)cdb[k_ra8_pmsc_cdb_off_lba_msb] << k_ra8_pmsc_shift_byte3) |
198 *out_block_count = ((uint32_t)cdb[k_ra8_pmsc_cdb_off_cnt_msb] << k_ra8_pmsc_shift_byte1) |
200}
201
202ra8_err_t priv_handle_inquiry(uint8_t* data_buf, uint32_t capacity, uint32_t* out_len)
203{
204 if (capacity < k_ra8_pmsc_inquiry_resp_len) {
206 }
207 priv_zero_bytes(data_buf, (uint32_t)k_ra8_pmsc_inquiry_resp_len);
208
214
215 /* Pad the three string fields with SPACE first so a backend that
216 * writes fewer bytes still produces a spec-conforming response. */
220
221 const ra8_err_t err =
222 g_usb_pmsc_state.storage.get_inquiry(g_usb_pmsc_state.storage.ctx,
223 &data_buf[k_ra8_pmsc_inq_off_vendor],
225 &data_buf[k_ra8_pmsc_inq_off_revision]);
226 if (err != k_ra8_ok) {
227 return err;
228 }
229 *out_len = (uint32_t)k_ra8_pmsc_inquiry_resp_len;
230 return k_ra8_ok;
231}
232
233ra8_err_t priv_handle_read_capacity(uint8_t* data_buf, uint32_t capacity, uint32_t* out_len)
234{
235 if (capacity < k_ra8_pmsc_read_capacity_resp_len) {
237 }
238 uint32_t block_count = 0U;
239 uint32_t block_size = 0U;
240 const ra8_err_t err =
241 g_usb_pmsc_state.storage.get_capacity(g_usb_pmsc_state.storage.ctx, &block_count, &block_size);
242 if (err != k_ra8_ok) {
243 return err;
244 }
245 /* Block count of zero is meaningless; degrade gracefully. */
246 const uint32_t last_lba = (block_count == 0U) ? 0U : (block_count - 1U);
250 *out_len = (uint32_t)k_ra8_pmsc_read_capacity_resp_len;
251 return k_ra8_ok;
252}
253
254ra8_err_t priv_handle_request_sense(uint8_t* data_buf, uint32_t capacity, uint32_t* out_len)
255{
256 if (capacity < k_ra8_pmsc_request_sense_resp_len) {
258 }
260 /* Byte 0 = response code (0x70 current error, valid bit clear). */
261 data_buf[0] = k_ra8_pmsc_sense_resp_code;
262 /* Byte 7 = additional sense length (n - 7 = 10). */
264 *out_len = (uint32_t)k_ra8_pmsc_request_sense_resp_len;
265 return k_ra8_ok;
266}
267
268ra8_err_t priv_handle_mode_sense(uint8_t* data_buf, uint32_t capacity, uint32_t* out_len)
269{
270 if (capacity < k_ra8_pmsc_mode_sense_resp_len) {
272 }
274 /* Mode data length (3, header-only response). */
276 *out_len = (uint32_t)k_ra8_pmsc_mode_sense_resp_len;
277 return k_ra8_ok;
278}
279
280ra8_err_t priv_handle_read10(uint8_t* data_buf, uint32_t capacity, uint32_t* out_len)
281{
282 uint32_t lba = 0U;
283 uint32_t block_count = 0U;
284 internal_decode_rw10(g_usb_pmsc_state.cbw_cdb, &lba, &block_count);
285 if (block_count == 0U) {
286 *out_len = 0U;
287 return k_ra8_ok;
288 }
289 uint32_t device_block_count = 0U;
290 uint32_t block_size = 0U;
291 const ra8_err_t cap_err = g_usb_pmsc_state.storage.get_capacity(g_usb_pmsc_state.storage.ctx,
292 &device_block_count,
293 &block_size);
294 if (cap_err != k_ra8_ok) {
295 return cap_err;
296 }
297 if (block_size == 0U) {
298 block_size = (uint32_t)k_ra8_pmsc_block_size_default;
299 }
300 const uint32_t bytes = block_count * block_size;
301 if (bytes > capacity) {
303 }
304 const ra8_err_t err =
305 g_usb_pmsc_state.storage.read_block(g_usb_pmsc_state.storage.ctx, lba, block_count, data_buf);
306 if (err != k_ra8_ok) {
307 return err;
308 }
309 *out_len = bytes;
310 return k_ra8_ok;
311}
312
313ra8_err_t priv_handle_write10(const uint8_t* data_buf, uint32_t* out_len)
314{
315 uint32_t lba = 0U;
316 uint32_t block_count = 0U;
317 internal_decode_rw10(g_usb_pmsc_state.cbw_cdb, &lba, &block_count);
318 if (block_count == 0U) {
319 *out_len = 0U;
320 return k_ra8_ok;
321 }
322 uint32_t device_block_count = 0U;
323 uint32_t block_size = 0U;
324 const ra8_err_t cap_err = g_usb_pmsc_state.storage.get_capacity(g_usb_pmsc_state.storage.ctx,
325 &device_block_count,
326 &block_size);
327 if (cap_err != k_ra8_ok) {
328 return cap_err;
329 }
330 if (block_size == 0U) {
331 block_size = (uint32_t)k_ra8_pmsc_block_size_default;
332 }
333 const ra8_err_t err =
334 g_usb_pmsc_state.storage.write_block(g_usb_pmsc_state.storage.ctx, lba, block_count, data_buf);
335 if (err != k_ra8_ok) {
336 return err;
337 }
338 *out_len = block_count * block_size;
339 return k_ra8_ok;
340}
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Error Code Definitions for ra8-firmware.
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ k_ra8_err_invalid_size
Invalid size parameter (too large, too small, or misaligned).
Definition ra8_err.h:167
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
Native USB controller driver public API (device + host modes).
void priv_zero_bytes(uint8_t *dst, uint32_t len)
Zero len bytes at dst byte-by-byte.
ra8_usb_pmsc_state_data_t g_usb_pmsc_state
Singleton shadow state shared by both device-MSC TUs.
Native USB device-side MSC (Mass Storage Class) class layer.
@ k_ra8_pmsc_inq_revision_len
Revision byte count.
@ k_ra8_pmsc_inq_vendor_len
Vendor ID byte count.
@ k_ra8_pmsc_inq_product_len
Product ID byte count.
@ k_ra8_pmsc_read_capacity_resp_len
READ_CAPACITY(10).
@ k_ra8_pmsc_request_sense_resp_len
REQUEST SENSE response.
@ k_ra8_pmsc_inquiry_resp_len
INQUIRY response len.
@ k_ra8_pmsc_block_size_default
SCSI default block.
@ k_ra8_pmsc_mode_sense_resp_len
MODE SENSE(6) response.
Cross-TU surface shared between the device-MSC BOT statemachine (ra8_usb_pmsc.c) and the SCSI command...
@ k_ra8_pmsc_shift_byte3
RA8 pmsc shift byte3.
@ k_ra8_pmsc_shift_byte1
RA8 pmsc shift byte1.
@ k_ra8_pmsc_shift_byte0
RA8 pmsc shift byte0.
@ k_ra8_pmsc_shift_byte2
RA8 pmsc shift byte2.
@ k_ra8_pmsc_byte_mask
RA8 pmsc byte mask.
ra8_usb_pmsc_inquiry_offset_t
Byte offsets inside the SBC-4 standard INQUIRY response the device returns.
@ k_ra8_pmsc_inq_off_removable
Byte 1 (removable).
@ k_ra8_pmsc_inq_off_addl_length
Byte 4 (addl length).
@ k_ra8_pmsc_inq_off_dev_type
Byte 0 (qual+devtype).
@ k_ra8_pmsc_inq_off_resp_format
Byte 3 (resp format).
@ k_ra8_pmsc_inq_off_version
Byte 2 (SPC version).
@ k_ra8_pmsc_inq_off_revision
Product revision.
@ k_ra8_pmsc_inq_off_vendor
Vendor ID start.
@ k_ra8_pmsc_inq_off_product
Product ID start.
ra8_err_t priv_handle_write10(const uint8_t *data_buf, uint32_t *out_len)
Run a SCSI WRITE(10) – the data buffer holds the host-supplied payload.
ra8_usb_pmsc_cdb_offset_t
SCSI CDB byte offsets used when decoding READ(10) / WRITE(10) blocks.
@ k_ra8_pmsc_cdb_off_cnt_lsb
READ(10): count low.
@ k_ra8_pmsc_cdb_off_lba_msb
READ(10): LBA byte 3.
@ k_ra8_pmsc_cdb_off_lba_lsb
READ(10): LBA byte 0.
@ k_ra8_pmsc_cdb_off_cnt_msb
READ(10): count high.
@ k_ra8_pmsc_cdb_off_lba_b1
READ(10): LBA byte 2.
@ k_ra8_pmsc_cdb_off_lba_b2
READ(10): LBA byte 1.
ra8_err_t priv_handle_read10(uint8_t *data_buf, uint32_t capacity, uint32_t *out_len)
Run a SCSI READ(10).
static void internal_pad_space(uint8_t *dst, uint32_t len)
Fill len bytes at dst with ASCII SPACE.
ra8_err_t priv_handle_inquiry(uint8_t *data_buf, uint32_t capacity, uint32_t *out_len)
Build the 36-byte SCSI INQUIRY response.
ra8_usb_pmsc_inquiry_byte_t
Pre-canned values for the standard INQUIRY response bytes.
@ k_ra8_pmsc_inq_byte_addl_length
36 - 5 = 31.
@ k_ra8_pmsc_inq_byte_resp_format
Current format.
@ k_ra8_pmsc_inq_byte_removable
Removable bit set.
@ k_ra8_pmsc_inq_byte_dev_type
Direct-access block.
@ k_ra8_pmsc_inq_byte_version
SPC-4.
ra8_usb_pmsc_ascii_t
ASCII constant used for SPACE-padding INQUIRY string fields.
@ k_ra8_pmsc_ascii_space
ASCII SPACE.
ra8_err_t priv_handle_mode_sense(uint8_t *data_buf, uint32_t capacity, uint32_t *out_len)
Build the minimal 4-byte MODE SENSE(6) header response.
ra8_err_t priv_handle_request_sense(uint8_t *data_buf, uint32_t capacity, uint32_t *out_len)
Build the 18-byte REQUEST SENSE response.
ra8_usb_pmsc_sense_t
Pre-canned values for the SCSI REQUEST SENSE response and the minimal MODE SENSE(6) header.
@ k_ra8_pmsc_sense_resp_code
Current error, valid clr.
@ k_ra8_pmsc_sense_addl_length_value
Additional length = 10.
@ k_ra8_pmsc_mode_data_length_value
Mode data len (3, hdr-only).
@ k_ra8_pmsc_sense_addl_length_byte
Byte index of addl-len.
ra8_usb_pmsc_capacity_offset_t
Byte offsets inside the SCSI READ_CAPACITY(10) 8-byte response (SBC-4 sec 5.10).
@ k_ra8_pmsc_cap_off_last_lba
Last valid LBA (big-endian).
@ k_ra8_pmsc_cap_off_blk_size
Block length (big-endian).
static void internal_decode_rw10(const uint8_t *cdb, uint32_t *out_lba, uint32_t *out_block_count)
Decode a 10-byte READ(10) / WRITE(10) CDB.
ra8_err_t priv_handle_read_capacity(uint8_t *data_buf, uint32_t capacity, uint32_t *out_len)
Build the 8-byte READ_CAPACITY(10) response.
static void internal_pack_u32_be(uint32_t value, uint8_t *dst)
Pack a uint32 into 4 big-endian bytes (SCSI on-wire order).