From 87bd29fec2de3a2a825b242e7cbc69160c9bf5a6 Mon Sep 17 00:00:00 2001 From: Gabriel Somlo Date: Sun, 16 Jan 2022 19:42:41 -0500 Subject: [PATCH] software/fatfs: allow sata, [spi]sdcard disk ops to co-exist At the moment, sata and [spi]sdcard fatfs disk access methods are mutually exclusive, as their names collide with each other. Implement a DISKOPS structure with media-specific disk access methods, and a way for the boot code to specifiy which media type's methods to use when loading files into RAM at boot time. Signed-off-by: Gabriel Somlo --- litex/soc/software/bios/boot.c | 3 + litex/soc/software/libfatfs/diskio.h | 15 ++- litex/soc/software/libfatfs/ff.c | 127 ++++++++++--------- litex/soc/software/liblitesata/sata.c | 16 ++- litex/soc/software/liblitesata/sata.h | 1 + litex/soc/software/liblitesdcard/sdcard.c | 16 ++- litex/soc/software/liblitesdcard/sdcard.h | 1 + litex/soc/software/liblitesdcard/spisdcard.c | 16 ++- litex/soc/software/liblitesdcard/spisdcard.h | 1 + 9 files changed, 118 insertions(+), 78 deletions(-) diff --git a/litex/soc/software/bios/boot.c b/litex/soc/software/bios/boot.c index 82723b3c1..4e475fdfd 100644 --- a/litex/soc/software/bios/boot.c +++ b/litex/soc/software/bios/boot.c @@ -812,9 +812,11 @@ void sdcardboot(void) { #ifdef CSR_SPISDCARD_BASE printf("Booting from SDCard in SPI-Mode...\n"); + fatfs_set_ops_spisdcard(); /* use spisdcard disk access ops */ #endif #ifdef CSR_SDCORE_BASE printf("Booting from SDCard in SD-Mode...\n"); + fatfs_set_ops_sdcard(); /* use sdcard disk access ops */ #endif /* Boot from boot.json */ @@ -986,6 +988,7 @@ static void sataboot_from_bin(const char * filename) void sataboot(void) { printf("Booting from SATA...\n"); + fatfs_set_ops_sata(); /* use sata disk access ops */ /* Boot from boot.json */ printf("Booting from boot.json...\n"); diff --git a/litex/soc/software/libfatfs/diskio.h b/litex/soc/software/libfatfs/diskio.h index 94a14d154..709f4dc58 100644 --- a/litex/soc/software/libfatfs/diskio.h +++ b/litex/soc/software/libfatfs/diskio.h @@ -26,13 +26,16 @@ typedef enum { /*---------------------------------------*/ /* Prototypes for disk control functions */ +typedef struct { + DSTATUS (*disk_initialize) (BYTE pdrv); + DSTATUS (*disk_status) (BYTE pdrv); + DRESULT (*disk_read) (BYTE pdrv, BYTE* buff, LBA_t sector, UINT count); + DRESULT (*disk_write) (BYTE pdrv, const BYTE* buff, LBA_t sector, UINT count); + DRESULT (*disk_ioctl) (BYTE pdrv, BYTE cmd, void* buff); +} DISKOPS; -DSTATUS disk_initialize (BYTE pdrv); -DSTATUS disk_status (BYTE pdrv); -DRESULT disk_read (BYTE pdrv, BYTE* buff, LBA_t sector, UINT count); -DRESULT disk_write (BYTE pdrv, const BYTE* buff, LBA_t sector, UINT count); -DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff); - +/* Global disk control ops pointer */ +extern DISKOPS *FfDiskOps; /* Disk Status Bits (DSTATUS) */ #define STA_NOINIT 0x01 /* Drive not initialized */ diff --git a/litex/soc/software/libfatfs/ff.c b/litex/soc/software/libfatfs/ff.c index b8ac2e3ea..08ece07bd 100644 --- a/litex/soc/software/libfatfs/ff.c +++ b/litex/soc/software/libfatfs/ff.c @@ -22,6 +22,7 @@ #include "ff.h" /* Declarations of FatFs API */ #include "diskio.h" /* Declarations of device I/O functions */ +DISKOPS *FfDiskOps; /* Global pointer to disk control ops */ /*-------------------------------------------------------------------------- @@ -1077,10 +1078,10 @@ static FRESULT sync_window ( /* Returns FR_OK or FR_DISK_ERR */ if (fs->wflag) { /* Is the disk access window dirty? */ - if (disk_write(fs->pdrv, fs->win, fs->winsect, 1) == RES_OK) { /* Write it back into the volume */ + if (FfDiskOps->disk_write(fs->pdrv, fs->win, fs->winsect, 1) == RES_OK) { /* Write it back into the volume */ fs->wflag = 0; /* Clear window dirty flag */ if (fs->winsect - fs->fatbase < fs->fsize) { /* Is it in the 1st FAT? */ - if (fs->n_fats == 2) disk_write(fs->pdrv, fs->win, fs->winsect + fs->fsize, 1); /* Reflect it to 2nd FAT if needed */ + if (fs->n_fats == 2) FfDiskOps->disk_write(fs->pdrv, fs->win, fs->winsect + fs->fsize, 1); /* Reflect it to 2nd FAT if needed */ } } else { res = FR_DISK_ERR; @@ -1104,7 +1105,7 @@ static FRESULT move_window ( /* Returns FR_OK or FR_DISK_ERR */ res = sync_window(fs); /* Flush the window */ #endif if (res == FR_OK) { /* Fill sector window with new data */ - if (disk_read(fs->pdrv, fs->win, sect, 1) != RES_OK) { + if (FfDiskOps->disk_read(fs->pdrv, fs->win, sect, 1) != RES_OK) { sect = (LBA_t)0 - 1; /* Invalidate window if read data is not valid */ res = FR_DISK_ERR; } @@ -1141,11 +1142,11 @@ static FRESULT sync_fs ( /* Returns FR_OK or FR_DISK_ERR */ st_dword(fs->win + FSI_Nxt_Free, fs->last_clst); /* Write it into the FSInfo sector */ fs->winsect = fs->volbase + 1; - disk_write(fs->pdrv, fs->win, fs->winsect, 1); + FfDiskOps->disk_write(fs->pdrv, fs->win, fs->winsect, 1); fs->fsi_flag = 0; } /* Make sure that no pending write process in the lower layer */ - if (disk_ioctl(fs->pdrv, CTRL_SYNC, 0) != RES_OK) res = FR_DISK_ERR; + if (FfDiskOps->disk_ioctl(fs->pdrv, CTRL_SYNC, 0) != RES_OK) res = FR_DISK_ERR; } return res; @@ -1494,7 +1495,7 @@ static FRESULT remove_chain ( /* FR_OK(0):succeeded, !=0:error */ #if FF_USE_TRIM rt[0] = clst2sect(fs, scl); /* Start of data area to be freed */ rt[1] = clst2sect(fs, ecl) + fs->csize - 1; /* End of data area to be freed */ - disk_ioctl(fs->pdrv, CTRL_TRIM, rt); /* Inform storage device that the data in the block may be erased */ + FfDiskOps->disk_ioctl(fs->pdrv, CTRL_TRIM, rt); /* Inform storage device that the data in the block may be erased */ #endif scl = ecl = nxt; } @@ -1691,13 +1692,13 @@ static FRESULT dir_clear ( /* Returns FR_OK or FR_DISK_ERR */ if (szb > SS(fs)) { /* Buffer allocated? */ mem_set(ibuf, 0, szb); szb /= SS(fs); /* Bytes -> Sectors */ - for (n = 0; n < fs->csize && disk_write(fs->pdrv, ibuf, sect + n, szb) == RES_OK; n += szb) ; /* Fill the cluster with 0 */ + for (n = 0; n < fs->csize && FfDiskOps->disk_write(fs->pdrv, ibuf, sect + n, szb) == RES_OK; n += szb) ; /* Fill the cluster with 0 */ ff_memfree(ibuf); } else #endif { ibuf = fs->win; szb = 1; /* Use window buffer (many single-sector writes may take a time) */ - for (n = 0; n < fs->csize && disk_write(fs->pdrv, ibuf, sect + n, szb) == RES_OK; n += szb) ; /* Fill the cluster with 0 */ + for (n = 0; n < fs->csize && FfDiskOps->disk_write(fs->pdrv, ibuf, sect + n, szb) == RES_OK; n += szb) ; /* Fill the cluster with 0 */ } return (n == fs->csize) ? FR_OK : FR_DISK_ERR; } @@ -3397,7 +3398,7 @@ static FRESULT mount_volume ( /* FR_OK(0): successful, !=0: an error occurred */ mode &= (BYTE)~FA_READ; /* Desired access mode, write access or not */ if (fs->fs_type != 0) { /* If the volume has been mounted */ - stat = disk_status(fs->pdrv); + stat = FfDiskOps->disk_status(fs->pdrv); if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized */ if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) { /* Check write protection if needed */ return FR_WRITE_PROTECTED; @@ -3411,7 +3412,7 @@ static FRESULT mount_volume ( /* FR_OK(0): successful, !=0: an error occurred */ fs->fs_type = 0; /* Clear the filesystem object */ fs->pdrv = LD2PD(vol); /* Volume hosting physical drive */ - stat = disk_initialize(fs->pdrv); /* Initialize the physical drive */ + stat = FfDiskOps->disk_initialize(fs->pdrv); /* Initialize the physical drive */ if (stat & STA_NOINIT) { /* Check if the initialization succeeded */ return FR_NOT_READY; /* Failed to initialize due to no medium or hard error */ } @@ -3419,7 +3420,7 @@ static FRESULT mount_volume ( /* FR_OK(0): successful, !=0: an error occurred */ return FR_WRITE_PROTECTED; } #if FF_MAX_SS != FF_MIN_SS /* Get sector size (multiple sector size cfg only) */ - if (disk_ioctl(fs->pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK) return FR_DISK_ERR; + if (FfDiskOps->disk_ioctl(fs->pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK) return FR_DISK_ERR; if (SS(fs) > FF_MAX_SS || SS(fs) < FF_MIN_SS || (SS(fs) & (SS(fs) - 1))) return FR_DISK_ERR; #endif @@ -3607,7 +3608,7 @@ static FRESULT validate ( /* Returns FR_OK or FR_INVALID_OBJECT */ if (obj && obj->fs && obj->fs->fs_type && obj->id == obj->fs->id) { /* Test if the object is valid */ #if FF_FS_REENTRANT if (lock_fs(obj->fs)) { /* Obtain the filesystem object */ - if (!(disk_status(obj->fs->pdrv) & STA_NOINIT)) { /* Test if the phsical drive is kept initialized */ + if (!(FfDiskOps->disk_status(obj->fs->pdrv) & STA_NOINIT)) { /* Test if the phsical drive is kept initialized */ res = FR_OK; } else { unlock_fs(obj->fs, FR_OK); @@ -3616,7 +3617,7 @@ static FRESULT validate ( /* Returns FR_OK or FR_INVALID_OBJECT */ res = FR_TIMEOUT; } #else - if (!(disk_status(obj->fs->pdrv) & STA_NOINIT)) { /* Test if the phsical drive is kept initialized */ + if (!(FfDiskOps->disk_status(obj->fs->pdrv) & STA_NOINIT)) { /* Test if the phsical drive is kept initialized */ res = FR_OK; } #endif @@ -3857,7 +3858,7 @@ FRESULT f_open ( } else { fp->sect = sc + (DWORD)(ofs / SS(fs)); #if !FF_FS_TINY - if (disk_read(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) res = FR_DISK_ERR; + if (FfDiskOps->disk_read(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) res = FR_DISK_ERR; #endif } } @@ -3932,7 +3933,7 @@ FRESULT f_read ( if (csect + cc > fs->csize) { /* Clip at cluster boundary */ cc = fs->csize - csect; } - if (disk_read(fs->pdrv, rbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR); + if (FfDiskOps->disk_read(fs->pdrv, rbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR); #if !FF_FS_READONLY && FF_FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */ #if FF_FS_TINY if (fs->wflag && fs->winsect - sect < cc) { @@ -3951,11 +3952,11 @@ FRESULT f_read ( if (fp->sect != sect) { /* Load data sector if not in cache */ #if !FF_FS_READONLY if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */ - if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); + if (FfDiskOps->disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); fp->flag &= (BYTE)~FA_DIRTY; } #endif - if (disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Fill sector cache */ + if (FfDiskOps->disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Fill sector cache */ } #endif fp->sect = sect; @@ -4036,7 +4037,7 @@ FRESULT f_write ( if (fs->winsect == fp->sect && sync_window(fs) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Write-back sector cache */ #else if (fp->flag & FA_DIRTY) { /* Write-back sector cache */ - if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); + if (FfDiskOps->disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); fp->flag &= (BYTE)~FA_DIRTY; } #endif @@ -4048,7 +4049,7 @@ FRESULT f_write ( if (csect + cc > fs->csize) { /* Clip at cluster boundary */ cc = fs->csize - csect; } - if (disk_write(fs->pdrv, wbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR); + if (FfDiskOps->disk_write(fs->pdrv, wbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR); #if FF_FS_MINIMIZE <= 2 #if FF_FS_TINY if (fs->winsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */ @@ -4073,7 +4074,7 @@ FRESULT f_write ( #else if (fp->sect != sect && /* Fill sector cache with file data */ fp->fptr < fp->obj.objsize && - disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) { + FfDiskOps->disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) { ABORT(fs, FR_DISK_ERR); } #endif @@ -4118,7 +4119,7 @@ FRESULT f_sync ( if (fp->flag & FA_MODIFIED) { /* Is there any change to the file? */ #if !FF_FS_TINY if (fp->flag & FA_DIRTY) { /* Write-back cached data if needed */ - if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) LEAVE_FF(fs, FR_DISK_ERR); + if (FfDiskOps->disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) LEAVE_FF(fs, FR_DISK_ERR); fp->flag &= (BYTE)~FA_DIRTY; } #endif @@ -4462,11 +4463,11 @@ FRESULT f_lseek ( #if !FF_FS_TINY #if !FF_FS_READONLY if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */ - if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); + if (FfDiskOps->disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); fp->flag &= (BYTE)~FA_DIRTY; } #endif - if (disk_read(fs->pdrv, fp->buf, dsc, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Load current sector */ + if (FfDiskOps->disk_read(fs->pdrv, fp->buf, dsc, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Load current sector */ #endif fp->sect = dsc; } @@ -4542,11 +4543,11 @@ FRESULT f_lseek ( #if !FF_FS_TINY #if !FF_FS_READONLY if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */ - if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); + if (FfDiskOps->disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); fp->flag &= (BYTE)~FA_DIRTY; } #endif - if (disk_read(fs->pdrv, fp->buf, nsect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Fill sector cache */ + if (FfDiskOps->disk_read(fs->pdrv, fp->buf, nsect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Fill sector cache */ #endif fp->sect = nsect; } @@ -4901,7 +4902,7 @@ FRESULT f_truncate ( fp->flag |= FA_MODIFIED; #if !FF_FS_TINY if (res == FR_OK && (fp->flag & FA_DIRTY)) { - if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) { + if (FfDiskOps->disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) { res = FR_DISK_ERR; } else { fp->flag &= (BYTE)~FA_DIRTY; @@ -5654,11 +5655,11 @@ FRESULT f_forward ( if (fp->sect != sect) { /* Fill sector cache with file data */ #if !FF_FS_READONLY if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */ - if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); + if (FfDiskOps->disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); fp->flag &= (BYTE)~FA_DIRTY; } #endif - if (disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); + if (FfDiskOps->disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); } dbuf = fp->buf; #endif @@ -5700,7 +5701,7 @@ static FRESULT create_partition ( BYTE *pte, hd, n_hd, sc, n_sc; /* Get drive size */ - if (disk_ioctl(drv, GET_SECTOR_COUNT, &sz_drv) != RES_OK) return FR_DISK_ERR; + if (FfDiskOps->disk_ioctl(drv, GET_SECTOR_COUNT, &sz_drv) != RES_OK) return FR_DISK_ERR; #if FF_LBA64 if (sz_drv >= FF_MIN_GPT) { /* Create partitions in GPT */ @@ -5711,7 +5712,7 @@ static FRESULT create_partition ( static const BYTE gpt_mbr[16] = {0x00, 0x00, 0x02, 0x00, 0xEE, 0xFE, 0xFF, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF}; #if FF_MAX_SS != FF_MIN_SS - if (disk_ioctl(drv, GET_SECTOR_SIZE, &ss) != RES_OK) return FR_DISK_ERR; /* Get sector size */ + if (FfDiskOps->disk_ioctl(drv, GET_SECTOR_SIZE, &ss) != RES_OK) return FR_DISK_ERR; /* Get sector size */ if (ss > FF_MAX_SS || ss < FF_MIN_SS || (ss & (ss - 1))) return FR_DISK_ERR; #else ss = FF_MAX_SS; @@ -5747,8 +5748,8 @@ static FRESULT create_partition ( } if ((pi + 1) * SZ_GPTE % ss == 0) { /* Write the buffer if it is filled up */ for (i = 0; i < ss; bcc = crc32(bcc, buf[i++])) ; /* Calculate table check sum */ - if (disk_write(drv, buf, 2 + pi * SZ_GPTE / ss, 1) != RES_OK) return FR_DISK_ERR; /* Primary table */ - if (disk_write(drv, buf, s_bpt + pi * SZ_GPTE / ss, 1) != RES_OK) return FR_DISK_ERR; /* Secondary table */ + if (FfDiskOps->disk_write(drv, buf, 2 + pi * SZ_GPTE / ss, 1) != RES_OK) return FR_DISK_ERR; /* Primary table */ + if (FfDiskOps->disk_write(drv, buf, s_bpt + pi * SZ_GPTE / ss, 1) != RES_OK) return FR_DISK_ERR; /* Secondary table */ } } while (++pi < GPT_ITEMS); @@ -5766,7 +5767,7 @@ static FRESULT create_partition ( rnd = make_rand(rnd, buf + GPTH_DskGuid, 16); /* Disk GUID */ for (i = 0, bcc= 0xFFFFFFFF; i < 92; bcc = crc32(bcc, buf[i++])) ; /* Calculate header check sum */ st_dword(buf + GPTH_Bcc, ~bcc); /* Header check sum */ - if (disk_write(drv, buf, 1, 1) != RES_OK) return FR_DISK_ERR; + if (FfDiskOps->disk_write(drv, buf, 1, 1) != RES_OK) return FR_DISK_ERR; /* Create secondary GPT header */ st_qword(buf + GPTH_CurLba, sz_drv - 1); /* LBA of this header */ @@ -5775,13 +5776,13 @@ static FRESULT create_partition ( st_dword(buf + GPTH_Bcc, 0); for (i = 0, bcc= 0xFFFFFFFF; i < 92; bcc = crc32(bcc, buf[i++])) ; /* Calculate header check sum */ st_dword(buf + GPTH_Bcc, ~bcc); /* Header check sum */ - if (disk_write(drv, buf, sz_drv - 1, 1) != RES_OK) return FR_DISK_ERR; + if (FfDiskOps->disk_write(drv, buf, sz_drv - 1, 1) != RES_OK) return FR_DISK_ERR; /* Create protective MBR */ mem_set(buf, 0, ss); mem_cpy(buf + MBR_Table, gpt_mbr, 16); /* Create a GPT partition */ st_word(buf + BS_55AA, 0xAA55); - if (disk_write(drv, buf, 0, 1) != RES_OK) return FR_DISK_ERR; + if (FfDiskOps->disk_write(drv, buf, 0, 1) != RES_OK) return FR_DISK_ERR; } else #endif @@ -5821,7 +5822,7 @@ static FRESULT create_partition ( } st_word(buf + BS_55AA, 0xAA55); /* MBR signature */ - if (disk_write(drv, buf, 0, 1) != RES_OK) return FR_DISK_ERR; /* Write it to the MBR */ + if (FfDiskOps->disk_write(drv, buf, 0, 1) != RES_OK) return FR_DISK_ERR; /* Write it to the MBR */ } return FR_OK; @@ -5860,14 +5861,14 @@ FRESULT f_mkfs ( if (!opt) opt = &defopt; /* Use default parameter if it is not given */ /* Get physical drive status (sz_drv, sz_blk, ss) */ - ds = disk_initialize(pdrv); + ds = FfDiskOps->disk_initialize(pdrv); if (ds & STA_NOINIT) return FR_NOT_READY; if (ds & STA_PROTECT) return FR_WRITE_PROTECTED; sz_blk = opt->align; - if (sz_blk == 0 && disk_ioctl(pdrv, GET_BLOCK_SIZE, &sz_blk) != RES_OK) sz_blk = 1; + if (sz_blk == 0 && FfDiskOps->disk_ioctl(pdrv, GET_BLOCK_SIZE, &sz_blk) != RES_OK) sz_blk = 1; if (sz_blk == 0 || sz_blk > 0x8000 || (sz_blk & (sz_blk - 1))) sz_blk = 1; #if FF_MAX_SS != FF_MIN_SS - if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &ss) != RES_OK) return FR_DISK_ERR; + if (FfDiskOps->disk_ioctl(pdrv, GET_SECTOR_SIZE, &ss) != RES_OK) return FR_DISK_ERR; if (ss > FF_MAX_SS || ss < FF_MIN_SS || (ss & (ss - 1))) return FR_DISK_ERR; #else ss = FF_MAX_SS; @@ -5892,7 +5893,7 @@ FRESULT f_mkfs ( b_vol = sz_vol = 0; if (FF_MULTI_PARTITION && ipart != 0) { /* Is the volume associated with any specific partition? */ /* Get partition location from the existing partition table */ - if (disk_read(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Load MBR */ + if (FfDiskOps->disk_read(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Load MBR */ if (ld_word(buf + BS_55AA) != 0xAA55) LEAVE_MKFS(FR_MKFS_ABORTED); /* Check if MBR is valid */ #if FF_LBA64 if (buf[MBR_Table + PTE_System] == 0xEE) { /* GPT protective MBR? */ @@ -5900,13 +5901,13 @@ FRESULT f_mkfs ( QWORD pt_lba; /* Get the partition location from GPT */ - if (disk_read(pdrv, buf, 1, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Load GPT header sector (next to MBR) */ + if (FfDiskOps->disk_read(pdrv, buf, 1, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Load GPT header sector (next to MBR) */ if (!test_gpt_header(buf)) LEAVE_MKFS(FR_MKFS_ABORTED); /* Check if GPT header is valid */ n_ent = ld_dword(buf + GPTH_PtNum); /* Number of entries */ pt_lba = ld_qword(buf + GPTH_PtOfs); /* Table start sector */ ofs = i = 0; while (n_ent) { /* Find MS Basic partition with order of ipart */ - if (ofs == 0 && disk_read(pdrv, buf, pt_lba++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Get PT sector */ + if (ofs == 0 && FfDiskOps->disk_read(pdrv, buf, pt_lba++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Get PT sector */ if (!mem_cmp(buf + ofs + GPTE_PtGuid, GUID_MS_Basic, 16) && ++i == ipart) { /* MS basic data partition? */ b_vol = ld_qword(buf + ofs + GPTE_FstLba); sz_vol = ld_qword(buf + ofs + GPTE_LstLba) - b_vol + 1; @@ -5925,7 +5926,7 @@ FRESULT f_mkfs ( sz_vol = ld_dword(pte + PTE_SizLba); /* Get volume size */ } } else { /* The volume is associated with a physical drive */ - if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_vol) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + if (FfDiskOps->disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_vol) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); if (!(fsopt & FM_SFD)) { /* To be partitioned? */ /* Create a single-partition on the drive in this function */ #if FF_LBA64 @@ -5974,7 +5975,7 @@ FRESULT f_mkfs ( if (sz_vol < 0x1000) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too small volume for exFAT? */ #if FF_USE_TRIM lba[0] = b_vol; lba[1] = b_vol + sz_vol - 1; /* Inform storage device that the volume area may be erased */ - disk_ioctl(pdrv, CTRL_TRIM, lba); + FfDiskOps->disk_ioctl(pdrv, CTRL_TRIM, lba); #endif /* Determine FAT location, data location and number of clusters */ if (sz_au == 0) { /* AU auto-selection */ @@ -6024,7 +6025,7 @@ FRESULT f_mkfs ( i += 2; szb_case += 2; if (si == 0 || i == sz_buf * ss) { /* Write buffered data when buffer full or end of process */ n = (i + ss - 1) / ss; - if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + if (FfDiskOps->disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); sect += n; i = 0; } } while (si); @@ -6039,7 +6040,7 @@ FRESULT f_mkfs ( for (i = 0; nb >= 8 && i < sz_buf * ss; buf[i++] = 0xFF, nb -= 8) ; for (b = 1; nb != 0 && i < sz_buf * ss; buf[i] |= b, b <<= 1, nb--) ; n = (nsect > sz_buf) ? sz_buf : nsect; /* Write the buffered data */ - if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + if (FfDiskOps->disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); sect += n; nsect -= n; } while (nsect); @@ -6060,7 +6061,7 @@ FRESULT f_mkfs ( if (nb == 0 && j < 3) nb = tbl[j++]; /* Next chain */ } while (nb != 0 && i < sz_buf * ss); n = (nsect > sz_buf) ? sz_buf : nsect; /* Write the buffered data */ - if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + if (FfDiskOps->disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); sect += n; nsect -= n; } while (nsect); @@ -6077,7 +6078,7 @@ FRESULT f_mkfs ( sect = b_data + sz_au * (tbl[0] + tbl[1]); nsect = sz_au; /* Start of the root directory and number of sectors */ do { /* Fill root directory sectors */ n = (nsect > sz_buf) ? sz_buf : nsect; - if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + if (FfDiskOps->disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); mem_set(buf, 0, ss); sect += n; nsect -= n; } while (nsect); @@ -6106,23 +6107,23 @@ FRESULT f_mkfs ( for (i = sum = 0; i < ss; i++) { /* VBR checksum */ if (i != BPB_VolFlagEx && i != BPB_VolFlagEx + 1 && i != BPB_PercInUseEx) sum = xsum32(buf[i], sum); } - if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + if (FfDiskOps->disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Extended bootstrap record (+1..+8) */ mem_set(buf, 0, ss); st_word(buf + ss - 2, 0xAA55); /* Signature (placed at end of sector) */ for (j = 1; j < 9; j++) { for (i = 0; i < ss; sum = xsum32(buf[i++], sum)) ; /* VBR checksum */ - if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + if (FfDiskOps->disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); } /* OEM/Reserved record (+9..+10) */ mem_set(buf, 0, ss); for ( ; j < 11; j++) { for (i = 0; i < ss; sum = xsum32(buf[i++], sum)) ; /* VBR checksum */ - if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + if (FfDiskOps->disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); } /* Sum record (+11) */ for (i = 0; i < ss; i += 4) st_dword(buf + i, sum); /* Fill with checksum value */ - if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + if (FfDiskOps->disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); } } else @@ -6204,7 +6205,7 @@ FRESULT f_mkfs ( #if FF_USE_TRIM lba[0] = b_vol; lba[1] = b_vol + sz_vol - 1; /* Inform storage device that the volume area may be erased */ - disk_ioctl(pdrv, CTRL_TRIM, lba); + FfDiskOps->disk_ioctl(pdrv, CTRL_TRIM, lba); #endif /* Create FAT VBR */ mem_set(buf, 0, ss); @@ -6240,19 +6241,19 @@ FRESULT f_mkfs ( mem_cpy(buf + BS_VolLab, "NO NAME " "FAT ", 19); /* Volume label, FAT signature */ } st_word(buf + BS_55AA, 0xAA55); /* Signature (offset is fixed here regardless of sector size) */ - if (disk_write(pdrv, buf, b_vol, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Write it to the VBR sector */ + if (FfDiskOps->disk_write(pdrv, buf, b_vol, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Write it to the VBR sector */ /* Create FSINFO record if needed */ if (fsty == FS_FAT32) { - disk_write(pdrv, buf, b_vol + 6, 1); /* Write backup VBR (VBR + 6) */ + FfDiskOps->disk_write(pdrv, buf, b_vol + 6, 1); /* Write backup VBR (VBR + 6) */ mem_set(buf, 0, ss); st_dword(buf + FSI_LeadSig, 0x41615252); st_dword(buf + FSI_StrucSig, 0x61417272); st_dword(buf + FSI_Free_Count, n_clst - 1); /* Number of free clusters */ st_dword(buf + FSI_Nxt_Free, 2); /* Last allocated cluster# */ st_word(buf + BS_55AA, 0xAA55); - disk_write(pdrv, buf, b_vol + 7, 1); /* Write backup FSINFO (VBR + 7) */ - disk_write(pdrv, buf, b_vol + 1, 1); /* Write original FSINFO (VBR + 1) */ + FfDiskOps->disk_write(pdrv, buf, b_vol + 7, 1); /* Write backup FSINFO (VBR + 7) */ + FfDiskOps->disk_write(pdrv, buf, b_vol + 1, 1); /* Write original FSINFO (VBR + 1) */ } /* Initialize FAT area */ @@ -6269,7 +6270,7 @@ FRESULT f_mkfs ( nsect = sz_fat; /* Number of FAT sectors */ do { /* Fill FAT sectors */ n = (nsect > sz_buf) ? sz_buf : nsect; - if (disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + if (FfDiskOps->disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); mem_set(buf, 0, ss); /* Rest of FAT all are cleared */ sect += n; nsect -= n; } while (nsect); @@ -6279,7 +6280,7 @@ FRESULT f_mkfs ( nsect = (fsty == FS_FAT32) ? pau : sz_dir; /* Number of root directory sectors */ do { n = (nsect > sz_buf) ? sz_buf : nsect; - if (disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + if (FfDiskOps->disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); sect += n; nsect -= n; } while (nsect); } @@ -6305,9 +6306,9 @@ FRESULT f_mkfs ( if (FF_MULTI_PARTITION && ipart != 0) { /* Volume is in the existing partition */ if (!FF_LBA64 || !(fsopt & 0x80)) { /* Update system ID in the partition table */ - if (disk_read(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Read the MBR */ + if (FfDiskOps->disk_read(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Read the MBR */ buf[MBR_Table + (ipart - 1) * SZ_PTE + PTE_System] = sys; /* Set system ID */ - if (disk_write(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Write it back to the MBR */ + if (FfDiskOps->disk_write(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Write it back to the MBR */ } } else { /* Volume as a new single partition */ if (!(fsopt & FM_SFD)) { /* Create partition table if not in SFD */ @@ -6317,7 +6318,7 @@ FRESULT f_mkfs ( } } - if (disk_ioctl(pdrv, CTRL_SYNC, 0) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + if (FfDiskOps->disk_ioctl(pdrv, CTRL_SYNC, 0) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); LEAVE_MKFS(FR_OK); } @@ -6340,7 +6341,7 @@ FRESULT f_fdisk ( DSTATUS stat; - stat = disk_initialize(pdrv); + stat = FfDiskOps->disk_initialize(pdrv); if (stat & STA_NOINIT) return FR_NOT_READY; if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; #if FF_USE_LFN == 3 diff --git a/litex/soc/software/liblitesata/sata.c b/litex/soc/software/liblitesata/sata.c index a8909598a..07f39b893 100644 --- a/litex/soc/software/liblitesata/sata.c +++ b/litex/soc/software/liblitesata/sata.c @@ -101,21 +101,31 @@ void sata_write(uint32_t sector, uint32_t count, uint8_t* buf) static DSTATUS satastatus = STA_NOINIT; -DSTATUS disk_status(BYTE drv) { +static DSTATUS sata_disk_status(BYTE drv) { if (drv) return STA_NOINIT; return satastatus; } -DSTATUS disk_initialize(BYTE drv) { +static DSTATUS sata_disk_initialize(BYTE drv) { if (drv) return STA_NOINIT; if (satastatus) satastatus = sata_init() ? 0 : STA_NOINIT; return satastatus; } -DRESULT disk_read(BYTE drv, BYTE *buf, LBA_t sector, UINT count) { +static DRESULT sata_disk_read(BYTE drv, BYTE *buf, LBA_t sector, UINT count) { sata_read(sector, count, buf); return RES_OK; } +static DISKOPS SataDiskOps = { + .disk_initialize = sata_disk_initialize, + .disk_status = sata_disk_status, + .disk_read = sata_disk_read, +}; + +void fatfs_set_ops_sata(void) { + FfDiskOps = &SataDiskOps; +} + #endif /* CSR_SATA_SECTOR2MEM_BASE */ diff --git a/litex/soc/software/liblitesata/sata.h b/litex/soc/software/liblitesata/sata.h index 7d45c408c..09d85ed74 100644 --- a/litex/soc/software/liblitesata/sata.h +++ b/litex/soc/software/liblitesata/sata.h @@ -13,6 +13,7 @@ #ifdef CSR_SATA_PHY_BASE int sata_init(void); +void fatfs_set_ops_sata(void); #endif diff --git a/litex/soc/software/liblitesdcard/sdcard.c b/litex/soc/software/liblitesdcard/sdcard.c index 15e189191..b7b169a90 100644 --- a/litex/soc/software/liblitesdcard/sdcard.c +++ b/litex/soc/software/liblitesdcard/sdcard.c @@ -565,21 +565,31 @@ void sdcard_write(uint32_t block, uint32_t count, uint8_t* buf) static DSTATUS sdcardstatus = STA_NOINIT; -DSTATUS disk_status(BYTE drv) { +static DSTATUS sd_disk_status(BYTE drv) { if (drv) return STA_NOINIT; return sdcardstatus; } -DSTATUS disk_initialize(BYTE drv) { +static DSTATUS sd_disk_initialize(BYTE drv) { if (drv) return STA_NOINIT; if (sdcardstatus) sdcardstatus = sdcard_init() ? 0 : STA_NOINIT; return sdcardstatus; } -DRESULT disk_read(BYTE drv, BYTE *buf, LBA_t block, UINT count) { +static DRESULT sd_disk_read(BYTE drv, BYTE *buf, LBA_t block, UINT count) { sdcard_read(block, count, buf); return RES_OK; } +static DISKOPS SdCardDiskOps = { + .disk_initialize = sd_disk_initialize, + .disk_status = sd_disk_status, + .disk_read = sd_disk_read, +}; + +void fatfs_set_ops_sdcard(void) { + FfDiskOps = &SdCardDiskOps; +} + #endif /* CSR_SDCORE_BASE */ diff --git a/litex/soc/software/liblitesdcard/sdcard.h b/litex/soc/software/liblitesdcard/sdcard.h index 17deb16df..eb0663211 100644 --- a/litex/soc/software/liblitesdcard/sdcard.h +++ b/litex/soc/software/liblitesdcard/sdcard.h @@ -103,6 +103,7 @@ void sdcard_decode_csd(void); int sdcard_init(void); void sdcard_read(uint32_t sector, uint32_t count, uint8_t* buf); void sdcard_write(uint32_t sector, uint32_t count, uint8_t* buf); +void fatfs_set_ops_sdcard(void); #endif /* CSR_SDCORE_BASE */ diff --git a/litex/soc/software/liblitesdcard/spisdcard.c b/litex/soc/software/liblitesdcard/spisdcard.c index f04e5b2df..99bf4246c 100644 --- a/litex/soc/software/liblitesdcard/spisdcard.c +++ b/litex/soc/software/liblitesdcard/spisdcard.c @@ -264,12 +264,12 @@ uint8_t spisdcard_init(void) { static DSTATUS spisdcardstatus = STA_NOINIT; -DSTATUS disk_status(BYTE drv) { +static DSTATUS spisd_disk_status(BYTE drv) { if (drv) return STA_NOINIT; return spisdcardstatus; } -DSTATUS disk_initialize(BYTE drv) { +static DSTATUS spisd_disk_initialize(BYTE drv) { if (drv) return STA_NOINIT; if (spisdcardstatus) { spisdcardstatus = spisdcard_init() ? 0 : STA_NOINIT; @@ -278,7 +278,7 @@ DSTATUS disk_initialize(BYTE drv) { return spisdcardstatus; } -DRESULT disk_read(BYTE drv, BYTE *buf, LBA_t block, UINT count) { +static DRESULT spisd_disk_read(BYTE drv, BYTE *buf, LBA_t block, UINT count) { uint8_t cmd; if (count > 1) cmd = CMD18; /* READ_MULTIPLE_BLOCK */ @@ -302,4 +302,14 @@ DRESULT disk_read(BYTE drv, BYTE *buf, LBA_t block, UINT count) { return RES_OK; } +static DISKOPS SpiSdDiskOps = { + .disk_initialize = spisd_disk_initialize, + .disk_status = spisd_disk_status, + .disk_read = spisd_disk_read, +}; + +void fatfs_set_ops_spisdcard(void) { + FfDiskOps = &SpiSdDiskOps; +} + #endif diff --git a/litex/soc/software/liblitesdcard/spisdcard.h b/litex/soc/software/liblitesdcard/spisdcard.h index 58d5e3137..deda3eb21 100644 --- a/litex/soc/software/liblitesdcard/spisdcard.h +++ b/litex/soc/software/liblitesdcard/spisdcard.h @@ -50,6 +50,7 @@ /*-----------------------------------------------------------------------*/ uint8_t spisdcard_init(void); +void fatfs_set_ops_spisdcard(void); #endif /* CSR_SPISDCARD_BASE */