Changeset eb522e8 in mainline for uspace/lib/drv/generic/driver.c


Ignore:
Timestamp:
2011-06-01T08:43:42Z (14 years ago)
Author:
Lubos Slovak <lubos.slovak@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
8d6c1f1
Parents:
9e2e715 (diff), e51a514 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Huuuuuge merge from development - all the work actually :)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/drv/generic/driver.c

    r9e2e715 reb522e8  
    11/*
    22 * Copyright (c) 2010 Lenka Trochtova
     3 * Copyright (c) 2011 Jiri Svoboda
    34 * All rights reserved.
    45 *
     
    4647#include <stdlib.h>
    4748#include <str.h>
     49#include <str_error.h>
    4850#include <ctype.h>
    4951#include <errno.h>
     52#include <inttypes.h>
     53#include <devman.h>
    5054
    5155#include <ipc/driver.h>
    5256
    53 #include "driver.h"
    54 
    55 /* driver structure */
    56 
     57#include "dev_iface.h"
     58#include "ddf/driver.h"
     59#include "ddf/interrupt.h"
     60
     61/** Driver structure */
    5762static driver_t *driver;
    5863
    59 /* devices */
    60 
    61 LIST_INITIALIZE(devices);
    62 FIBRIL_MUTEX_INITIALIZE(devices_mutex);
    63 
    64 /* interrupts */
    65 
     64/** Devices */
     65LIST_INITIALIZE(functions);
     66FIBRIL_MUTEX_INITIALIZE(functions_mutex);
     67
     68/** Interrupts */
    6669static interrupt_context_list_t interrupt_contexts;
    6770
     
    7780};
    7881
     82static ddf_dev_t *create_device(void);
     83static void delete_device(ddf_dev_t *);
     84static remote_handler_t *function_get_default_handler(ddf_fun_t *);
     85static void *function_get_ops(ddf_fun_t *, dev_inferface_idx_t);
    7986
    8087static void driver_irq_handler(ipc_callid_t iid, ipc_call_t *icall)
    8188{
    82         int id = (int)IPC_GET_METHOD(*icall);
     89        int id = (int)IPC_GET_IMETHOD(*icall);
    8390        interrupt_context_t *ctx;
    8491       
    8592        ctx = find_interrupt_context_by_id(&interrupt_contexts, id);
    86         if (NULL != ctx && NULL != ctx->handler)
     93        if (ctx != NULL && ctx->handler != NULL)
    8794                (*ctx->handler)(ctx->dev, iid, icall);
    8895}
    8996
     97interrupt_context_t *create_interrupt_context(void)
     98{
     99        interrupt_context_t *ctx;
     100       
     101        ctx = (interrupt_context_t *) malloc(sizeof(interrupt_context_t));
     102        if (ctx != NULL)
     103                memset(ctx, 0, sizeof(interrupt_context_t));
     104       
     105        return ctx;
     106}
     107
     108void delete_interrupt_context(interrupt_context_t *ctx)
     109{
     110        if (ctx != NULL)
     111                free(ctx);
     112}
     113
     114void init_interrupt_context_list(interrupt_context_list_t *list)
     115{
     116        memset(list, 0, sizeof(interrupt_context_list_t));
     117        fibril_mutex_initialize(&list->mutex);
     118        list_initialize(&list->contexts);
     119}
     120
     121void
     122add_interrupt_context(interrupt_context_list_t *list, interrupt_context_t *ctx)
     123{
     124        fibril_mutex_lock(&list->mutex);
     125        ctx->id = list->curr_id++;
     126        list_append(&ctx->link, &list->contexts);
     127        fibril_mutex_unlock(&list->mutex);
     128}
     129
     130void remove_interrupt_context(interrupt_context_list_t *list,
     131    interrupt_context_t *ctx)
     132{
     133        fibril_mutex_lock(&list->mutex);
     134        list_remove(&ctx->link);
     135        fibril_mutex_unlock(&list->mutex);
     136}
     137
     138interrupt_context_t *
     139find_interrupt_context_by_id(interrupt_context_list_t *list, int id)
     140{
     141        fibril_mutex_lock(&list->mutex);
     142       
     143        link_t *link = list->contexts.next;
     144        interrupt_context_t *ctx;
     145       
     146        while (link != &list->contexts) {
     147                ctx = list_get_instance(link, interrupt_context_t, link);
     148                if (ctx->id == id) {
     149                        fibril_mutex_unlock(&list->mutex);
     150                        return ctx;
     151                }
     152                link = link->next;
     153        }
     154       
     155        fibril_mutex_unlock(&list->mutex);
     156        return NULL;
     157}
     158
     159interrupt_context_t *
     160find_interrupt_context(interrupt_context_list_t *list, ddf_dev_t *dev, int irq)
     161{
     162        fibril_mutex_lock(&list->mutex);
     163       
     164        link_t *link = list->contexts.next;
     165        interrupt_context_t *ctx;
     166       
     167        while (link != &list->contexts) {
     168                ctx = list_get_instance(link, interrupt_context_t, link);
     169                if (ctx->irq == irq && ctx->dev == dev) {
     170                        fibril_mutex_unlock(&list->mutex);
     171                        return ctx;
     172                }
     173                link = link->next;
     174        }
     175       
     176        fibril_mutex_unlock(&list->mutex);
     177        return NULL;
     178}
     179
     180
    90181int
    91 register_interrupt_handler(device_t *dev, int irq, interrupt_handler_t *handler,
     182register_interrupt_handler(ddf_dev_t *dev, int irq, interrupt_handler_t *handler,
    92183    irq_code_t *pseudocode)
    93184{
     
    100191        add_interrupt_context(&interrupt_contexts, ctx);
    101192       
    102         if (NULL == pseudocode)
     193        if (pseudocode == NULL)
    103194                pseudocode = &default_pseudocode;
    104195       
    105         int res = ipc_register_irq(irq, dev->handle, ctx->id, pseudocode);
    106         if (0 != res) {
     196        int res = register_irq(irq, dev->handle, ctx->id, pseudocode);
     197        if (res != EOK) {
    107198                remove_interrupt_context(&interrupt_contexts, ctx);
    108199                delete_interrupt_context(ctx);
     
    112203}
    113204
    114 int unregister_interrupt_handler(device_t *dev, int irq)
     205int unregister_interrupt_handler(ddf_dev_t *dev, int irq)
    115206{
    116207        interrupt_context_t *ctx = find_interrupt_context(&interrupt_contexts,
    117208            dev, irq);
    118         int res = ipc_unregister_irq(irq, dev->handle);
    119 
    120         if (NULL != ctx) {
     209        int res = unregister_irq(irq, dev->handle);
     210       
     211        if (ctx != NULL) {
    121212                remove_interrupt_context(&interrupt_contexts, ctx);
    122213                delete_interrupt_context(ctx);
    123214        }
     215       
    124216        return res;
    125217}
    126218
    127 static void add_to_devices_list(device_t *dev)
    128 {
    129         fibril_mutex_lock(&devices_mutex);
    130         list_append(&dev->link, &devices);
    131         fibril_mutex_unlock(&devices_mutex);
    132 }
    133 
    134 static void remove_from_devices_list(device_t *dev)
    135 {
    136         fibril_mutex_lock(&devices_mutex);
    137         list_remove(&dev->link);
    138         fibril_mutex_unlock(&devices_mutex);
    139 }
    140 
    141 static device_t * driver_get_device(link_t *devices, device_handle_t handle)
    142 {
    143         device_t *dev = NULL;
    144        
    145         fibril_mutex_lock(&devices_mutex);
    146         link_t *link = devices->next;
    147         while (link != devices) {
    148                 dev = list_get_instance(link, device_t, link);
    149                 if (handle == dev->handle) {
    150                         fibril_mutex_unlock(&devices_mutex);
    151                         return dev;
     219static void add_to_functions_list(ddf_fun_t *fun)
     220{
     221        fibril_mutex_lock(&functions_mutex);
     222        list_append(&fun->link, &functions);
     223        fibril_mutex_unlock(&functions_mutex);
     224}
     225
     226static void remove_from_functions_list(ddf_fun_t *fun)
     227{
     228        fibril_mutex_lock(&functions_mutex);
     229        list_remove(&fun->link);
     230        fibril_mutex_unlock(&functions_mutex);
     231}
     232
     233static ddf_fun_t *driver_get_function(link_t *functions, devman_handle_t handle)
     234{
     235        ddf_fun_t *fun = NULL;
     236       
     237        fibril_mutex_lock(&functions_mutex);
     238        link_t *link = functions->next;
     239       
     240        while (link != functions) {
     241                fun = list_get_instance(link, ddf_fun_t, link);
     242                if (fun->handle == handle) {
     243                        fibril_mutex_unlock(&functions_mutex);
     244                        return fun;
    152245                }
     246               
    153247                link = link->next;
    154248        }
    155         fibril_mutex_unlock(&devices_mutex);
    156 
     249       
     250        fibril_mutex_unlock(&functions_mutex);
     251       
    157252        return NULL;
    158253}
     
    161256{
    162257        char *dev_name = NULL;
    163         int res = EOK;
    164        
    165         device_handle_t dev_handle =  IPC_GET_ARG1(*icall);
    166         device_t *dev = create_device();
     258        int res;
     259       
     260        devman_handle_t dev_handle = IPC_GET_ARG1(*icall);
     261        devman_handle_t parent_fun_handle = IPC_GET_ARG2(*icall);
     262       
     263        ddf_dev_t *dev = create_device();
    167264        dev->handle = dev_handle;
    168        
     265
    169266        async_data_write_accept((void **) &dev_name, true, 0, 0, 0, 0);
    170267        dev->name = dev_name;
    171        
    172         add_to_devices_list(dev);
     268
     269        /*
     270         * Currently not used, parent fun handle is stored in context
     271         * of the connection to the parent device driver.
     272         */
     273        (void) parent_fun_handle;
     274       
    173275        res = driver->driver_ops->add_device(dev);
    174         if (0 == res) {
    175                 printf("%s: new device with handle = %x was added.\n",
    176                     driver->name, dev_handle);
    177         } else {
    178                 printf("%s: failed to add a new device with handle = %d.\n",
    179                     driver->name, dev_handle);
    180                 remove_from_devices_list(dev);
     276        if (res != EOK)
    181277                delete_device(dev);
    182         }
    183        
    184         ipc_answer_0(iid, res);
     278       
     279        async_answer_0(iid, res);
    185280}
    186281
     
    188283{
    189284        /* Accept connection */
    190         ipc_answer_0(iid, EOK);
    191 
     285        async_answer_0(iid, EOK);
     286       
    192287        bool cont = true;
    193288        while (cont) {
    194289                ipc_call_t call;
    195290                ipc_callid_t callid = async_get_call(&call);
    196 
    197                 switch (IPC_GET_METHOD(call)) {
     291               
     292                switch (IPC_GET_IMETHOD(call)) {
    198293                case IPC_M_PHONE_HUNGUP:
    199294                        cont = false;
     
    203298                        break;
    204299                default:
    205                         if (!(callid & IPC_CALLID_NOTIFICATION))
    206                                 ipc_answer_0(callid, ENOENT);
     300                        async_answer_0(callid, ENOENT);
    207301                }
    208302        }
     
    221315         * the device to which the client connected.
    222316         */
    223         device_handle_t handle = IPC_GET_ARG2(*icall);
    224         device_t *dev = driver_get_device(&devices, handle);
    225 
    226         if (dev == NULL) {
    227                 printf("%s: driver_connection_gen error - no device with handle"
    228                     " %x was found.\n", driver->name, handle);
    229                 ipc_answer_0(iid, ENOENT);
     317        devman_handle_t handle = IPC_GET_ARG2(*icall);
     318        ddf_fun_t *fun = driver_get_function(&functions, handle);
     319
     320        if (fun == NULL) {
     321                printf("%s: driver_connection_gen error - no function with handle"
     322                    " %" PRIun " was found.\n", driver->name, handle);
     323                async_answer_0(iid, ENOENT);
    230324                return;
    231325        }
     
    236330         * use the device.
    237331         */
    238 
     332       
    239333        int ret = EOK;
    240         /* open the device */
    241         if (NULL != dev->ops && NULL != dev->ops->open)
    242                 ret = (*dev->ops->open)(dev);
    243        
    244         ipc_answer_0(iid, ret);
    245         if (EOK != ret)
     334        /* Open device function */
     335        if (fun->ops != NULL && fun->ops->open != NULL)
     336                ret = (*fun->ops->open)(fun);
     337       
     338        async_answer_0(iid, ret);
     339        if (ret != EOK)
    246340                return;
    247 
     341       
    248342        while (1) {
    249343                ipc_callid_t callid;
    250344                ipc_call_t call;
    251345                callid = async_get_call(&call);
    252                 ipcarg_t method = IPC_GET_METHOD(call);
     346                sysarg_t method = IPC_GET_IMETHOD(call);
    253347                int iface_idx;
    254348               
    255349                switch  (method) {
    256                 case IPC_M_PHONE_HUNGUP:               
    257                         /* close the device */
    258                         if (NULL != dev->ops && NULL != dev->ops->close)
    259                                 (*dev->ops->close)(dev);
    260                         ipc_answer_0(callid, EOK);
     350                case IPC_M_PHONE_HUNGUP:
     351                        /* Close device function */
     352                        if (fun->ops != NULL && fun->ops->close != NULL)
     353                                (*fun->ops->close)(fun);
     354                        async_answer_0(callid, EOK);
    261355                        return;
    262                 default:               
     356                default:
    263357                        /* convert ipc interface id to interface index */
    264358                       
     
    267361                        if (!is_valid_iface_idx(iface_idx)) {
    268362                                remote_handler_t *default_handler =
    269                                     device_get_default_handler(dev);
    270                                 if (NULL != default_handler) {
    271                                         (*default_handler)(dev, callid, &call);
     363                                    function_get_default_handler(fun);
     364                                if (default_handler != NULL) {
     365                                        (*default_handler)(fun, callid, &call);
    272366                                        break;
    273367                                }
     368                               
    274369                                /*
    275                                  * This is not device's interface and the
     370                                 * Function has no such interface and
    276371                                 * default handler is not provided.
    277372                                 */
     
    279374                                    "invalid interface id %d.",
    280375                                    driver->name, iface_idx);
    281                                 ipc_answer_0(callid, ENOTSUP);
     376                                async_answer_0(callid, ENOTSUP);
    282377                                break;
    283378                        }
    284 
    285                         /* calling one of the device's interfaces */
    286379                       
    287                         /* get the device interface structure */
    288                         void *iface = device_get_iface(dev, iface_idx);
    289                         if (NULL == iface) {
     380                        /* calling one of the function's interfaces */
     381                       
     382                        /* Get the interface ops structure. */
     383                        void *ops = function_get_ops(fun, iface_idx);
     384                        if (ops == NULL) {
    290385                                printf("%s: driver_connection_gen error - ",
    291386                                    driver->name);
    292                                 printf("device with handle %d has no interface "
     387                                printf("Function with handle %" PRIun " has no interface "
    293388                                    "with id %d.\n", handle, iface_idx);
    294                                 ipc_answer_0(callid, ENOTSUP);
     389                                async_answer_0(callid, ENOTSUP);
    295390                                break;
    296391                        }
    297 
     392                       
    298393                        /*
    299394                         * Get the corresponding interface for remote request
    300395                         * handling ("remote interface").
    301396                         */
    302                         remote_iface_t* rem_iface = get_remote_iface(iface_idx);
    303                         assert(NULL != rem_iface);
    304 
     397                        remote_iface_t *rem_iface = get_remote_iface(iface_idx);
     398                        assert(rem_iface != NULL);
     399                       
    305400                        /* get the method of the remote interface */
    306                         ipcarg_t iface_method_idx = IPC_GET_ARG1(call);
     401                        sysarg_t iface_method_idx = IPC_GET_ARG1(call);
    307402                        remote_iface_func_ptr_t iface_method_ptr =
    308403                            get_remote_method(rem_iface, iface_method_idx);
    309                         if (NULL == iface_method_ptr) {
    310                                 // the interface has not such method
     404                        if (iface_method_ptr == NULL) {
     405                                /* The interface has not such method */
    311406                                printf("%s: driver_connection_gen error - "
    312                                     "invalid interface method.", driver->name);
    313                                 ipc_answer_0(callid, ENOTSUP);
     407                                    "invalid interface method "
     408                                    "(index %" PRIun ").\n",
     409                                    driver->name, iface_method_idx);
     410                                async_answer_0(callid, ENOTSUP);
    314411                                break;
    315412                        }
     
    319416                         * receive parameters from the remote client and it will
    320417                         * pass it to the corresponding local interface method
    321                          * associated with the device by its driver.
     418                         * associated with the function by its driver.
    322419                         */
    323                         (*iface_method_ptr)(dev, iface, callid, &call);
     420                        (*iface_method_ptr)(fun, ops, callid, &call);
    324421                        break;
    325422                }
     
    337434}
    338435
    339 
    340436/** Function for handling connections to device driver. */
    341437static void driver_connection(ipc_callid_t iid, ipc_call_t *icall)
    342438{
    343439        /* Select interface */
    344         switch ((ipcarg_t) (IPC_GET_ARG1(*icall))) {
     440        switch ((sysarg_t) (IPC_GET_ARG1(*icall))) {
    345441        case DRIVER_DEVMAN:
    346                 /* handle PnP events from device manager */
     442                /* Handle request from device manager */
    347443                driver_connection_devman(iid, icall);
    348444                break;
    349445        case DRIVER_DRIVER:
    350                 /* handle request from drivers of child devices */
     446                /* Handle request from drivers of child devices */
    351447                driver_connection_driver(iid, icall);
    352448                break;
    353449        case DRIVER_CLIENT:
    354                 /* handle requests from client applications */
     450                /* Handle request from client applications */
    355451                driver_connection_client(iid, icall);
    356452                break;
    357 
    358453        default:
    359454                /* No such interface */
    360                 ipc_answer_0(iid, ENOENT);
    361         }
    362 }
    363 
    364 int child_device_register(device_t *child, device_t *parent)
    365 {
    366         assert(NULL != child->name);
    367 
     455                async_answer_0(iid, ENOENT);
     456        }
     457}
     458
     459/** Create new device structure.
     460 *
     461 * @return              The device structure.
     462 */
     463static ddf_dev_t *create_device(void)
     464{
     465        ddf_dev_t *dev;
     466
     467        dev = malloc(sizeof(ddf_dev_t));
     468        if (dev == NULL)
     469                return NULL;
     470
     471        memset(dev, 0, sizeof(ddf_dev_t));
     472        return dev;
     473}
     474
     475/** Create new function structure.
     476 *
     477 * @return              The device structure.
     478 */
     479static ddf_fun_t *create_function(void)
     480{
     481        ddf_fun_t *fun;
     482
     483        fun = calloc(1, sizeof(ddf_fun_t));
     484        if (fun == NULL)
     485                return NULL;
     486
     487        init_match_ids(&fun->match_ids);
     488        link_initialize(&fun->link);
     489
     490        return fun;
     491}
     492
     493/** Delete device structure.
     494 *
     495 * @param dev           The device structure.
     496 */
     497static void delete_device(ddf_dev_t *dev)
     498{
     499        free(dev);
     500}
     501
     502/** Delete device structure.
     503 *
     504 * @param dev           The device structure.
     505 */
     506static void delete_function(ddf_fun_t *fun)
     507{
     508        clean_match_ids(&fun->match_ids);
     509        if (fun->name != NULL)
     510                free(fun->name);
     511        free(fun);
     512}
     513
     514/** Create a DDF function node.
     515 *
     516 * Create a DDF function (in memory). Both child devices and external clients
     517 * communicate with a device via its functions.
     518 *
     519 * The created function node is fully formed, but only exists in the memory
     520 * of the client task. In order to be visible to the system, the function
     521 * must be bound using ddf_fun_bind().
     522 *
     523 * This function should only fail if there is not enough free memory.
     524 * Specifically, this function succeeds even if @a dev already has
     525 * a (bound) function with the same name.
     526 *
     527 * Type: A function of type fun_inner indicates that DDF should attempt
     528 * to attach child devices to the function. fun_exposed means that
     529 * the function should be exported to external clients (applications).
     530 *
     531 * @param dev           Device to which we are adding function
     532 * @param ftype         Type of function (fun_inner or fun_exposed)
     533 * @param name          Name of function
     534 *
     535 * @return              New function or @c NULL if memory is not available
     536 */
     537ddf_fun_t *ddf_fun_create(ddf_dev_t *dev, fun_type_t ftype, const char *name)
     538{
     539        ddf_fun_t *fun;
     540
     541        fun = create_function();
     542        if (fun == NULL)
     543                return NULL;
     544
     545        fun->bound = false;
     546        fun->dev = dev;
     547        fun->ftype = ftype;
     548
     549        fun->name = str_dup(name);
     550        if (fun->name == NULL) {
     551                delete_function(fun);
     552                return NULL;
     553        }
     554
     555        return fun;
     556}
     557
     558/** Destroy DDF function node.
     559 *
     560 * Destroy a function previously created with ddf_fun_create(). The function
     561 * must not be bound.
     562 *
     563 * @param fun           Function to destroy
     564 */
     565void ddf_fun_destroy(ddf_fun_t *fun)
     566{
     567        assert(fun->bound == false);
     568        delete_function(fun);
     569}
     570
     571static void *function_get_ops(ddf_fun_t *fun, dev_inferface_idx_t idx)
     572{
     573        assert(is_valid_iface_idx(idx));
     574        if (fun->ops == NULL)
     575                return NULL;
     576        return fun->ops->interfaces[idx];
     577}
     578
     579/** Bind a function node.
     580 *
     581 * Bind the specified function to the system. This effectively makes
     582 * the function visible to the system (uploads it to the server).
     583 *
     584 * This function can fail for several reasons. Specifically,
     585 * it will fail if the device already has a bound function of
     586 * the same name.
     587 *
     588 * @param fun           Function to bind
     589 * @return              EOK on success or negative error code
     590 */
     591int ddf_fun_bind(ddf_fun_t *fun)
     592{
     593        assert(fun->name != NULL);
     594       
    368595        int res;
    369596       
    370         add_to_devices_list(child);
    371         res = devman_child_device_register(child->name, &child->match_ids,
    372             parent->handle, &child->handle);
    373         if (EOK == res)
     597        add_to_functions_list(fun);
     598        res = devman_add_function(fun->name, fun->ftype, &fun->match_ids,
     599            fun->dev->handle, &fun->handle);
     600        if (res != EOK) {
     601                remove_from_functions_list(fun);
    374602                return res;
    375         remove_from_devices_list(child);       
     603        }
     604       
     605        fun->bound = true;
    376606        return res;
    377607}
    378608
    379 int driver_main(driver_t *drv)
    380 {
     609/** Add single match ID to inner function.
     610 *
     611 * Construct and add a single match ID to the specified function.
     612 * Cannot be called when the function node is bound.
     613 *
     614 * @param fun                   Function
     615 * @param match_id_str          Match string
     616 * @param match_score           Match score
     617 * @return                      EOK on success, ENOMEM if out of memory.
     618 */
     619int ddf_fun_add_match_id(ddf_fun_t *fun, const char *match_id_str,
     620    int match_score)
     621{
     622        match_id_t *match_id;
     623       
     624        assert(fun->bound == false);
     625        assert(fun->ftype == fun_inner);
     626       
     627        match_id = create_match_id();
     628        if (match_id == NULL)
     629                return ENOMEM;
     630       
     631        match_id->id = match_id_str;
     632        match_id->score = 90;
     633       
     634        add_match_id(&fun->match_ids, match_id);
     635        return EOK;
     636}
     637
     638/** Get default handler for client requests */
     639static remote_handler_t *function_get_default_handler(ddf_fun_t *fun)
     640{
     641        if (fun->ops == NULL)
     642                return NULL;
     643        return fun->ops->default_handler;
     644}
     645
     646/** Add exposed function to class.
     647 *
     648 * Must only be called when the function is bound.
     649 */
     650int ddf_fun_add_to_class(ddf_fun_t *fun, const char *class_name)
     651{
     652        assert(fun->bound == true);
     653        assert(fun->ftype == fun_exposed);
     654       
     655        return devman_add_device_to_class(fun->handle, class_name);
     656}
     657
     658int ddf_driver_main(driver_t *drv)
     659{
     660        int rc;
     661
    381662        /*
    382663         * Remember the driver structure - driver_ops will be called by generic
     
    384665         */
    385666        driver = drv;
    386 
     667       
    387668        /* Initialize the list of interrupt contexts. */
    388669        init_interrupt_context_list(&interrupt_contexts);
     
    392673       
    393674        /*
    394          * Register driver by device manager with generic handler for incoming
    395          * connections.
     675         * Register driver with device manager using generic handler for
     676         * incoming connections.
    396677         */
    397         devman_driver_register(driver->name, driver_connection);
     678        rc = devman_driver_register(driver->name, driver_connection);
     679        if (rc != EOK) {
     680                printf("Error: Failed to register driver with device manager "
     681                    "(%s).\n", (rc == EEXISTS) ? "driver already started" :
     682                    str_error(rc));
     683               
     684                return 1;
     685        }
     686       
     687        /* Return success from the task since server has started. */
     688        rc = task_retval(0);
     689        if (rc != EOK)
     690                return 1;
    398691
    399692        async_manager();
    400 
     693       
    401694        /* Never reached. */
    402695        return 0;
Note: See TracChangeset for help on using the changeset viewer.