1e6865dcdSopenharmony_ci/*----------------------------------------------------------------------/
2e6865dcdSopenharmony_ci/ Low level disk I/O module function checker                            /
3e6865dcdSopenharmony_ci/-----------------------------------------------------------------------/
4e6865dcdSopenharmony_ci/ WARNING: The data on the target drive will be lost!
5e6865dcdSopenharmony_ci*/
6e6865dcdSopenharmony_ci
7e6865dcdSopenharmony_ci#include <stdio.h>
8e6865dcdSopenharmony_ci#include <string.h>
9e6865dcdSopenharmony_ci#include "ff.h"         /* Declarations of sector size */
10e6865dcdSopenharmony_ci#include "diskio.h"     /* Declarations of disk functions */
11e6865dcdSopenharmony_ci
12e6865dcdSopenharmony_ci
13e6865dcdSopenharmony_ci
14e6865dcdSopenharmony_cistatic DWORD pn (       /* Pseudo random number generator */
15e6865dcdSopenharmony_ci    DWORD pns   /* 0:Initialize, !0:Read */
16e6865dcdSopenharmony_ci)
17e6865dcdSopenharmony_ci{
18e6865dcdSopenharmony_ci    static DWORD lfsr;
19e6865dcdSopenharmony_ci    UINT n;
20e6865dcdSopenharmony_ci
21e6865dcdSopenharmony_ci
22e6865dcdSopenharmony_ci    if (pns) {
23e6865dcdSopenharmony_ci        lfsr = pns;
24e6865dcdSopenharmony_ci        for (n = 0; n < 32; n++) pn(0);
25e6865dcdSopenharmony_ci    }
26e6865dcdSopenharmony_ci    if (lfsr & 1) {
27e6865dcdSopenharmony_ci        lfsr >>= 1;
28e6865dcdSopenharmony_ci        lfsr ^= 0x80200003;
29e6865dcdSopenharmony_ci    } else {
30e6865dcdSopenharmony_ci        lfsr >>= 1;
31e6865dcdSopenharmony_ci    }
32e6865dcdSopenharmony_ci    return lfsr;
33e6865dcdSopenharmony_ci}
34e6865dcdSopenharmony_ci
35e6865dcdSopenharmony_ci
36e6865dcdSopenharmony_ciint test_diskio (
37e6865dcdSopenharmony_ci    BYTE pdrv,      /* Physical drive number to be checked (all data on the drive will be lost) */
38e6865dcdSopenharmony_ci    UINT ncyc,      /* Number of test cycles */
39e6865dcdSopenharmony_ci    DWORD* buff,    /* Pointer to the working buffer */
40e6865dcdSopenharmony_ci    UINT sz_buff    /* Size of the working buffer in unit of byte */
41e6865dcdSopenharmony_ci)
42e6865dcdSopenharmony_ci{
43e6865dcdSopenharmony_ci    UINT n, cc, ns;
44e6865dcdSopenharmony_ci    DWORD sz_drv, lba, lba2, sz_eblk, pns = 1;
45e6865dcdSopenharmony_ci    WORD sz_sect;
46e6865dcdSopenharmony_ci    BYTE *pbuff = (BYTE*)buff;
47e6865dcdSopenharmony_ci    DSTATUS ds;
48e6865dcdSopenharmony_ci    DRESULT dr;
49e6865dcdSopenharmony_ci
50e6865dcdSopenharmony_ci
51e6865dcdSopenharmony_ci    printf("test_diskio(%u, %u, 0x%08X, 0x%08X)\n", pdrv, ncyc, (UINT)buff, sz_buff);
52e6865dcdSopenharmony_ci
53e6865dcdSopenharmony_ci    if (sz_buff < FF_MAX_SS + 8) {
54e6865dcdSopenharmony_ci        printf("Insufficient work area to run the program.\n");
55e6865dcdSopenharmony_ci        return 1;
56e6865dcdSopenharmony_ci    }
57e6865dcdSopenharmony_ci
58e6865dcdSopenharmony_ci    for (cc = 1; cc <= ncyc; cc++) {
59e6865dcdSopenharmony_ci        printf("**** Test cycle %u of %u start ****\n", cc, ncyc);
60e6865dcdSopenharmony_ci
61e6865dcdSopenharmony_ci        printf(" disk_initalize(%u)", pdrv);
62e6865dcdSopenharmony_ci        ds = disk_initialize(pdrv);
63e6865dcdSopenharmony_ci        if (ds & STA_NOINIT) {
64e6865dcdSopenharmony_ci            printf(" - failed.\n");
65e6865dcdSopenharmony_ci            return 2;
66e6865dcdSopenharmony_ci        } else {
67e6865dcdSopenharmony_ci            printf(" - ok.\n");
68e6865dcdSopenharmony_ci        }
69e6865dcdSopenharmony_ci
70e6865dcdSopenharmony_ci        printf("**** Get drive size ****\n");
71e6865dcdSopenharmony_ci        printf(" disk_ioctl(%u, GET_SECTOR_COUNT, 0x%08X)", pdrv, (UINT)&sz_drv);
72e6865dcdSopenharmony_ci        sz_drv = 0;
73e6865dcdSopenharmony_ci        dr = disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_drv);
74e6865dcdSopenharmony_ci        if (dr == RES_OK) {
75e6865dcdSopenharmony_ci            printf(" - ok.\n");
76e6865dcdSopenharmony_ci        } else {
77e6865dcdSopenharmony_ci            printf(" - failed.\n");
78e6865dcdSopenharmony_ci            return 3;
79e6865dcdSopenharmony_ci        }
80e6865dcdSopenharmony_ci        if (sz_drv < 128) {
81e6865dcdSopenharmony_ci            printf("Failed: Insufficient drive size to test.\n");
82e6865dcdSopenharmony_ci            return 4;
83e6865dcdSopenharmony_ci        }
84e6865dcdSopenharmony_ci        printf(" Number of sectors on the drive %u is %lu.\n", pdrv, sz_drv);
85e6865dcdSopenharmony_ci
86e6865dcdSopenharmony_ci#if FF_MAX_SS != FF_MIN_SS
87e6865dcdSopenharmony_ci        printf("**** Get sector size ****\n");
88e6865dcdSopenharmony_ci        printf(" disk_ioctl(%u, GET_SECTOR_SIZE, 0x%X)", pdrv, (UINT)&sz_sect);
89e6865dcdSopenharmony_ci        sz_sect = 0;
90e6865dcdSopenharmony_ci        dr = disk_ioctl(pdrv, GET_SECTOR_SIZE, &sz_sect);
91e6865dcdSopenharmony_ci        if (dr == RES_OK) {
92e6865dcdSopenharmony_ci            printf(" - ok.\n");
93e6865dcdSopenharmony_ci        } else {
94e6865dcdSopenharmony_ci            printf(" - failed.\n");
95e6865dcdSopenharmony_ci            return 5;
96e6865dcdSopenharmony_ci        }
97e6865dcdSopenharmony_ci        printf(" Size of sector is %u bytes.\n", sz_sect);
98e6865dcdSopenharmony_ci#else
99e6865dcdSopenharmony_ci        sz_sect = FF_MAX_SS;
100e6865dcdSopenharmony_ci#endif
101e6865dcdSopenharmony_ci
102e6865dcdSopenharmony_ci        printf("**** Get block size ****\n");
103e6865dcdSopenharmony_ci        printf(" disk_ioctl(%u, GET_BLOCK_SIZE, 0x%X)", pdrv, (UINT)&sz_eblk);
104e6865dcdSopenharmony_ci        sz_eblk = 0;
105e6865dcdSopenharmony_ci        dr = disk_ioctl(pdrv, GET_BLOCK_SIZE, &sz_eblk);
106e6865dcdSopenharmony_ci        if (dr == RES_OK) {
107e6865dcdSopenharmony_ci            printf(" - ok.\n");
108e6865dcdSopenharmony_ci        } else {
109e6865dcdSopenharmony_ci            printf(" - failed.\n");
110e6865dcdSopenharmony_ci        }
111e6865dcdSopenharmony_ci        if (dr == RES_OK || sz_eblk >= 2) {
112e6865dcdSopenharmony_ci            printf(" Size of the erase block is %lu sectors.\n", sz_eblk);
113e6865dcdSopenharmony_ci        } else {
114e6865dcdSopenharmony_ci            printf(" Size of the erase block is unknown.\n");
115e6865dcdSopenharmony_ci        }
116e6865dcdSopenharmony_ci
117e6865dcdSopenharmony_ci        /* Single sector write test */
118e6865dcdSopenharmony_ci        printf("**** Single sector write test ****\n");
119e6865dcdSopenharmony_ci        lba = 0;
120e6865dcdSopenharmony_ci        for (n = 0, pn(pns); n < sz_sect; n++) pbuff[n] = (BYTE)pn(0);
121e6865dcdSopenharmony_ci        printf(" disk_write(%u, 0x%X, %lu, 1)", pdrv, (UINT)pbuff, lba);
122e6865dcdSopenharmony_ci        dr = disk_write(pdrv, pbuff, lba, 1);
123e6865dcdSopenharmony_ci        if (dr == RES_OK) {
124e6865dcdSopenharmony_ci            printf(" - ok.\n");
125e6865dcdSopenharmony_ci        } else {
126e6865dcdSopenharmony_ci            printf(" - failed.\n");
127e6865dcdSopenharmony_ci            return 6;
128e6865dcdSopenharmony_ci        }
129e6865dcdSopenharmony_ci        printf(" disk_ioctl(%u, CTRL_SYNC, NULL)", pdrv);
130e6865dcdSopenharmony_ci        dr = disk_ioctl(pdrv, CTRL_SYNC, 0);
131e6865dcdSopenharmony_ci        if (dr == RES_OK) {
132e6865dcdSopenharmony_ci            printf(" - ok.\n");
133e6865dcdSopenharmony_ci        } else {
134e6865dcdSopenharmony_ci            printf(" - failed.\n");
135e6865dcdSopenharmony_ci            return 7;
136e6865dcdSopenharmony_ci        }
137e6865dcdSopenharmony_ci        memset(pbuff, 0, sz_sect);
138e6865dcdSopenharmony_ci        printf(" disk_read(%u, 0x%X, %lu, 1)", pdrv, (UINT)pbuff, lba);
139e6865dcdSopenharmony_ci        dr = disk_read(pdrv, pbuff, lba, 1);
140e6865dcdSopenharmony_ci        if (dr == RES_OK) {
141e6865dcdSopenharmony_ci            printf(" - ok.\n");
142e6865dcdSopenharmony_ci        } else {
143e6865dcdSopenharmony_ci            printf(" - failed.\n");
144e6865dcdSopenharmony_ci            return 8;
145e6865dcdSopenharmony_ci        }
146e6865dcdSopenharmony_ci        for (n = 0, pn(pns); n < sz_sect && pbuff[n] == (BYTE)pn(0); n++) ;
147e6865dcdSopenharmony_ci        if (n == sz_sect) {
148e6865dcdSopenharmony_ci            printf(" Read data matched.\n");
149e6865dcdSopenharmony_ci        } else {
150e6865dcdSopenharmony_ci            printf(" Read data differs from the data written.\n");
151e6865dcdSopenharmony_ci            return 10;
152e6865dcdSopenharmony_ci        }
153e6865dcdSopenharmony_ci        pns++;
154e6865dcdSopenharmony_ci
155e6865dcdSopenharmony_ci        printf("**** Multiple sector write test ****\n");
156e6865dcdSopenharmony_ci        lba = 5; ns = sz_buff / sz_sect;
157e6865dcdSopenharmony_ci        if (ns > 4) ns = 4;
158e6865dcdSopenharmony_ci        if (ns > 1) {
159e6865dcdSopenharmony_ci            for (n = 0, pn(pns); n < (UINT)(sz_sect * ns); n++) pbuff[n] = (BYTE)pn(0);
160e6865dcdSopenharmony_ci            printf(" disk_write(%u, 0x%X, %lu, %u)", pdrv, (UINT)pbuff, lba, ns);
161e6865dcdSopenharmony_ci            dr = disk_write(pdrv, pbuff, lba, ns);
162e6865dcdSopenharmony_ci            if (dr == RES_OK) {
163e6865dcdSopenharmony_ci                printf(" - ok.\n");
164e6865dcdSopenharmony_ci            } else {
165e6865dcdSopenharmony_ci                printf(" - failed.\n");
166e6865dcdSopenharmony_ci                return 11;
167e6865dcdSopenharmony_ci            }
168e6865dcdSopenharmony_ci            printf(" disk_ioctl(%u, CTRL_SYNC, NULL)", pdrv);
169e6865dcdSopenharmony_ci            dr = disk_ioctl(pdrv, CTRL_SYNC, 0);
170e6865dcdSopenharmony_ci            if (dr == RES_OK) {
171e6865dcdSopenharmony_ci                printf(" - ok.\n");
172e6865dcdSopenharmony_ci            } else {
173e6865dcdSopenharmony_ci                printf(" - failed.\n");
174e6865dcdSopenharmony_ci                return 12;
175e6865dcdSopenharmony_ci            }
176e6865dcdSopenharmony_ci            memset(pbuff, 0, sz_sect * ns);
177e6865dcdSopenharmony_ci            printf(" disk_read(%u, 0x%X, %lu, %u)", pdrv, (UINT)pbuff, lba, ns);
178e6865dcdSopenharmony_ci            dr = disk_read(pdrv, pbuff, lba, ns);
179e6865dcdSopenharmony_ci            if (dr == RES_OK) {
180e6865dcdSopenharmony_ci                printf(" - ok.\n");
181e6865dcdSopenharmony_ci            } else {
182e6865dcdSopenharmony_ci                printf(" - failed.\n");
183e6865dcdSopenharmony_ci                return 13;
184e6865dcdSopenharmony_ci            }
185e6865dcdSopenharmony_ci            for (n = 0, pn(pns); n < (UINT)(sz_sect * ns) && pbuff[n] == (BYTE)pn(0); n++) ;
186e6865dcdSopenharmony_ci            if (n == (UINT)(sz_sect * ns)) {
187e6865dcdSopenharmony_ci                printf(" Read data matched.\n");
188e6865dcdSopenharmony_ci            } else {
189e6865dcdSopenharmony_ci                printf(" Read data differs from the data written.\n");
190e6865dcdSopenharmony_ci                return 14;
191e6865dcdSopenharmony_ci            }
192e6865dcdSopenharmony_ci        } else {
193e6865dcdSopenharmony_ci            printf(" Test skipped.\n");
194e6865dcdSopenharmony_ci        }
195e6865dcdSopenharmony_ci        pns++;
196e6865dcdSopenharmony_ci
197e6865dcdSopenharmony_ci        printf("**** Single sector write test (unaligned buffer address) ****\n");
198e6865dcdSopenharmony_ci        lba = 5;
199e6865dcdSopenharmony_ci        for (n = 0, pn(pns); n < sz_sect; n++) pbuff[n+3] = (BYTE)pn(0);
200e6865dcdSopenharmony_ci        printf(" disk_write(%u, 0x%X, %lu, 1)", pdrv, (UINT)(pbuff+3), lba);
201e6865dcdSopenharmony_ci        dr = disk_write(pdrv, pbuff+3, lba, 1);
202e6865dcdSopenharmony_ci        if (dr == RES_OK) {
203e6865dcdSopenharmony_ci            printf(" - ok.\n");
204e6865dcdSopenharmony_ci        } else {
205e6865dcdSopenharmony_ci            printf(" - failed.\n");
206e6865dcdSopenharmony_ci            return 15;
207e6865dcdSopenharmony_ci        }
208e6865dcdSopenharmony_ci        printf(" disk_ioctl(%u, CTRL_SYNC, NULL)", pdrv);
209e6865dcdSopenharmony_ci        dr = disk_ioctl(pdrv, CTRL_SYNC, 0);
210e6865dcdSopenharmony_ci        if (dr == RES_OK) {
211e6865dcdSopenharmony_ci            printf(" - ok.\n");
212e6865dcdSopenharmony_ci        } else {
213e6865dcdSopenharmony_ci            printf(" - failed.\n");
214e6865dcdSopenharmony_ci            return 16;
215e6865dcdSopenharmony_ci        }
216e6865dcdSopenharmony_ci        memset(pbuff+5, 0, sz_sect);
217e6865dcdSopenharmony_ci        printf(" disk_read(%u, 0x%X, %lu, 1)", pdrv, (UINT)(pbuff+5), lba);
218e6865dcdSopenharmony_ci        dr = disk_read(pdrv, pbuff+5, lba, 1);
219e6865dcdSopenharmony_ci        if (dr == RES_OK) {
220e6865dcdSopenharmony_ci            printf(" - ok.\n");
221e6865dcdSopenharmony_ci        } else {
222e6865dcdSopenharmony_ci            printf(" - failed.\n");
223e6865dcdSopenharmony_ci            return 17;
224e6865dcdSopenharmony_ci        }
225e6865dcdSopenharmony_ci        for (n = 0, pn(pns); n < sz_sect && pbuff[n+5] == (BYTE)pn(0); n++) ;
226e6865dcdSopenharmony_ci        if (n == sz_sect) {
227e6865dcdSopenharmony_ci            printf(" Read data matched.\n");
228e6865dcdSopenharmony_ci        } else {
229e6865dcdSopenharmony_ci            printf(" Read data differs from the data written.\n");
230e6865dcdSopenharmony_ci            return 18;
231e6865dcdSopenharmony_ci        }
232e6865dcdSopenharmony_ci        pns++;
233e6865dcdSopenharmony_ci
234e6865dcdSopenharmony_ci        printf("**** 4GB barrier test ****\n");
235e6865dcdSopenharmony_ci        if (sz_drv >= 128 + 0x80000000 / (sz_sect / 2)) {
236e6865dcdSopenharmony_ci            lba = 6; lba2 = lba + 0x80000000 / (sz_sect / 2);
237e6865dcdSopenharmony_ci            for (n = 0, pn(pns); n < (UINT)(sz_sect * 2); n++) pbuff[n] = (BYTE)pn(0);
238e6865dcdSopenharmony_ci            printf(" disk_write(%u, 0x%X, %lu, 1)", pdrv, (UINT)pbuff, lba);
239e6865dcdSopenharmony_ci            dr = disk_write(pdrv, pbuff, lba, 1);
240e6865dcdSopenharmony_ci            if (dr == RES_OK) {
241e6865dcdSopenharmony_ci                printf(" - ok.\n");
242e6865dcdSopenharmony_ci            } else {
243e6865dcdSopenharmony_ci                printf(" - failed.\n");
244e6865dcdSopenharmony_ci                return 19;
245e6865dcdSopenharmony_ci            }
246e6865dcdSopenharmony_ci            printf(" disk_write(%u, 0x%X, %lu, 1)", pdrv, (UINT)(pbuff+sz_sect), lba2);
247e6865dcdSopenharmony_ci            dr = disk_write(pdrv, pbuff+sz_sect, lba2, 1);
248e6865dcdSopenharmony_ci            if (dr == RES_OK) {
249e6865dcdSopenharmony_ci                printf(" - ok.\n");
250e6865dcdSopenharmony_ci            } else {
251e6865dcdSopenharmony_ci                printf(" - failed.\n");
252e6865dcdSopenharmony_ci                return 20;
253e6865dcdSopenharmony_ci            }
254e6865dcdSopenharmony_ci            printf(" disk_ioctl(%u, CTRL_SYNC, NULL)", pdrv);
255e6865dcdSopenharmony_ci            dr = disk_ioctl(pdrv, CTRL_SYNC, 0);
256e6865dcdSopenharmony_ci            if (dr == RES_OK) {
257e6865dcdSopenharmony_ci            printf(" - ok.\n");
258e6865dcdSopenharmony_ci            } else {
259e6865dcdSopenharmony_ci                printf(" - failed.\n");
260e6865dcdSopenharmony_ci                return 21;
261e6865dcdSopenharmony_ci            }
262e6865dcdSopenharmony_ci            memset(pbuff, 0, sz_sect * 2);
263e6865dcdSopenharmony_ci            printf(" disk_read(%u, 0x%X, %lu, 1)", pdrv, (UINT)pbuff, lba);
264e6865dcdSopenharmony_ci            dr = disk_read(pdrv, pbuff, lba, 1);
265e6865dcdSopenharmony_ci            if (dr == RES_OK) {
266e6865dcdSopenharmony_ci                printf(" - ok.\n");
267e6865dcdSopenharmony_ci            } else {
268e6865dcdSopenharmony_ci                printf(" - failed.\n");
269e6865dcdSopenharmony_ci                return 22;
270e6865dcdSopenharmony_ci            }
271e6865dcdSopenharmony_ci            printf(" disk_read(%u, 0x%X, %lu, 1)", pdrv, (UINT)(pbuff+sz_sect), lba2);
272e6865dcdSopenharmony_ci            dr = disk_read(pdrv, pbuff+sz_sect, lba2, 1);
273e6865dcdSopenharmony_ci            if (dr == RES_OK) {
274e6865dcdSopenharmony_ci                printf(" - ok.\n");
275e6865dcdSopenharmony_ci            } else {
276e6865dcdSopenharmony_ci                printf(" - failed.\n");
277e6865dcdSopenharmony_ci                return 23;
278e6865dcdSopenharmony_ci            }
279e6865dcdSopenharmony_ci            for (n = 0, pn(pns); pbuff[n] == (BYTE)pn(0) && n < (UINT)(sz_sect * 2); n++) ;
280e6865dcdSopenharmony_ci            if (n == (UINT)(sz_sect * 2)) {
281e6865dcdSopenharmony_ci                printf(" Read data matched.\n");
282e6865dcdSopenharmony_ci            } else {
283e6865dcdSopenharmony_ci                printf(" Read data differs from the data written.\n");
284e6865dcdSopenharmony_ci                return 24;
285e6865dcdSopenharmony_ci            }
286e6865dcdSopenharmony_ci        } else {
287e6865dcdSopenharmony_ci            printf(" Test skipped.\n");
288e6865dcdSopenharmony_ci        }
289e6865dcdSopenharmony_ci        pns++;
290e6865dcdSopenharmony_ci
291e6865dcdSopenharmony_ci        printf("**** Test cycle %u of %u completed ****\n\n", cc, ncyc);
292e6865dcdSopenharmony_ci    }
293e6865dcdSopenharmony_ci
294e6865dcdSopenharmony_ci    return 0;
295e6865dcdSopenharmony_ci}
296e6865dcdSopenharmony_ci
297e6865dcdSopenharmony_ci
298e6865dcdSopenharmony_ci
299e6865dcdSopenharmony_ciint main (int argc, char* argv[])
300e6865dcdSopenharmony_ci{
301e6865dcdSopenharmony_ci    int rc;
302e6865dcdSopenharmony_ci    DWORD buff[FF_MAX_SS];  /* Working buffer (4 sector in size) */
303e6865dcdSopenharmony_ci
304e6865dcdSopenharmony_ci    /* Check function/compatibility of the physical drive #0 */
305e6865dcdSopenharmony_ci    rc = test_diskio(0, 3, buff, sizeof buff);
306e6865dcdSopenharmony_ci
307e6865dcdSopenharmony_ci    if (rc) {
308e6865dcdSopenharmony_ci        printf("Sorry the function/compatibility test failed. (rc=%d)\nFatFs will not work with this disk driver.\n", rc);
309e6865dcdSopenharmony_ci    } else {
310e6865dcdSopenharmony_ci        printf("Congratulations! The disk driver works well.\n");
311e6865dcdSopenharmony_ci    }
312e6865dcdSopenharmony_ci
313e6865dcdSopenharmony_ci    return rc;
314e6865dcdSopenharmony_ci}
315e6865dcdSopenharmony_ci
316