+/*----------------------------------------------------------------------/\r
+/ Low level disk I/O module function checker /\r
+/-----------------------------------------------------------------------/\r
+/ WARNING: The data on the target drive will be lost!\r
+*/\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include "ff.h" /* Declarations of sector size */\r
+#include "diskio.h" /* Declarations of disk functions */\r
+\r
+\r
+static\r
+DWORD pn ( /* Pseudo random number generator */\r
+ DWORD pns /* 0:Initialize, !0:Read */\r
+)\r
+{\r
+ static DWORD lfsr;\r
+ UINT n;\r
+\r
+\r
+ if (pns) {\r
+ lfsr = pns;\r
+ for (n = 0; n < 32; n++) pn(0);\r
+ }\r
+ if (lfsr & 1) {\r
+ lfsr >>= 1;\r
+ lfsr ^= 0x80200003;\r
+ } else {\r
+ lfsr >>= 1;\r
+ }\r
+ return lfsr;\r
+}\r
+\r
+\r
+int test_diskio (\r
+ BYTE pdrv, /* Physical drive number to be checked (all data on the drive will be lost) */\r
+ UINT ncyc, /* Number of test cycles */\r
+ DWORD* buff, /* Pointer to the working buffer */\r
+ UINT sz_buff /* Size of the working buffer in unit of byte */\r
+)\r
+{\r
+ UINT n, cc, ns;\r
+ DWORD sz_drv, lba, lba2, sz_eblk, pns = 1;\r
+ WORD sz_sect;\r
+ BYTE *pbuff = (BYTE*)buff;\r
+ DSTATUS ds;\r
+ DRESULT dr;\r
+\r
+\r
+ printf("test_diskio(%u, %u, 0x%08X, 0x%08X)\n", pdrv, ncyc, (UINT)buff, sz_buff);\r
+\r
+ if (sz_buff < _MAX_SS + 4) {\r
+ printf("Insufficient work area to run program.\n");\r
+ return 1;\r
+ }\r
+\r
+ for (cc = 1; cc <= ncyc; cc++) {\r
+ printf("**** Test cycle %u of %u start ****\n", cc, ncyc);\r
+\r
+ printf(" disk_initalize(%u)", pdrv);\r
+ ds = disk_initialize(pdrv);\r
+ if (ds & STA_NOINIT) {\r
+ printf(" - failed.\n");\r
+ return 2;\r
+ } else {\r
+ printf(" - ok.\n");\r
+ }\r
+\r
+ printf("**** Get drive size ****\n");\r
+ printf(" disk_ioctl(%u, GET_SECTOR_COUNT, 0x%08X)", pdrv, (UINT)&sz_drv);\r
+ sz_drv = 0;\r
+ dr = disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_drv);\r
+ if (dr == RES_OK) {\r
+ printf(" - ok.\n");\r
+ } else {\r
+ printf(" - failed.\n");\r
+ return 3;\r
+ }\r
+ if (sz_drv < 128) {\r
+ printf("Failed: Insufficient drive size to test.\n");\r
+ return 4;\r
+ }\r
+ printf(" Number of sectors on the drive %u is %lu.\n", pdrv, sz_drv);\r
+\r
+#if FF_MAX_SS != FF_MIN_SS\r
+ printf("**** Get sector size ****\n");\r
+ printf(" disk_ioctl(%u, GET_SECTOR_SIZE, 0x%X)", pdrv, (UINT)&sz_sect);\r
+ sz_sect = 0;\r
+ dr = disk_ioctl(pdrv, GET_SECTOR_SIZE, &sz_sect);\r
+ if (dr == RES_OK) {\r
+ printf(" - ok.\n");\r
+ } else {\r
+ printf(" - failed.\n");\r
+ return 5;\r
+ }\r
+ printf(" Size of sector is %u bytes.\n", sz_sect);\r
+#else\r
+ sz_sect = FF_MAX_SS;\r
+#endif\r
+\r
+ printf("**** Get block size ****\n");\r
+ printf(" disk_ioctl(%u, GET_BLOCK_SIZE, 0x%X)", pdrv, (UINT)&sz_eblk);\r
+ sz_eblk = 0;\r
+ dr = disk_ioctl(pdrv, GET_BLOCK_SIZE, &sz_eblk);\r
+ if (dr == RES_OK) {\r
+ printf(" - ok.\n");\r
+ } else {\r
+ printf(" - failed.\n");\r
+ }\r
+ if (dr == RES_OK || sz_eblk >= 2) {\r
+ printf(" Size of the erase block is %lu sectors.\n", sz_eblk);\r
+ } else {\r
+ printf(" Size of the erase block is unknown.\n");\r
+ }\r
+\r
+ /* Single sector write test */\r
+ printf("**** Single sector write test 1 ****\n");\r
+ lba = 0;\r
+ for (n = 0, pn(pns); n < sz_sect; n++) pbuff[n] = (BYTE)pn(0);\r
+ printf(" disk_write(%u, 0x%X, %lu, 1)", pdrv, (UINT)pbuff, lba);\r
+ dr = disk_write(pdrv, pbuff, lba, 1);\r
+ if (dr == RES_OK) {\r
+ printf(" - ok.\n");\r
+ } else {\r
+ printf(" - failed.\n");\r
+ return 6;\r
+ }\r
+ printf(" disk_ioctl(%u, CTRL_SYNC, NULL)", pdrv);\r
+ dr = disk_ioctl(pdrv, CTRL_SYNC, 0);\r
+ if (dr == RES_OK) {\r
+ printf(" - ok.\n");\r
+ } else {\r
+ printf(" - failed.\n");\r
+ return 7;\r
+ }\r
+ memset(pbuff, 0, sz_sect);\r
+ printf(" disk_read(%u, 0x%X, %lu, 1)", pdrv, (UINT)pbuff, lba);\r
+ dr = disk_read(pdrv, pbuff, lba, 1);\r
+ if (dr == RES_OK) {\r
+ printf(" - ok.\n");\r
+ } else {\r
+ printf(" - failed.\n");\r
+ return 8;\r
+ }\r
+ for (n = 0, pn(pns); n < sz_sect && pbuff[n] == (BYTE)pn(0); n++) ;\r
+ if (n == sz_sect) {\r
+ printf(" Data matched.\n");\r
+ } else {\r
+ printf("Failed: Read data differs from the data written.\n");\r
+ return 10;\r
+ }\r
+ pns++;\r
+\r
+ printf("**** Multiple sector write test ****\n");\r
+ lba = 1; ns = sz_buff / sz_sect;\r
+ if (ns > 4) ns = 4;\r
+ for (n = 0, pn(pns); n < (UINT)(sz_sect * ns); n++) pbuff[n] = (BYTE)pn(0);\r
+ printf(" disk_write(%u, 0x%X, %lu, %u)", pdrv, (UINT)pbuff, lba, ns);\r
+ dr = disk_write(pdrv, pbuff, lba, ns);\r
+ if (dr == RES_OK) {\r
+ printf(" - ok.\n");\r
+ } else {\r
+ printf(" - failed.\n");\r
+ return 11;\r
+ }\r
+ printf(" disk_ioctl(%u, CTRL_SYNC, NULL)", pdrv);\r
+ dr = disk_ioctl(pdrv, CTRL_SYNC, 0);\r
+ if (dr == RES_OK) {\r
+ printf(" - ok.\n");\r
+ } else {\r
+ printf(" - failed.\n");\r
+ return 12;\r
+ }\r
+ memset(pbuff, 0, sz_sect * ns);\r
+ printf(" disk_read(%u, 0x%X, %lu, %u)", pdrv, (UINT)pbuff, lba, ns);\r
+ dr = disk_read(pdrv, pbuff, lba, ns);\r
+ if (dr == RES_OK) {\r
+ printf(" - ok.\n");\r
+ } else {\r
+ printf(" - failed.\n");\r
+ return 13;\r
+ }\r
+ for (n = 0, pn(pns); n < (UINT)(sz_sect * ns) && pbuff[n] == (BYTE)pn(0); n++) ;\r
+ if (n == (UINT)(sz_sect * ns)) {\r
+ printf(" Data matched.\n");\r
+ } else {\r
+ printf("Failed: Read data differs from the data written.\n");\r
+ return 14;\r
+ }\r
+ pns++;\r
+\r
+ printf("**** Single sector write test (misaligned address) ****\n");\r
+ lba = 5;\r
+ for (n = 0, pn(pns); n < sz_sect; n++) pbuff[n+3] = (BYTE)pn(0);\r
+ printf(" disk_write(%u, 0x%X, %lu, 1)", pdrv, (UINT)(pbuff+3), lba);\r
+ dr = disk_write(pdrv, pbuff+3, lba, 1);\r
+ if (dr == RES_OK) {\r
+ printf(" - ok.\n");\r
+ } else {\r
+ printf(" - failed.\n");\r
+ return 15;\r
+ }\r
+ printf(" disk_ioctl(%u, CTRL_SYNC, NULL)", pdrv);\r
+ dr = disk_ioctl(pdrv, CTRL_SYNC, 0);\r
+ if (dr == RES_OK) {\r
+ printf(" - ok.\n");\r
+ } else {\r
+ printf(" - failed.\n");\r
+ return 16;\r
+ }\r
+ memset(pbuff+5, 0, sz_sect);\r
+ printf(" disk_read(%u, 0x%X, %lu, 1)", pdrv, (UINT)(pbuff+5), lba);\r
+ dr = disk_read(pdrv, pbuff+5, lba, 1);\r
+ if (dr == RES_OK) {\r
+ printf(" - ok.\n");\r
+ } else {\r
+ printf(" - failed.\n");\r
+ return 17;\r
+ }\r
+ for (n = 0, pn(pns); n < sz_sect && pbuff[n+5] == (BYTE)pn(0); n++) ;\r
+ if (n == sz_sect) {\r
+ printf(" Data matched.\n");\r
+ } else {\r
+ printf("Failed: Read data differs from the data written.\n");\r
+ return 18;\r
+ }\r
+ pns++;\r
+\r
+ printf("**** 4GB barrier test ****\n");\r
+ if (sz_drv >= 128 + 0x80000000 / (sz_sect / 2)) {\r
+ lba = 6; lba2 = lba + 0x80000000 / (sz_sect / 2);\r
+ for (n = 0, pn(pns); n < (UINT)(sz_sect * 2); n++) pbuff[n] = (BYTE)pn(0);\r
+ printf(" disk_write(%u, 0x%X, %lu, 1)", pdrv, (UINT)pbuff, lba);\r
+ dr = disk_write(pdrv, pbuff, lba, 1);\r
+ if (dr == RES_OK) {\r
+ printf(" - ok.\n");\r
+ } else {\r
+ printf(" - failed.\n");\r
+ return 19;\r
+ }\r
+ printf(" disk_write(%u, 0x%X, %lu, 1)", pdrv, (UINT)(pbuff+sz_sect), lba2);\r
+ dr = disk_write(pdrv, pbuff+sz_sect, lba2, 1);\r
+ if (dr == RES_OK) {\r
+ printf(" - ok.\n");\r
+ } else {\r
+ printf(" - failed.\n");\r
+ return 20;\r
+ }\r
+ printf(" disk_ioctl(%u, CTRL_SYNC, NULL)", pdrv);\r
+ dr = disk_ioctl(pdrv, CTRL_SYNC, 0);\r
+ if (dr == RES_OK) {\r
+ printf(" - ok.\n");\r
+ } else {\r
+ printf(" - failed.\n");\r
+ return 21;\r
+ }\r
+ memset(pbuff, 0, sz_sect * 2);\r
+ printf(" disk_read(%u, 0x%X, %lu, 1)", pdrv, (UINT)pbuff, lba);\r
+ dr = disk_read(pdrv, pbuff, lba, 1);\r
+ if (dr == RES_OK) {\r
+ printf(" - ok.\n");\r
+ } else {\r
+ printf(" - failed.\n");\r
+ return 22;\r
+ }\r
+ printf(" disk_read(%u, 0x%X, %lu, 1)", pdrv, (UINT)(pbuff+sz_sect), lba2);\r
+ dr = disk_read(pdrv, pbuff+sz_sect, lba2, 1);\r
+ if (dr == RES_OK) {\r
+ printf(" - ok.\n");\r
+ } else {\r
+ printf(" - failed.\n");\r
+ return 23;\r
+ }\r
+ for (n = 0, pn(pns); pbuff[n] == (BYTE)pn(0) && n < (UINT)(sz_sect * 2); n++) ;\r
+ if (n == (UINT)(sz_sect * 2)) {\r
+ printf(" Data matched.\n");\r
+ } else {\r
+ printf("Failed: Read data differs from the data written.\n");\r
+ return 24;\r
+ }\r
+ } else {\r
+ printf(" Test skipped.\n");\r
+ }\r
+ pns++;\r
+\r
+ printf("**** Test cycle %u of %u completed ****\n\n", cc, ncyc);\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+\r
+\r
+int main (int argc, char* argv[])\r
+{\r
+ int rc;\r
+ DWORD buff[FF_MAX_SS]; /* Working buffer (4 sector in size) */\r
+\r
+ /* Check function/compatibility of the physical drive #0 */\r
+ rc = test_diskio(0, 3, buff, sizeof buff);\r
+\r
+ if (rc) {\r
+ printf("Sorry the function/compatibility test failed. (rc=%d)\nFatFs will not work with this disk driver.\n", rc);\r
+ } else {\r
+ printf("Congratulations! The disk driver works well.\n");\r
+ }\r
+\r
+ return rc;\r
+}\r
+\r