Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:13

0001 /**
0002  * @file
0003  *
0004  * @ingroup rtems_blkdev
0005  *
0006  * @brief Block Device Management
0007  */
0008 
0009 /*
0010  * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
0011  * Author: Victor V. Vengerov <vvv@oktet.ru>
0012  */
0013 
0014 #ifndef _RTEMS_BLKDEV_H
0015 #define _RTEMS_BLKDEV_H
0016 
0017 #include <rtems.h>
0018 #include <rtems/diskdevs.h>
0019 #include <rtems/print.h>
0020 #include <sys/ioccom.h>
0021 #include <stdio.h>
0022 
0023 #ifdef __cplusplus
0024 extern "C" {
0025 #endif
0026 
0027 /**
0028  * @defgroup rtems_blkdev Block Device Management
0029  *
0030  * @ingroup rtems_libblock
0031  *
0032  * Interface between device drivers and the
0033  * @ref rtems_bdbuf "block device buffer module".
0034  *
0035  * The heart of the block device driver is the @ref RTEMS_BLKIO_REQUEST IO
0036  * control. This call puts IO @ref rtems_blkdev_request "requests" to the block
0037  * device for asynchronous processing. When a driver executes a request, it
0038  * invokes the request done callback function to finish the request.
0039  */
0040 /**@{**/
0041 
0042 /**
0043  * @brief Block device request type.
0044  *
0045  * @warning The sync request is an IO one and only used from the cache. Use the
0046  *          Block IO when operating at the device level. We need a sync request
0047  *          to avoid requests looping for ever.
0048  */
0049 typedef enum rtems_blkdev_request_op {
0050   RTEMS_BLKDEV_REQ_READ,       /**< Read the requested blocks of data. */
0051   RTEMS_BLKDEV_REQ_WRITE,      /**< Write the requested blocks of data. */
0052   RTEMS_BLKDEV_REQ_SYNC        /**< Sync any data with the media. */
0053 } rtems_blkdev_request_op;
0054 
0055 struct rtems_blkdev_request;
0056 
0057 /**
0058  * @brief Block device request done callback function type.
0059  */
0060 typedef void (*rtems_blkdev_request_cb)(
0061   struct rtems_blkdev_request *req,
0062   rtems_status_code status
0063 );
0064 
0065 /**
0066  * @brief Block device scatter or gather buffer structure.
0067  */
0068 typedef struct rtems_blkdev_sg_buffer {
0069   /**
0070    * Block index.
0071    */
0072   rtems_blkdev_bnum block;
0073 
0074   /**
0075    * Buffer length.
0076    */
0077   uint32_t length;
0078 
0079   /**
0080    * Buffer pointer.
0081    */
0082   void *buffer;
0083 
0084   /**
0085    * User pointer.
0086    */
0087   void *user;
0088 } rtems_blkdev_sg_buffer;
0089 
0090 /**
0091  * @brief The block device transfer request is used to read or write a number
0092  * of blocks from or to the device.
0093  *
0094  * Transfer requests are issued to the disk device driver with the
0095  * @ref RTEMS_BLKIO_REQUEST IO control.  The transfer request completion status
0096  * must be signalled with rtems_blkdev_request_done().  This function must be
0097  * called exactly once per request.  The return value of the IO control will be
0098  * ignored for transfer requests.
0099  *
0100  * @see rtems_blkdev_create().
0101  */
0102 typedef struct rtems_blkdev_request {
0103   /**
0104    * Block device operation (read or write).
0105    */
0106   rtems_blkdev_request_op req;
0107 
0108   /**
0109    * Request done callback function.
0110    */
0111   rtems_blkdev_request_cb done;
0112 
0113   /**
0114    * Argument to be passed to callback function.
0115    */
0116   void *done_arg;
0117 
0118   /**
0119    * Last IO operation completion status.
0120    */
0121   rtems_status_code status;
0122 
0123   /**
0124    * Number of blocks for this request.
0125    */
0126   uint32_t bufnum;
0127 
0128   /**
0129    * The task requesting the IO operation.
0130    */
0131   rtems_id io_task;
0132 
0133   /*
0134    * TODO: The use of these req blocks is not a great design. The req is a
0135    *       struct with a single 'bufs' declared in the req struct and the
0136    *       others are added in the outer level struct. This relies on the
0137    *       structs joining as a single array and that assumes the compiler
0138    *       packs the structs. Why not just place on a list ? The BD has a
0139    *       node that can be used.
0140    */
0141 
0142   /**
0143    * List of scatter or gather buffers.
0144    */
0145   rtems_blkdev_sg_buffer bufs[RTEMS_ZERO_LENGTH_ARRAY];
0146 } rtems_blkdev_request;
0147 
0148 /**
0149  * @brief Signals transfer request completion status.
0150  *
0151  * This function must be called exactly once per request.
0152  *
0153  * @param[in,out] req The transfer request.
0154  * @param[in] status The status of the operation should be
0155  *  - @c RTEMS_SUCCESSFUL, if the operation was successful,
0156  *  - @c RTEMS_IO_ERROR, if some sort of input or output error occurred, or
0157  *  - @c RTEMS_UNSATISFIED, if media is no more present.
0158  */
0159 static inline void rtems_blkdev_request_done(
0160   rtems_blkdev_request *req,
0161   rtems_status_code status
0162 )
0163 {
0164   (*req->done)(req, status);
0165 }
0166 
0167 /**
0168  * @brief The start block in a request.
0169  *
0170  * Only valid if the driver has returned the
0171  * @ref RTEMS_BLKDEV_CAP_MULTISECTOR_CONT capability.
0172  */
0173 #define RTEMS_BLKDEV_START_BLOCK(req) (req->bufs[0].block)
0174 
0175 /**
0176  * @name IO Control Request Codes
0177  */
0178 /**@{**/
0179 
0180 #define RTEMS_BLKIO_REQUEST         _IOWR('B', 1, rtems_blkdev_request)
0181 #define RTEMS_BLKIO_GETMEDIABLKSIZE _IOR('B', 2, uint32_t)
0182 #define RTEMS_BLKIO_GETBLKSIZE      _IOR('B', 3, uint32_t)
0183 #define RTEMS_BLKIO_SETBLKSIZE      _IOW('B', 4, uint32_t)
0184 #define RTEMS_BLKIO_GETSIZE         _IOR('B', 5, rtems_blkdev_bnum)
0185 #define RTEMS_BLKIO_SYNCDEV         _IO('B', 6)
0186 #define RTEMS_BLKIO_DELETED         _IO('B', 7)
0187 #define RTEMS_BLKIO_CAPABILITIES    _IO('B', 8)
0188 #define RTEMS_BLKIO_GETDISKDEV      _IOR('B', 9, rtems_disk_device *)
0189 #define RTEMS_BLKIO_PURGEDEV        _IO('B', 10)
0190 #define RTEMS_BLKIO_GETDEVSTATS     _IOR('B', 11, rtems_blkdev_stats *)
0191 #define RTEMS_BLKIO_RESETDEVSTATS   _IO('B', 12)
0192 
0193 /** @} */
0194 
0195 static inline int rtems_disk_fd_get_media_block_size(
0196   int fd,
0197   uint32_t *media_block_size
0198 )
0199 {
0200   return ioctl(fd, RTEMS_BLKIO_GETMEDIABLKSIZE, media_block_size);
0201 }
0202 
0203 static inline int rtems_disk_fd_get_block_size(int fd, uint32_t *block_size)
0204 {
0205   return ioctl(fd, RTEMS_BLKIO_GETBLKSIZE, block_size);
0206 }
0207 
0208 static inline int rtems_disk_fd_set_block_size(int fd, uint32_t block_size)
0209 {
0210   return ioctl(fd, RTEMS_BLKIO_SETBLKSIZE, &block_size);
0211 }
0212 
0213 static inline int rtems_disk_fd_get_block_count(
0214   int fd,
0215   rtems_blkdev_bnum *block_count
0216 )
0217 {
0218   return ioctl(fd, RTEMS_BLKIO_GETSIZE, block_count);
0219 }
0220 
0221 static inline int rtems_disk_fd_get_disk_device(
0222   int fd,
0223   rtems_disk_device **dd_ptr
0224 )
0225 {
0226   return ioctl(fd, RTEMS_BLKIO_GETDISKDEV, dd_ptr);
0227 }
0228 
0229 static inline int rtems_disk_fd_sync(int fd)
0230 {
0231   return ioctl(fd, RTEMS_BLKIO_SYNCDEV);
0232 }
0233 
0234 static inline int rtems_disk_fd_purge(int fd)
0235 {
0236   return ioctl(fd, RTEMS_BLKIO_PURGEDEV);
0237 }
0238 
0239 static inline int rtems_disk_fd_get_device_stats(
0240   int fd,
0241   rtems_blkdev_stats *stats
0242 )
0243 {
0244   return ioctl(fd, RTEMS_BLKIO_GETDEVSTATS, stats);
0245 }
0246 
0247 static inline int rtems_disk_fd_reset_device_stats(int fd)
0248 {
0249   return ioctl(fd, RTEMS_BLKIO_RESETDEVSTATS);
0250 }
0251 
0252 /**
0253  * @name Block Device Driver Capabilities
0254  */
0255 /**@{**/
0256 
0257 /**
0258  * @brief Only consecutive multi-sector buffer requests are supported.
0259  *
0260  * This option means the cache will only supply multiple buffers that are
0261  * inorder so the ATA multi-sector command for example can be used. This is a
0262  * hack to work around the current ATA driver.
0263  */
0264 #define RTEMS_BLKDEV_CAP_MULTISECTOR_CONT (1 << 0)
0265 
0266 /**
0267  * @brief The driver will accept a sync call.
0268  *
0269  * A sync call is made to a driver after a bdbuf cache sync has finished.
0270  */
0271 #define RTEMS_BLKDEV_CAP_SYNC (1 << 1)
0272 
0273 /** @} */
0274 
0275 /**
0276  * @brief Common IO control primitive.
0277  *
0278  * Use this in all block devices to handle the common set of IO control
0279  * requests.
0280  */
0281 int
0282 rtems_blkdev_ioctl(rtems_disk_device *dd, uint32_t req, void *argp);
0283 
0284 /**
0285  * @brief Creates a block device.
0286  *
0287  * The block size is set to the media block size.
0288  *
0289  * @param[in] device The path for the new block device.
0290  * @param[in] media_block_size The media block size in bytes.  Must be positive.
0291  * @param[in] media_block_count The media block count.  Must be positive.
0292  * @param[in] handler The block device IO control handler.  Must not be @c NULL.
0293  * @param[in] driver_data The block device driver data.
0294  *
0295  * @retval RTEMS_SUCCESSFUL Successful operation.
0296  * @retval RTEMS_INVALID_NUMBER Media block size or count is not positive.
0297  * @retval RTEMS_NO_MEMORY Not enough memory.
0298  * @retval RTEMS_UNSATISFIED Cannot create generic device node.
0299  * @retval RTEMS_INCORRECT_STATE Cannot initialize bdbuf.
0300  *
0301  * @see rtems_blkdev_create_partition(), rtems_bdbuf_set_block_size(), and
0302  * rtems_blkdev_request.
0303  */
0304 rtems_status_code rtems_blkdev_create(
0305   const char *device,
0306   uint32_t media_block_size,
0307   rtems_blkdev_bnum media_block_count,
0308   rtems_block_device_ioctl handler,
0309   void *driver_data
0310 );
0311 
0312 /**
0313  * @brief Creates a partition within a parent block device.
0314  *
0315  * A partition manages a subset of consecutive blocks contained in a parent block
0316  * device.  The blocks must be within the range of blocks managed by the
0317  * associated parent block device.  The media block size and IO control
0318  * handler are inherited by the parent block device.  The block size is set to
0319  * the media block size.
0320  *
0321  * @param[in] partition The path for the new partition device.
0322  * @param[in] parent_block_device The parent block device path.
0323  * @param[in] media_block_begin The media block begin of the partition within
0324  * the parent block device.
0325  * @param[in] media_block_count The media block count of the partition.
0326  *
0327  * @retval RTEMS_SUCCESSFUL Successful operation.
0328  * @retval RTEMS_INVALID_ID Block device node does not exist.
0329  * @retval RTEMS_INVALID_NODE File system node is not a block device.
0330  * @retval RTEMS_NOT_IMPLEMENTED Block device implementation is incomplete.
0331  * @retval RTEMS_INVALID_NUMBER Block begin or block count is invalid.
0332  * @retval RTEMS_NO_MEMORY Not enough memory.
0333  * @retval RTEMS_UNSATISFIED Cannot create generic device node.
0334  *
0335  * @see rtems_blkdev_create() and rtems_bdbuf_set_block_size().
0336  */
0337 rtems_status_code rtems_blkdev_create_partition(
0338   const char *partition,
0339   const char *parent_block_device,
0340   rtems_blkdev_bnum media_block_begin,
0341   rtems_blkdev_bnum media_block_count
0342 );
0343 
0344 /**
0345  * @brief Prints the block device statistics.
0346  */
0347 void rtems_blkdev_print_stats(
0348   const rtems_blkdev_stats *stats,
0349   uint32_t media_block_size,
0350   uint32_t media_block_count,
0351   uint32_t block_size,
0352   const rtems_printer* printer
0353 );
0354 
0355 /**
0356  * @brief Block device statistics command.
0357  */
0358 void rtems_blkstats(
0359   const rtems_printer *printer,
0360   const char *device,
0361   bool reset
0362 );
0363 
0364 /** @} */
0365 
0366 /**
0367  * @defgroup rtems_blkdev_generic Generic Disk Device
0368  *
0369  * @ingroup rtems_blkdev
0370  *
0371  * Generic disk device operations for standard RTEMS IO drivers.
0372  */
0373 /**@{**/
0374 
0375 /**
0376  * The device driver interface conventions suppose that a driver may contain an
0377  * initialize, open, close, read, write and IO control entry points. These
0378  * primitives (except initialize) can be implemented in a generic fashion based
0379  * upon the supplied block device driver IO control handler. Every block device
0380  * driver should provide an initialize entry point, which registers the
0381  * appropriate IO control handler.
0382  */
0383 #define RTEMS_GENERIC_BLOCK_DEVICE_DRIVER_ENTRIES \
0384   rtems_blkdev_generic_open, \
0385   rtems_blkdev_generic_close, \
0386   rtems_blkdev_generic_read, \
0387   rtems_blkdev_generic_write, \
0388   rtems_blkdev_generic_ioctl
0389 
0390 /* Use rtems_blkdev_create() instead */
0391 RTEMS_DEPRECATED rtems_device_driver
0392 rtems_blkdev_generic_read(
0393     rtems_device_major_number major,
0394     rtems_device_minor_number minor,
0395     void                    * arg
0396 );
0397 
0398 /* Use rtems_blkdev_create() instead */
0399 RTEMS_DEPRECATED rtems_device_driver
0400 rtems_blkdev_generic_write(
0401     rtems_device_major_number major,
0402     rtems_device_minor_number minor,
0403     void                    * arg
0404 );
0405 
0406 /* Use rtems_blkdev_create() instead */
0407 RTEMS_DEPRECATED rtems_device_driver
0408 rtems_blkdev_generic_open(
0409     rtems_device_major_number major,
0410     rtems_device_minor_number minor,
0411     void                    * arg
0412 );
0413 
0414 /* Use rtems_blkdev_create() instead */
0415 RTEMS_DEPRECATED rtems_device_driver
0416 rtems_blkdev_generic_close(
0417     rtems_device_major_number major,
0418     rtems_device_minor_number minor,
0419     void                    * arg
0420 );
0421 
0422 /* Use rtems_blkdev_create() instead */
0423 RTEMS_DEPRECATED rtems_device_driver
0424 rtems_blkdev_generic_ioctl(
0425     rtems_device_major_number major,
0426     rtems_device_minor_number minor,
0427     void                    * arg
0428 );
0429 
0430 /* Use rtems_blkdev_create() instead */
0431 RTEMS_DEPRECATED extern const rtems_driver_address_table rtems_blkdev_generic_ops;
0432 
0433 /** @} */
0434 
0435 #ifdef __cplusplus
0436 }
0437 #endif
0438 
0439 #endif