Changeset 7eaeec1 in mainline for uspace/drv/char/i8042/i8042.c


Ignore:
Timestamp:
2012-08-20T21:27:38Z (12 years ago)
Author:
Sean Bartell <wingedtachikoma@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
6a97f2e
Parents:
f3a37e28 (diff), dd13349 (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:

Merge mainline changes

File:
1 edited

Legend:

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

    rf3a37e28 r7eaeec1  
    3939 */
    4040
    41 #include <devman.h>
    4241#include <device/hw_res.h>
    4342#include <ddi.h>
     
    140139};
    141140
     141/** Get i8042 soft state from device node. */
     142static i8042_t *dev_i8042(ddf_dev_t *dev)
     143{
     144        return ddf_dev_data_get(dev);
     145}
     146
    142147/** Wait until it is safe to write to the device. */
    143148static void wait_ready(i8042_t *dev)
     
    159164    ipc_call_t *call)
    160165{
    161         if ((!dev) || (!dev->driver_data))
    162                 return;
    163        
    164         i8042_t *controller = dev->driver_data;
     166        i8042_t *controller = dev_i8042(dev);
    165167       
    166168        const uint8_t status = IPC_GET_ARG1(*call);
     
    188190    int irq_mouse, ddf_dev_t *ddf_dev)
    189191{
    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;
     192        const size_t range_count = sizeof(i8042_ranges) /
     193            sizeof(irq_pio_range_t);
     194        irq_pio_range_t ranges[range_count];
     195        const size_t cmd_count = sizeof(i8042_cmds) / sizeof(irq_cmd_t);
     196        irq_cmd_t cmds[cmd_count];
     197
     198        int rc;
     199        bool kbd_bound = false;
     200        bool aux_bound = false;
     201
     202        dev->kbd_fun = NULL;
     203        dev->aux_fun = NULL;
     204       
     205        if (reg_size < sizeof(i8042_regs_t)) {
     206                rc = EINVAL;
     207                goto error;
     208        }
     209       
     210        if (pio_enable(regs, sizeof(i8042_regs_t), (void **) &dev->regs) != 0) {
     211                rc = EIO;
     212                goto error;
     213        }
    198214       
    199215        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         }
     216        if (dev->kbd_fun == NULL) {
     217                rc = ENOMEM;
     218                goto error;
     219        };
     220       
     221        rc = ddf_fun_add_match_id(dev->kbd_fun, "char/xtkbd", 90);
     222        if (rc != EOK)
     223                goto error;
    208224       
    209225        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;
     226        if (dev->aux_fun == NULL) {
     227                rc = ENOMEM;
     228                goto error;
     229        }
     230       
     231        rc = ddf_fun_add_match_id(dev->aux_fun, "char/ps2mouse", 90);
     232        if (rc != EOK)
     233                goto error;
     234       
     235        ddf_fun_set_ops(dev->kbd_fun, &ops);
     236        ddf_fun_set_ops(dev->aux_fun, &ops);
    226237       
    227238        buffer_init(&dev->kbd_buffer, dev->kbd_data, BUFFER_SIZE);
     
    229240        fibril_mutex_initialize(&dev->write_guard);
    230241       
    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));
     242        rc = ddf_fun_bind(dev->kbd_fun);
     243        if (rc != EOK) {
     244                ddf_msg(LVL_ERROR, "Failed to bind keyboard function: %s.",
     245                    ddf_fun_get_name(dev->kbd_fun));
     246                goto error;
     247        }
     248        kbd_bound = true;
     249       
     250        rc = ddf_fun_bind(dev->aux_fun);
     251        if (rc != EOK) {
     252                ddf_msg(LVL_ERROR, "Failed to bind aux function: %s.",
     253                    ddf_fun_get_name(dev->aux_fun));
     254                goto error;
     255        }
     256        aux_bound = true;
    238257       
    239258        /* Disable kbd and aux */
     
    247266                (void) pio_read_8(&dev->regs->data);
    248267
    249         const size_t range_count = sizeof(i8042_ranges) /
    250             sizeof(irq_pio_range_t);
    251         irq_pio_range_t ranges[range_count];
    252268        memcpy(ranges, i8042_ranges, sizeof(i8042_ranges));
    253269        ranges[0].base = (uintptr_t) regs;
    254270
    255         const size_t cmd_count = sizeof(i8042_cmds) / sizeof(irq_cmd_t);
    256         irq_cmd_t cmds[cmd_count];
    257271        memcpy(cmds, i8042_cmds, sizeof(i8042_cmds));
    258272        cmds[0].addr = (void *) &(((i8042_regs_t *) regs)->status);
     
    266280        };
    267281       
    268         ret = register_interrupt_handler(ddf_dev, irq_kbd, i8042_irq_handler,
     282        rc = register_interrupt_handler(ddf_dev, irq_kbd, i8042_irq_handler,
    269283            &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,
     284        if (rc != EOK) {
     285                ddf_msg(LVL_ERROR, "Failed set handler for kbd: %s.",
     286                    ddf_dev_get_name(ddf_dev));
     287                goto error;
     288        }
     289       
     290        rc = register_interrupt_handler(ddf_dev, irq_mouse, i8042_irq_handler,
    274291            &irq_code);
    275         CHECK_RET_UNBIND_DESTROY(ret, "Failed set handler for mouse: %s.",
    276             str_error(ret));
     292        if (rc != EOK) {
     293                ddf_msg(LVL_ERROR, "Failed set handler for mouse: %s.",
     294                    ddf_dev_get_name(ddf_dev));
     295                goto error;
     296        }
    277297       
    278298        /* 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.");
     299        async_sess_t *parent_sess = ddf_dev_parent_sess_get(ddf_dev);
     300        assert(parent_sess != NULL);
    284301       
    285302        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.");
     303        if (!enabled) {
     304                log_msg(LVL_ERROR, "Failed to enable interrupts: %s.",
     305                    ddf_dev_get_name(ddf_dev));
     306                rc = EIO;
     307                goto error;
     308        }
    289309       
    290310        /* Enable port interrupts. */
     
    296316       
    297317        return EOK;
     318error:
     319        if (kbd_bound)
     320                ddf_fun_unbind(dev->kbd_fun);
     321        if (aux_bound)
     322                ddf_fun_unbind(dev->aux_fun);
     323        if (dev->kbd_fun != NULL)
     324                ddf_fun_destroy(dev->kbd_fun);
     325        if (dev->aux_fun != NULL)
     326                ddf_fun_destroy(dev->aux_fun);
     327
     328        return rc;
    298329}
    299330
     
    315346static int i8042_write(ddf_fun_t *fun, char *buffer, size_t size)
    316347{
    317         assert(fun);
    318         assert(fun->driver_data);
    319        
    320         i8042_t *controller = fun->driver_data;
     348        i8042_t *controller = dev_i8042(ddf_fun_get_dev(fun));
    321349        fibril_mutex_lock(&controller->write_guard);
    322350       
     
    347375static int i8042_read(ddf_fun_t *fun, char *data, size_t size)
    348376{
    349         assert(fun);
    350         assert(fun->driver_data);
    351        
    352         i8042_t *controller = fun->driver_data;
     377        i8042_t *controller = dev_i8042(ddf_fun_get_dev(fun));
    353378        buffer_t *buffer = (fun == controller->aux_fun) ?
    354379            &controller->aux_buffer : &controller->kbd_buffer;
Note: See TracChangeset for help on using the changeset viewer.