ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_usb_pmsc_scsi.c File Reference

Native USB device-side MSC (Mass Storage Class) SCSI command handlers. More...

#include <stdint.h>
#include "ra8_attributes.h"
#include "ra8_err.h"
#include "ra8_usb.h"
#include "ra8_usb_pmsc.h"
#include "ra8_usb_pmsc_internal.h"
Include dependency graph for ra8_usb_pmsc_scsi.c:

Go to the source code of this file.

Enumerations

enum  ra8_usb_pmsc_cdb_offset_t : uint8_t {
  k_ra8_pmsc_cdb_off_lba_msb = 2U ,
  k_ra8_pmsc_cdb_off_lba_b1 = 3U ,
  k_ra8_pmsc_cdb_off_lba_b2 = 4U ,
  k_ra8_pmsc_cdb_off_lba_lsb = 5U ,
  k_ra8_pmsc_cdb_off_cnt_msb = 7U ,
  k_ra8_pmsc_cdb_off_cnt_lsb = 8U
}
 SCSI CDB byte offsets used when decoding READ(10) / WRITE(10) blocks. More...
enum  ra8_usb_pmsc_inquiry_offset_t : uint8_t {
  k_ra8_pmsc_inq_off_dev_type = 0U ,
  k_ra8_pmsc_inq_off_removable = 1U ,
  k_ra8_pmsc_inq_off_version = 2U ,
  k_ra8_pmsc_inq_off_resp_format = 3U ,
  k_ra8_pmsc_inq_off_addl_length = 4U ,
  k_ra8_pmsc_inq_off_vendor = 8U ,
  k_ra8_pmsc_inq_off_product = 16U ,
  k_ra8_pmsc_inq_off_revision = 32U
}
 Byte offsets inside the SBC-4 standard INQUIRY response the device returns. More...
enum  ra8_usb_pmsc_inquiry_byte_t : uint8_t {
  k_ra8_pmsc_inq_byte_dev_type = 0x00U ,
  k_ra8_pmsc_inq_byte_removable = 0x80U ,
  k_ra8_pmsc_inq_byte_version = 0x04U ,
  k_ra8_pmsc_inq_byte_resp_format = 0x02U ,
  k_ra8_pmsc_inq_byte_addl_length = 0x1FU
}
 Pre-canned values for the standard INQUIRY response bytes. More...
enum  ra8_usb_pmsc_capacity_offset_t : uint8_t {
  k_ra8_pmsc_cap_off_last_lba = 0U ,
  k_ra8_pmsc_cap_off_blk_size = 4U
}
 Byte offsets inside the SCSI READ_CAPACITY(10) 8-byte response (SBC-4 sec 5.10). More...
enum  ra8_usb_pmsc_sense_t : uint8_t {
  k_ra8_pmsc_sense_resp_code = 0x70U ,
  k_ra8_pmsc_sense_addl_length_byte = 7U ,
  k_ra8_pmsc_sense_addl_length_value = 0x0AU ,
  k_ra8_pmsc_mode_data_length_value = 0x03U
}
 Pre-canned values for the SCSI REQUEST SENSE response and the minimal MODE SENSE(6) header. More...
enum  ra8_usb_pmsc_ascii_t : uint8_t { k_ra8_pmsc_ascii_space = 0x20U }
 ASCII constant used for SPACE-padding INQUIRY string fields. More...

Functions

static void internal_pack_u32_be (uint32_t value, uint8_t *dst)
 Pack a uint32 into 4 big-endian bytes (SCSI on-wire order).
static void internal_pad_space (uint8_t *dst, uint32_t len)
 Fill len bytes at dst with ASCII SPACE.
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_inquiry (uint8_t *data_buf, uint32_t capacity, uint32_t *out_len)
 Build the 36-byte SCSI INQUIRY response.
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.
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_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_read10 (uint8_t *data_buf, uint32_t capacity, uint32_t *out_len)
 Run a SCSI READ(10).
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.

Detailed Description

Native USB device-side MSC (Mass Storage Class) SCSI command handlers.

Tag
[Ring 3 / HAL] {World: NS}

Companion translation unit to ra8_usb_pmsc.c. Holds the SCSI command handlers (INQUIRY, READ_CAPACITY(10), REQUEST SENSE, MODE SENSE(6), READ(10), WRITE(10)) that the BOT dispatcher in ra8_usb_pmsc.c invokes once a CDB has been decoded. The two TUs share the g_usb_pmsc_state shadow singleton and a handful of serialisation helpers via ra8_usb_pmsc_internal.h. FSP's pmsc_atapi_command_processing is reference material only – no FSP source is pulled in verbatim.

