Ignore:
File:
1 edited

Legend:

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

    r1ae74c6 r9d58539  
    3939 */
    4040
     41#include <devman.h>
    4142#include <device/hw_res.h>
    4243#include <ddi.h>
     44#include <libarch/ddi.h>
    4345#include <errno.h>
    4446#include <str_error.h>
     
    118120        },
    119121        {
    120                 .cmd = CMD_AND,
     122                .cmd = CMD_BTEST,
    121123                .value = i8042_OUTPUT_FULL,
    122124                .srcarg = 1,
     
    138140};
    139141
    140 /** Get i8042 soft state from device node. */
    141 static i8042_t *dev_i8042(ddf_dev_t *dev)
    142 {
    143         return ddf_dev_data_get(dev);
    144 }
    145 
    146142/** Wait until it is safe to write to the device. */
    147143static void wait_ready(i8042_t *dev)
     
    163159    ipc_call_t *call)
    164160{
    165         i8042_t *controller = dev_i8042(dev);
     161        if ((!dev) || (!dev->driver_data))
     162                return;
     163       
     164        i8042_t *controller = dev->driver_data;
    166165       
    167166        const uint8_t status = IPC_GET_ARG1(*call);
     
    189188    int irq_mouse, ddf_dev_t *ddf_dev)
    190189{
    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         }
     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;
    213198       
    214199        dev->kbd_fun = ddf_fun_create(ddf_dev, fun_inner, "ps2a");
    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;
     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        }
    223208       
    224209        dev->aux_fun = ddf_fun_create(ddf_dev, fun_inner, "ps2b");
    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);
     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;
    236226       
    237227        buffer_init(&dev->kbd_buffer, dev->kbd_data, BUFFER_SIZE);
     
    239229        fibril_mutex_initialize(&dev->write_guard);
    240230       
    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;
     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));
    256238       
    257239        /* Disable kbd and aux */
     
    265247                (void) pio_read_8(&dev->regs->data);
    266248
     249        const size_t range_count = sizeof(i8042_ranges) /
     250            sizeof(irq_pio_range_t);
     251        irq_pio_range_t ranges[range_count];
    267252        memcpy(ranges, i8042_ranges, sizeof(i8042_ranges));
    268253        ranges[0].base = (uintptr_t) regs;
    269254
     255        const size_t cmd_count = sizeof(i8042_cmds) / sizeof(irq_cmd_t);
     256        irq_cmd_t cmds[cmd_count];
    270257        memcpy(cmds, i8042_cmds, sizeof(i8042_cmds));
    271258        cmds[0].addr = (void *) &(((i8042_regs_t *) regs)->status);
     
    279266        };
    280267       
    281         rc = register_interrupt_handler(ddf_dev, irq_kbd, i8042_irq_handler,
     268        ret = register_interrupt_handler(ddf_dev, irq_kbd, i8042_irq_handler,
    282269            &irq_code);
    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,
     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,
    290274            &irq_code);
    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         }
     275        CHECK_RET_UNBIND_DESTROY(ret, "Failed set handler for mouse: %s.",
     276            str_error(ret));
    296277       
    297278        /* Enable interrupts */
    298         async_sess_t *parent_sess = ddf_dev_parent_sess_get(ddf_dev);
    299         assert(parent_sess != NULL);
     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.");
    300284       
    301285        const bool enabled = hw_res_enable_interrupt(parent_sess);
    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         }
     286        async_hangup(parent_sess);
     287        ret = enabled ? EOK : EIO;
     288        CHECK_RET_UNBIND_DESTROY(ret, "Failed to enable interrupts: %s.");
    308289       
    309290        /* Enable port interrupts. */
     
    315296       
    316297        return EOK;
    317 error:
    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;
    328298}
    329299
     
    345315static int i8042_write(ddf_fun_t *fun, char *buffer, size_t size)
    346316{
    347         i8042_t *controller = dev_i8042(ddf_fun_get_dev(fun));
     317        assert(fun);
     318        assert(fun->driver_data);
     319       
     320        i8042_t *controller = fun->driver_data;
    348321        fibril_mutex_lock(&controller->write_guard);
    349322       
     
    374347static int i8042_read(ddf_fun_t *fun, char *data, size_t size)
    375348{
    376         i8042_t *controller = dev_i8042(ddf_fun_get_dev(fun));
     349        assert(fun);
     350        assert(fun->driver_data);
     351       
     352        i8042_t *controller = fun->driver_data;
    377353        buffer_t *buffer = (fun == controller->aux_fun) ?
    378354            &controller->aux_buffer : &controller->kbd_buffer;
Note: See TracChangeset for help on using the changeset viewer.