00001
00038 #ifndef BLOCK_DEVICE_H_INCLUDED
00039 #define BLOCK_DEVICE_H_INCLUDED
00040
00041 #include <buffer.h>
00042 #include <slist.h>
00043 #include <types.h>
00044 #include <status_codes.h>
00045
00055 typedef uint32_t block_addr_t;
00056
00060 typedef uint32_t block_len_t;
00061
00062 struct block_device;
00063
00073 struct block_request {
00075 struct slist buf_list;
00076 void (*req_started)(struct block_device *bdev,
00077 struct block_request *req);
00085 void (*req_done)(struct block_device *bdev, struct block_request *req);
00086 void (*buf_list_done)(struct block_device *bdev,
00087 struct block_request *req, struct slist *buf_list);
00088 void (*req_submit)(struct block_device *bdev,
00089 struct block_request *req);
00090 int (*req_submit_buf_list)(struct block_device *bdev,
00091 struct block_request *req, struct slist *buf_list);
00092 void (*req_abort)(struct block_device *bdev,
00093 struct block_request *req);
00098 void *context;
00109 enum status_code status;
00110 block_len_t bytes_xfered;
00112 struct block_device *bdev;
00113 };
00114
00118 enum block_device_flag {
00119 BDEV_UNIT_ATTENTION,
00120 BDEV_PRESENT,
00121 BDEV_WRITEABLE,
00122 };
00123
00127 enum block_operation {
00128 BLK_OP_READ,
00129 BLK_OP_WRITE,
00130 };
00131
00138 struct block_device {
00140 uint32_t nr_blocks;
00141 #ifndef CONFIG_BLOCK_FIXED_BLOCK_SIZE
00142
00143 uint16_t block_size;
00144 #endif
00145
00146 uint8_t flags;
00148 void (*prepare_req)(struct block_device *bdev,
00149 struct block_request *req,
00150 block_addr_t lba, block_len_t nr_blocks,
00151 enum block_operation operation);
00153 struct block_request *(*alloc_req)(struct block_device *bdev);
00155 void (*free_req)(struct block_device *bdev, struct block_request *req);
00157 uint32_t (*get_dev_id)(struct block_device *bdev);
00158 };
00159
00173 static inline uint16_t blkdev_get_block_size(struct block_device *bdev)
00174 {
00175 #ifdef CONFIG_BLOCK_FIXED_BLOCK_SIZE
00176 return CONFIG_BLOCK_FIXED_BLOCK_SIZE;
00177 #else
00178 return bdev->block_size;
00179 #endif
00180 }
00181
00192 static inline void blkdev_set_block_size(struct block_device *bdev,
00193 uint16_t block_size)
00194 {
00195 #ifdef CONFIG_BLOCK_FIXED_BLOCK_SIZE
00196 assert(block_size == CONFIG_BLOCK_FIXED_BLOCK_SIZE);
00197 #else
00198 bdev->block_size = block_size;
00199 #endif
00200 }
00201
00202 extern struct block_request *block_alloc_request(struct block_device *bdev);
00203 extern void block_free_request(struct block_device *bdev,
00204 struct block_request *req);
00205
00222 static inline void block_prepare_req(struct block_device *bdev,
00223 struct block_request *req, block_addr_t lba,
00224 block_len_t nr_blocks, enum block_operation operation)
00225 {
00226 assert(bdev == req->bdev);
00227
00228 bdev->prepare_req(bdev, req, lba, nr_blocks, operation);
00229 }
00230
00240 static inline void block_submit_req(struct block_device *bdev,
00241 struct block_request *req)
00242 {
00243 assert(bdev == req->bdev);
00244
00245 req->req_submit(bdev, req);
00246 }
00247
00248 static inline void block_queue_req(struct block_device *bdev,
00249 struct block_request *req, block_addr_t lba,
00250 block_len_t nr_blocks, enum block_operation operation)
00251 {
00252 block_prepare_req(bdev, req, lba, nr_blocks, operation);
00253 block_submit_req(bdev, req);
00254 }
00255
00256 static inline void block_abort_req(struct block_device *bdev,
00257 struct block_request *req)
00258 {
00259
00260 }
00261
00262 static inline uint32_t block_get_dev_id(struct block_device *bdev)
00263 {
00264 assert(bdev);
00265 assert(bdev->get_dev_id);
00266
00267 return bdev->get_dev_id(bdev);
00268 }
00269
00287 static inline int block_submit_buf_list(struct block_device *bdev,
00288 struct block_request *breq, struct slist *buf_list)
00289 {
00290 assert(breq->bdev == bdev);
00291 assert(breq->req_submit_buf_list);
00292
00293 return breq->req_submit_buf_list(bdev, breq, buf_list);
00294 }
00295
00308 static inline block_len_t blk_req_get_blocks_xfered(struct block_device *bdev,
00309 struct block_request *breq)
00310 {
00311 assert(bdev == breq->bdev);
00312
00313 return breq->bytes_xfered / blkdev_get_block_size(bdev);
00314 }
00315
00328 static inline block_len_t blk_req_get_bytes_xfered(struct block_device *bdev,
00329 struct block_request *breq)
00330 {
00331 assert(bdev == breq->bdev);
00332
00333 return breq->bytes_xfered;
00334 }
00335
00339 static inline void blk_req_add_buffer(struct block_request *req,
00340 struct buffer *buf)
00341 {
00342 slist_insert_tail(&req->buf_list, &buf->node);
00343 }
00344
00351 static inline void blk_req_add_buffer_list(struct block_request *req,
00352 struct slist *list)
00353 {
00354 slist_move_to_tail(&req->buf_list, list);
00355 }
00356
00358
00359 #endif