Changeset 132ab5d1 in mainline for uspace/drv/char/i8042/i8042.c


Ignore:
Timestamp:
2018-01-30T03:20:45Z (8 years ago)
Author:
Jenda <jenda.jzqk73@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
5a6cc679
Parents:
8bfb163 (diff), 6a5d05b (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 commit '6a5d05bd2551e64111bea4f9332dd7448c26ce84' into forwardport

Separate return value from error code in gen_irq_code*().

File:
1 edited

Legend:

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

    r8bfb163 r132ab5d1  
    22 * Copyright (c) 2001-2004 Jakub Jermar
    33 * Copyright (c) 2006 Josef Cejka
    4  * Copyright (c) 2014 Jiri Svoboda
     4 * Copyright (c) 2017 Jiri Svoboda
    55 * Copyright (c) 2011 Jan Vesely
    66 * All rights reserved.
     
    3939 */
    4040
     41#include <adt/circ_buf.h>
    4142#include <ddf/log.h>
    4243#include <ddf/interrupt.h>
     
    6768
    6869static void i8042_char_conn(ipc_callid_t, ipc_call_t *, void *);
    69 static int i8042_read(chardev_srv_t *, void *, size_t);
    70 static int i8042_write(chardev_srv_t *, const void *, size_t);
     70static int i8042_read(chardev_srv_t *, void *, size_t, size_t *);
     71static int i8042_write(chardev_srv_t *, const void *, size_t, size_t *);
    7172
    7273static chardev_ops_t i8042_chardev_ops = {
     
    121122 * Write new data to the corresponding buffer.
    122123 *
    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_callid_t iid, ipc_call_t *call,
    129     ddf_dev_t *dev)
     128static void i8042_irq_handler(ipc_call_t *call, ddf_dev_t *dev)
    130129{
    131130        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         buffer_t *buffer = (status & i8042_AUX_DATA) ?
    137             &controller->aux_buffer : &controller->kbd_buffer;
    138        
    139         buffer_write(buffer, data);
     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);
    140147}
    141148
     
    159166        const size_t cmd_count = sizeof(i8042_cmds) / sizeof(irq_cmd_t);
    160167        irq_cmd_t cmds[cmd_count];
     168        ddf_fun_t *kbd_fun;
     169        ddf_fun_t *aux_fun;
    161170        i8042_regs_t *ar;
    162 
     171       
    163172        int rc;
    164173        bool kbd_bound = false;
    165174        bool aux_bound = false;
    166 
    167         dev->kbd_fun = NULL;
    168         dev->aux_fun = NULL;
    169175       
    170176        if (regs->size < sizeof(i8042_regs_t)) {
     
    178184        }
    179185       
    180         dev->kbd_fun = ddf_fun_create(ddf_dev, fun_inner, "ps2a");
    181         if (dev->kbd_fun == NULL) {
     186        kbd_fun = ddf_fun_create(ddf_dev, fun_inner, "ps2a");
     187        if (kbd_fun == NULL) {
    182188                rc = ENOMEM;
    183189                goto error;
    184190        };
    185191       
    186         dev->kbd = ddf_fun_data_alloc(dev->kbd_fun, sizeof(i8042_port_t));
     192        dev->kbd = ddf_fun_data_alloc(kbd_fun, sizeof(i8042_port_t));
    187193        if (dev->kbd == NULL) {
    188194                rc = ENOMEM;
     
    190196        }
    191197       
     198        dev->kbd->fun = kbd_fun;
    192199        dev->kbd->ctl = dev;
    193200        chardev_srvs_init(&dev->kbd->cds);
    194201        dev->kbd->cds.ops = &i8042_chardev_ops;
    195202        dev->kbd->cds.sarg = dev->kbd;
    196        
    197         rc = ddf_fun_add_match_id(dev->kbd_fun, "char/xtkbd", 90);
     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);
    198207        if (rc != EOK)
    199208                goto error;
    200209       
    201         dev->aux_fun = ddf_fun_create(ddf_dev, fun_inner, "ps2b");
    202         if (dev->aux_fun == NULL) {
     210        aux_fun = ddf_fun_create(ddf_dev, fun_inner, "ps2b");
     211        if (aux_fun == NULL) {
    203212                rc = ENOMEM;
    204213                goto error;
    205214        }
    206215       
    207         dev->aux = ddf_fun_data_alloc(dev->aux_fun, sizeof(i8042_port_t));
     216        dev->aux = ddf_fun_data_alloc(aux_fun, sizeof(i8042_port_t));
    208217        if (dev->aux == NULL) {
    209218                rc = ENOMEM;
     
    211220        }
    212221       
     222        dev->aux->fun = aux_fun;
    213223        dev->aux->ctl = dev;
    214224        chardev_srvs_init(&dev->aux->cds);
    215225        dev->aux->cds.ops = &i8042_chardev_ops;
    216226        dev->aux->cds.sarg = dev->aux;
    217        
    218         rc = ddf_fun_add_match_id(dev->aux_fun, "char/ps2mouse", 90);
     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);
    219231        if (rc != EOK)
    220232                goto error;
    221233       
    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);
     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);
    227239        fibril_mutex_initialize(&dev->write_guard);
    228240       
    229         rc = ddf_fun_bind(dev->kbd_fun);
     241        rc = ddf_fun_bind(dev->kbd->fun);
    230242        if (rc != EOK) {
    231243                ddf_msg(LVL_ERROR, "Failed to bind keyboard function: %s.",
    232                     ddf_fun_get_name(dev->kbd_fun));
     244                    ddf_fun_get_name(dev->kbd->fun));
    233245                goto error;
    234246        }
    235247        kbd_bound = true;
    236248       
    237         rc = ddf_fun_bind(dev->aux_fun);
     249        rc = ddf_fun_bind(dev->aux->fun);
    238250        if (rc != EOK) {
    239251                ddf_msg(LVL_ERROR, "Failed to bind aux function: %s.",
    240                     ddf_fun_get_name(dev->aux_fun));
     252                    ddf_fun_get_name(dev->aux->fun));
    241253                goto error;
    242254        }
     
    269281        };
    270282       
    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;
     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) {
    275287                ddf_msg(LVL_ERROR, "Failed set handler for kbd: %s.",
    276288                    ddf_dev_get_name(ddf_dev));
     
    278290        }
    279291       
    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;
     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) {
    284296                ddf_msg(LVL_ERROR, "Failed set handler for mouse: %s.",
    285297                    ddf_dev_get_name(ddf_dev));
     
    317329error:
    318330        if (kbd_bound)
    319                 ddf_fun_unbind(dev->kbd_fun);
     331                ddf_fun_unbind(dev->kbd->fun);
    320332        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);
     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);
    326338
    327339        return rc;
     
    333345 * @param buffer Data source
    334346 * @param size   Data size
    335  *
    336  * @return Bytes written.
    337  *
    338  */
    339 static int i8042_write(chardev_srv_t *srv, const void *data, size_t 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 */
     352static int i8042_write(chardev_srv_t *srv, const void *data, size_t size,
     353    size_t *nwr)
    340354{
    341355        i8042_port_t *port = (i8042_port_t *)srv->srvs->sarg;
     
    357371       
    358372        fibril_mutex_unlock(&i8042->write_guard);
    359         return size;
     373        *nwr = size;
     374        return EOK;
    360375}
    361376
     
    365380 * @param buffer Data place
    366381 * @param size   Data place size
    367  *
    368  * @return Bytes read.
    369  *
    370  */
    371 static int i8042_read(chardev_srv_t *srv, void *dest, size_t 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 */
     387static int i8042_read(chardev_srv_t *srv, void *dest, size_t size,
     388    size_t *nread)
    372389{
    373390        i8042_port_t *port = (i8042_port_t *)srv->srvs->sarg;
    374         i8042_t *i8042 = port->ctl;
     391        size_t p;
    375392        uint8_t *destp = (uint8_t *)dest;
    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;
     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;
    384412}
    385413
Note: See TracChangeset for help on using the changeset viewer.