dfs_elm.c 17.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13
/*
 * File      : dfs_elm.c
 * This file is part of Device File System in RT-Thread RTOS
 * COPYRIGHT (C) 2008-2011, RT-Thread Development Team
 *
 * The license and distribution terms for this file may be
 * found in the file LICENSE in this distribution or at
 * http://www.rt-thread.org/license/LICENSE.
 *
 * Change Logs:
 * Date           Author       Notes
 * 2008-02-22     QiuYi        The first version.
 * 2011-10-08     Bernard      fixed the block size in statfs.
B
bernard.xiong@gmail.com 已提交
14
 * 2011-11-23     Bernard      fixed the rename issue.
15
 * 2012-07-26     aozima       implement ff_memalloc and ff_memfree.
16
 * 2012-12-19     Bernard      fixed the O_APPEND and lseek issue.
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
 */
 
#include <rtthread.h>
#include "ffconf.h"
#include "ff.h"

/* ELM FatFs provide a DIR struct */
#define HAVE_DIR_STRUCTURE

#include <dfs_fs.h>
#include <dfs_def.h>

static rt_device_t disk[_VOLUMES] = {0};

static int elm_result_to_dfs(FRESULT result)
{
	int status = DFS_STATUS_OK;

	switch (result)
	{
	case FR_OK:
		break;

	case FR_NO_FILE:
	case FR_NO_PATH:
	case FR_NO_FILESYSTEM:
		status = -DFS_STATUS_ENOENT;
		break;

	case FR_INVALID_NAME:
		status = -DFS_STATUS_EINVAL;
		break;

	case FR_EXIST:
	case FR_INVALID_OBJECT:
		status = -DFS_STATUS_EEXIST;
		break;

	case FR_DISK_ERR:
	case FR_NOT_READY:
	case FR_INT_ERR:
		status = -DFS_STATUS_EIO;
		break;

	case FR_WRITE_PROTECTED:
	case FR_DENIED:
		status = -DFS_STATUS_EROFS;
		break;

	case FR_MKFS_ABORTED:
		status = -DFS_STATUS_EINVAL;
		break;

	default:
		status = -1;
		break;
	}

	return status;
}

78 79 80 81 82
/* results:
 *  -1, no space to install fatfs driver 
 *  >= 0, there is an space to install fatfs driver 
 */
static int get_disk(rt_device_t id)
83
{
84
    int index;
85 86 87

	for (index = 0; index < _VOLUMES; index ++)
	{
88 89
		if (disk[index] == id)
            return index;
90
	}
91 92 93 94 95 96 97 98 99 100 101 102 103
    
    return -1;
}

int dfs_elm_mount(struct dfs_filesystem *fs, unsigned long rwflag, const void *data)
{
	FATFS *fat;
	FRESULT result;
	int index;

	/* get an empty position */
    index = get_disk(RT_NULL); 
	if (index == -1)
104
		return -DFS_STATUS_ENOSPC;
105

106
	/* save device */
107 108
	disk[index] = fs->dev_id;

109
	fat = (FATFS *)rt_malloc(sizeof(FATFS));
110 111
	if (fat == RT_NULL)
	{
112
        disk[index] = RT_NULL;
113 114 115 116
		return -1;
	}

	/* mount fatfs, always 0 logic driver */
117
	result = f_mount((BYTE)index, fat);
118
	if (result == FR_OK)
119 120 121 122
	{
		char drive[8];
		DIR * dir;

123
		rt_snprintf(drive, sizeof(drive), "%d:/", index);
124 125 126 127 128 129 130
		dir = (DIR *)rt_malloc(sizeof(DIR));
		if (dir == RT_NULL)
			return -DFS_STATUS_ENOMEM;

		/* open the root directory to test whether the fatfs is valid */
		result = f_opendir(dir, drive);
		if (result != FR_OK)
131
            goto __err;
132

133
        /* mount succeed! */
134
		fs->data = fat;
135 136
		rt_free(dir);
	    return 0;
137 138
	}

139 140 141 142
__err:
    disk[index] = RT_NULL;
	rt_free(fat);
	return elm_result_to_dfs(result);
143 144
}

