2 * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 /************************************************************************/
21 /* PROJECT : exFAT & FAT12/16/32 File System */
22 /* FILE : exfat_blkdev.c */
23 /* PURPOSE : exFAT Block Device Driver Glue Layer */
25 /*----------------------------------------------------------------------*/
28 /*----------------------------------------------------------------------*/
29 /* REVISION HISTORY (Ver 0.9) */
31 /* - 2010.11.15 [Joosun Hahn] : first writing */
33 /************************************************************************/
35 #include <linux/blkdev.h>
37 #include "exfat_config.h"
38 #include "exfat_global.h"
39 #include "exfat_blkdev.h"
40 #include "exfat_data.h"
41 #include "exfat_api.h"
42 #include "exfat_super.h"
44 /*----------------------------------------------------------------------*/
45 /* Constant & Macro Definitions */
46 /*----------------------------------------------------------------------*/
48 /*----------------------------------------------------------------------*/
49 /* Global Variable Definitions */
50 /*----------------------------------------------------------------------*/
52 /*----------------------------------------------------------------------*/
53 /* Local Variable Definitions */
54 /*----------------------------------------------------------------------*/
56 /*======================================================================*/
57 /* Function Definitions */
58 /*======================================================================*/
65 INT32
bdev_shutdown(void)
70 INT32
bdev_open(struct super_block
*sb
)
72 BD_INFO_T
*p_bd
= &(EXFAT_SB(sb
)->bd_info
);
74 if (p_bd
->opened
) return(FFS_SUCCESS
);
76 p_bd
->sector_size
= bdev_logical_block_size(sb
->s_bdev
);
77 p_bd
->sector_size_bits
= my_log2(p_bd
->sector_size
);
78 p_bd
->sector_size_mask
= p_bd
->sector_size
- 1;
79 p_bd
->num_sectors
= i_size_read(sb
->s_bdev
->bd_inode
) >> p_bd
->sector_size_bits
;
86 INT32
bdev_close(struct super_block
*sb
)
88 BD_INFO_T
*p_bd
= &(EXFAT_SB(sb
)->bd_info
);
90 if (!p_bd
->opened
) return(FFS_SUCCESS
);
96 INT32
bdev_read(struct super_block
*sb
, UINT32 secno
, struct buffer_head
**bh
, UINT32 num_secs
, INT32 read
)
98 BD_INFO_T
*p_bd
= &(EXFAT_SB(sb
)->bd_info
);
99 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
100 #if EXFAT_CONFIG_KERNEL_DEBUG
101 struct exfat_sb_info
*sbi
= EXFAT_SB(sb
);
102 long flags
= sbi
->debug_flags
;
104 if (flags
& EXFAT_DEBUGFLAGS_ERROR_RW
) return (FFS_MEDIAERR
);
105 #endif /* EXFAT_CONFIG_KERNEL_DEBUG */
107 if (!p_bd
->opened
) return(FFS_MEDIAERR
);
109 if (*bh
) __brelse(*bh
);
112 *bh
= __bread(sb
->s_bdev
, secno
, num_secs
<< p_bd
->sector_size_bits
);
114 *bh
= __getblk(sb
->s_bdev
, secno
, num_secs
<< p_bd
->sector_size_bits
);
116 if (*bh
) return(FFS_SUCCESS
);
118 WARN(!p_fs
->dev_ejected
,
119 "[EXFAT] No bh, device seems wrong or to be ejected.\n");
121 return(FFS_MEDIAERR
);
124 INT32
bdev_write(struct super_block
*sb
, UINT32 secno
, struct buffer_head
*bh
, UINT32 num_secs
, INT32 sync
)
127 struct buffer_head
*bh2
;
128 BD_INFO_T
*p_bd
= &(EXFAT_SB(sb
)->bd_info
);
129 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
130 #if EXFAT_CONFIG_KERNEL_DEBUG
131 struct exfat_sb_info
*sbi
= EXFAT_SB(sb
);
132 long flags
= sbi
->debug_flags
;
134 if (flags
& EXFAT_DEBUGFLAGS_ERROR_RW
) return (FFS_MEDIAERR
);
135 #endif /* EXFAT_CONFIG_KERNEL_DEBUG */
137 if (!p_bd
->opened
) return(FFS_MEDIAERR
);
139 if (secno
== bh
->b_blocknr
) {
141 set_buffer_uptodate(bh
);
142 mark_buffer_dirty(bh
);
144 if (sync
&& (sync_dirty_buffer(bh
) != 0))
145 return (FFS_MEDIAERR
);
147 count
= num_secs
<< p_bd
->sector_size_bits
;
149 bh2
= __getblk(sb
->s_bdev
, secno
, count
);
155 MEMCPY(bh2
->b_data
, bh
->b_data
, count
);
156 set_buffer_uptodate(bh2
);
157 mark_buffer_dirty(bh2
);
159 if (sync
&& (sync_dirty_buffer(bh2
) != 0)) {
169 WARN(!p_fs
->dev_ejected
,
170 "[EXFAT] No bh, device seems wrong or to be ejected.\n");
172 return (FFS_MEDIAERR
);
175 INT32
bdev_sync(struct super_block
*sb
)
177 BD_INFO_T
*p_bd
= &(EXFAT_SB(sb
)->bd_info
);
178 #if EXFAT_CONFIG_KERNEL_DEBUG
179 struct exfat_sb_info
*sbi
= EXFAT_SB(sb
);
180 long flags
= sbi
->debug_flags
;
182 if (flags
& EXFAT_DEBUGFLAGS_ERROR_RW
) return (FFS_MEDIAERR
);
183 #endif /* EXFAT_CONFIG_KERNEL_DEBUG */
185 if (!p_bd
->opened
) return(FFS_MEDIAERR
);
187 return sync_blockdev(sb
->s_bdev
);
190 /* end of exfat_blkdev.c */