Definition in file ra8_usb_pmsc_scsi.c.

Enumeration Type Documentation

◆ ra8_usb_pmsc_ascii_t

enum ra8_usb_pmsc_ascii_t : uint8_t

ASCII constant used for SPACE-padding INQUIRY string fields.

Enumerator
k_ra8_pmsc_ascii_space 

ASCII SPACE.

Definition at line 120 of file ra8_usb_pmsc_scsi.c.

◆ ra8_usb_pmsc_capacity_offset_t

Byte offsets inside the SCSI READ_CAPACITY(10) 8-byte response (SBC-4 sec 5.10).

Enumerator
k_ra8_pmsc_cap_off_last_lba 

Last valid LBA (big-endian).

k_ra8_pmsc_cap_off_blk_size 

Block length (big-endian).

Definition at line 95 of file ra8_usb_pmsc_scsi.c.

◆ ra8_usb_pmsc_cdb_offset_t

enum ra8_usb_pmsc_cdb_offset_t : uint8_t

SCSI CDB byte offsets used when decoding READ(10) / WRITE(10) blocks.

The operation-code offset (byte 0) is shared with the BOT dispatcher and lives in ra8_usb_pmsc_internal.h as k_ra8_pmsc_cdb_off_opcode.

Enumerator
k_ra8_pmsc_cdb_off_lba_msb 

READ(10): LBA byte 3.

k_ra8_pmsc_cdb_off_lba_b1 

READ(10): LBA byte 2.

k_ra8_pmsc_cdb_off_lba_b2 

READ(10): LBA byte 1.

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_cnt_lsb 

READ(10): count low.

Definition at line 45 of file ra8_usb_pmsc_scsi.c.

◆ ra8_usb_pmsc_inquiry_byte_t

Pre-canned values for the standard INQUIRY response bytes.

See SBC-4 sec 6.6 + SPC-4 sec 6.6:

  • byte 0: peripheral qualifier 0 + peripheral device type 0 (direct-access block device).
  • byte 1: bit 7 = 1 (removable medium).
  • byte 2: SPC version 4 (SPC-4).
  • byte 3: response data format 2 (current format).
  • byte 4: additional length n-4 = 31.
Enumerator
k_ra8_pmsc_inq_byte_dev_type 

Direct-access block.

k_ra8_pmsc_inq_byte_removable 

Removable bit set.

k_ra8_pmsc_inq_byte_version 

SPC-4.

k_ra8_pmsc_inq_byte_resp_format 

Current format.

k_ra8_pmsc_inq_byte_addl_length 

36 - 5 = 31.

Definition at line 82 of file ra8_usb_pmsc_scsi.c.

◆ ra8_usb_pmsc_inquiry_offset_t

Byte offsets inside the SBC-4 standard INQUIRY response the device returns.

Enumerator
k_ra8_pmsc_inq_off_dev_type 

Byte 0 (qual+devtype).

k_ra8_pmsc_inq_off_removable 

Byte 1 (removable).

k_ra8_pmsc_inq_off_version 

Byte 2 (SPC version).

k_ra8_pmsc_inq_off_resp_format 

Byte 3 (resp format).

k_ra8_pmsc_inq_off_addl_length 

Byte 4 (addl length).

k_ra8_pmsc_inq_off_vendor 

Vendor ID start.

k_ra8_pmsc_inq_off_product 

Product ID start.

k_ra8_pmsc_inq_off_revision 

Product revision.

Definition at line 59 of file ra8_usb_pmsc_scsi.c.

◆ ra8_usb_pmsc_sense_t

enum ra8_usb_pmsc_sense_t : uint8_t

Pre-canned values for the SCSI REQUEST SENSE response and the minimal MODE SENSE(6) header.

See SPC-4 sec 6.30 (REQUEST SENSE) and sec 6.11 (MODE SENSE). The starter does not track sense state so it always answers "no sense" with a current-error response code.

Enumerator
k_ra8_pmsc_sense_resp_code 

Current error, valid clr.

k_ra8_pmsc_sense_addl_length_byte 

Byte index of addl-len.

k_ra8_pmsc_sense_addl_length_value 

Additional length = 10.

k_ra8_pmsc_mode_data_length_value 

Mode data len (3, hdr-only).

