- Added support of exFAT file system. (_FS_EXFAT) - Added f_expand(). (_USE_EXPAND) - Changed some members in FINFO structure and behavior of f_readdir(). - Added an option _USE_CHMOD and removed an option _WORD_ACCESS. - Fixed errors in the case conversion teble of Unicode (cc*.c).
		
			
				
	
	
		
			318 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			318 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*----------------------------------------------------------------------/
 | |
| / Low level disk I/O module function checker
 | |
| /-----------------------------------------------------------------------/
 | |
| / WARNING: The data on the target drive will be lost!
 | |
| */
 | |
| 
 | |
| #include <stdio.h>
 | |
| #include <string.h>
 | |
| #include "ff.h"
 | |
| #include "diskio.h"
 | |
| 
 | |
| 
 | |
| static
 | |
| DWORD pn (
 | |
|     DWORD pns
 | |
| )
 | |
| {
 | |
|     static DWORD lfsr;
 | |
|     UINT n;
 | |
| 
 | |
| 
 | |
|     if (pns) {
 | |
|         lfsr = pns;
 | |
|         for (n = 0; n < 32; n++) pn(0);
 | |
|     }
 | |
|     if (lfsr & 1) {
 | |
|         lfsr >>= 1;
 | |
|         lfsr ^= 0x80200003;
 | |
|     } else {
 | |
|         lfsr >>= 1;
 | |
|     }
 | |
|     return lfsr;
 | |
| }
 | |
| 
 | |
| 
 | |
| int test_diskio (
 | |
|     BYTE pdrv,      /* Physical drive number to be checked (all data on the drive will be lost) */
 | |
|     UINT ncyc,      /* Number of test cycles */
 | |
|     DWORD* buff,    /* Pointer to the working buffer */
 | |
|     UINT sz_buff    /* Size of the working buffer in unit of byte */
 | |
| )
 | |
