/*----------------------------------------------------------------------/ / Low level disk I/O module function checker /-----------------------------------------------------------------------/ / WARNING: The data on the target drive will be lost! */ #include #include #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, 1, buff, sizeof buff); if (res) { printf("Sorry the function/compatibility test failed.\nFatFs will not work on this disk driver.\n"); } else { printf("Congratulations! The disk I/O layer works well.\n"); } return rc; }