bchdev_driver.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. /****************************************************************************
  2. * drivers/bch/bchdev_driver.c
  3. *
  4. * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
  5. * Author: Gregory Nutt <gnutt@nuttx.org>
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in
  15. * the documentation and/or other materials provided with the
  16. * distribution.
  17. * 3. Neither the name NuttX nor the names of its contributors may be
  18. * used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  28. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  29. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32. * POSSIBILITY OF SUCH DAMAGE.
  33. *
  34. ****************************************************************************/
  35. /****************************************************************************
  36. * Compilation Switches
  37. ****************************************************************************/
  38. /****************************************************************************
  39. * Included Files
  40. ****************************************************************************/
  41. #include <nuttx/config.h>
  42. #include <sys/types.h>
  43. #include <sys/stat.h>
  44. #include <sys/ioctl.h>
  45. #include <unistd.h>
  46. #include <string.h>
  47. #include <fcntl.h>
  48. #include <sched.h>
  49. #include <errno.h>
  50. #include <assert.h>
  51. #include <debug.h>
  52. #include <nuttx/fs/fs.h>
  53. #include <nuttx/fs/ioctl.h>
  54. #include "bch_internal.h"
  55. /****************************************************************************
  56. * Definitions
  57. ****************************************************************************/
  58. /****************************************************************************
  59. * Private Function Prototypes
  60. ****************************************************************************/
  61. static int bch_open(FAR struct file *filp);
  62. static int bch_close(FAR struct file *filp);
  63. static ssize_t bch_read(FAR struct file *, FAR char *, size_t);
  64. static ssize_t bch_write(FAR struct file *, FAR const char *, size_t);
  65. static int bch_ioctl(FAR struct file *filp, int cmd, unsigned long arg);
  66. /****************************************************************************
  67. * Public Data
  68. ****************************************************************************/
  69. const struct file_operations bch_fops =
  70. {
  71. bch_open, /* open */
  72. bch_close, /* close */
  73. bch_read, /* read */
  74. bch_write, /* write */
  75. 0, /* seek */
  76. bch_ioctl /* ioctl */
  77. #ifndef CONFIG_DISABLE_POLL
  78. , 0 /* poll */
  79. #endif
  80. };
  81. /****************************************************************************
  82. * Private Functions
  83. ****************************************************************************/
  84. /****************************************************************************
  85. * Name: bch_open
  86. *
  87. * Description: Open the block device
  88. *
  89. ****************************************************************************/
  90. static int bch_open(FAR struct file *filp)
  91. {
  92. FAR struct inode *inode = filp->f_inode;
  93. FAR struct bchlib_s *bch;
  94. DEBUGASSERT(inode && inode->i_private);
  95. bch = (FAR struct bchlib_s *)inode->i_private;
  96. /* Increment the reference count */
  97. bchlib_semtake(bch);
  98. if (bch->refs == MAX_OPENCNT)
  99. {
  100. return -EMFILE;
  101. }
  102. else
  103. {
  104. bch->refs++;
  105. }
  106. bchlib_semgive(bch);
  107. return OK;
  108. }
  109. /****************************************************************************
  110. * Name: bch_close
  111. *
  112. * Description: close the block device
  113. *
  114. ****************************************************************************/
  115. static int bch_close(FAR struct file *filp)
  116. {
  117. FAR struct inode *inode = filp->f_inode;
  118. FAR struct bchlib_s *bch;
  119. int ret = OK;
  120. DEBUGASSERT(inode && inode->i_private);
  121. bch = (FAR struct bchlib_s *)inode->i_private;
  122. /* Flush any dirty pages remaining in the cache */
  123. bchlib_semtake(bch);
  124. (void)bchlib_flushsector(bch);
  125. /* Decrement the reference count (I don't use bchlib_decref() because I
  126. * want the entire close operation to be atomic wrt other driver operations.
  127. */
  128. if (bch->refs == 0)
  129. {
  130. ret = -EIO;
  131. }
  132. else
  133. {
  134. bch->refs--;
  135. }
  136. bchlib_semgive(bch);
  137. return ret;
  138. }
  139. /****************************************************************************
  140. * Name:bch_read
  141. ****************************************************************************/
  142. static ssize_t bch_read(FAR struct file *filp, FAR char *buffer, size_t len)
  143. {
  144. FAR struct inode *inode = filp->f_inode;
  145. FAR struct bchlib_s *bch;
  146. int ret;
  147. DEBUGASSERT(inode && inode->i_private);
  148. bch = (FAR struct bchlib_s *)inode->i_private;
  149. bchlib_semtake(bch);
  150. ret = bchlib_read(bch, buffer, filp->f_pos, len);
  151. if (ret > 0)
  152. {
  153. filp->f_pos += len;
  154. }
  155. bchlib_semgive(bch);
  156. return ret;
  157. }
  158. /****************************************************************************
  159. * Name:bch_write
  160. ****************************************************************************/
  161. static ssize_t bch_write(FAR struct file *filp, FAR const char *buffer, size_t len)
  162. {
  163. FAR struct inode *inode = filp->f_inode;
  164. FAR struct bchlib_s *bch;
  165. int ret = -EACCES;
  166. DEBUGASSERT(inode && inode->i_private);
  167. bch = (FAR struct bchlib_s *)inode->i_private;
  168. if (!bch->readonly)
  169. {
  170. bchlib_semtake(bch);
  171. ret = bchlib_write(bch, buffer, filp->f_pos, len);
  172. if (ret > 0)
  173. {
  174. filp->f_pos += len;
  175. }
  176. bchlib_semgive(bch);
  177. }
  178. return ret;
  179. }
  180. /****************************************************************************
  181. * Name: bch_ioctl
  182. *
  183. * Description: Return device geometry
  184. *
  185. ****************************************************************************/
  186. static int bch_ioctl(FAR struct file *filp, int cmd, unsigned long arg)
  187. {
  188. FAR struct inode *inode = filp->f_inode;
  189. FAR struct bchlib_s *bch;
  190. int ret = -ENOTTY;
  191. DEBUGASSERT(inode && inode->i_private);
  192. bch = (FAR struct bchlib_s *)inode->i_private;
  193. if (cmd == DIOC_GETPRIV)
  194. {
  195. FAR struct bchlib_s **bchr = (FAR struct bchlib_s **)((uintptr_t)arg);
  196. bchlib_semtake(bch);
  197. if (!bchr && bch->refs < 255)
  198. {
  199. ret = -EINVAL;
  200. }
  201. else
  202. {
  203. bch->refs++;
  204. *bchr = bch;
  205. }
  206. bchlib_semgive(bch);
  207. }
  208. return ret;
  209. }
  210. /****************************************************************************
  211. * Public Functions
  212. ****************************************************************************/