Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/libblock/libblock.c

    r7a56b1ed r08232ee  
    4747#include <as.h>
    4848#include <assert.h>
    49 #include <fibril_sync.h>
     49#include <fibril_synch.h>
    5050#include <adt/list.h>
    5151#include <adt/hash_table.h>
     52#include <macros.h>
    5253#include <mem.h>
    5354
     
    6263typedef struct {
    6364        fibril_mutex_t lock;
    64         size_t block_size;              /**< Block size. */
     65        size_t lblock_size;             /**< Logical block size. */
    6566        unsigned block_count;           /**< Total number of blocks. */
    6667        unsigned blocks_cached;         /**< Number of cached blocks. */
     
    7475        dev_handle_t dev_handle;
    7576        int dev_phone;
    76         fibril_mutex_t com_area_lock;
    77         void *com_area;
    78         size_t com_size;
     77        fibril_mutex_t comm_area_lock;
     78        void *comm_area;
     79        size_t comm_size;
    7980        void *bb_buf;
    80         off_t bb_off;
    81         size_t bb_size;
     81        bn_t bb_addr;
     82        size_t pblock_size;             /**< Physical block size. */
    8283        cache_t *cache;
    8384} devcon_t;
    8485
    85 static int read_block(devcon_t *devcon, bn_t boff, size_t block_size);
    86 static int write_block(devcon_t *devcon, bn_t boff, size_t block_size);
     86static int read_blocks(devcon_t *devcon, bn_t ba, size_t cnt);
     87static int write_blocks(devcon_t *devcon, bn_t ba, size_t cnt);
     88static int get_block_size(int dev_phone, size_t *bsize);
     89static int get_num_blocks(int dev_phone, bn_t *nblocks);
    8790
    8891static devcon_t *devcon_search(dev_handle_t dev_handle)
     
    102105}
    103106
    104 static int devcon_add(dev_handle_t dev_handle, int dev_phone, void *com_area,
    105    size_t com_size)
     107static int devcon_add(dev_handle_t dev_handle, int dev_phone, size_t bsize,
     108    void *comm_area, size_t comm_size)
    106109{
    107110        link_t *cur;
    108111        devcon_t *devcon;
     112
     113        if (comm_size < bsize)
     114                return EINVAL;
    109115
    110116        devcon = malloc(sizeof(devcon_t));
     
    115121        devcon->dev_handle = dev_handle;
    116122        devcon->dev_phone = dev_phone;
    117         fibril_mutex_initialize(&devcon->com_area_lock);
    118         devcon->com_area = com_area;
    119         devcon->com_size = com_size;
     123        fibril_mutex_initialize(&devcon->comm_area_lock);
     124        devcon->comm_area = comm_area;
     125        devcon->comm_size = comm_size;
    120126        devcon->bb_buf = NULL;
    121         devcon->bb_off = 0;
    122         devcon->bb_size = 0;
     127        devcon->bb_addr = 0;
     128        devcon->pblock_size = bsize;
    123129        devcon->cache = NULL;
    124130
     
    144150}
    145151
    146 int block_init(dev_handle_t dev_handle, size_t com_size)
     152int block_init(dev_handle_t dev_handle, size_t comm_size)
    147153{
    148154        int rc;
    149155        int dev_phone;
    150         void *com_area;
    151        
    152         com_area = mmap(NULL, com_size, PROTO_READ | PROTO_WRITE,
     156        void *comm_area;
     157        size_t bsize;
     158
     159        comm_area = mmap(NULL, comm_size, PROTO_READ | PROTO_WRITE,
    153160            MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
    154         if (!com_area) {
     161        if (!comm_area) {
    155162                return ENOMEM;
    156163        }
     
    158165        dev_phone = devmap_device_connect(dev_handle, IPC_FLAG_BLOCKING);
    159166        if (dev_phone < 0) {
    160                 munmap(com_area, com_size);
     167                munmap(comm_area, comm_size);
    161168                return dev_phone;
    162169        }
    163170
    164         rc = ipc_share_out_start(dev_phone, com_area,
     171        rc = async_share_out_start(dev_phone, comm_area,
    165172            AS_AREA_READ | AS_AREA_WRITE);
    166173        if (rc != EOK) {
    167                 munmap(com_area, com_size);
     174                munmap(comm_area, comm_size);
    168175                ipc_hangup(dev_phone);
    169176                return rc;
    170177        }
    171        
    172         rc = devcon_add(dev_handle, dev_phone, com_area, com_size);
     178
     179        if (get_block_size(dev_phone, &bsize) != EOK) {
     180                munmap(comm_area, comm_size);
     181                ipc_hangup(dev_phone);
     182                return rc;
     183        }
     184       
     185        rc = devcon_add(dev_handle, dev_phone, bsize, comm_area, comm_size);
    173186        if (rc != EOK) {
    174                 munmap(com_area, com_size);
     187                munmap(comm_area, comm_size);
    175188                ipc_hangup(dev_phone);
    176189                return rc;
     
    195208        }
    196209
    197         munmap(devcon->com_area, devcon->com_size);
     210        munmap(devcon->comm_area, devcon->comm_size);
    198211        ipc_hangup(devcon->dev_phone);
    199212
     
    201214}
    202215
    203 int block_bb_read(dev_handle_t dev_handle, off_t off, size_t size)
     216int block_bb_read(dev_handle_t dev_handle, bn_t ba)
    204217{
    205218        void *bb_buf;
     
    211224        if (devcon->bb_buf)
    212225                return EEXIST;
    213         bb_buf = malloc(size);
     226        bb_buf = malloc(devcon->pblock_size);
    214227        if (!bb_buf)
    215228                return ENOMEM;
    216        
    217         fibril_mutex_lock(&devcon->com_area_lock);
    218         rc = read_block(devcon, 0, size);
     229
     230        fibril_mutex_lock(&devcon->comm_area_lock);
     231        rc = read_blocks(devcon, 0, 1);
    219232        if (rc != EOK) {
    220                 fibril_mutex_unlock(&devcon->com_area_lock);
     233                fibril_mutex_unlock(&devcon->comm_area_lock);
    221234                free(bb_buf);
    222235                return rc;
    223236        }
    224         memcpy(bb_buf, devcon->com_area, size);
    225         fibril_mutex_unlock(&devcon->com_area_lock);
     237        memcpy(bb_buf, devcon->comm_area, devcon->pblock_size);
     238        fibril_mutex_unlock(&devcon->comm_area_lock);
    226239
    227240        devcon->bb_buf = bb_buf;
    228         devcon->bb_off = off;
    229         devcon->bb_size = size;
     241        devcon->bb_addr = ba;
    230242
    231243        return EOK;
     
    275287        fibril_mutex_initialize(&cache->lock);
    276288        list_initialize(&cache->free_head);
    277         cache->block_size = size;
     289        cache->lblock_size = size;
    278290        cache->block_count = blocks;
    279291        cache->blocks_cached = 0;
    280292        cache->mode = mode;
     293
     294        /* No block size translation a.t.m. */
     295        assert(cache->lblock_size == devcon->pblock_size);
    281296
    282297        if (!hash_table_create(&cache->block_hash, CACHE_BUCKETS, 1,
     
    371386                        if (!b)
    372387                                goto recycle;
    373                         b->data = malloc(cache->block_size);
     388                        b->data = malloc(cache->lblock_size);
    374389                        if (!b->data) {
    375390                                free(b);
     
    405420                                list_append(&b->free_link, &cache->free_head);
    406421                                fibril_mutex_unlock(&cache->lock);
    407                                 fibril_mutex_lock(&devcon->com_area_lock);
    408                                 memcpy(devcon->com_area, b->data, b->size);
    409                                 rc = write_block(devcon, b->boff,
    410                                     cache->block_size);
    411                                 fibril_mutex_unlock(&devcon->com_area_lock);
     422                                fibril_mutex_lock(&devcon->comm_area_lock);
     423                                memcpy(devcon->comm_area, b->data, b->size);
     424                                rc = write_blocks(devcon, b->boff, 1);
     425                                fibril_mutex_unlock(&devcon->comm_area_lock);
    412426                                if (rc != EOK) {
    413427                                        /*
     
    444458                block_initialize(b);
    445459                b->dev_handle = dev_handle;
    446                 b->size = cache->block_size;
     460                b->size = cache->lblock_size;
    447461                b->boff = boff;
    448462                hash_table_insert(&cache->block_hash, &key, &b->hash_link);
     
    461475                         * the new contents from the device.
    462476                         */
    463                         fibril_mutex_lock(&devcon->com_area_lock);
    464                         rc = read_block(devcon, b->boff, cache->block_size);
    465                         memcpy(b->data, devcon->com_area, cache->block_size);
    466                         fibril_mutex_unlock(&devcon->com_area_lock);
     477                        fibril_mutex_lock(&devcon->comm_area_lock);
     478                        rc = read_blocks(devcon, b->boff, 1);
     479                        memcpy(b->data, devcon->comm_area, cache->lblock_size);
     480                        fibril_mutex_unlock(&devcon->comm_area_lock);
    467481                        if (rc != EOK)
    468482                                b->toxic = true;
     
    521535        if (block->dirty && (block->refcnt == 1) &&
    522536            (blocks_cached > CACHE_HI_WATERMARK || mode != CACHE_MODE_WB)) {
    523                 fibril_mutex_lock(&devcon->com_area_lock);
    524                 memcpy(devcon->com_area, block->data, block->size);
    525                 rc = write_block(devcon, block->boff, block->size);
    526                 fibril_mutex_unlock(&devcon->com_area_lock);
     537                fibril_mutex_lock(&devcon->comm_area_lock);
     538                memcpy(devcon->comm_area, block->data, block->size);
     539                rc = write_blocks(devcon, block->boff, 1);
     540                fibril_mutex_unlock(&devcon->comm_area_lock);
    527541                block->dirty = false;
    528542        }
     
    601615 */
    602616int block_seqread(dev_handle_t dev_handle, off_t *bufpos, size_t *buflen,
    603     off_t *pos, void *dst, size_t size, size_t block_size)
     617    off_t *pos, void *dst, size_t size)
    604618{
    605619        off_t offset = 0;
    606620        size_t left = size;
    607         devcon_t *devcon = devcon_search(dev_handle);
    608         assert(devcon);
    609        
    610         fibril_mutex_lock(&devcon->com_area_lock);
     621        size_t block_size;
     622        devcon_t *devcon;
     623
     624        devcon = devcon_search(dev_handle);
     625        assert(devcon);
     626        block_size = devcon->pblock_size;
     627       
     628        fibril_mutex_lock(&devcon->comm_area_lock);
    611629        while (left > 0) {
    612630                size_t rd;
     
    622640                         * destination buffer.
    623641                         */
    624                         memcpy(dst + offset, devcon->com_area + *bufpos, rd);
     642                        memcpy(dst + offset, devcon->comm_area + *bufpos, rd);
    625643                        offset += rd;
    626644                        *bufpos += rd;
     
    633651                        int rc;
    634652
    635                         rc = read_block(devcon, *pos / block_size, block_size);
     653                        rc = read_blocks(devcon, *pos / block_size, 1);
    636654                        if (rc != EOK) {
    637                                 fibril_mutex_unlock(&devcon->com_area_lock);
     655                                fibril_mutex_unlock(&devcon->comm_area_lock);
    638656                                return rc;
    639657                        }
     
    643661                }
    644662        }
    645         fibril_mutex_unlock(&devcon->com_area_lock);
     663        fibril_mutex_unlock(&devcon->comm_area_lock);
    646664       
    647665        return EOK;
    648666}
    649667
    650 /** Read block from block device.
     668/** Read blocks directly from device (bypass cache).
     669 *
     670 * @param dev_handle    Device handle of the block device.
     671 * @param ba            Address of first block.
     672 * @param cnt           Number of blocks.
     673 * @param src           Buffer for storing the data.
     674 *
     675 * @return              EOK on success or negative error code on failure.
     676 */
     677int block_read_direct(dev_handle_t dev_handle, bn_t ba, size_t cnt, void *buf)
     678{
     679        devcon_t *devcon;
     680        int rc;
     681
     682        devcon = devcon_search(dev_handle);
     683        assert(devcon);
     684       
     685        fibril_mutex_lock(&devcon->comm_area_lock);
     686
     687        rc = read_blocks(devcon, ba, cnt);
     688        if (rc == EOK)
     689                memcpy(buf, devcon->comm_area, devcon->pblock_size * cnt);
     690
     691        fibril_mutex_unlock(&devcon->comm_area_lock);
     692
     693        return rc;
     694}
     695
     696/** Write blocks directly to device (bypass cache).
     697 *
     698 * @param dev_handle    Device handle of the block device.
     699 * @param ba            Address of first block.
     700 * @param cnt           Number of blocks.
     701 * @param src           The data to be written.
     702 *
     703 * @return              EOK on success or negative error code on failure.
     704 */
     705int block_write_direct(dev_handle_t dev_handle, bn_t ba, size_t cnt,
     706    const void *data)
     707{
     708        devcon_t *devcon;
     709        int rc;
     710
     711        devcon = devcon_search(dev_handle);
     712        assert(devcon);
     713       
     714        fibril_mutex_lock(&devcon->comm_area_lock);
     715
     716        memcpy(devcon->comm_area, data, devcon->pblock_size * cnt);
     717        rc = write_blocks(devcon, ba, cnt);
     718
     719        fibril_mutex_unlock(&devcon->comm_area_lock);
     720
     721        return rc;
     722}
     723
     724/** Get device block size.
     725 *
     726 * @param dev_handle    Device handle of the block device.
     727 * @param bsize         Output block size.
     728 *
     729 * @return              EOK on success or negative error code on failure.
     730 */
     731int block_get_bsize(dev_handle_t dev_handle, size_t *bsize)
     732{
     733        devcon_t *devcon;
     734
     735        devcon = devcon_search(dev_handle);
     736        assert(devcon);
     737       
     738        return get_block_size(devcon->dev_phone, bsize);
     739}
     740
     741/** Get number of blocks on device.
     742 *
     743 * @param dev_handle    Device handle of the block device.
     744 * @param nblocks       Output number of blocks.
     745 *
     746 * @return              EOK on success or negative error code on failure.
     747 */
     748int block_get_nblocks(dev_handle_t dev_handle, bn_t *nblocks)
     749{
     750        devcon_t *devcon;
     751
     752        devcon = devcon_search(dev_handle);
     753        assert(devcon);
     754       
     755        return get_num_blocks(devcon->dev_phone, nblocks);
     756}
     757
     758/** Read blocks from block device.
    651759 *
    652760 * @param devcon        Device connection.
    653  * @param boff          Block index.
    654  * @param block_size    Block size.
     761 * @param ba            Address of first block.
     762 * @param cnt           Number of blocks.
    655763 * @param src           Buffer for storing the data.
    656764 *
    657765 * @return              EOK on success or negative error code on failure.
    658766 */
    659 static int read_block(devcon_t *devcon, bn_t boff, size_t block_size)
    660 {
    661         ipcarg_t retval;
     767static int read_blocks(devcon_t *devcon, bn_t ba, size_t cnt)
     768{
    662769        int rc;
    663770
    664771        assert(devcon);
    665         rc = async_req_2_1(devcon->dev_phone, BD_READ_BLOCK, boff, block_size,
    666             &retval);
    667         if ((rc != EOK) || (retval != EOK))
    668                 return (rc != EOK ? rc : (int) retval);
    669 
    670         return EOK;
     772        rc = async_req_3_0(devcon->dev_phone, BD_READ_BLOCKS, LOWER32(ba),
     773            UPPER32(ba), cnt);
     774        return rc;
    671775}
    672776
     
    674778 *
    675779 * @param devcon        Device connection.
    676  * @param boff          Block index.
    677  * @param block_size    Block size.
     780 * @param ba            Address of first block.
     781 * @param cnt           Number of blocks.
    678782 * @param src           Buffer containing the data to write.
    679783 *
    680784 * @return              EOK on success or negative error code on failure.
    681785 */
    682 static int write_block(devcon_t *devcon, bn_t boff, size_t block_size)
    683 {
    684         ipcarg_t retval;
     786static int write_blocks(devcon_t *devcon, bn_t ba, size_t cnt)
     787{
    685788        int rc;
    686789
    687790        assert(devcon);
    688         rc = async_req_2_1(devcon->dev_phone, BD_WRITE_BLOCK, boff, block_size,
    689             &retval);
    690         if ((rc != EOK) || (retval != EOK))
    691                 return (rc != EOK ? rc : (int) retval);
    692 
    693         return EOK;
     791        rc = async_req_3_0(devcon->dev_phone, BD_WRITE_BLOCKS, LOWER32(ba),
     792            UPPER32(ba), cnt);
     793        return rc;
     794}
     795
     796/** Get block size used by the device. */
     797static int get_block_size(int dev_phone, size_t *bsize)
     798{
     799        ipcarg_t bs;
     800        int rc;
     801
     802        rc = async_req_0_1(dev_phone, BD_GET_BLOCK_SIZE, &bs);
     803        if (rc == EOK)
     804                *bsize = (size_t) bs;
     805
     806        return rc;
     807}
     808
     809/** Get total number of blocks on block device. */
     810static int get_num_blocks(int dev_phone, bn_t *nblocks)
     811{
     812        ipcarg_t nb_l, nb_h;
     813        int rc;
     814
     815        rc = async_req_0_2(dev_phone, BD_GET_NUM_BLOCKS, &nb_l, &nb_h);
     816        if (rc == EOK) {
     817                *nblocks = (bn_t) MERGE_LOUP32(nb_l, nb_h);
     818        }
     819
     820        return rc;
    694821}
    695822
Note: See TracChangeset for help on using the changeset viewer.