145
int dfs_elm_unmount(struct dfs_filesystem *fs)
146 147 148
{
	FATFS *fat;
	FRESULT result;
149
	int  index;
150

151
	fat = (FATFS *)fs->data;
152 153 154 155

	RT_ASSERT(fat != RT_NULL);

	/* find the device index and then umount it */
156 157 158
    index = get_disk(fs->dev_id);
    if (index == -1) /* not found */
	    return -DFS_STATUS_ENOENT;
159

160 161 162 163 164 165 166
	result = f_mount((BYTE)index, RT_NULL);
	if (result != FR_OK)
    	return elm_result_to_dfs(result);

	fs->data = RT_NULL;
	disk[index] = RT_NULL;
	rt_free(fat);
167

168
	return DFS_STATUS_OK;
169 170
}

171
int dfs_elm_mkfs(rt_device_t dev_id)
172
{
173 174 175 176
#define FSM_STATUS_INIT            0
#define FSM_STATUS_USE_TEMP_DRIVER 1
    FATFS *fat;
    int flag;
177
	FRESULT result;
178
    int index;
179

180 181
    if (dev_id == RT_NULL)
        return -DFS_STATUS_EINVAL;
182

183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
	/* if the device is already mounted, then just do mkfs to the drv,
     * while if it is not mounted yet, then find an empty drive to do mkfs
     */

    flag = FSM_STATUS_INIT;
    index = get_disk(dev_id);
    if (index == -1)
    {
        /* not found the device id */
        index = get_disk(RT_NULL);
    	if (index == -1) 
        {	
            /* no space to store an temp driver */
        	rt_kprintf("sorry, there is no space to do mkfs! \n");
    		return -DFS_STATUS_ENOSPC;
        }
        else
        {
            fat = rt_malloc(sizeof(FATFS));
            if (fat == RT_NULL)
                return -DFS_STATUS_ENOMEM;

            flag = FSM_STATUS_USE_TEMP_DRIVER;

            disk[index] = dev_id;

            /* just fill the FatFs[vol] in ff.c, or mkfs will failded! 
             * consider this condition: you just umount the elm fat, 
             * then the space in FatFs[index] is released, and now do mkfs 
             * on the disk, you will get a failure. so we need f_mount here, 
             * just fill the FatFS[index] in elm fatfs to make mkfs work.
             */
            f_mount((BYTE)index, fat);
        }
    }

	/* 1: no partition table */
	/* 0: auto selection of cluster size */
	result = f_mkfs((BYTE)index, 1, 0);

    /* check flag status, we need clear the temp driver stored in disk[] */
    if (flag == FSM_STATUS_USE_TEMP_DRIVER)
    {
        rt_free(fat);
        f_mount((BYTE)index, RT_NULL);
        disk[index] = RT_NULL;
    }

	if (result != FR_OK)
	{
		rt_kprintf("format error\n");
		return elm_result_to_dfs(result);
235 236
	}

237
	return DFS_STATUS_OK;
238 239
}

240
int dfs_elm_statfs(struct dfs_filesystem *fs, struct statfs *buf)
241 242 243 244 245 246 247 248 249
{
	FATFS *f;
	FRESULT res;
	char driver[4];
	DWORD fre_clust, fre_sect, tot_sect;

	RT_ASSERT(fs != RT_NULL);
	RT_ASSERT(buf != RT_NULL);

250
	f = (FATFS *)fs->data;
251 252 253

	rt_snprintf(driver, sizeof(driver), "%d:", f->drv);
	res = f_getfree(driver, &fre_clust, &f);
254 255
	if (res) 
		return elm_result_to_dfs(res);
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271

	/* Get total sectors and free sectors */
	tot_sect = (f->n_fatent - 2) * f->csize;
	fre_sect = fre_clust * f->csize;

	buf->f_bfree = fre_sect;
	buf->f_blocks = tot_sect;
#if _MAX_SS != 512
	buf->f_bsize = f->ssize;
#else
    buf->f_bsize = 512;
#endif

	return 0;
}

