Changeset 916bf1a in mainline


Ignore:
Timestamp:
2008-10-28T17:49:23Z (16 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
0d974d8
Parents:
7858bc5f
Message:

libblock is now ready to handle connections to multiple device instances.

File:
1 edited

Legend:

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

    r7858bc5f r916bf1a  
    4747#include <as.h>
    4848#include <assert.h>
    49 
    50 static int dev_phone = -1;              /* FIXME */
    51 static void *dev_buffer = NULL;         /* FIXME */
    52 static size_t dev_buffer_len = 0;       /* FIXME */
    53 static void *bblock = NULL;             /* FIXME */
     49#include <futex.h>
     50#include <libadt/list.h>
     51
     52/** Lock protecting the device connection list */
     53static futex_t dcl_lock = FUTEX_INITIALIZER;
     54/** Device connection list head. */
     55static LIST_INITIALIZE(dcl_head);
     56
     57typedef struct {
     58        link_t link;
     59        int dev_handle;
     60        int dev_phone;
     61        void *com_area;
     62        size_t com_size;
     63        void *bb_buf;
     64        off_t bb_off;
     65        size_t bb_size;
     66} devcon_t;
     67
     68static devcon_t *devcon_search(dev_handle_t dev_handle)
     69{
     70        link_t *cur;
     71
     72        futex_down(&dcl_lock);
     73        for (cur = dcl_head.next; cur != &dcl_head; cur = cur->next) {
     74                devcon_t *devcon = list_get_instance(cur, devcon_t, link);
     75                if (devcon->dev_handle == dev_handle) {
     76                        futex_up(&dcl_lock);
     77                        return devcon;
     78                }
     79        }
     80        futex_up(&dcl_lock);
     81        return NULL;
     82}
     83
     84static int devcon_add(dev_handle_t dev_handle, int dev_phone, void *com_area,
     85   size_t com_size, void *bb_buf, off_t bb_off, size_t bb_size)
     86{
     87        link_t *cur;
     88        devcon_t *devcon;
     89
     90        devcon = malloc(sizeof(devcon_t));
     91        if (!devcon)
     92                return ENOMEM;
     93       
     94        link_initialize(&devcon->link);
     95        devcon->dev_handle = dev_handle;
     96        devcon->dev_phone = dev_phone;
     97        devcon->com_area = com_area;
     98        devcon->com_size = com_size;
     99        devcon->bb_buf = bb_buf;
     100        devcon->bb_off = bb_off;
     101        devcon->bb_size = bb_size;
     102
     103        futex_down(&dcl_lock);
     104        for (cur = dcl_head.next; cur != &dcl_head; cur = cur->next) {
     105                devcon_t *d = list_get_instance(cur, devcon_t, link);
     106                if (d->dev_handle == dev_handle) {
     107                        futex_up(&dcl_lock);
     108                        free(devcon);
     109                        return EEXIST;
     110                }
     111        }
     112        list_append(&devcon->link, &dcl_head);
     113        futex_up(&dcl_lock);
     114        return EOK;
     115}
     116
     117static void devcon_remove(devcon_t *devcon)
     118{
     119        futex_down(&dcl_lock);
     120        list_remove(&devcon->link);
     121        futex_up(&dcl_lock);
     122}
    54123
    55124int
     
    58127{
    59128        int rc;
    60 
    61         bblock = malloc(bb_size);
    62         if (!bblock)
     129        int dev_phone;
     130        void *com_area;
     131        void *bb_buf;
     132       
     133        bb_buf = malloc(bb_size);
     134        if (!bb_buf)
    63135                return ENOMEM;
    64         dev_buffer_len = com_size;
    65         dev_buffer = mmap(NULL, com_size, PROTO_READ | PROTO_WRITE,
     136       
     137        com_area = mmap(NULL, com_size, PROTO_READ | PROTO_WRITE,
    66138            MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
    67         if (!dev_buffer) {
    68                 free(bblock);
     139        if (!com_area) {
     140                free(bb_buf);
    69141                return ENOMEM;
    70142        }
     
    73145
    74146        if (dev_phone < 0) {
    75                 free(bblock);
    76                 munmap(dev_buffer, com_size);
     147                free(bb_buf);
     148                munmap(com_area, com_size);
    77149                return dev_phone;
    78150        }
    79151
    80         rc = ipc_share_out_start(dev_phone, dev_buffer,
     152        rc = ipc_share_out_start(dev_phone, com_area,
    81153            AS_AREA_READ | AS_AREA_WRITE);
    82154        if (rc != EOK) {
     155                free(bb_buf);
     156                munmap(com_area, com_size);
    83157                ipc_hangup(dev_phone);
    84                 free(bblock);
    85                 munmap(dev_buffer, com_size);
    86158                return rc;
    87159        }
     160       
     161        rc = devcon_add(dev_handle, dev_phone, com_area, com_size, bb_buf,
     162            bb_off, bb_size);
     163        if (rc != EOK) {
     164                free(bb_buf);
     165                munmap(com_area, com_size);
     166                ipc_hangup(dev_phone);
     167                return rc;
     168        }
     169
    88170        off_t bufpos = 0;
    89171        size_t buflen = 0;
    90172        if (!block_read(dev_handle, &bufpos, &buflen, &bb_off,
    91             bblock, bb_size, bb_size)) {
    92                 ipc_hangup(dev_phone);
    93                 free(bblock);
    94                 munmap(dev_buffer, com_size);
     173            bb_buf, bb_size, bb_size)) {
     174                block_fini(dev_handle);
    95175                return EIO;     /* XXX real error code */
    96176        }
     177       
    97178        return EOK;
    98179}
     
    100181void block_fini(dev_handle_t dev_handle)
    101182{
    102         /* XXX */
    103         free(bblock);
    104         munmap(dev_buffer, dev_buffer_len);
    105         ipc_hangup(dev_phone);
     183        devcon_t *devcon = devcon_search(dev_handle);
     184        assert(devcon);
     185       
     186        devcon_remove(devcon);
     187
     188        free(devcon->bb_buf);
     189        munmap(devcon->com_area, devcon->com_size);
     190        ipc_hangup(devcon->dev_phone);
     191
     192        free(devcon);   
    106193}
    107194
    108195void *block_bb_get(dev_handle_t dev_handle)
    109196{
    110         /* XXX */
    111         return bblock;
     197        devcon_t *devcon = devcon_search(dev_handle);
     198        assert(devcon);
     199        return devcon->bb_buf;
    112200}
    113201
     
    132220        off_t offset = 0;
    133221        size_t left = size;
     222        devcon_t *devcon = devcon_search(dev_handle);
     223        assert(devcon);
    134224       
    135225        while (left > 0) {
     
    146236                         * destination buffer.
    147237                         */
    148                         memcpy(dst + offset, dev_buffer + *bufpos, rd);
     238                        memcpy(dst + offset, devcon->com_area + *bufpos, rd);
    149239                        offset += rd;
    150240                        *bufpos += rd;
     
    156246                        /* Refill the communication buffer with a new block. */
    157247                        ipcarg_t retval;
    158                         int rc = async_req_2_1(dev_phone, RD_READ_BLOCK,
     248                        int rc = async_req_2_1(devcon->dev_phone, RD_READ_BLOCK,
    159249                            *pos / block_size, block_size, &retval);
    160250                        if ((rc != EOK) || (retval != EOK))
     
    177267        off_t pos = offset * bs;
    178268
    179         assert(dev_phone != -1);
    180         assert(dev_buffer);
    181 
    182269        b = malloc(sizeof(block_t));
    183270        if (!b)
Note: See TracChangeset for help on using the changeset viewer.