ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
usb_host_msc_browse_steps.c
Go to the documentation of this file.
1
27
29
30#include <stdint.h>
31#include <string.h>
32
33#ifndef RA8_OFF_TARGET
34
35#include "ra8_board_ek_ra8d2.h"
36#include "ux_api.h"
37#include "ux_device_class_storage.h"
38
39/* SCSI sense triple for an unsupported / out-of-range request. */
45
47typedef enum : uint8_t {
51
71
76typedef enum : uint32_t {
78 k_word_mask = 0xFFFFU,
80
82static const UCHAR s_fat_oem_name[8] = {'R', 'A', '8', 'D', '2', 'F', 'W', ' '};
83
85static const UCHAR s_fat_volume_label[11] = {'R', 'A', '8', 'D', '2', ' ', 'M', 'R', 'A', 'M', ' '};
86
88static const UCHAR s_fat_fs_type[8] = {'F', 'A', 'T', '1', '6', ' ', ' ', ' '};
89
91static const UCHAR s_fat_file_name[11] = {'M', 'R', 'A', 'M', ' ', ' ', ' ', ' ', 'B', 'I', 'N'};
92
94static volatile uint32_t s_dbg_read_calls;
95
96/* -------------------------------------------------------------------------- */
97/* FAT16 synthesis (identical layout to usb_msc_mram) */
98/* -------------------------------------------------------------------------- */
99
116static void selftest_put16(UCHAR* dst, uint16_t value)
117{
118 dst[0] = (UCHAR)(value & (uint16_t)k_byte_mask);
119 dst[1] = (UCHAR)((value >> (uint16_t)k_byte_shift) & (uint16_t)k_byte_mask);
120}
121
138static void selftest_put32(UCHAR* dst, uint32_t value)
139{
140 selftest_put16(dst, (uint16_t)(value & (uint32_t)k_word_mask));
141 selftest_put16(dst + 2U, (uint16_t)(value >> (uint32_t)k_word_shift));
142}
143
160static void selftest_fat_fill_boot(UCHAR* out)
161{
162 out[k_bpb_off_jmp] = (UCHAR)k_boot_jmp0;
163 out[k_bpb_off_jmp + 1U] = (UCHAR)k_boot_jmp1;
164 out[k_bpb_off_jmp + 2U] = (UCHAR)k_boot_jmp2;
165 (void)memcpy(&out[k_bpb_off_oem], s_fat_oem_name, sizeof(s_fat_oem_name));
167 out[k_bpb_off_spc] = 1U;
169 out[k_bpb_off_nfats] = (UCHAR)k_fat_num_fats;
172 out[k_bpb_off_media] = (UCHAR)k_boot_media;
177 out[k_bpb_off_bootsig] = (UCHAR)k_boot_ext_sig;
180 (void)memcpy(&out[k_bpb_off_fstype], s_fat_fs_type, sizeof(s_fat_fs_type));
181 out[k_boot_sig_lo_off] = (UCHAR)k_boot_sig_lo;
182 out[k_boot_sig_hi_off] = (UCHAR)k_boot_sig_hi;
183}
184
204static void selftest_fat_fill_fat(uint32_t fat_sector, UCHAR* out)
205{
206 const uint32_t first_entry = fat_sector * (uint32_t)k_fat_entries_per_sec;
207 for (uint32_t j = 0U; j < (uint32_t)k_fat_entries_per_sec; j++) {
208 const uint32_t entry = first_entry + j;
209 uint16_t value = 0U;
210 if (entry < (uint32_t)k_fat_first_cluster) {
211 value = (entry == 0U) ? (uint16_t)k_fat_entry0 : (uint16_t)k_fat_eoc;
212 } else if (entry < (uint32_t)k_fat_last_mram_clus) {
213 value = (uint16_t)(entry + 1U);
214 } else if (entry == (uint32_t)k_fat_last_mram_clus) {
215 value = (uint16_t)k_fat_eoc;
216 } else {
217 value = 0U;
218 }
219 selftest_put16(&out[j * 2U], value);
220 }
221}
222
241static void selftest_fat_fill_root(uint32_t root_sector, UCHAR* out)
242{
243 if (root_sector != 0U) {
244 return;
245 }
246 /* Entry 0: volume label. */
247 (void)memcpy(&out[0], s_fat_volume_label, (size_t)k_dir_name_bytes);
248 out[k_dir_off_attr] = (UCHAR)k_dir_attr_volume;
249 /* Entry 1: MRAM.BIN, read-only, cluster 2, 1 MiB. */
250 UCHAR* entry = &out[k_dir_entry_bytes];
251 (void)memcpy(entry, s_fat_file_name, (size_t)k_dir_name_bytes);
252 entry[k_dir_off_attr] = (UCHAR)k_dir_attr_read_only;
254 selftest_put32(&entry[k_dir_off_size], (uint32_t)k_mram_bytes);
255}
256
276static void selftest_fat_fill_sector(uint32_t lba, UCHAR* out)
277{
278 (void)memset(out, 0, (size_t)k_selftest_block_size);
279 if (lba == 0U) {
281 return;
282 }
283 if (lba < (uint32_t)k_fat_root_lba) {
284 selftest_fat_fill_fat(lba - (uint32_t)k_fat_fat_lba, out);
285 return;
286 }
287 if (lba < (uint32_t)k_fat_data_lba) {
288 selftest_fat_fill_root(lba - (uint32_t)k_fat_root_lba, out);
289 return;
290 }
291 const uint32_t cluster = (lba - (uint32_t)k_fat_data_lba) + (uint32_t)k_fat_first_cluster;
292 if (cluster <= (uint32_t)k_fat_last_mram_clus) {
293 const uint32_t offset =
294 (cluster - (uint32_t)k_fat_first_cluster) * (uint32_t)k_selftest_block_size;
295 const UCHAR* mram = (const UCHAR*)(uintptr_t)((uint32_t)k_mram_base_addr + offset);
296 (void)memcpy(out, mram, (size_t)k_selftest_block_size);
297 }
298}
299
300/* -------------------------------------------------------------------------- */
301/* Storage class media callbacks (read / write / status) */
302/* -------------------------------------------------------------------------- */
303
305 ULONG lun,
306 UCHAR* data_pointer,
307 ULONG number_blocks,
308 ULONG lba,
309 ULONG* media_status)
310{
311 (void)storage;
312 (void)lun;
314 if ((lba + number_blocks) > (ULONG)k_fat_total_sectors) {
315 *media_status = UX_DEVICE_CLASS_STORAGE_SENSE_STATUS(k_scsi_sense_illegal_request,
318 return UX_ERROR;
319 }
320 for (ULONG i = 0UL; i < number_blocks; i++) {
321 selftest_fat_fill_sector((uint32_t)(lba + i), &data_pointer[i * (ULONG)k_selftest_block_size]);
322 }
323 *media_status = 0UL;
325 return UX_SUCCESS;
326}
327
329 VOID* storage,
330 ULONG lun,
331 UCHAR* data_pointer, // NOLINT(readability-non-const-parameter) -- USBX media-write callback ABI.
332 ULONG number_blocks,
333 ULONG lba,
334 ULONG* media_status)
335{
336 (void)storage;
337 (void)lun;
338 (void)data_pointer;
339 (void)number_blocks;
340 (void)lba;
341 *media_status = UX_DEVICE_CLASS_STORAGE_SENSE_STATUS(k_scsi_sense_data_protect,
344 return UX_ERROR;
345}
346
347UINT selftest_msc_status(VOID* storage, ULONG lun, ULONG media_id, ULONG* media_status)
348{
349 (void)storage;
350 (void)lun;
351 (void)media_id;
352 *media_status = 0UL;
353 return UX_SUCCESS;
354}
355
356#endif /* !RA8_OFF_TARGET */
scsi_sense_code_t
SCSI sense triple for an unsupported / out-of-range request.
Definition main.c:144
@ k_scsi_ascq_none
ASCQ: none.
Definition main.c:147
@ k_scsi_asc_write_protected
ASC: WRITE PROTECTED.
Definition main.c:149
@ k_scsi_sense_illegal_request
Sense key: ILLEGAL REQUEST.
Definition main.c:145
@ k_scsi_sense_data_protect
Sense key: DATA PROTECT.
Definition main.c:148
@ k_scsi_asc_lba_out_of_range
ASC: LBA out of range.
Definition main.c:146
static volatile uint32_t s_dbg_read_calls
Device-side media_read invocations.
Definition main.c:213
Board-support layer for the Renesas EK-RA8D2 v1 evaluation kit.
ra8_err_t ra8_board_led_toggle(ra8_board_led_id_t led)
Toggle led's output state.
@ k_ra8_board_led1
LED1, BLUE, P600 (jumper E27).
void * memset(void *dst, int value, size_t n)
Fill memory with a constant byte value.
void * memcpy(void *dst, const void *src, size_t n)
Copy memory area between non-overlapping regions.
@ k_dir_off_attr
MS FAT spec sec 6 "DIR_Attr".
@ k_byte_mask
Byte mask.
@ k_word_mask
Word mask.
unsigned int UINT
ThreadX-compatible unsigned int (host stub).
unsigned long ULONG
ThreadX-compatible unsigned long (host stub).
scsi_wp_sense_t
SCSI sense triple for a write to the protected medium.
static const UCHAR s_fat_oem_name[8]
Boot-sector OEM name (8 bytes, space padded).
static const UCHAR s_fat_fs_type[8]
Filesystem-type tag, 8 bytes space padded.
UINT selftest_msc_status(VOID *storage, ULONG lun, ULONG media_id, ULONG *media_status)
Storage media-status callback.
static void selftest_put16(UCHAR *dst, uint16_t value)
Write a 16-bit value little-endian into a byte buffer.
static const UCHAR s_fat_volume_label[11]
Volume label, 11 bytes space padded (also the root entry).
static void selftest_fat_fill_root(uint32_t root_sector, UCHAR *out)
Synthesize one root-directory sector.
selftest_fat_boot_t
Boot-sector field values (MS FAT spec 1.03 sec 3.1).
@ k_boot_sig_hi_off
Signature high-byte offset.
@ k_boot_jmp0
Short JMP opcode.
@ k_boot_num_heads
Geometry filler.
@ k_boot_sig_lo_off
Signature low-byte offset.
@ k_boot_sig_hi
Boot signature high byte.
@ k_boot_jmp1
JMP displacement.
@ k_boot_sig_lo
Boot signature low byte.
@ k_boot_media
Fixed-disk media byte.
@ k_boot_sec_per_trk
Geometry filler.
@ k_boot_ext_sig
Extended boot signature.
@ k_boot_drive_num
BIOS drive number.
@ k_boot_jmp2
NOP.
@ k_boot_volume_id
Arbitrary volume serial.
static void selftest_fat_fill_sector(uint32_t lba, UCHAR *out)
Synthesize one 512-byte sector of the read-only volume.
UINT selftest_msc_read(VOID *storage, ULONG lun, UCHAR *data_pointer, ULONG number_blocks, ULONG lba, ULONG *media_status)
Storage media-read callback: synthesize sectors over MRAM.
static const UCHAR s_fat_file_name[11]
8.3 directory name of the exposed file: "MRAM.BIN".
static void selftest_fat_fill_boot(UCHAR *out)
Synthesize the FAT16 boot sector (MS FAT spec 1.03 sec 3.1).
static void selftest_fat_fill_fat(uint32_t fat_sector, UCHAR *out)
Synthesize one FAT16 sector of the cluster chain.
UINT selftest_msc_write(VOID *storage, ULONG lun, UCHAR *data_pointer, ULONG number_blocks, ULONG lba, ULONG *media_status)
Storage media-write callback: always rejects (write-protected).
static void selftest_put32(UCHAR *dst, uint32_t value)
Write a 32-bit value little-endian into a byte buffer.
selftest_word_pack_t
32-bit little-endian split constants.
@ k_word_shift
Bits per half-word.
Shared constants + device-side FAT16/MSC step declarations.
@ k_fat_root_entries
Root directory entries.
@ k_fat_eoc
End-of-chain marker.
@ k_fat_data_lba
First data sector (cluster 2).
@ k_fat_root_lba
First root-directory sector.
@ k_fat_fat_sectors
FAT16 size for 4098 entries.
@ k_fat_fat_lba
First FAT sector.
@ k_fat_first_cluster
FAT data area starts at cluster 2.
@ k_fat_entry0
FAT[0]: media F8 + filler.
@ k_fat_reserved_sectors
Boot sector only.
@ k_fat_entries_per_sec
FAT16 entries per 512-byte sector.
@ k_fat_total_sectors
1 + 17 + 32 + 4096.
@ k_fat_last_mram_clus
Last cluster of MRAM.BIN.
@ k_fat_num_fats
Single FAT copy.
@ k_dir_entry_bytes
Directory entry size.
@ k_bpb_off_spt
Sectors per track.
@ k_bpb_off_label
Volume label (11 bytes).
@ k_dir_attr_volume
Volume-label attribute.
@ k_bpb_off_media
Media descriptor.
@ k_bpb_off_bps
Bytes per sector.
@ k_dir_off_size
File size (32-bit LE).
@ k_bpb_off_jmp
Jump instruction.
@ k_bpb_off_heads
Head count.
@ k_bpb_off_oem
OEM name (8 bytes).
@ k_bpb_off_volid
Volume serial (4 bytes).
@ k_bpb_off_bootsig
Extended boot signature.
@ k_bpb_off_fatsz16
Sectors per FAT.
@ k_bpb_off_rsvd
Reserved sector count.
@ k_bpb_off_drvnum
Drive number.
@ k_bpb_off_fstype
Filesystem type (8 bytes).
@ k_bpb_off_rootent
Root entry count.
@ k_dir_name_bytes
8.3 name field length.
@ k_byte_shift
Bits per byte for LE packing.
@ k_dir_off_cluster_lo
First cluster (low word).
@ k_bpb_off_nfats
Number of FATs.
@ k_bpb_off_spc
Sectors per cluster.
@ k_bpb_off_totsec16
Total sectors (16-bit).
@ k_dir_attr_read_only
Read-only attribute.
@ k_mram_bytes
1 MiB window size.
@ k_mram_base_addr
MRAM code window base address.
@ k_selftest_block_size
SCSI logical block size (bytes).