Definition at line 109 of file ra8_usb_pmsc_scsi.c.

Function Documentation

◆ internal_decode_rw10()

void internal_decode_rw10 ( const uint8_t * cdb,
uint32_t * out_lba,
uint32_t * out_block_count )
static

Decode a 10-byte READ(10) / WRITE(10) CDB.

See implementation.

Parameters
[in]cdbSee implementation.
[in]out_lbaSee implementation.
[in]out_block_countSee implementation.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 192 of file ra8_usb_pmsc_scsi.c.

References k_ra8_pmsc_cdb_off_cnt_lsb, k_ra8_pmsc_cdb_off_cnt_msb, k_ra8_pmsc_cdb_off_lba_b1, k_ra8_pmsc_cdb_off_lba_b2, k_ra8_pmsc_cdb_off_lba_lsb, k_ra8_pmsc_cdb_off_lba_msb, k_ra8_pmsc_shift_byte0, k_ra8_pmsc_shift_byte1, k_ra8_pmsc_shift_byte2, and k_ra8_pmsc_shift_byte3.

Referenced by priv_handle_read10(), and priv_handle_write10().

◆ internal_pack_u32_be()

void internal_pack_u32_be ( uint32_t value,
uint8_t * dst )
static

Pack a uint32 into 4 big-endian bytes (SCSI on-wire order).

See implementation.

Parameters
[in]valueSee implementation.
[in]dstSee implementation.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 143 of file ra8_usb_pmsc_scsi.c.

References k_ra8_pmsc_byte_mask, k_ra8_pmsc_shift_byte0, k_ra8_pmsc_shift_byte1, k_ra8_pmsc_shift_byte2, and k_ra8_pmsc_shift_byte3.

Referenced by priv_handle_read_capacity().

◆ internal_pad_space()

void internal_pad_space ( uint8_t * dst,
uint32_t len )
static

Fill len bytes at dst with ASCII SPACE.

See implementation.

Parameters
[in]dstSee implementation.
[in]lenSee implementation.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 165 of file ra8_usb_pmsc_scsi.c.

References k_ra8_pmsc_ascii_space.

Referenced by priv_handle_inquiry().

◆ priv_handle_inquiry()

ra8_err_t priv_handle_inquiry ( uint8_t * data_buf,
uint32_t capacity,
uint32_t * out_len )

Build the 36-byte SCSI INQUIRY response.

Asks the storage backend for the three ASCII strings (vendor, product, revision) and bakes them into the response per SBC-4 sec 6.6. SPACE-padding is applied if the backend returns a shorter string.

Parameters
[out]data_bufDestination response buffer.
[in]capacityCapacity of data_buf in bytes.
[out]out_lenReceives the response length.
Returns
Result code.
Return values
k_ra8_okOperation succeeded.
k_ra8_err_invalid_sizeBuffer too small.
Precondition
Module state is consistent.
Storage backend is attached.
Postcondition
Caller-visible state matches the documented contract.
*out_len holds the response length on success.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 202 of file ra8_usb_pmsc_scsi.c.

References g_usb_pmsc_state, internal_pad_space(), k_ra8_err_invalid_size, k_ra8_ok, k_ra8_pmsc_inq_byte_addl_length, k_ra8_pmsc_inq_byte_dev_type, k_ra8_pmsc_inq_byte_removable, k_ra8_pmsc_inq_byte_resp_format, k_ra8_pmsc_inq_byte_version, k_ra8_pmsc_inq_off_addl_length, k_ra8_pmsc_inq_off_dev_type, k_ra8_pmsc_inq_off_product, k_ra8_pmsc_inq_off_removable, k_ra8_pmsc_inq_off_resp_format, k_ra8_pmsc_inq_off_revision, k_ra8_pmsc_inq_off_vendor, k_ra8_pmsc_inq_off_version, k_ra8_pmsc_inq_product_len, k_ra8_pmsc_inq_revision_len, k_ra8_pmsc_inq_vendor_len, k_ra8_pmsc_inquiry_resp_len, and priv_zero_bytes().

Referenced by internal_dispatch_scsi().

◆ priv_handle_mode_sense()

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.

Per SPC-4 sec 6.11 a header-only response is legal when no descriptors / pages are present. Byte 0 = mode data length (3). Byte 1 = medium type (0). Byte 2 = device-specific parameter (0). Byte 3 = block descriptor length (0).

