Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/char/i8042/i8042.c

    r9d58539 r1ae74c6  
    3939 */
    4040
    41 #include <devman.h>
    4241#include <device/hw_res.h>
    4342#include <ddi.h>
    44 #include <libarch/ddi.h>
    4543#include <errno.h>
    4644#include <str_error.h>
     
    120118        },
    121119        {
    122                 .cmd = CMD_BTEST,
     120                .cmd = CMD_AND,
    123121                .value = i8042_OUTPUT_FULL,
    124122                .srcarg = 1,
     
    140138};
    141139
     140/** Get i8042 soft state from device node. */
     141static i8042_t *dev_i8042(ddf_dev_t *dev)
     142{
     143        return ddf_dev_data_get(dev);
     144}
     145
    142146/** Wait until it is safe to write to the device. */
    143147static void wait_ready(i8042_t *dev)
     
    159163    ipc_call_t *call)
    160164{
    161         if ((!dev) || (!dev->driver_data))
    162                 return;
    163        
    164         i8042_t *controller = dev->driver_data;
     165        i8042_t *controller = dev_i8042(dev);
    165166       
    166167        const uint8_t status = IPC_GET_ARG1(*call);
     
    188189    int irq_mouse, ddf_dev_t *ddf_dev)
    189190{
    190         assert(ddf_dev);
    191         assert(dev);
    192        
    193         if (reg_size < sizeof(i8042_regs_t))
    194                 return EINVAL;
    195        
    196         if (pio_enable(regs, sizeof(i8042_regs_t), (void **) &dev->regs) != 0)
    197                 return -1;
     191        const size_t range_count = sizeof(i8042_ranges) /
     192            sizeof(irq_pio_range_t);
     193        irq_pio_range_t ranges[range_count];
     194        const size_t cmd_count = sizeof(i8042_cmds) / sizeof(irq_cmd_t);
     195        irq_cmd_t cmds[cmd_count];
     196
     197        int rc;
     198        bool kbd_bound = false;
     199        bool aux_bound = false;
     200
     201        dev->kbd_fun = NULL;
     202        dev->aux_fun = NULL;
     203       
     204        if (reg_size < sizeof(i8042_regs_t)) {
     205                rc = EINVAL;
     206                goto error;
     207        }
     208       
     209        if (pio_enable(regs, sizeof(i8042_regs_t), (void **) &dev->regs) != 0) {
     210                rc = EIO;
     211                goto error;
     212        }
    198213       
    199214        dev->kbd_fun = ddf_fun_create(ddf_dev, fun_inner, "ps2a");
    200         if (!dev->kbd_fun)
    201                 return ENOMEM;
    202        
    203         int ret = ddf_fun_add_match_id(dev->kbd_fun, "char/xtkbd", 90);
    204         if (ret != EOK) {
    205                 ddf_fun_destroy(dev->kbd_fun);
    206                 return ret;
    207         }
     215        if (dev->kbd_fun == NULL) {
     216                rc = ENOMEM;
     217                goto error;
     218        };
     219       
     220        rc = ddf_fun_add_match_id(dev->kbd_fun, "char/xtkbd", 90);
     221        if (rc != EOK)
     222                goto error;
    208223       
    209224        dev->aux_fun = ddf_fun_create(ddf_dev, fun_inner, "ps2b");
    210         if (!dev->aux_fun) {
    211                 ddf_fun_destroy(dev->kbd_fun);
    212                 return ENOMEM;
    213         }
    214        
    215         ret = ddf_fun_add_match_id(dev->aux_fun, "char/ps2mouse", 90);
    216         if (ret != EOK) {
    217                 ddf_fun_destroy(dev->kbd_fun);
    218                 ddf_fun_destroy(dev->aux_fun);
    219                 return ret;
    220         }
    221        
    222         dev->kbd_fun->ops = &ops;
    223         dev->aux_fun->ops = &ops;
    224         dev->kbd_fun->driver_data = dev;
    225         dev->aux_fun->driver_data = dev;
     225        if (dev->aux_fun == NULL) {
     226                rc = ENOMEM;
     227                goto error;
     228        }
     229       
     230        rc = ddf_fun_add_match_id(dev->aux_fun, "char/ps2mouse", 90);
     231        if (rc != EOK)
     232                goto error;
     233       
     234        ddf_fun_set_ops(dev->kbd_fun, &ops);
     235        ddf_fun_set_ops(dev->aux_fun, &ops);
    226236       
    227237        buffer_init(&dev->kbd_buffer, dev->kbd_data, BUFFER_SIZE);
     
    229239        fibril_mutex_initialize(&dev->write_guard);
    230240       
    231         ret = ddf_fun_bind(dev->kbd_fun);
    232         CHECK_RET_DESTROY(ret, "Failed to bind keyboard function: %s.",
    233             str_error(ret));
    234        
    235         ret = ddf_fun_bind(dev->aux_fun);
    236         CHECK_RET_DESTROY(ret, "Failed to bind mouse function: %s.",
    237             str_error(ret));
     241        rc = ddf_fun_bind(dev->kbd_fun);
     242        if (rc != EOK) {
     243                ddf_msg(LVL_ERROR, "Failed to bind keyboard function: %s.",
     244                    ddf_fun_get_name(dev->kbd_fun));
     245                goto error;
     246        }
     247        kbd_bound = true;
     248       
     249        rc = ddf_fun_bind(dev->aux_fun);
     250        if (rc != EOK) {
     251                ddf_msg(LVL_ERROR, "Failed to bind aux function: %s.",
     252                    ddf_fun_get_name(dev->aux_fun));
     253                goto error;
     254        }
     255        aux_bound = true;
    238256       
    239257        /* Disable kbd and aux */
     
    247265                (void) pio_read_8(&dev->regs->data);
    248266
    249         const size_t range_count = sizeof(i8042_ranges) /
    250             sizeof(irq_pio_range_t);
    251         irq_pio_range_t ranges[range_count];
    252267        memcpy(ranges, i8042_ranges, sizeof(i8042_ranges));
    253268        ranges[0].base = (uintptr_t) regs;
    254269
    255         const size_t cmd_count = sizeof(i8042_cmds) / sizeof(irq_cmd_t);
    256         irq_cmd_t cmds[cmd_count];
    257270        memcpy(cmds, i8042_cmds, sizeof(i8042_cmds));
    258271        cmds[0].addr = (void *) &(((i8042_regs_t *) regs)->status);
     
    266279        };
    267280       
    268         ret = register_interrupt_handler(ddf_dev, irq_kbd, i8042_irq_handler,
     281        rc = register_interrupt_handler(ddf_dev, irq_kbd, i8042_irq_handler,
    269282            &irq_code);
    270         CHECK_RET_UNBIND_DESTROY(ret, "Failed set handler for kbd: %s.",
    271             str_error(ret));
    272        
    273         ret = register_interrupt_handler(ddf_dev, irq_mouse, i8042_irq_handler,
     283        if (rc != EOK) {
     284                ddf_msg(LVL_ERROR, "Failed set handler for kbd: %s.",
     285                    ddf_dev_get_name(ddf_dev));
     286                goto error;
     287        }
     288       
     289        rc = register_interrupt_handler(ddf_dev, irq_mouse, i8042_irq_handler,
    274290            &irq_code);
    275         CHECK_RET_UNBIND_DESTROY(ret, "Failed set handler for mouse: %s.",
    276             str_error(ret));
     291        if (rc != EOK) {
     292                ddf_msg(LVL_ERROR, "Failed set handler for mouse: %s.",
     293                    ddf_dev_get_name(ddf_dev));
     294                goto error;
     295        }
    277296       
    278297        /* Enable interrupts */
    279         async_sess_t *parent_sess =
    280             devman_parent_device_connect(EXCHANGE_SERIALIZE, ddf_dev->handle,
    281             IPC_FLAG_BLOCKING);
    282         ret = parent_sess ? EOK : ENOMEM;
    283         CHECK_RET_UNBIND_DESTROY(ret, "Failed to create parent connection.");
     298        async_sess_t *parent_sess = ddf_dev_parent_sess_get(ddf_dev);
     299        assert(parent_sess != NULL);
    284300       
    285301        const bool enabled = hw_res_enable_interrupt(parent_sess);
    286         async_hangup(parent_sess);
    287         ret = enabled ? EOK : EIO;
    288         CHECK_RET_UNBIND_DESTROY(ret, "Failed to enable interrupts: %s.");
     302        if (!enabled) {
     303                log_msg(LOG_DEFAULT, LVL_ERROR, "Failed to enable interrupts: %s.",
     304                    ddf_dev_get_name(ddf_dev));
     305                rc = EIO;
     306                goto error;
     307        }
    289308       
    290309        /* Enable port interrupts. */
     
    296315       
    297316        return EOK;
     317error:
     318        if (kbd_bound)
     319                ddf_fun_unbind(dev->kbd_fun);
     320        if (aux_bound)
     321                ddf_fun_unbind(dev->aux_fun);
     322        if (dev->kbd_fun != NULL)
     323                ddf_fun_destroy(dev->kbd_fun);
     324        if (dev->aux_fun != NULL)
     325                ddf_fun_destroy(dev->aux_fun);
     326
     327        return rc;
    298328}
    299329
     
    315345static int i8042_write(ddf_fun_t *fun, char *buffer, size_t size)
    316346{
    317         assert(fun);
    318         assert(fun->driver_data);
    319        
    320         i8042_t *controller = fun->driver_data;
     347        i8042_t *controller = dev_i8042(ddf_fun_get_dev(fun));
    321348        fibril_mutex_lock(&controller->write_guard);
    322349       
     
    347374static int i8042_read(ddf_fun_t *fun, char *data, size_t size)
    348375{
    349         assert(fun);
    350         assert(fun->driver_data);
    351        
    352         i8042_t *controller = fun->driver_data;
     376        i8042_t *controller = dev_i8042(ddf_fun_get_dev(fun));
    353377        buffer_t *buffer = (fun == controller->aux_fun) ?
    354378            &controller->aux_buffer : &controller->kbd_buffer;
Note: See TracChangeset for help on using the changeset viewer.