| {
 | |
|     UINT n, cc, ns;
 | |
|     DWORD sz_drv, lba, lba2, pns = 1;
 | |
|     WORD sz_sect, sz_eblk;
 | |
|     BYTE *pbuff = (BYTE*)buff;
 | |
|     DSTATUS ds;
 | |
|     DRESULT dr;
 | |
| 
 | |
| 
 | |
|     printf("test_diskio(%u, %u, 0x%08X, 0x%08X)\n", pdrv, ncyc, (UINT)buff, sz_buff);
 | |
| 
 | |
|     if (sz_buff < _MAX_SS + 4) {
 | |
|         printf("Insufficient work area to test.\n");
 | |
|         return 1;
 | |
|     }
 | |
| 
 | |
|     for (cc = 1; cc <= ncyc; cc++) {
 | |
|         printf("**** Test cycle %u of %u start ****\n", cc, ncyc);
 | |
| 
 | |
|         /* Initialization */
 | |
|         printf(" disk_initalize(%u)", pdrv);
 | |
|         ds = disk_initialize(pdrv);
 | |
|         if (ds & STA_NOINIT) {
 | |
|             printf(" - failed.\n");
 | |
|             return 2;
 | |
|         } else {
 | |
|             printf(" - ok.\n");
 | |
|         }
 | |
| 
 | |
|         /* Get drive size */
 | |
|         printf("**** Get drive size ****\n");
 | |
|         printf(" disk_ioctl(%u, GET_SECTOR_COUNT, 0x%08X)", pdrv, (UINT)&sz_drv);
 | |
|         sz_drv = 0;
 | |
|         dr = disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_drv);
 | |
|         if (dr == RES_OK) {
 | |
|             printf(" - ok.\n");
 | |
|         } else {
 | |
|             printf(" - failed.\n");
 | |
|             return 3;
 | |
|         }
 | |
|         if (sz_drv < 128) {
 | |
|             printf("Failed: Insufficient drive size to test.\n");
 | |
|             return 4;
 | |
|         }
 | |
|         printf(" Number of sectors on the drive %u is %lu.\n", pdrv, sz_drv);
 | |
| 
 | |
| #if _MAX_SS != _MIN_SS
 | |
|         /* Get sector size */
 | |
|         printf("**** Get sector size ****\n");
 | |
|         printf(" disk_ioctl(%u, GET_SECTOR_SIZE, 0x%X)", pdrv, (UINT)&sz_sect);
 | |
|         sz_sect = 0;
 | |
|         dr = disk_ioctl(pdrv, GET_SECTOR_SIZE, &sz_sect);
 | |
|         if (dr == RES_OK) {
 | |
|             printf(" - ok.\n");
 | |
|         } else {
 | |
|             printf(" - failed.\n");
 | |
|             return 5;
 | |
|         }
 | |
|         printf(" Size of sector is %u bytes.\n", sz_sect);
 | |
| #else
 | |
|         sz_sect = _MAX_SS;
 | |
| #endif
 | |
| 
 | |
|         /* Get erase block size */
 | |
|         printf("**** Get block size ****\n");
 | |
|         printf(" disk_ioctl(%u, GET_BLOCK_SIZE, 0x%X)", pdrv, (UINT)&sz_eblk);
 | |
|         sz_eblk = 0;
 | |
|         dr = disk_ioctl(pdrv, GET_BLOCK_SIZE, &sz_eblk);
 | |
|         if (dr == RES_OK) {
 | |
|             printf(" - ok.\n");
 | |
|         } else {
 | |
|             printf(" - failed.\n");
 | |
|         }
 | |
|         if (dr == RES_OK || sz_eblk >= 2) {
 | |
|             printf(" Size of the erase block is %u sectors.\n", sz_eblk);
 | |
|         } else {
 | |
|             printf(" Size of the erase block is unknown.\n");
 | |
|         }
 | |
| 
 | |
|         /* Single sector write test */
 | |
|         printf("**** Single sector write test 1 ****\n");
 | |
|         lba = 0;
 | |
|         for (n = 0, pn(pns); n < sz_sect; n++) pbuff[n] = (BYTE)pn(0);
 | |
|         printf(" disk_write(%u, 0x%X, %lu, 1)", pdrv, (UINT)pbuff, lba);
 | |
|         dr = disk_write(pdrv, pbuff, lba, 1);
 | |
|         if (dr == RES_OK) {
 | |
|             printf(" - ok.\n");
 | |
|         } else {
 | |
|             printf(" - failed.\n");
 | |
|             return 6;
 | |
|         }
 | |
|         printf(" disk_ioctl(%u, CTRL_SYNC, NULL)", pdrv);
 | |
|         dr = disk_ioctl(pdrv, CTRL_SYNC, 0);
 | |
|         if (dr == RES_OK) {
 | |
|             printf(" - ok.\n");
 | |
|         } else {
 | |
|             printf(" - failed.\n");
 | |
|             return 7;
 | |
|         }
 | |
|         memset(pbuff, 0, sz_sect);
 | |
|         printf(" disk_read(%u, 0x%X, %lu, 1)", pdrv, (UINT)pbuff, lba);
 | |
|         dr = disk_read(pdrv, pbuff, lba, 1);
 | |
|         if (dr == RES_OK) {
 | |
|             printf(" - ok.\n");
 | |
|         } else {
 | |
|             printf(" - failed.\n");
 | |
|             return 8;
 | |
|         }
 | |
|         for (n = 0, pn(pns); n < sz_sect && pbuff[n] == (BYTE)pn(0); n++) ;
 | |
|         if (n == sz_sect) {
 | |
|             printf(" Data matched.\n");
 | |
|         } else {
 | |
|             printf("Failed: Read data differs from the data written.\n");
 | |
|             return 10;
 | |
|         }
 | |
|         pns++;
 | |
| 
 | |
|         /* Multiple sector write test */
 | |
|         printf("**** Multiple sector write test ****\n");
 | |
|         lba = 1; ns = sz_buff / sz_sect;
 | |
|         if (ns > 4) ns = 4;
 | |
|         for (n = 0, pn(pns); n < (UINT)(sz_sect * ns); n++) pbuff[n] = (BYTE)pn(0);
 | |
|         printf(" disk_write(%u, 0x%X, %lu, %u)", pdrv, (UINT)pbuff, lba, ns);
 | |
|         dr = disk_write(pdrv, pbuff, lba, ns);
 | |
|         if (dr == RES_OK) {
 | |
|             printf(" - ok.\n");
 | |
|         } else {
 | |
|             printf(" - failed.\n");
 | |
|             return 11;
 | |
|         }
 | |
|         printf(" disk_ioctl(%u, CTRL_SYNC, NULL)", pdrv);
 | |
|         dr = disk_ioctl(pdrv, CTRL_SYNC, 0);
 | |
|         if (dr == RES_OK) {
 | |
|             printf(" - ok.\n");
 | |
|         } else {
 | |
|             printf(" - failed.\n");
 | |
|             return 12;
 | |
|         }
 | |
|         memset(pbuff, 0, sz_sect * ns);
 | |
|         printf(" disk_read(%u, 0x%X, %lu, %u)", pdrv, (UINT)pbuff, lba, ns);
 | |
|         dr = disk_read(pdrv, pbuff, lba, ns);
 | |
|         if (dr == RES_OK) {
 | |
|             printf(" - ok.\n");
 | |
|         } else {
 | |
|             printf(" - failed.\n");
 | |
|             return 13;
 | |
|         }
 | |
|         for (n = 0, pn(pns); n < (UINT)(sz_sect * ns) && pbuff[n] == (BYTE)pn(0); n++) ;
 | |
|         if (n == (UINT)(sz_sect * ns)) {
 | |
|             printf(" Data matched.\n");
 | |
|         } else {
 | |
|             printf("Failed: Read data differs from the data written.\n");
 | |
|             return 14;
 | |
|         }
 | |
|         pns++;
 | |
| 
 | |
|         /* Single sector write test (misaligned memory address) */
 | |
|         printf("**** Single sector write test 2 ****\n");
 | |
|         lba = 5;
 | |
|         for (n = 0, pn(pns); n < sz_sect; n++) pbuff[n+3] = (BYTE)pn(0);
 | |
|         printf(" disk_write(%u, 0x%X, %lu, 1)", pdrv, (UINT)(pbuff+3), lba);
 | |
|         dr = disk_write(pdrv, pbuff+3, lba, 1);
 | |
|         if (dr == RES_OK) {
 | |
|             printf(" - ok.\n");
 | |
|         } else {
 | |
|             printf(" - failed.\n");
 | |
|             return 15;
 | |
|         }
 | |
|         printf(" disk_ioctl(%u, CTRL_SYNC, NULL)", pdrv);
 | |
|         dr = disk_ioctl(pdrv, CTRL_SYNC, 0);
 | |
|         if (dr == RES_OK) {
 | |
|             printf(" - ok.\n");
 | |
|         } else {
 | |
|             printf(" - failed.\n");
 | |
|             return 16;
 | |
|         }
 | |
|         memset(pbuff+5, 0, sz_sect);
 | |
|         printf(" disk_read(%u, 0x%X, %lu, 1)", pdrv, (UINT)(pbuff+5), lba);
 | |
|         dr = disk_read(pdrv, pbuff+5, lba, 1);
 | |
|         if (dr == RES_OK) {
 | |
|             printf(" - ok.\n");
 | |
|         } else {
 | |
|             printf(" - failed.\n");
 | |
|             return 17;
 | |
|         }
 | |
|         for (n = 0, pn(pns); n < sz_sect && pbuff[n+5] == (BYTE)pn(0); n++) ;
 | |
|         if (n == sz_sect) {
 | |
|             printf(" Data matched.\n");
 | |
|         } else {
 | |
|             printf("Failed: Read data differs from the data written.\n");
 | |
|             return 18;
 | |
|         }
 | |
|         pns++;
 | |
| 
 | |
|         /* 4GB barrier test */
 | |
|         printf("**** 4GB barrier test ****\n");
 | |
|         if (sz_drv >= 128 + 0x80000000 / (sz_sect / 2)) {
 | |
|             lba = 6; lba2 = lba + 0x80000000 / (sz_sect / 2);
 | |
|             for (n = 0, pn(pns); n < (UINT)(sz_sect * 2); n++) pbuff[n] = (BYTE)pn(0);
 | |
|             printf(" disk_write(%u, 0x%X, %lu, 1)", pdrv, (UINT)pbuff, lba);
 | |
|             dr = disk_write(pdrv, pbuff, lba, 1);
 | |
|             if (dr == RES_OK) {
 | |
|                 printf(" - ok.\n");
 | |
|             } else {
 | |
|                 printf(" - failed.\n");
 | |
|                 return 19;
 | |
|             }
 | |
|             printf(" disk_write(%u, 0x%X, %lu, 1)", pdrv, (UINT)(pbuff+sz_sect), lba2);
 | |
|             dr = disk_write(pdrv, pbuff+sz_sect, lba2, 1);
 | |
|             if (dr == RES_OK) {
 | |
|                 printf(" - ok.\n");
 | |
|             } else {
 | |
|                 printf(" - failed.\n");
 | |
|                 return 20;
 | |
|             }
 | |
|             printf(" disk_ioctl(%u, CTRL_SYNC, NULL)", pdrv);
 | |
|             dr = disk_ioctl(pdrv, CTRL_SYNC, 0);
 | |
|             if (dr == RES_OK) {
 | |
|             printf(" - ok.\n");
 | |
|             } else {
 | |
|                 printf(" - failed.\n");
 | |
|                 return 21;
 | |
|             }
 | |
|             memset(pbuff, 0, sz_sect * 2);
 | |
|             printf(" disk_read(%u, 0x%X, %lu, 1)", pdrv, (UINT)pbuff, lba);
 | |
|             dr = disk_read(pdrv, pbuff, lba, 1);
 | |
|             if (dr == RES_OK) {
 | |
|                 printf(" - ok.\n");
 | |
|             } else {
 | |
|                 printf(" - failed.\n");
 | |
|                 return 22;
 | |
|             }
 | |
|             printf(" disk_read(%u, 0x%X, %lu, 1)", pdrv, (UINT)(pbuff+sz_sect), lba2);
 | |
|             dr = disk_read(pdrv, pbuff+sz_sect, lba2, 1);
 | |
|             if (dr == RES_OK) {
 | |
|                 printf(" - ok.\n");
 | |
|             } else {
 | |
|                 printf(" - failed.\n");
 | |
|                 return 23;
 | |
|             }
 | |
|             for (n = 0, pn(pns); pbuff[n] == (BYTE)pn(0) && n < (UINT)(sz_sect * 2); n++) ;
 | |
|             if (n == (UINT)(sz_sect * 2)) {
 | |
|                 printf(" Data matched.\n");
 | |
|             } else {
 | |
|                 printf("Failed: Read data differs from the data written.\n");
 | |
|                 return 24;
 | |
|             }
 | |
|         } else {
 | |
|             printf(" Test skipped.\n");
 | |
|         }
 | |
|         pns++;
 | |
| 
 | |
|         printf("**** Test cycle %u of %u completed ****\n\n", cc, ncyc);
 | |
|     }
 | |
| 
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| int main (int argc, char* argv[])
 | |
| {
 | |
|     int rc;
 | |
|     DWORD buff[512];  /* 2048 byte working buffer */
 | |
| 
 | |
|     /* Check function/compatibility of the physical drive #0 */
 | |
|     rc = test_diskio(0, 3, buff, sizeof buff);
 | |
|     if (rc) {
 | |
|         printf("Sorry the function/compatibility test failed. (rc=%d)\nFatFs will not work on this disk driver.\n", rc);
 | |
|     } else {
 | |
|         printf("Congratulations! The disk driver works well.\n");
 | |
|     }
 | |
| 
 | |
|     return rc;
 | |
| }
 | |
| 
 |