Parameters
[out]data_bufDestination response buffer.
[in]capacityCapacity of data_buf in bytes.
[out]out_lenReceives the response length.
Returns
Result code.
Return values
k_ra8_okOperation succeeded.
k_ra8_err_invalid_sizeBuffer too small.
Precondition
Module state is consistent.
Storage backend is attached.
Postcondition
Caller-visible state matches the documented contract.
*out_len holds the response length on success.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 268 of file ra8_usb_pmsc_scsi.c.

References k_ra8_err_invalid_size, k_ra8_ok, k_ra8_pmsc_mode_data_length_value, k_ra8_pmsc_mode_sense_resp_len, and priv_zero_bytes().

Referenced by internal_dispatch_scsi().

◆ priv_handle_read10()

ra8_err_t priv_handle_read10 ( uint8_t * data_buf,
uint32_t capacity,
uint32_t * out_len )

Run a SCSI READ(10).

Decodes the cached READ(10) CDB, asks the backend for the geometry, and reads the requested blocks into data_buf.

Parameters
[out]data_bufDestination data buffer.
[in]capacityCapacity of data_buf in bytes.
[out]out_lenReceives the transferred byte count.
Returns
Result code.
Return values
k_ra8_okOperation succeeded.
k_ra8_err_invalid_sizeBuffer too small for the read.
Precondition
Module state is consistent.
Storage backend is attached.
Postcondition
Caller-visible state matches the documented contract.
*out_len holds the transferred byte count on success.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 280 of file ra8_usb_pmsc_scsi.c.

References g_usb_pmsc_state, internal_decode_rw10(), k_ra8_err_invalid_size, k_ra8_ok, and k_ra8_pmsc_block_size_default.

Referenced by internal_dispatch_scsi().

◆ priv_handle_read_capacity()

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.

Per SBC-4 sec 5.10 the response is the LAST valid LBA (block_count - 1, big-endian) followed by the block size (big-endian).

Parameters
[out]data_bufDestination response buffer.
[in]capacityCapacity of data_buf in bytes.
[out]out_lenReceives the response length.
Returns
Result code.
Return values
k_ra8_okOperation succeeded.
k_ra8_err_invalid_sizeBuffer too small.
Precondition
Module state is consistent.
Storage backend is attached.
Postcondition
Caller-visible state matches the documented contract.
*out_len holds the response length on success.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 233 of file ra8_usb_pmsc_scsi.c.

References g_usb_pmsc_state, internal_pack_u32_be(), k_ra8_err_invalid_size, k_ra8_ok, k_ra8_pmsc_cap_off_blk_size, k_ra8_pmsc_cap_off_last_lba, k_ra8_pmsc_read_capacity_resp_len, and priv_zero_bytes().

Referenced by internal_dispatch_scsi().

◆ priv_handle_request_sense()

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.

Per SPC-4 sec 6.30 the device returns "no sense" (0x00) once the CHECK CONDITION has been cleared. The starter does not track sense state; it always answers "no sense" so subsequent commands proceed.

Parameters
[out]data_bufDestination response buffer.
[in]capacityCapacity of data_buf in bytes.
[out]out_lenReceives the response length.
Returns
Result code.
Return values
k_ra8_okOperation succeeded.
k_ra8_err_invalid_sizeBuffer too small.
Precondition
Module state is consistent.
Storage backend is attached.
Postcondition
Caller-visible state matches the documented contract.
*out_len holds the response length on success.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 254 of file ra8_usb_pmsc_scsi.c.

References k_ra8_err_invalid_size, k_ra8_ok, k_ra8_pmsc_request_sense_resp_len, k_ra8_pmsc_sense_addl_length_byte, k_ra8_pmsc_sense_addl_length_value, k_ra8_pmsc_sense_resp_code, and priv_zero_bytes().

Referenced by internal_dispatch_scsi().

◆ priv_handle_write10()

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.

Decodes the cached WRITE(10) CDB, asks the backend for the geometry, and writes the supplied blocks through the backend.

Parameters
[in]data_bufHost-supplied payload buffer.
[out]out_lenReceives the transferred byte count.
Returns
Result code.
Return values
k_ra8_okOperation succeeded.
Precondition
Module state is consistent.
Storage backend is attached.
Postcondition
Caller-visible state matches the documented contract.
*out_len holds the transferred byte count on success.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 313 of file ra8_usb_pmsc_scsi.c.

References g_usb_pmsc_state, internal_decode_rw10(), k_ra8_ok, and k_ra8_pmsc_block_size_default.

Referenced by internal_dispatch_scsi().