source: rtems/cpukit/libblock/include/rtems/blkdev.h @ 9f0a68c

4.115
Last change on this file since 9f0a68c was 9f0a68c, checked in by Sebastian Huber <sebastian.huber@…>, on 10/31/12 at 10:54:39

libblock: Block device transfer request API change

Add and use rtems_blkdev_request_done(). Block device transfer requests
must signal the completion status now with rtems_blkdev_request_done().
The return value of the block device IO control will be ignored for
transfer requests.

The first parameter of rtems_blkdev_request_cb is now the transfer
request structure.

Renamed rtems_blkdev_request::req_done to rtems_blkdev_request::done to
break third party drivers at compile time, otherwise this API change
would result in runtime errors.

  • Property mode set to 100644
File size: 11.2 KB
RevLine 
[b80dd59d]1/**
[57aa979]2 * @file
3 *
[4670d91]4 * @ingroup rtems_blkdev
5 *
[57aa979]6 * Block device management.
[b80dd59d]7 */
[33c3b54d]8
[8b96149]9/*
[e51bd96]10 * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
11 * Author: Victor V. Vengerov <vvv@oktet.ru>
12 */
13
[a6f5d89]14#ifndef _RTEMS_BLKDEV_H
15#define _RTEMS_BLKDEV_H
[e51bd96]16
17#include <rtems.h>
[b96e09c]18#include <rtems/diskdevs.h>
[9f527308]19#include <rtems/bspIo.h>
[e51bd96]20#include <sys/ioctl.h>
[9f527308]21#include <stdio.h>
[e51bd96]22
23#ifdef __cplusplus
24extern "C" {
25#endif
26
[57aa979]27/**
28 * @defgroup rtems_blkdev Block Device Management
29 *
30 * @ingroup rtems_libblock
31 *
[d8602eb]32 * Interface between device drivers and the
[33c3b54d]33 * @ref rtems_bdbuf "block device buffer module".
[57aa979]34 *
35 * The heart of the block device driver is the @ref RTEMS_BLKIO_REQUEST IO
36 * control. This call puts IO @ref rtems_blkdev_request "requests" to the block
37 * device for asynchronous processing. When a driver executes a request, it
38 * invokes the request done callback function to finish the request.
39 *
40 * @{
[e51bd96]41 */
42
[57aa979]43/**
44 * Block device request type.
[8aa608df]45 *
46 * @warning The sync request is an IO one and only used from the cache. Use the
47 *          Block IO when operating at the device level. We need a sync request
48 *          to avoid requests looping for ever.
[57aa979]49 */
[3899a537]50typedef enum rtems_blkdev_request_op {
[945884fe]51  RTEMS_BLKDEV_REQ_READ,       /**< Read the requested blocks of data. */
52  RTEMS_BLKDEV_REQ_WRITE,      /**< Write the requested blocks of data. */
[8aa608df]53  RTEMS_BLKDEV_REQ_SYNC        /**< Sync any data with the media. */
[3899a537]54} rtems_blkdev_request_op;
55
[9f0a68c]56struct rtems_blkdev_request;
57
[57aa979]58/**
[5c587596]59 * @brief Block device request done callback function type.
[e51bd96]60 */
[9f0a68c]61typedef void (*rtems_blkdev_request_cb)(
62  struct rtems_blkdev_request *req,
63  rtems_status_code status
64);
[e51bd96]65
[3899a537]66/**
[57aa979]67 * Block device scatter or gather buffer structure.
[e51bd96]68 */
[3899a537]69typedef struct rtems_blkdev_sg_buffer {
[57aa979]70  /**
71   * Block index.
72   */
73  rtems_blkdev_bnum block;
74
75  /**
76   * Buffer length.
77   */
78  uint32_t length;
79
80  /**
81   * Buffer pointer.
82   */
83  void *buffer;
84
85  /**
86   * User pointer.
87   */
88  void *user;
[3899a537]89} rtems_blkdev_sg_buffer;
[e51bd96]90
[57aa979]91/**
[9f0a68c]92 * @brief The block device transfer request is used to read or write a number
93 * of blocks from or to the device.
94 *
95 * Transfer requests are issued to the disk device driver with the
96 * @ref RTEMS_BLKIO_REQUEST IO control.  The transfer request completion status
97 * must be signalled with rtems_blkdev_request_done().  This function must be
98 * called exactly once per request.  The return value of the IO control will be
99 * ignored for transfer requests.
[6d612944]100 *
[9f0a68c]101 * @see rtems_blkdev_create().
[e51bd96]102 */
[3899a537]103typedef struct rtems_blkdev_request {
[57aa979]104  /**
105   * Block device operation (read or write).
106   */
107  rtems_blkdev_request_op req;
108
109  /**
110   * Request done callback function.
111   */
[9f0a68c]112  rtems_blkdev_request_cb done;
[57aa979]113
114  /**
115   * Argument to be passed to callback function.
116   */
117  void *done_arg;
118
119  /**
120   * Last IO operation completion status.
121   */
[33c3b54d]122  rtems_status_code status;
[57aa979]123
124  /**
125   * Number of blocks for this request.
126   */
127  uint32_t bufnum;
128
129  /**
130   * The task requesting the IO operation.
131   */
132  rtems_id io_task;
133
[9f0a68c]134  /*
135   * TODO: The use of these req blocks is not a great design. The req is a
136   *       struct with a single 'bufs' declared in the req struct and the
137   *       others are added in the outer level struct. This relies on the
138   *       structs joining as a single array and that assumes the compiler
139   *       packs the structs. Why not just place on a list ? The BD has a
140   *       node that can be used.
141   */
142
[57aa979]143  /**
144   * List of scatter or gather buffers.
145   */
146  rtems_blkdev_sg_buffer bufs[0];
[3899a537]147} rtems_blkdev_request;
[e51bd96]148
[9f0a68c]149/**
150 * @brief Signals transfer request completion status.
151 *
152 * This function must be called exactly once per request.
153 *
154 * @param[in,out] req The transfer request.
155 * @param[in] status The status of the operation should be
156 *  - @c RTEMS_SUCCESSFUL, if the operation was successful,
157 *  - @c RTEMS_IO_ERROR, if some sort of input or output error occured, or
158 *  - @c RTEMS_UNSATISFIED, if media is no more present.
159 */
160static inline void rtems_blkdev_request_done(
161  rtems_blkdev_request *req,
162  rtems_status_code status
163)
164{
165  (*req->done)(req, status);
166}
167
[57aa979]168/**
169 * The start block in a request.
170 *
[8aa608df]171 * Only valid if the driver has returned the @ref RTEMS_BLKIO_CAPABILITIES of
[57aa979]172 * @ref RTEMS_BLKDEV_CAP_MULTISECTOR_CONT.
173 */
174#define RTEMS_BLKDEV_START_BLOCK(req) (req->bufs[0].block)
[e51bd96]175
[57aa979]176/**
177 * @name IO Control Request Codes
178 *
179 * @{
[e51bd96]180 */
181
[945884fe]182#define RTEMS_BLKIO_REQUEST         _IOWR('B', 1, rtems_blkdev_request)
[c0e0a928]183#define RTEMS_BLKIO_GETMEDIABLKSIZE _IOR('B', 2, uint32_t)
184#define RTEMS_BLKIO_GETBLKSIZE      _IOR('B', 3, uint32_t)
185#define RTEMS_BLKIO_SETBLKSIZE      _IOW('B', 4, uint32_t)
186#define RTEMS_BLKIO_GETSIZE         _IOR('B', 5, rtems_blkdev_bnum)
[945884fe]187#define RTEMS_BLKIO_SYNCDEV         _IO('B', 6)
[e41369ef]188#define RTEMS_BLKIO_DELETED         _IO('B', 7)
[8aa608df]189#define RTEMS_BLKIO_CAPABILITIES    _IO('B', 8)
[4f3cbd9]190#define RTEMS_BLKIO_GETDISKDEV      _IOR('B', 9, rtems_disk_device *)
[84ab4fce]191#define RTEMS_BLKIO_PURGEDEV        _IO('B', 10)
[9f527308]192#define RTEMS_BLKIO_GETDEVSTATS     _IOR('B', 11, rtems_blkdev_stats *)
193#define RTEMS_BLKIO_RESETDEVSTATS   _IO('B', 12)
[57aa979]194
195/** @} */
196
[c649976]197static inline int rtems_disk_fd_get_media_block_size(
198  int fd,
199  uint32_t *media_block_size
200)
201{
202  return ioctl(fd, RTEMS_BLKIO_GETMEDIABLKSIZE, media_block_size);
203}
204
205static inline int rtems_disk_fd_get_block_size(int fd, uint32_t *block_size)
206{
207  return ioctl(fd, RTEMS_BLKIO_GETBLKSIZE, block_size);
208}
209
210static inline int rtems_disk_fd_set_block_size(int fd, uint32_t block_size)
211{
212  return ioctl(fd, RTEMS_BLKIO_SETBLKSIZE, &block_size);
213}
214
215static inline int rtems_disk_fd_get_block_count(
216  int fd,
217  rtems_blkdev_bnum *block_count
218)
219{
220  return ioctl(fd, RTEMS_BLKIO_GETSIZE, block_count);
221}
222
223static inline int rtems_disk_fd_get_disk_device(
224  int fd,
[40284de]225  rtems_disk_device **dd_ptr
[c649976]226)
227{
228  return ioctl(fd, RTEMS_BLKIO_GETDISKDEV, dd_ptr);
229}
230
231static inline int rtems_disk_fd_sync(int fd)
232{
233  return ioctl(fd, RTEMS_BLKIO_SYNCDEV);
234}
235
[84ab4fce]236static inline int rtems_disk_fd_purge(int fd)
237{
238  return ioctl(fd, RTEMS_BLKIO_PURGEDEV);
239}
240
[9f527308]241static inline int rtems_disk_fd_get_device_stats(
242  int fd,
243  rtems_blkdev_stats *stats
244)
245{
246  return ioctl(fd, RTEMS_BLKIO_GETDEVSTATS, stats);
247}
248
249static inline int rtems_disk_fd_reset_device_stats(int fd)
250{
251  return ioctl(fd, RTEMS_BLKIO_RESETDEVSTATS);
252}
253
[8aa608df]254/**
255 * Only consecutive multi-sector buffer requests are supported.
256 *
257 * This option means the cache will only supply multiple buffers that are
258 * inorder so the ATA multi-sector command for example can be used. This is a
259 * hack to work around the current ATA driver.
260 */
261#define RTEMS_BLKDEV_CAP_MULTISECTOR_CONT (1 << 0)
262
263/**
264 * The driver will accept a sync call. A sync call is made to a driver
265 * after a bdbuf cache sync has finished.
266 */
267#define RTEMS_BLKDEV_CAP_SYNC (1 << 1)
268
[57aa979]269/**
270 * The device driver interface conventions suppose that a driver may contain an
271 * initialize, open, close, read, write and IO control entry points. These
272 * primitives (except initialize) can be implemented in a generic fashion based
273 * upon the supplied block device driver IO control handler. Every block device
274 * driver should provide an initialize entry point, which registers the
275 * appropriate IO control handler.
276 */
[3899a537]277#define RTEMS_GENERIC_BLOCK_DEVICE_DRIVER_ENTRIES \
[47c2327]278  rtems_blkdev_generic_open, \
279  rtems_blkdev_generic_close, \
280  rtems_blkdev_generic_read, \
281  rtems_blkdev_generic_write, \
282  rtems_blkdev_generic_ioctl
[e51bd96]283
[57aa979]284/**
285 * Generic block device read primitive.
286 *
287 * Implemented using block device buffer management primitives.
[e51bd96]288 */
289rtems_device_driver
290rtems_blkdev_generic_read(
291    rtems_device_major_number major,
292    rtems_device_minor_number minor,
293    void                    * arg
294);
295
[57aa979]296/**
297 * Generic block device write primitive.
298 *
299 * Implemented using block device buffer management primitives.
[e51bd96]300 */
301rtems_device_driver
302rtems_blkdev_generic_write(
303    rtems_device_major_number major,
304    rtems_device_minor_number minor,
305    void                    * arg
306);
307
[57aa979]308/**
309 * Generic block device open primitive.
310 *
311 * Implemented using block device buffer management primitives.
[e51bd96]312 */
313rtems_device_driver
314rtems_blkdev_generic_open(
315    rtems_device_major_number major,
316    rtems_device_minor_number minor,
317    void                    * arg
318);
319
[57aa979]320/**
321 * Generic block device close primitive.
322 *
323 * Implemented using block device buffer management primitives.
[e51bd96]324 */
325rtems_device_driver
326rtems_blkdev_generic_close(
327    rtems_device_major_number major,
328    rtems_device_minor_number minor,
329    void                    * arg
330);
331
[57aa979]332/**
333 * Generic block device IO control primitive.
334 *
335 * Implemented using block device buffer management primitives.
[e51bd96]336 */
337rtems_device_driver
338rtems_blkdev_generic_ioctl(
339    rtems_device_major_number major,
340    rtems_device_minor_number minor,
341    void                    * arg
342);
343
[945884fe]344/**
345 * Common IO control primitive.
346 *
347 * Use this in all block devices to handle the common set of ioctl requests.
348 */
349int
[b96e09c]350rtems_blkdev_ioctl(rtems_disk_device *dd, uint32_t req, void *argp);
[945884fe]351
[1680638]352/**
353 * @brief Generic block operations driver address table.
354 */
355extern const rtems_driver_address_table rtems_blkdev_generic_ops;
356
[01211720]357/**
358 * @brief Creates a block device.
359 *
360 * @param[in] device The path for the new block device.
361 * @param[in] block_size The block size.  Must be positive.
362 * @param[in] block_count The block count.  Must be positive.
363 * @param[in] handler The block device IO control handler.  Must not be @c NULL.
364 * @param[in] driver_data The block device driver data.
365 *
366 * @retval RTEMS_SUCCESSFUL Successful operation.
367 * @retval RTEMS_INVALID_NUMBER Block size or block count is not positive.
368 * @retval RTEMS_NO_MEMORY Not enough memory.
369 * @retval RTEMS_UNSATISFIED Cannot create generic device node.
[9f0a68c]370 *
371 * @see rtems_blkdev_create_partition() and rtems_blkdev_request.
[01211720]372 */
373rtems_status_code rtems_blkdev_create(
374  const char *device,
375  uint32_t block_size,
376  rtems_blkdev_bnum block_count,
377  rtems_block_device_ioctl handler,
378  void *driver_data
379);
380
381/**
382 * @brief Creates a partition within a block device.
383 *
384 * A partition manages a subset of consecutive blocks contained in a block
385 * device.  The blocks must be within the range of blocks managed by the
386 * associated block device.  The media block size, block size, and IO control
387 * handler are inherited by the block device.
388 *
389 * @param[in] partition The path for the new partition device.
390 * @param[in] device The block device path.
391 * @param[in] block_begin The block begin of the partition.
392 * @param[in] block_count The block count of the partition.
393 *
394 * @retval RTEMS_SUCCESSFUL Successful operation.
395 * @retval RTEMS_INVALID_ID Block device node does not exist.
396 * @retval RTEMS_INVALID_NODE File system node is not a block device.
397 * @retval RTEMS_NOT_IMPLEMENTED Block device implementation is incomplete.
398 * @retval RTEMS_INVALID_NUMBER Block begin or block count is invalid.
399 * @retval RTEMS_NO_MEMORY Not enough memory.
400 * @retval RTEMS_UNSATISFIED Cannot create generic device node.
[9f0a68c]401 *
402 * @see rtems_blkdev_create().
[01211720]403 */
404rtems_status_code rtems_blkdev_create_partition(
405  const char *partition,
406  const char *device,
407  rtems_blkdev_bnum block_begin,
408  rtems_blkdev_bnum block_count
409);
410
[9f527308]411/**
412 * @brief Prints the block device statistics.
413 */
414void rtems_blkdev_print_stats(
415  const rtems_blkdev_stats *stats,
416  rtems_printk_plugin_t print,
417  void *print_arg
418);
419
420/**
421 * @brief Block device statistics command.
422 */
423void rtems_blkstats(
424  FILE *output,
425  const char *device,
426  bool reset
427);
428
[57aa979]429/** @} */
430
[e51bd96]431#ifdef __cplusplus
432}
433#endif
434
435#endif
Note: See TracBrowser for help on using the repository browser.