Ignore:
File:
1 edited

Legend:

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

    r7a56b1ed r1e4cada  
    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);
    8789
    8890static devcon_t *devcon_search(dev_handle_t dev_handle)
     
    102104}
    103105
    104 static int devcon_add(dev_handle_t dev_handle, int dev_phone, void *com_area,
    105    size_t com_size)
     106static int devcon_add(dev_handle_t dev_handle, int dev_phone, size_t bsize,
     107    void *comm_area, size_t comm_size)
    106108{
    107109        link_t *cur;
    108110        devcon_t *devcon;
     111
     112        if (comm_size < bsize)
     113                return EINVAL;
    109114
    110115        devcon = malloc(sizeof(devcon_t));
     
    115120        devcon->dev_handle = dev_handle;
    116121        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;
     122        fibril_mutex_initialize(&devcon->comm_area_lock);
     123        devcon->comm_area = comm_area;
     124        devcon->comm_size = comm_size;
    120125        devcon->bb_buf = NULL;
    121         devcon->bb_off = 0;
    122         devcon->bb_size = 0;
     126        devcon->bb_addr = 0;
     127        devcon->pblock_size = bsize;
    123128        devcon->cache = NULL;
    124129
     
    144149}
    145150
    146 int block_init(dev_handle_t dev_handle, size_t com_size)
     151int block_init(dev_handle_t dev_handle, size_t comm_size)
    147152{
    148153        int rc;
    149154        int dev_phone;
    150         void *com_area;
    151        
    152         com_area = mmap(NULL, com_size, PROTO_READ | PROTO_WRITE,
     155        void *comm_area;
     156        size_t bsize;
     157
     158        comm_area = mmap(NULL, comm_size, PROTO_READ | PROTO_WRITE,
    153159            MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
    154         if (!com_area) {
     160        if (!comm_area) {
    155161                return ENOMEM;
    156162        }
     
    158164        dev_phone = devmap_device_connect(dev_handle, IPC_FLAG_BLOCKING);
    159165        if (dev_phone < 0) {
    160                 munmap(com_area, com_size);
     166                munmap(comm_area, comm_size);
    161167                return dev_phone;
    162168        }
    163169
    164         rc = ipc_share_out_start(dev_phone, com_area,
     170        rc = async_share_out_start(dev_phone, comm_area,
    165171            AS_AREA_READ | AS_AREA_WRITE);
    166172        if (rc != EOK) {
    167                 munmap(com_area, com_size);
     173                munmap(comm_area, comm_size);
    168174                ipc_hangup(dev_phone);
    169175                return rc;
    170176        }
    171        
    172         rc = devcon_add(dev_handle, dev_phone, com_area, com_size);
     177
     178        if (get_block_size(dev_phone, &bsize) != EOK) {
     179                munmap(comm_area, comm_size);
     180                ipc_hangup(dev_phone);
     181                return rc;
     182        }
     183       
     184        rc = devcon_add(dev_handle, dev_phone, bsize, comm_area, comm_size);
    173185        if (rc != EOK) {
    174                 munmap(com_area, com_size);
     186                munmap(comm_area, comm_size);
    175187                ipc_hangup(dev_phone);
    176188                return rc;
     
    195207        }
    196208
    197         munmap(devcon->com_area, devcon->com_size);
     209        munmap(devcon->comm_area, devcon->comm_size);
    198210        ipc_hangup(devcon->dev_phone);
    199211
     
    201213}
    202214
    203 int block_bb_read(dev_handle_t dev_handle, off_t off, size_t size)
     215int block_bb_read(dev_handle_t dev_handle, bn_t ba)
    204216{
    205217        void *bb_buf;
     
    211223        if (devcon->bb_buf)
    212224                return EEXIST;
    213         bb_buf = malloc(size);
     225        bb_buf = malloc(devcon->pblock_size);
    214226        if (!bb_buf)
    215227                return ENOMEM;
    216        
    217         fibril_mutex_lock(&devcon->com_area_lock);
    218         rc = read_block(devcon, 0, size);
     228
     229        fibril_mutex_lock(&devcon->comm_area_lock);
     230        rc = read_blocks(devcon, 0, 1);
    219231        if (rc != EOK) {
    220                 fibril_mutex_unlock(&devcon->com_area_lock);
     232                fibril_mutex_unlock(&devcon->comm_area_lock);
    221233                free(bb_buf);
    222234                return rc;
    223235        }
    224         memcpy(bb_buf, devcon->com_area, size);
    225         fibril_mutex_unlock(&devcon->com_area_lock);
     236        memcpy(bb_buf, devcon->comm_area, devcon->pblock_size);
     237        fibril_mutex_unlock(&devcon->comm_area_lock);
    226238
    227239        devcon->bb_buf = bb_buf;
    228         devcon->bb_off = off;
    229         devcon->bb_size = size;
     240        devcon->bb_addr = ba;
    230241
    231242        return EOK;
     
    275286        fibril_mutex_initialize(&cache->lock);
    276287        list_initialize(&cache->free_head);
    277         cache->block_size = size;
     288        cache->lblock_size = size;
    278289        cache->block_count = blocks;
    279290        cache->blocks_cached = 0;
    280291        cache->mode = mode;
     292
     293        /* No block size translation a.t.m. */
     294        assert(cache->lblock_size == devcon->pblock_size);
    281295
    282296        if (!hash_table_create(&cache->block_hash, CACHE_BUCKETS, 1,
     
    371385                        if (!b)
    372386                                goto recycle;
    373                         b->data = malloc(cache->block_size);
     387                        b->data = malloc(cache->lblock_size);
    374388                        if (!b->data) {
    375389                                free(b);
     
    405419                                list_append(&b->free_link, &cache->free_head);
    406420                                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);
     421                                fibril_mutex_lock(&devcon->comm_area_lock);
     422                                memcpy(devcon->comm_area, b->data, b->size);
     423                                rc = write_blocks(devcon, b->boff, 1);
     424                                fibril_mutex_unlock(&devcon->comm_area_lock);
    412425                                if (rc != EOK) {
    413426                                        /*
     
    444457                block_initialize(b);
    445458                b->dev_handle = dev_handle;
    446                 b->size = cache->block_size;
     459                b->size = cache->lblock_size;
    447460                b->boff = boff;
    448461                hash_table_insert(&cache->block_hash, &key, &b->hash_link);
     
    461474                         * the new contents from the device.
    462475                         */
    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);
     476                        fibril_mutex_lock(&devcon->comm_area_lock);
     477                        rc = read_blocks(devcon, b->boff, 1);
     478                        memcpy(b->data, devcon->comm_area, cache->lblock_size);
     479                        fibril_mutex_unlock(&devcon->comm_area_lock);
    467480                        if (rc != EOK)
    468481                                b->toxic = true;
     
    521534        if (block->dirty && (block->refcnt == 1) &&
    522535            (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);
     536                fibril_mutex_lock(&devcon->comm_area_lock);
     537                memcpy(devcon->comm_area, block->data, block->size);
     538                rc = write_blocks(devcon, block->boff, 1);
     539                fibril_mutex_unlock(&devcon->comm_area_lock);
    527540                block->dirty = false;
    528541        }
     
    601614 */
    602615int 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)
     616    off_t *pos, void *dst, size_t size)
    604617{
    605618        off_t offset = 0;
    606619        size_t left = size;
    607         devcon_t *devcon = devcon_search(dev_handle);
    608         assert(devcon);
    609        
    610         fibril_mutex_lock(&devcon->com_area_lock);
     620        size_t block_size;
     621        devcon_t *devcon;
     622
     623        devcon = devcon_search(dev_handle);
     624        assert(devcon);
     625        block_size = devcon->pblock_size;
     626       
     627        fibril_mutex_lock(&devcon->comm_area_lock);
    611628        while (left > 0) {
    612629                size_t rd;
     
    622639                         * destination buffer.
    623640                         */
    624                         memcpy(dst + offset, devcon->com_area + *bufpos, rd);
     641                        memcpy(dst + offset, devcon->comm_area + *bufpos, rd);
    625642                        offset += rd;
    626643                        *bufpos += rd;
     
    633650                        int rc;
    634651
    635                         rc = read_block(devcon, *pos / block_size, block_size);
     652                        rc = read_blocks(devcon, *pos / block_size, 1);
    636653                        if (rc != EOK) {
    637                                 fibril_mutex_unlock(&devcon->com_area_lock);
     654                                fibril_mutex_unlock(&devcon->comm_area_lock);
    638655                                return rc;
    639656                        }
     
    643660                }
    644661        }
    645         fibril_mutex_unlock(&devcon->com_area_lock);
     662        fibril_mutex_unlock(&devcon->comm_area_lock);
    646663       
    647664        return EOK;
    648665}
    649666
    650 /** Read block from block device.
     667/** Read blocks directly from device (bypass cache).
     668 *
     669 * @param dev_handle    Device handle of the block device.
     670 * @param ba            Address of first block.
     671 * @param cnt           Number of blocks.
     672 * @param src           Buffer for storing the data.
     673 *
     674 * @return              EOK on success or negative error code on failure.
     675 */
     676int block_read_direct(dev_handle_t dev_handle, bn_t ba, size_t cnt, void *buf)
     677{
     678        devcon_t *devcon;
     679        int rc;
     680
     681        devcon = devcon_search(dev_handle);
     682        assert(devcon);
     683       
     684        fibril_mutex_lock(&devcon->comm_area_lock);
     685
     686        rc = read_blocks(devcon, ba, cnt);
     687        if (rc == EOK)
     688                memcpy(buf, devcon->comm_area, devcon->pblock_size * cnt);
     689
     690        fibril_mutex_unlock(&devcon->comm_area_lock);
     691
     692        return rc;
     693}
     694
     695/** Write blocks directly to device (bypass cache).
     696 *
     697 * @param dev_handle    Device handle of the block device.
     698 * @param ba            Address of first block.
     699 * @param cnt           Number of blocks.
     700 * @param src           The data to be written.
     701 *
     702 * @return              EOK on success or negative error code on failure.
     703 */
     704int block_write_direct(dev_handle_t dev_handle, bn_t ba, size_t cnt,
     705    const void *data)
     706{
     707        devcon_t *devcon;
     708        int rc;
     709
     710        devcon = devcon_search(dev_handle);
     711        assert(devcon);
     712       
     713        fibril_mutex_lock(&devcon->comm_area_lock);
     714
     715        memcpy(devcon->comm_area, data, devcon->pblock_size * cnt);
     716        rc = read_blocks(devcon, ba, cnt);
     717
     718        fibril_mutex_unlock(&devcon->comm_area_lock);
     719
     720        return rc;
     721}
     722
     723/** Get device block size.
     724 *
     725 * @param dev_handle    Device handle of the block device.
     726 * @param bsize         Output block size.
     727 *
     728 * @return              EOK on success or negative error code on failure.
     729 */
     730int block_get_bsize(dev_handle_t dev_handle, size_t *bsize)
     731{
     732        devcon_t *devcon;
     733
     734        devcon = devcon_search(dev_handle);
     735        assert(devcon);
     736       
     737        return get_block_size(devcon->dev_phone, bsize);
     738}
     739
     740/** Read blocks from block device.
    651741 *
    652742 * @param devcon        Device connection.
    653  * @param boff          Block index.
    654  * @param block_size    Block size.
     743 * @param ba            Address of first block.
     744 * @param cnt           Number of blocks.
    655745 * @param src           Buffer for storing the data.
    656746 *
    657747 * @return              EOK on success or negative error code on failure.
    658748 */
    659 static int read_block(devcon_t *devcon, bn_t boff, size_t block_size)
    660 {
    661         ipcarg_t retval;
     749static int read_blocks(devcon_t *devcon, bn_t ba, size_t cnt)
     750{
    662751        int rc;
    663752
    664753        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;
     754        rc = async_req_3_0(devcon->dev_phone, BD_READ_BLOCKS, LOWER32(ba),
     755            UPPER32(ba), cnt);
     756        return rc;
    671757}
    672758
     
    674760 *
    675761 * @param devcon        Device connection.
    676  * @param boff          Block index.
    677  * @param block_size    Block size.
     762 * @param ba            Address of first block.
     763 * @param cnt           Number of blocks.
    678764 * @param src           Buffer containing the data to write.
    679765 *
    680766 * @return              EOK on success or negative error code on failure.
    681767 */
    682 static int write_block(devcon_t *devcon, bn_t boff, size_t block_size)
    683 {
    684         ipcarg_t retval;
     768static int write_blocks(devcon_t *devcon, bn_t ba, size_t cnt)
     769{
    685770        int rc;
    686771
    687772        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;
     773        rc = async_req_3_0(devcon->dev_phone, BD_WRITE_BLOCKS, LOWER32(ba),
     774            UPPER32(ba), cnt);
     775        return rc;
     776}
     777
     778/** Get block size used by the device. */
     779static int get_block_size(int dev_phone, size_t *bsize)
     780{
     781        ipcarg_t bs;
     782        int rc;
     783
     784        rc = async_req_0_1(dev_phone, BD_GET_BLOCK_SIZE, &bs);
     785        if (rc == EOK)
     786                *bsize = (size_t) bs;
     787
     788        return rc;
    694789}
    695790
Note: See TracChangeset for help on using the changeset viewer.