272
int dfs_elm_open(struct dfs_fd *file)
273
{
274
	FIL *fd;
275 276 277 278 279 280 281 282 283 284
	BYTE mode;
	FRESULT result;
	char *drivers_fn;

#if (_VOLUMES > 1)
	int vol;
	extern int elm_get_vol(FATFS *fat);

	/* add path for ELM FatFS driver support */
	vol = elm_get_vol((FATFS *)file->fs->data);
285 286
	if (vol < 0)
		return -DFS_STATUS_ENOENT;
287
	drivers_fn = rt_malloc(256);
288 289
	if (drivers_fn == RT_NULL)
		return -DFS_STATUS_ENOMEM;
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338

	rt_snprintf(drivers_fn, 256, "%d:%s", vol, file->path);
#else
	drivers_fn = file->path;
#endif

	if (file->flags & DFS_O_DIRECTORY)
	{
		DIR *dir;

		if (file->flags & DFS_O_CREAT)
		{
			result = f_mkdir(drivers_fn);
			if (result != FR_OK)
			{
#if _VOLUMES > 1
				rt_free(drivers_fn);
#endif
				return elm_result_to_dfs(result);
			}
		}

		/* open directory */
		dir = (DIR *)rt_malloc(sizeof(DIR));
		if (dir == RT_NULL)
		{
#if _VOLUMES > 1
			rt_free(drivers_fn);
#endif
			return -DFS_STATUS_ENOMEM;
		}

		result = f_opendir(dir, drivers_fn);
#if _VOLUMES > 1
		rt_free(drivers_fn);
#endif
		if (result != FR_OK)
		{
			rt_free(dir);
			return elm_result_to_dfs(result);
		}

		file->data = dir;
		return DFS_STATUS_OK;
	}
	else
	{
		mode = FA_READ;

339 340 341 342
		if (file->flags & DFS_O_WRONLY)
			mode |= FA_WRITE;
		if ((file->flags & DFS_O_ACCMODE) & DFS_O_RDWR)
			mode |= FA_WRITE;
343
		/* Opens the file, if it is existing. If not, a new file is created. */
344 345
		if (file->flags & DFS_O_CREAT)
			mode |= FA_OPEN_ALWAYS;
346
		/* Creates a new file. If the file is existing, it is truncated and overwritten. */
347 348
		if (file->flags & DFS_O_TRUNC)
			mode |= FA_CREATE_ALWAYS;
349
		/* Creates a new file. The function fails if the file is already existing. */
350 351
		if (file->flags & DFS_O_EXCL)
			mode |= FA_CREATE_NEW;
352 353

		/* allocate a fd */
354
		fd = (FIL *)rt_malloc(sizeof(FIL));
355 356
		if (fd == RT_NULL)
		{
357 358 359
#if _VOLUMES > 1
			rt_free(drivers_fn);
#endif
360 361 362 363 364 365 366 367 368 369 370 371 372 373 374
			return -DFS_STATUS_ENOMEM;
		}

		result = f_open(fd, drivers_fn, mode);
#if _VOLUMES > 1
		rt_free(drivers_fn);
#endif
		if (result == FR_OK)
		{
			file->pos  = fd->fptr;
			file->size = fd->fsize;
			file->data = fd;

			if (file->flags & DFS_O_APPEND)
			{
375 376 377
				/* seek to the end of file */
				f_lseek(fd, fd->fsize);
				file->pos = fd->fptr;
378 379 380 381 382 383 384 385 386 387 388 389 390
			}
		}
		else
		{
			/* open failed, return */
			rt_free(fd);
			return elm_result_to_dfs(result);
		}
	}

	return DFS_STATUS_OK;
}

