Ignore:
File:
1 edited

Legend:

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

    r071a1ddb rcccd60c3  
    22 * Copyright (c) 2001-2004 Jakub Jermar
    33 * Copyright (c) 2006 Josef Cejka
    4  * Copyright (c) 2017 Jiri Svoboda
     4 * Copyright (c) 2014 Jiri Svoboda
    55 * Copyright (c) 2011 Jan Vesely
    66 * All rights reserved.
     
    3939 */
    4040
    41 #include <adt/circ_buf.h>
    4241#include <ddf/log.h>
    4342#include <ddf/interrupt.h>
     
    6867
    6968static void i8042_char_conn(ipc_callid_t, ipc_call_t *, void *);
    70 static int i8042_read(chardev_srv_t *, void *, size_t, size_t *);
    71 static int i8042_write(chardev_srv_t *, const void *, size_t, size_t *);
     69static int i8042_read(chardev_srv_t *, void *, size_t);
     70static int i8042_write(chardev_srv_t *, const void *, size_t);
    7271
    7372static chardev_ops_t i8042_chardev_ops = {
     
    122121 * Write new data to the corresponding buffer.
    123122 *
     123 * @param iid  Call id.
    124124 * @param call pointerr to call data.
    125125 * @param dev  Device that caued the interrupt.
    126126 *
    127127 */
    128 static void i8042_irq_handler(ipc_call_t *call, ddf_dev_t *dev)
     128static void i8042_irq_handler(ipc_callid_t iid, ipc_call_t *call,
     129    ddf_dev_t *dev)
    129130{
    130131        i8042_t *controller = ddf_dev_data_get(dev);
    131         int rc;
    132132       
    133133        const uint8_t status = IPC_GET_ARG1(*call);
    134134        const uint8_t data = IPC_GET_ARG2(*call);
    135135       
    136         i8042_port_t *port = (status & i8042_AUX_DATA) ?
    137             controller->aux : controller->kbd;
    138        
    139         fibril_mutex_lock(&port->buf_lock);
    140        
    141         rc = circ_buf_push(&port->cbuf, &data);
    142         if (rc != EOK)
    143                 ddf_msg(LVL_ERROR, "Buffer overrun");
    144 
    145         fibril_mutex_unlock(&port->buf_lock);
    146         fibril_condvar_broadcast(&port->buf_cv);
     136        buffer_t *buffer = (status & i8042_AUX_DATA) ?
     137            &controller->aux_buffer : &controller->kbd_buffer;
     138       
     139        buffer_write(buffer, data);
    147140}
    148141
     
    166159        const size_t cmd_count = sizeof(i8042_cmds) / sizeof(irq_cmd_t);
    167160        irq_cmd_t cmds[cmd_count];
    168         ddf_fun_t *kbd_fun;
    169         ddf_fun_t *aux_fun;
    170161        i8042_regs_t *ar;
    171        
     162
    172163        int rc;
    173164        bool kbd_bound = false;
    174165        bool aux_bound = false;
     166
     167        dev->kbd_fun = NULL;
     168        dev->aux_fun = NULL;
    175169       
    176170        if (regs->size < sizeof(i8042_regs_t)) {
     
    184178        }
    185179       
    186         kbd_fun = ddf_fun_create(ddf_dev, fun_inner, "ps2a");
    187         if (kbd_fun == NULL) {
     180        dev->kbd_fun = ddf_fun_create(ddf_dev, fun_inner, "ps2a");
     181        if (dev->kbd_fun == NULL) {
    188182                rc = ENOMEM;
    189183                goto error;
    190184        };
    191185       
    192         dev->kbd = ddf_fun_data_alloc(kbd_fun, sizeof(i8042_port_t));
     186        dev->kbd = ddf_fun_data_alloc(dev->kbd_fun, sizeof(i8042_port_t));
    193187        if (dev->kbd == NULL) {
    194188                rc = ENOMEM;
     
    196190        }
    197191       
    198         dev->kbd->fun = kbd_fun;
    199192        dev->kbd->ctl = dev;
    200193        chardev_srvs_init(&dev->kbd->cds);
    201194        dev->kbd->cds.ops = &i8042_chardev_ops;
    202195        dev->kbd->cds.sarg = dev->kbd;
    203         fibril_mutex_initialize(&dev->kbd->buf_lock);
    204         fibril_condvar_initialize(&dev->kbd->buf_cv);
    205        
    206         rc = ddf_fun_add_match_id(dev->kbd->fun, "char/xtkbd", 90);
     196       
     197        rc = ddf_fun_add_match_id(dev->kbd_fun, "char/xtkbd", 90);
    207198        if (rc != EOK)
    208199                goto error;
    209200       
    210         aux_fun = ddf_fun_create(ddf_dev, fun_inner, "ps2b");
    211         if (aux_fun == NULL) {
     201        dev->aux_fun = ddf_fun_create(ddf_dev, fun_inner, "ps2b");
     202        if (dev->aux_fun == NULL) {
    212203                rc = ENOMEM;
    213204                goto error;
    214205        }
    215206       
    216         dev->aux = ddf_fun_data_alloc(aux_fun, sizeof(i8042_port_t));
     207        dev->aux = ddf_fun_data_alloc(dev->aux_fun, sizeof(i8042_port_t));
    217208        if (dev->aux == NULL) {
    218209                rc = ENOMEM;
     
    220211        }
    221212       
    222         dev->aux->fun = aux_fun;
    223213        dev->aux->ctl = dev;
    224214        chardev_srvs_init(&dev->aux->cds);
    225215        dev->aux->cds.ops = &i8042_chardev_ops;
    226216        dev->aux->cds.sarg = dev->aux;
    227         fibril_mutex_initialize(&dev->aux->buf_lock);
    228         fibril_condvar_initialize(&dev->aux->buf_cv);
    229        
    230         rc = ddf_fun_add_match_id(dev->aux->fun, "char/ps2mouse", 90);
     217       
     218        rc = ddf_fun_add_match_id(dev->aux_fun, "char/ps2mouse", 90);
    231219        if (rc != EOK)
    232220                goto error;
    233221       
    234         ddf_fun_set_conn_handler(dev->kbd->fun, i8042_char_conn);
    235         ddf_fun_set_conn_handler(dev->aux->fun, i8042_char_conn);
    236        
    237         circ_buf_init(&dev->kbd->cbuf, dev->kbd->buf_data, BUFFER_SIZE, 1);
    238         circ_buf_init(&dev->aux->cbuf, dev->aux->buf_data, BUFFER_SIZE, 1);
     222        ddf_fun_set_conn_handler(dev->kbd_fun, i8042_char_conn);
     223        ddf_fun_set_conn_handler(dev->aux_fun, i8042_char_conn);
     224       
     225        buffer_init(&dev->kbd_buffer, dev->kbd_data, BUFFER_SIZE);
     226        buffer_init(&dev->aux_buffer, dev->aux_data, BUFFER_SIZE);
    239227        fibril_mutex_initialize(&dev->write_guard);
    240228       
    241         rc = ddf_fun_bind(dev->kbd->fun);
     229        rc = ddf_fun_bind(dev->kbd_fun);
    242230        if (rc != EOK) {
    243231                ddf_msg(LVL_ERROR, "Failed to bind keyboard function: %s.",
    244                     ddf_fun_get_name(dev->kbd->fun));
     232                    ddf_fun_get_name(dev->kbd_fun));
    245233                goto error;
    246234        }
    247235        kbd_bound = true;
    248236       
    249         rc = ddf_fun_bind(dev->aux->fun);
     237        rc = ddf_fun_bind(dev->aux_fun);
    250238        if (rc != EOK) {
    251239                ddf_msg(LVL_ERROR, "Failed to bind aux function: %s.",
    252                     ddf_fun_get_name(dev->aux->fun));
     240                    ddf_fun_get_name(dev->aux_fun));
    253241                goto error;
    254242        }
     
    281269        };
    282270       
    283         int irq_kbd_cap;
    284         rc = register_interrupt_handler(ddf_dev, irq_kbd,
    285             i8042_irq_handler, &irq_code, &irq_kbd_cap);
    286         if (rc != EOK) {
     271        const int irq_kbd_cap = register_interrupt_handler(ddf_dev, irq_kbd,
     272            i8042_irq_handler, &irq_code);
     273        if (irq_kbd_cap < 0) {
     274                rc = irq_kbd_cap;
    287275                ddf_msg(LVL_ERROR, "Failed set handler for kbd: %s.",
    288276                    ddf_dev_get_name(ddf_dev));
     
    290278        }
    291279       
    292         int irq_mouse_cap;
    293         rc = register_interrupt_handler(ddf_dev, irq_mouse,
    294             i8042_irq_handler, &irq_code, &irq_mouse_cap);
    295         if (rc != EOK) {
     280        const int irq_mouse_cap = register_interrupt_handler(ddf_dev, irq_mouse,
     281            i8042_irq_handler, &irq_code);
     282        if (irq_mouse_cap < 0) {
     283                rc = irq_mouse_cap;
    296284                ddf_msg(LVL_ERROR, "Failed set handler for mouse: %s.",
    297285                    ddf_dev_get_name(ddf_dev));
     
    329317error:
    330318        if (kbd_bound)
    331                 ddf_fun_unbind(dev->kbd->fun);
     319                ddf_fun_unbind(dev->kbd_fun);
    332320        if (aux_bound)
    333                 ddf_fun_unbind(dev->aux->fun);
    334         if (dev->kbd->fun != NULL)
    335                 ddf_fun_destroy(dev->kbd->fun);
    336         if (dev->aux->fun != NULL)
    337                 ddf_fun_destroy(dev->aux->fun);
     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);
    338326
    339327        return rc;
     
    345333 * @param buffer Data source
    346334 * @param size   Data size
    347  * @param nwr    Place to store number of bytes successfully written
    348  *
    349  * @return EOK on success or non-zero error code
    350  *
    351  */
    352 static int i8042_write(chardev_srv_t *srv, const void *data, size_t size,
    353     size_t *nwr)
     335 *
     336 * @return Bytes written.
     337 *
     338 */
     339static int i8042_write(chardev_srv_t *srv, const void *data, size_t size)
    354340{
    355341        i8042_port_t *port = (i8042_port_t *)srv->srvs->sarg;
     
    371357       
    372358        fibril_mutex_unlock(&i8042->write_guard);
    373         *nwr = size;
    374         return EOK;
     359        return size;
    375360}
    376361
     
    380365 * @param buffer Data place
    381366 * @param size   Data place size
    382  * @param nread  Place to store number of bytes successfully read
    383  *
    384  * @return EOK on success or non-zero error code
    385  *
    386  */
    387 static int i8042_read(chardev_srv_t *srv, void *dest, size_t size,
    388     size_t *nread)
     367 *
     368 * @return Bytes read.
     369 *
     370 */
     371static int i8042_read(chardev_srv_t *srv, void *dest, size_t size)
    389372{
    390373        i8042_port_t *port = (i8042_port_t *)srv->srvs->sarg;
    391         size_t p;
     374        i8042_t *i8042 = port->ctl;
    392375        uint8_t *destp = (uint8_t *)dest;
    393         int rc;
    394        
    395         fibril_mutex_lock(&port->buf_lock);
    396        
    397         while (circ_buf_nused(&port->cbuf) == 0)
    398                 fibril_condvar_wait(&port->buf_cv, &port->buf_lock);
    399 
    400         p = 0;
    401         while (p < size) {
    402                 rc = circ_buf_pop(&port->cbuf, &destp[p]);
    403                 if (rc != EOK)
    404                         break;
    405                 ++p;
    406         }
    407 
    408         fibril_mutex_unlock(&port->buf_lock);
    409 
    410         *nread = p;
    411         return EOK;
     376       
     377        buffer_t *buffer = (port == i8042->aux) ?
     378            &i8042->aux_buffer : &i8042->kbd_buffer;
     379       
     380        for (size_t i = 0; i < size; ++i)
     381                *destp++ = buffer_read(buffer);
     382       
     383        return size;
    412384}
    413385
Note: See TracChangeset for help on using the changeset viewer.