Changeset a8f7029 in mainline


Ignore:
Timestamp:
2011-12-25T21:39:52Z (13 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
e747303
Parents:
b1f44b4
Message:

i8042: Implement char device interfaces.

Location:
uspace/drv/char/i8042
Files:
2 edited

Legend:

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

    rb1f44b4 ra8f7029  
    5151#include <ddf/interrupt.h>
    5252
     53#include <ops/char_dev.h>
     54
    5355#include "i8042.h"
    5456
    5557#define NAME       "i8042"
     58
     59static int i8042_write_kbd(ddf_fun_t *, char *, size_t);
     60static int i8042_read_kbd(ddf_fun_t *, char *, size_t);
     61static int i8042_write_aux(ddf_fun_t *, char *, size_t);
     62static int i8042_read_aux(ddf_fun_t *, char *, size_t);
     63
     64static char_dev_ops_t kbd_iface = {
     65    .read = i8042_read_kbd,
     66    .write = i8042_write_kbd,
     67};
     68
     69static char_dev_ops_t aux_iface = {
     70    .read = i8042_read_aux,
     71    .write = i8042_write_aux,
     72};
     73
     74static ddf_dev_ops_t kbd_ops = {
     75        .interfaces[CHAR_DEV_IFACE] = &kbd_iface
     76};
     77
     78static ddf_dev_ops_t aux_ops = {
     79        .interfaces[CHAR_DEV_IFACE] = &aux_iface
     80};
    5681
    5782/* Interesting bits for status register */
     
    6994#define i8042_KBD_DISABLE       0x10
    7095#define i8042_AUX_DISABLE       0x20
    71 #define i8042_KBD_TRANSLATE     0x40
     96#define i8042_KBD_TRANSLATE     0x40 /* Use this to switch to XT scancodes */
    7297
    7398static const irq_cmd_t i8042_cmds[] = {
     
    97122        }
    98123};
    99 
     124/*----------------------------------------------------------------------------*/
    100125static void wait_ready(i8042_t *dev)
    101126{
     
    103128        while (pio_read_8(&dev->regs->status) & i8042_INPUT_FULL);
    104129}
    105 
     130/*----------------------------------------------------------------------------*/
     131static void wait_ready_write(i8042_t *dev)
     132{
     133        assert(dev);
     134        while (pio_read_8(&dev->regs->status) & i8042_OUTPUT_FULL);
     135}
     136/*----------------------------------------------------------------------------*/
    106137static void i8042_irq_handler(
    107138    ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call)
    108139{
    109 
    110         const int status = IPC_GET_ARG1(*call);
    111         const int data = IPC_GET_ARG2(*call);
    112         const int devid = (status & i8042_AUX_DATA) ? DEVID_AUX : DEVID_PRI;
    113         ddf_msg(LVL_WARN, "Unhandled %s data: %x , status: %x.",
    114             (devid == DEVID_AUX) ? "AUX" : "PRIMARY", data, status);
    115 #if 0
    116140        if (!dev || !dev->driver_data)
    117141                return;
    118 
    119         if (device.port[devid].client_sess != NULL) {
    120                 async_exch_t *exch =
    121                     async_exchange_begin(device.port[devid].client_sess);
    122                 if (exch) {
    123                         async_msg_1(exch, IPC_FIRST_USER_METHOD, data);
    124                         async_exchange_end(exch);
    125                 }
     142        i8042_t *controller = dev->driver_data;
     143        fibril_mutex_lock(&controller->guard);
     144
     145        const uint8_t status = IPC_GET_ARG1(*call);
     146        const uint8_t data = IPC_GET_ARG2(*call);
     147        char ** buffer = (status & i8042_AUX_DATA) ?
     148            &controller->aux_buffer : &controller->kbd_buffer;
     149        char * buffer_end = (status & i8042_AUX_DATA) ?
     150            controller->aux_buffer_end : controller->kbd_buffer_end;
     151        if (*buffer != NULL && *buffer < buffer_end) {
     152                *(*buffer)++ = data;
     153                if (*buffer == buffer_end)
     154                        fibril_condvar_signal(&controller->data_avail);
    126155        } else {
    127                 ddf_msg(LVL_WARN, "No client session.\n");
    128         }
    129 #endif
     156                ddf_msg(LVL_WARN, "Unhandled %s data: %x , status: %x.",
     157                    (status & i8042_AUX_DATA) ? "AUX" : "KBD", data, status);
     158        }
     159
     160        fibril_mutex_unlock(&controller->guard);
    130161}
    131162/*----------------------------------------------------------------------------*/
     
    151182                return ENOMEM;
    152183        }
     184
     185        dev->kbd_fun->ops = &kbd_ops;
     186        dev->mouse_fun->ops = &aux_ops;
     187        dev->kbd_fun->driver_data = dev;
     188        dev->mouse_fun->driver_data = dev;
     189
     190        fibril_mutex_initialize(&dev->guard);
     191        fibril_condvar_initialize(&dev->data_avail);
     192        dev->kbd_buffer = NULL;
     193        dev->kbd_buffer_end = NULL;
     194        dev->aux_buffer = NULL;
     195        dev->aux_buffer_end = NULL;
    153196
    154197#define CHECK_RET_DESTROY(ret, msg...) \
     
    215258            "Failed set handler for mouse: %s.\n", str_error(ret));
    216259
    217 #if 0
    218         ret = ddf_fun_add_to_category(dev->kbd_fun, "keyboard");
    219         if (ret != EOK)
    220                 ddf_msg(LVL_WARN, "Failed to register kbd fun to category.\n");
    221         ret = ddf_fun_add_to_category(dev->mouse_fun, "mouse");
    222         if (ret != EOK)
    223                 ddf_msg(LVL_WARN, "Failed to register mouse fun to category.\n");
    224 #endif
    225260        /* Enable interrupts */
    226261        async_sess_t *parent_sess =
     
    229264        ret = parent_sess ? EOK : ENOMEM;
    230265        CHECK_RET_UNBIND_DESTROY(ret, "Failed to create parent connection.\n");
     266
    231267        const bool enabled = hw_res_enable_interrupt(parent_sess);
    232268        async_hangup(parent_sess);
     
    243279        return EOK;
    244280}
     281/*----------------------------------------------------------------------------*/
     282static int i8042_write_kbd(ddf_fun_t *fun, char *buffer, size_t size)
     283{
     284        assert(fun);
     285        assert(fun->driver_data);
     286        i8042_t *controller = fun->driver_data;
     287        fibril_mutex_lock(&controller->guard);
     288        for (size_t i = 0; i < size; ++i) {
     289                wait_ready_write(controller);
     290                pio_write_8(&controller->regs->data, buffer[i]);
     291        }
     292        fibril_mutex_unlock(&controller->guard);
     293        return EOK;
     294}
     295/*----------------------------------------------------------------------------*/
     296static int i8042_read_kbd(ddf_fun_t *fun, char *buffer, size_t size)
     297{
     298        assert(fun);
     299        assert(fun->driver_data);
     300        bzero(buffer, size);
     301
     302        i8042_t *controller = fun->driver_data;
     303        fibril_mutex_lock(&controller->guard);
     304        /* There is someone else reading from the device. */
     305        if (controller->kbd_buffer) {
     306                fibril_mutex_unlock(&controller->guard);
     307                return EBUSY;
     308        }
     309        controller->kbd_buffer = buffer;
     310        controller->kbd_buffer_end = buffer + size;
     311        /* Wait for buffer to be filled */
     312        while (controller->kbd_buffer != controller->kbd_buffer_end)
     313                fibril_condvar_wait(
     314                    &controller->data_avail, &controller->guard);
     315
     316        controller->kbd_buffer = NULL;
     317        controller->kbd_buffer_end = NULL;
     318        fibril_mutex_unlock(&controller->guard);
     319        return EOK;
     320}
     321/*----------------------------------------------------------------------------*/
     322static int i8042_write_aux(ddf_fun_t *fun, char *buffer, size_t size)
     323{
     324        assert(fun);
     325        assert(fun->driver_data);
     326        i8042_t *controller = fun->driver_data;
     327        fibril_mutex_lock(&controller->guard);
     328        for (size_t i = 0; i < size; ++i) {
     329                wait_ready_write(controller);
     330                pio_write_8(&controller->regs->status, i8042_CMD_WRITE_AUX);
     331                pio_write_8(&controller->regs->data, buffer[i]);
     332        }
     333        fibril_mutex_unlock(&controller->guard);
     334        return EOK;
     335}
     336/*----------------------------------------------------------------------------*/
     337static int i8042_read_aux(ddf_fun_t *fun, char *buffer, size_t size)
     338{
     339        assert(fun);
     340        assert(fun->driver_data);
     341        bzero(buffer, size);
     342
     343        i8042_t *controller = fun->driver_data;
     344        fibril_mutex_lock(&controller->guard);
     345        /* There is someone else reading from the device. */
     346        if (controller->aux_buffer) {
     347                fibril_mutex_unlock(&controller->guard);
     348                return EBUSY;
     349        }
     350        controller->aux_buffer = buffer;
     351        controller->aux_buffer_end = buffer + size;
     352        /* Wait for buffer to be filled */
     353        while (controller->aux_buffer != controller->aux_buffer_end)
     354                fibril_condvar_wait(
     355                    &controller->data_avail, &controller->guard);
     356
     357        controller->aux_buffer = NULL;
     358        controller->aux_buffer_end = NULL;
     359        fibril_mutex_unlock(&controller->guard);
     360        return EOK;
     361}
     362/*----------------------------------------------------------------------------*/
    245363
    246364/** Character device connection handler */
  • uspace/drv/char/i8042/i8042.h

    rb1f44b4 ra8f7029  
    7373        ddf_fun_t *kbd_fun;
    7474        ddf_fun_t *mouse_fun;
     75        char * kbd_buffer;
     76        char * kbd_buffer_end;
     77        char * aux_buffer;
     78        char * aux_buffer_end;
    7579        fibril_mutex_t guard;
    7680        fibril_condvar_t data_avail;
     
    7882
    7983int i8042_init(i8042_t *, void *, size_t, int, int, ddf_dev_t *);
    80 int i8042_write_kbd(i8042_t *, uint8_t);
    81 int i8042_read_kbd(i8042_t *, uint8_t *);
    82 int i8042_write_aux(i8042_t *, uint8_t);
    83 int i8042_read_aux(i8042_t *, uint8_t *);
    84 
    8584#endif
    8685/**
Note: See TracChangeset for help on using the changeset viewer.