391
int dfs_elm_close(struct dfs_fd *file)
392 393 394 395 396 397
{
	FRESULT result;

	result = FR_OK;
	if (file->type == FT_DIRECTORY)
	{
398
		DIR *dir;
399

400
		dir = (DIR *)(file->data);
401 402 403 404 405 406 407
		RT_ASSERT(dir != RT_NULL);

		/* release memory */
		rt_free(dir);
	}
	else if (file->type == FT_REGULAR)
	{
408 409
		FIL *fd;
		fd = (FIL *)(file->data);
410 411 412 413 414 415 416 417 418 419 420 421 422
		RT_ASSERT(fd != RT_NULL);

		result = f_close(fd);
		if (result == FR_OK)
		{
			/* release memory */
			rt_free(fd);
		}
	}

	return elm_result_to_dfs(result);
}

423
int dfs_elm_ioctl(struct dfs_fd *file, int cmd,	void *args)
424 425 426 427
{
	return -DFS_STATUS_ENOSYS;
}

428
int dfs_elm_read(struct dfs_fd *file, void *buf, rt_size_t len)
429
{
430
	FIL *fd;
431 432 433 434 435 436 437 438
	FRESULT result;
	UINT byte_read;

	if (file->type == FT_DIRECTORY)
	{
		return -DFS_STATUS_EISDIR;
	}

439
	fd = (FIL *)(file->data);
440 441 442 443 444
	RT_ASSERT(fd != RT_NULL);

	result = f_read(fd, buf, len, &byte_read);
	/* update position */
	file->pos  = fd->fptr;
445 446
	if (result == FR_OK)
		return byte_read;
447 448 449 450

	return elm_result_to_dfs(result);
}

451
int dfs_elm_write(struct dfs_fd *file, const void *buf, rt_size_t len)
452
{
453
	FIL *fd;
454 455 456 457 458 459 460 461
	FRESULT result;
	UINT byte_write;

	if (file->type == FT_DIRECTORY)
	{
		return -DFS_STATUS_EISDIR;
	}

462
	fd = (FIL *)(file->data);
463 464 465 466 467 468
	RT_ASSERT(fd != RT_NULL);

	result = f_write(fd, buf, len, &byte_write);
	/* update position and file size */
	file->pos  = fd->fptr;
	file->size = fd->fsize;
469 470
	if (result == FR_OK)
		return byte_write;
471 472 473 474

	return elm_result_to_dfs(result);
}

475
int dfs_elm_flush(struct dfs_fd *file)
476
{
477
	FIL *fd;
478 479
	FRESULT result;

480
	fd = (FIL *)(file->data);
481 482 483 484 485 486
	RT_ASSERT(fd != RT_NULL);

	result = f_sync(fd);
	return elm_result_to_dfs(result);
}

487
int dfs_elm_lseek(struct dfs_fd *file, rt_off_t offset)
488
{
wuyangyong's avatar
wuyangyong 已提交
489
	FRESULT result = FR_OK;
490 491
	if (file->type == FT_REGULAR)
	{
492
		FIL *fd;
493 494

		/* regular file type */
495
		fd = (FIL *)(file->data);
496 497 498 499 500 501
		RT_ASSERT(fd != RT_NULL);
		
		result = f_lseek(fd, offset);
		if (result == FR_OK)
		{
			/* return current position */
502
			file->pos = fd->fptr;
503 504 505 506 507 508
			return fd->fptr;
		}
	}
	else if (file->type == FT_DIRECTORY)
	{
		/* which is a directory */
509
		DIR *dir;
510

511
		dir = (DIR *)(file->data);
512 513 514 515 516 517 518 519 520 521 522 523 524 525
		RT_ASSERT(dir != RT_NULL);

		result = f_seekdir(dir, offset / sizeof(struct dirent));
		if (result == FR_OK)
		{
			/* update file position */
			file->pos = offset;
			return file->pos;
		}
	}

	return elm_result_to_dfs(result);
}

526
int dfs_elm_getdents(struct dfs_fd *file, struct dirent *dirp, rt_uint32_t count)
527
{
528
	DIR *dir;
529 530 531
	FILINFO fno;
	FRESULT result;
	rt_uint32_t index;
532
	struct dirent *d;
533

534
	dir = (DIR *)(file->data);
535 536 537 538
	RT_ASSERT(dir != RT_NULL);

	/* make integer count */
	count = (count / sizeof(struct dirent)) * sizeof(struct dirent);
539 540
	if (count == 0)
		return -DFS_STATUS_EINVAL;
541 542 543 544 545 546 547 548 549 550 551 552 553 554 555

#if _USE_LFN
	/* allocate long file name */
	fno.lfname = rt_malloc(256);
	fno.lfsize = 256;
#endif

	index = 0;
	while (1)
	{
		char *fn;

		d = dirp + index;

		result = f_readdir(dir, &fno);
556 557
		if (result != FR_OK || fno.fname[0] == 0)
			break;
558 559 560 561 562 563 564 565

#if _USE_LFN
		fn = *fno.lfname? fno.lfname : fno.fname;
#else
		fn = fno.fname;
#endif

		d->d_type = DFS_DT_UNKNOWN;
566 567 568 569
		if (fno.fattrib & AM_DIR)
			d->d_type = DFS_DT_DIR;
		else
			d->d_type = DFS_DT_REG;
570

571
		d->d_namlen = (rt_uint8_t)rt_strlen(fn);
572 573 574 575
		d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
		rt_strncpy(d->d_name, fn, rt_strlen(fn) + 1);

		index ++;
576
		if (index * sizeof(struct dirent) >= count)
577 578 579 580 581 582 583 584 585 586 587 588 589 590 591
			break;
	}

#if _USE_LFN
	rt_free(fno.lfname);
#endif

	if (index == 0)
		return elm_result_to_dfs(result);

	file->pos += index * sizeof(struct dirent);

	return index * sizeof(struct dirent);
}

592
int dfs_elm_unlink(struct dfs_filesystem *fs, const char *path)
593 594 595 596 597 598 599 600 601 602
{
	FRESULT result;

#if _VOLUMES > 1
	int vol;
	char *drivers_fn;
	extern int elm_get_vol(FATFS *fat);

	/* add path for ELM FatFS driver support */
	vol = elm_get_vol((FATFS *)fs->data);
603 604
	if (vol < 0)
		return -DFS_STATUS_ENOENT;
605
	drivers_fn = rt_malloc(256);
606 607
	if (drivers_fn == RT_NULL)
		return -DFS_STATUS_ENOMEM;
608 609 610 611 612 613 614 615 616 617 618 619 620 621

	rt_snprintf(drivers_fn, 256, "%d:%s", vol, path);
#else
	const char *drivers_fn;
	drivers_fn = path;
#endif

	result = f_unlink(drivers_fn);
#if _VOLUMES > 1
	rt_free(drivers_fn);
#endif
	return elm_result_to_dfs(result);
}

622
int dfs_elm_rename(struct dfs_filesystem *fs, const char *oldpath, const char *newpath)
623 624 625 626
{
	FRESULT result;

#if _VOLUMES > 1
B
bernard.xiong@gmail.com 已提交
627 628
	char *drivers_oldfn;
	const char *drivers_newfn;
629 630 631 632 633
	int vol;
	extern int elm_get_vol(FATFS *fat);

	/* add path for ELM FatFS driver support */
	vol = elm_get_vol((FATFS *)fs->data);
634 635
	if (vol < 0)
		return -DFS_STATUS_ENOENT;
636 637

	drivers_oldfn = rt_malloc(256);
638 639
	if (drivers_oldfn == RT_NULL)
		return -DFS_STATUS_ENOMEM;
B
bernard.xiong@gmail.com 已提交
640
	drivers_newfn = newpath;
641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656

	rt_snprintf(drivers_oldfn, 256, "%d:%s", vol, oldpath);
#else
	const char *drivers_oldfn, *drivers_newfn;

	drivers_oldfn = oldpath;
	drivers_newfn = newpath;
#endif

	result = f_rename(drivers_oldfn, drivers_newfn);
#if _VOLUMES > 1
	rt_free(drivers_oldfn);
#endif
	return elm_result_to_dfs(result);
}

657
int dfs_elm_stat(struct dfs_filesystem *fs, const char *path, struct stat *st)
658 659 660 661 662 663 664 665 666 667 668
{
	FILINFO file_info;
	FRESULT result;

#if _VOLUMES > 1
	int vol;
	char *drivers_fn;
	extern int elm_get_vol(FATFS *fat);

	/* add path for ELM FatFS driver support */
	vol = elm_get_vol((FATFS *)fs->data);
669 670
	if (vol < 0)
		return -DFS_STATUS_ENOENT;
671
	drivers_fn = rt_malloc(256);
672 673
	if (drivers_fn == RT_NULL)
		return -DFS_STATUS_ENOMEM;
674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693

	rt_snprintf(drivers_fn, 256, "%d:%s", vol, path);
#else
	const char *drivers_fn;
	drivers_fn = path;
#endif

#if _USE_LFN
	/* allocate long file name */
	file_info.lfname = rt_malloc(256);
	file_info.lfsize = 256;
#endif

	result = f_stat(drivers_fn, &file_info);
#if _VOLUMES > 1
	rt_free(drivers_fn);
#endif
	if (result == FR_OK)
	{
		/* convert to dfs stat structure */
694
		st->st_dev = 0;
695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720

		st->st_mode = DFS_S_IFREG | DFS_S_IRUSR | DFS_S_IRGRP | DFS_S_IROTH |
		DFS_S_IWUSR | DFS_S_IWGRP | DFS_S_IWOTH;
		if (file_info.fattrib & AM_DIR)
		{
			st->st_mode &= ~DFS_S_IFREG;
			st->st_mode |= DFS_S_IFDIR | DFS_S_IXUSR | DFS_S_IXGRP | DFS_S_IXOTH;
		}
		if (file_info.fattrib & AM_RDO)
			st->st_mode &= ~(DFS_S_IWUSR | DFS_S_IWGRP | DFS_S_IWOTH);

		st->st_size  = file_info.fsize;
		st->st_mtime = file_info.ftime;
		st->st_blksize = 512;
	}

#if _USE_LFN
	rt_free(file_info.lfname);
#endif

	return elm_result_to_dfs(result);
}

static const struct dfs_filesystem_operation dfs_elm =
{
	"elm",
721
	DFS_FS_FLAG_DEFAULT,
722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752
	dfs_elm_mount,
	dfs_elm_unmount,
	dfs_elm_mkfs,
	dfs_elm_statfs,

	dfs_elm_open,
	dfs_elm_close,
	dfs_elm_ioctl,
	dfs_elm_read,
	dfs_elm_write,
	dfs_elm_flush,
	dfs_elm_lseek,
	dfs_elm_getdents,
	dfs_elm_unlink,
	dfs_elm_stat,
	dfs_elm_rename,
};

int elm_init(void)
{
    /* register fatfs file system */
    dfs_register(&dfs_elm);

	return 0;
}

/*
 * RT-Thread Device Interface for ELM FatFs
 */
#include "diskio.h"

753
/* Initialize a Drive */
754
DSTATUS disk_initialize(BYTE drv)
755 756 757 758 759
{
	return 0;
}

/* Return Disk Status */
760
DSTATUS disk_status(BYTE drv)
761 762 763 764 765
{
	return 0;
}

/* Read Sector(s) */
766
DRESULT disk_read(BYTE drv, BYTE *buff, DWORD sector, BYTE count)
767 768 769 770 771 772 773 774 775 776 777 778 779 780
{
	rt_size_t result;
	rt_device_t device = disk[drv];

	result = rt_device_read(device, sector, buff, count);
	if (result == count)
	{
		return RES_OK;
	}

	return RES_ERROR;
}

/* Write Sector(s) */
781
DRESULT disk_write(BYTE drv, const BYTE *buff, DWORD sector, BYTE count)
782 783 784 785 786 787 788 789 790 791 792 793 794 795
{
	rt_size_t result;
	rt_device_t device = disk[drv];

	result = rt_device_write(device, sector, buff, count);
	if (result == count)
	{
		return RES_OK;
	}

	return RES_ERROR;
}

/* Miscellaneous Functions */
796
DRESULT disk_ioctl(BYTE drv, BYTE ctrl, void *buff)
797 798 799
{
	rt_device_t device = disk[drv];

800 801
	if (device == RT_NULL)
		return RES_ERROR;
802 803 804 805 806 807 808 809

	if (ctrl == GET_SECTOR_COUNT)
	{
		struct rt_device_blk_geometry geometry;

		rt_memset(&geometry, 0, sizeof(geometry));
		rt_device_control(device, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry);

810 811 812
		*(DWORD *)buff = geometry.sector_count;
		if (geometry.sector_count == 0)
			return RES_ERROR;
813 814 815 816 817 818 819 820
	}
	else if (ctrl == GET_SECTOR_SIZE)
	{
		struct rt_device_blk_geometry geometry;

		rt_memset(&geometry, 0, sizeof(geometry));
		rt_device_control(device, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry);

821
		*(WORD *)buff = (WORD)(geometry.bytes_per_sector);
822 823 824 825 826 827 828 829
	}
	else if (ctrl == GET_BLOCK_SIZE) /* Get erase block size in unit of sectors (DWORD) */
	{
		struct rt_device_blk_geometry geometry;

		rt_memset(&geometry, 0, sizeof(geometry));
		rt_device_control(device, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry);

830
		*(DWORD *)buff = geometry.block_size/geometry.bytes_per_sector;
831
	}
832
	else if (ctrl == CTRL_SYNC)
G
goprife@gmail.com 已提交
833
	{
834
		rt_device_control(device, RT_DEVICE_CTRL_BLK_SYNC, RT_NULL);
G
goprife@gmail.com 已提交
835 836 837 838 839 840
	}
	else if (ctrl == CTRL_ERASE_SECTOR)
	{
		rt_device_control(device, RT_DEVICE_CTRL_BLK_ERASE, buff);
	}
	
841 842 843
	return RES_OK;
}

844
rt_time_t get_fattime(void)
845 846 847 848 849
{
	return 0;
}

#if _FS_REENTRANT
850
int ff_cre_syncobj(BYTE drv, _SYNC_t *m)
851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867
{
    char name[8];
    rt_mutex_t mutex;

    rt_snprintf(name, sizeof(name), "fat%d", drv);
    mutex = rt_mutex_create(name, RT_IPC_FLAG_FIFO);
    if (mutex != RT_NULL)
    {
        *m = mutex;
        return RT_TRUE;
    }

    return RT_FALSE;
}

int ff_del_syncobj(_SYNC_t m)
{
868 869
    if (m != RT_NULL)
        rt_mutex_delete(m);
870 871 872 873 874 875

    return RT_TRUE;
}

int ff_req_grant(_SYNC_t m)
{
876 877
    if (rt_mutex_take(m, _FS_TIMEOUT) == RT_EOK)
		return RT_TRUE;
878 879 880 881 882 883 884 885 886 887

    return RT_FALSE;
}

void ff_rel_grant(_SYNC_t m)
{
	rt_mutex_release(m);
}

#endif
888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903

/* Memory functions */
#if _USE_LFN == 3
/* Allocate memory block */
void* ff_memalloc (UINT size)
{
    return rt_malloc(size);
}

/* Free memory block */
void ff_memfree (void* mem)
{
    rt_free(mem);
}
#endif /* _USE_LFN == 3 */