Changeset 7a6065c in mainline


Ignore:
Timestamp:
2017-11-23T11:56:31Z (6 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
221176c1
Parents:
74017ce
git-author:
Jiri Svoboda <jiri@…> (2017-11-22 19:55:36)
git-committer:
Jiri Svoboda <jiri@…> (2017-11-23 11:56:31)
Message:

Convert ipc/char.h users to chardev.

Location:
uspace
Files:
3 added
11 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/char/msim-con/msim-con.c

    r74017ce r7a6065c  
    3737#include <ddi.h>
    3838#include <errno.h>
    39 #include <ipc/char.h>
     39#include <io/chardev_srv.h>
    4040
    4141#include "msim-con.h"
    4242
    4343static void msim_con_connection(ipc_callid_t, ipc_call_t *, void *);
     44
     45static int msim_con_read(chardev_srv_t *, void *, size_t, size_t *);
     46static int msim_con_write(chardev_srv_t *, const void *, size_t, size_t *);
     47
     48static chardev_ops_t msim_con_chardev_ops = {
     49        .read = msim_con_read,
     50        .write = msim_con_write
     51};
    4452
    4553static irq_cmd_t msim_cmds_proto[] = {
     
    5866        msim_con_t *con = (msim_con_t *) arg;
    5967        uint8_t c;
     68        int rc;
     69
     70        fibril_mutex_lock(&con->buf_lock);
    6071
    6172        c = IPC_GET_ARG2(*call);
    62 
    63         if (con->client_sess != NULL) {
    64                 async_exch_t *exch = async_exchange_begin(con->client_sess);
    65                 async_msg_1(exch, CHAR_NOTIF_BYTE, c);
    66                 async_exchange_end(exch);
    67         }
     73        rc = circ_buf_push(&con->cbuf, &c);
     74        if (rc != EOK)
     75                ddf_msg(LVL_ERROR, "Buffer overrun");
     76
     77        fibril_mutex_unlock(&con->buf_lock);
     78        fibril_condvar_broadcast(&con->buf_cv);
    6879}
    6980
     
    7586        irq_cmd_t *msim_cmds = NULL;
    7687        int rc;
     88
     89        circ_buf_init(&con->cbuf, con->buf, msim_con_buf_size, 1);
     90        fibril_mutex_initialize(&con->buf_lock);
     91        fibril_condvar_initialize(&con->buf_cv);
    7792
    7893        msim_cmds = malloc(sizeof(msim_cmds_proto));
     
    106121        async_irq_subscribe(res->irq, msim_irq_handler, con, &con->irq_code);
    107122        subscribed = true;
     123
     124        chardev_srvs_init(&con->cds);
     125        con->cds.ops = &msim_con_chardev_ops;
     126        con->cds.sarg = con;
    108127
    109128        rc = ddf_fun_bind(fun);
     
    140159}
    141160
     161/** Read from msim console device */
     162static int msim_con_read(chardev_srv_t *srv, void *buf, size_t size,
     163    size_t *nread)
     164{
     165        msim_con_t *con = (msim_con_t *) srv->srvs->sarg;
     166        size_t p;
     167        uint8_t *bp = (uint8_t *) buf;
     168        int rc;
     169
     170        fibril_mutex_lock(&con->buf_lock);
     171
     172        while (circ_buf_nused(&con->cbuf) == 0)
     173                fibril_condvar_wait(&con->buf_cv, &con->buf_lock);
     174
     175        p = 0;
     176        while (p < size) {
     177                rc = circ_buf_pop(&con->cbuf, &bp[p]);
     178                if (rc != EOK)
     179                        break;
     180                ++p;
     181        }
     182
     183        fibril_mutex_unlock(&con->buf_lock);
     184
     185        *nread = p;
     186        return EOK;
     187}
     188
     189/** Write to msim console device */
     190static int msim_con_write(chardev_srv_t *srv, const void *data, size_t size,
     191    size_t *nwr)
     192{
     193        msim_con_t *con = (msim_con_t *) srv->srvs->sarg;
     194        size_t i;
     195        uint8_t *dp = (uint8_t *) data;
     196
     197        for (i = 0; i < size; i++)
     198                msim_con_putchar(con, dp[i]);
     199
     200        *nwr = size;
     201        return EOK;
     202}
     203
    142204/** Character device connection handler. */
    143205static void msim_con_connection(ipc_callid_t iid, ipc_call_t *icall,
    144206    void *arg)
    145207{
    146         msim_con_t *con;
    147 
    148         /* Answer the IPC_M_CONNECT_ME_TO call. */
    149         async_answer_0(iid, EOK);
    150 
    151         con = (msim_con_t *)ddf_dev_data_get(ddf_fun_get_dev((ddf_fun_t *)arg));
    152 
    153         while (true) {
    154                 ipc_call_t call;
    155                 ipc_callid_t callid = async_get_call(&call);
    156                 sysarg_t method = IPC_GET_IMETHOD(call);
    157 
    158                 if (!method) {
    159                         /* The other side has hung up. */
    160                         async_answer_0(callid, EOK);
    161                         return;
    162                 }
    163 
    164                 async_sess_t *sess =
    165                     async_callback_receive_start(EXCHANGE_SERIALIZE, &call);
    166                 if (sess != NULL) {
    167                         if (con->client_sess == NULL) {
    168                                 con->client_sess = sess;
    169                                 async_answer_0(callid, EOK);
    170                         } else
    171                                 async_answer_0(callid, ELIMIT);
    172                 } else {
    173                         switch (method) {
    174                         case CHAR_WRITE_BYTE:
    175                                 ddf_msg(LVL_DEBUG, "Write %" PRIun " to device\n",
    176                                     IPC_GET_ARG1(call));
    177                                 msim_con_putchar(con, (uint8_t) IPC_GET_ARG1(call));
    178                                 async_answer_0(callid, EOK);
    179                                 break;
    180                         default:
    181                                 async_answer_0(callid, EINVAL);
    182                         }
    183                 }
    184         }
     208        msim_con_t *con = (msim_con_t *) ddf_dev_data_get(
     209            ddf_fun_get_dev((ddf_fun_t *) arg));
     210
     211        chardev_conn(iid, icall, &con->cds);
    185212}
    186213
  • uspace/drv/char/msim-con/msim-con.h

    r74017ce r7a6065c  
    3636#define MSIM_CON_H
    3737
     38#include <adt/circ_buf.h>
    3839#include <async.h>
    3940#include <ddf/driver.h>
     41#include <fibril_synch.h>
     42#include <io/chardev_srv.h>
    4043#include <loc.h>
    4144#include <stdint.h>
     45
     46enum {
     47        msim_con_buf_size = 64
     48};
    4249
    4350/** MSIM console resources */
     
    5158        async_sess_t *client_sess;
    5259        ddf_dev_t *dev;
     60        chardev_srvs_t cds;
    5361        msim_con_res_t res;
    5462        irq_pio_range_t irq_range[1];
    5563        irq_code_t irq_code;
     64        circ_buf_t cbuf;
     65        uint8_t buf[msim_con_buf_size];
     66        fibril_mutex_t buf_lock;
     67        fibril_condvar_t buf_cv;
    5668} msim_con_t;
    5769
  • uspace/drv/char/ski-con/ski-con.c

    r74017ce r7a6065c  
    11/*
    22 * Copyright (c) 2005 Jakub Jermar
    3  * Copyright (c) 2011 Jiri Svoboda
     3 * Copyright (c) 2017 Jiri Svoboda
    44 * All rights reserved.
    55 *
     
    3434#include <ddf/log.h>
    3535#include <errno.h>
    36 #include <ipc/char.h>
     36#include <fibril.h>
     37#include <io/chardev.h>
    3738#include <stdint.h>
    3839#include <stdlib.h>
    39 #include <thread.h>
    4040#include <stdbool.h>
    4141
     
    4646#define POLL_INTERVAL           10000
    4747
    48 static void ski_con_thread_impl(void *arg);
     48static int ski_con_fibril(void *arg);
    4949static int32_t ski_con_getchar(void);
    5050static void ski_con_connection(ipc_callid_t, ipc_call_t *, void *);
    5151
     52static int ski_con_read(chardev_srv_t *, void *, size_t, size_t *);
     53static int ski_con_write(chardev_srv_t *, const void *, size_t, size_t *);
     54
     55static chardev_ops_t ski_con_chardev_ops = {
     56        .read = ski_con_read,
     57        .write = ski_con_write
     58};
     59
    5260/** Add ski console device. */
    5361int ski_con_add(ski_con_t *con)
    5462{
    55         thread_id_t tid;
     63        fid_t fid;
    5664        ddf_fun_t *fun = NULL;
    5765        bool bound = false;
    5866        int rc;
     67
     68        circ_buf_init(&con->cbuf, con->buf, ski_con_buf_size, 1);
     69        fibril_mutex_initialize(&con->buf_lock);
     70        fibril_condvar_initialize(&con->buf_cv);
    5971
    6072        fun = ddf_fun_create(con->dev, fun_exposed, "a");
     
    6779        ddf_fun_set_conn_handler(fun, ski_con_connection);
    6880
     81        chardev_srvs_init(&con->cds);
     82        con->cds.ops = &ski_con_chardev_ops;
     83        con->cds.sarg = con;
     84
    6985        rc = ddf_fun_bind(fun);
    7086        if (rc != EOK) {
     
    7591        bound = true;
    7692
    77         rc = thread_create(ski_con_thread_impl, con, "kbd_poll", &tid);
    78         if (rc != 0) {
    79                 return rc;
    80         }
    81 
     93        fid = fibril_create(ski_con_fibril, con);
     94        if (fid == 0) {
     95                ddf_msg(LVL_ERROR, "Error creating fibril.");
     96                rc = ENOMEM;
     97                goto error;
     98        }
     99
     100        fibril_add_ready(fid);
    82101        return EOK;
    83102error:
     
    102121}
    103122
    104 /** Thread to poll Ski for keypresses. */
    105 static void ski_con_thread_impl(void *arg)
     123/** Poll Ski for keypresses. */
     124static int ski_con_fibril(void *arg)
    106125{
    107126        int32_t c;
    108127        ski_con_t *con = (ski_con_t *) arg;
     128        int rc;
    109129
    110130        while (1) {
     
    114134                                break;
    115135
    116                         if (con->client_sess != NULL) {
    117                                 async_exch_t *exch = async_exchange_begin(con->client_sess);
    118                                 async_msg_1(exch, CHAR_NOTIF_BYTE, c);
    119                                 async_exchange_end(exch);
    120                         }
     136                        fibril_mutex_lock(&con->buf_lock);
     137
     138                        rc = circ_buf_push(&con->cbuf, &c);
     139                        if (rc != EOK)
     140                                ddf_msg(LVL_ERROR, "Buffer overrun");
     141
     142                        fibril_mutex_unlock(&con->buf_lock);
     143                        fibril_condvar_broadcast(&con->buf_cv);
    121144                }
    122145
    123                 thread_usleep(POLL_INTERVAL);
    124         }
     146                fibril_usleep(POLL_INTERVAL);
     147        }
     148
     149        return 0;
    125150}
    126151
     
    157182}
    158183
     184/** Read from Ski console device */
     185static int ski_con_read(chardev_srv_t *srv, void *buf, size_t size,
     186    size_t *nread)
     187{
     188        ski_con_t *con = (ski_con_t *) srv->srvs->sarg;
     189        size_t p;
     190        uint8_t *bp = (uint8_t *) buf;
     191        int rc;
     192
     193        fibril_mutex_lock(&con->buf_lock);
     194
     195        while (circ_buf_nused(&con->cbuf) == 0)
     196                fibril_condvar_wait(&con->buf_cv, &con->buf_lock);
     197
     198        p = 0;
     199        while (p < size) {
     200                rc = circ_buf_pop(&con->cbuf, &bp[p]);
     201                if (rc != EOK)
     202                        break;
     203                ++p;
     204        }
     205
     206        fibril_mutex_unlock(&con->buf_lock);
     207
     208        *nread = p;
     209        return EOK;
     210}
     211
     212/** Write to Ski console device */
     213static int ski_con_write(chardev_srv_t *srv, const void *data, size_t size,
     214    size_t *nwr)
     215{
     216        ski_con_t *con = (ski_con_t *) srv->srvs->sarg;
     217        size_t i;
     218        uint8_t *dp = (uint8_t *) data;
     219
     220        for (i = 0; i < size; i++)
     221                ski_con_putchar(con, dp[i]);
     222
     223        *nwr = size;
     224        return EOK;
     225}
     226
    159227/** Character device connection handler. */
    160228static void ski_con_connection(ipc_callid_t iid, ipc_call_t *icall,
    161229    void *arg)
    162230{
    163         ski_con_t *con;
    164 
    165         /* Answer the IPC_M_CONNECT_ME_TO call. */
    166         async_answer_0(iid, EOK);
    167 
    168         con = (ski_con_t *)ddf_dev_data_get(ddf_fun_get_dev((ddf_fun_t *)arg));
    169 
    170         while (true) {
    171                 ipc_call_t call;
    172                 ipc_callid_t callid = async_get_call(&call);
    173                 sysarg_t method = IPC_GET_IMETHOD(call);
    174 
    175                 if (!method) {
    176                         /* The other side has hung up. */
    177                         async_answer_0(callid, EOK);
    178                         return;
    179                 }
    180 
    181                 async_sess_t *sess =
    182                     async_callback_receive_start(EXCHANGE_SERIALIZE, &call);
    183                 if (sess != NULL) {
    184                         if (con->client_sess == NULL) {
    185                                 con->client_sess = sess;
    186                                 async_answer_0(callid, EOK);
    187                         } else
    188                                 async_answer_0(callid, ELIMIT);
    189                 } else {
    190                         switch (method) {
    191                         case CHAR_WRITE_BYTE:
    192                                 ddf_msg(LVL_DEBUG, "Write %" PRIun " to device\n",
    193                                     IPC_GET_ARG1(call));
    194                                 ski_con_putchar(con, (uint8_t) IPC_GET_ARG1(call));
    195                                 async_answer_0(callid, EOK);
    196                                 break;
    197                         default:
    198                                 async_answer_0(callid, EINVAL);
    199                         }
    200                 }
    201         }
     231        ski_con_t *con = (ski_con_t *) ddf_dev_data_get(
     232            ddf_fun_get_dev((ddf_fun_t *) arg));
     233
     234        chardev_conn(iid, icall, &con->cds);
    202235}
    203236
  • uspace/drv/char/ski-con/ski-con.h

    r74017ce r7a6065c  
    3636#define SKI_CON_H
    3737
     38#include <adt/circ_buf.h>
    3839#include <async.h>
    3940#include <ddf/driver.h>
     41#include <io/chardev_srv.h>
    4042#include <loc.h>
    4143#include <stdint.h>
     44
     45enum {
     46        ski_con_buf_size = 64
     47};
    4248
    4349/** Ski console */
     
    4551        async_sess_t *client_sess;
    4652        ddf_dev_t *dev;
     53        chardev_srvs_t cds;
     54        circ_buf_t cbuf;
     55        uint8_t buf[ski_con_buf_size];
     56        fibril_mutex_t buf_lock;
     57        fibril_condvar_t buf_cv;
    4758} ski_con_t;
    4859
  • uspace/drv/char/sun4v-con/sun4v-con.c

    r74017ce r7a6065c  
    11/*
    22 * Copyright (c) 2008 Pavel Rimsky
    3  * Copyright (c) 2011 Jiri Svoboda
     3 * Copyright (c) 2017 Jiri Svoboda
    44 * All rights reserved.
    55 *
     
    3636#include <ddi.h>
    3737#include <errno.h>
    38 #include <ipc/char.h>
     38#include <io/chardev_srv.h>
    3939#include <stdbool.h>
    4040#include <thread.h>
     
    6262static input_buffer_t input_buffer;
    6363
    64 static void sun4v_thread_impl(void *arg);
     64static int sun4v_con_read(chardev_srv_t *, void *, size_t, size_t *);
     65static int sun4v_con_write(chardev_srv_t *, const void *, size_t, size_t *);
     66
     67static chardev_ops_t sun4v_con_chardev_ops = {
     68        .read = sun4v_con_read,
     69        .write = sun4v_con_write
     70};
    6571
    6672static void sun4v_con_putchar(sun4v_con_t *con, uint8_t data)
     
    8692        }
    8793
     94        chardev_srvs_init(&con->cds);
     95        con->cds.ops = &sun4v_con_chardev_ops;
     96        con->cds.sarg = con;
     97
    8898        ddf_fun_set_conn_handler(fun, sun4v_con_connection);
    8999
     
    94104                goto error;
    95105        }
    96 
    97         thread_id_t tid;
    98         rc = thread_create(sun4v_thread_impl, con, "kbd_poll", &tid);
    99         if (rc != EOK)
    100                 goto error;
    101106
    102107        rc = ddf_fun_bind(fun);
     
    131136}
    132137
    133 /**
    134  * Called regularly by the polling thread. Reads codes of all the
    135  * pressed keys from the buffer.
    136  */
    137 static void sun4v_key_pressed(sun4v_con_t *con)
     138/** Read from Sun4v console device */
     139static int sun4v_con_read(chardev_srv_t *srv, void *buf, size_t size,
     140    size_t *nread)
    138141{
     142        size_t p;
     143        uint8_t *bp = (uint8_t *) buf;
    139144        char c;
    140145
    141         while (input_buffer->read_ptr != input_buffer->write_ptr) {
     146        while (input_buffer->read_ptr == input_buffer->write_ptr)
     147                fibril_usleep(POLL_INTERVAL);
     148
     149        p = 0;
     150        while (p < size && input_buffer->read_ptr != input_buffer->write_ptr) {
    142151                c = input_buffer->data[input_buffer->read_ptr];
    143152                input_buffer->read_ptr =
    144153                    ((input_buffer->read_ptr) + 1) % INPUT_BUFFER_SIZE;
    145                 if (con->client_sess != NULL) {
    146                         async_exch_t *exch = async_exchange_begin(con->client_sess);
    147                         async_msg_1(exch, CHAR_NOTIF_BYTE, c);
    148                         async_exchange_end(exch);
    149                 }
    150                 (void) c;
     154                bp[p++] = c;
    151155        }
     156
     157        *nread = p;
     158        return EOK;
    152159}
    153160
    154 /**
    155  * Thread to poll Sun4v console for keypresses.
    156  */
    157 static void sun4v_thread_impl(void *arg)
     161/** Write to Sun4v console device */
     162static int sun4v_con_write(chardev_srv_t *srv, const void *data, size_t size,
     163    size_t *nwr)
    158164{
    159         sun4v_con_t *con = (sun4v_con_t *) arg;
     165        sun4v_con_t *con = (sun4v_con_t *) srv->srvs->sarg;
     166        size_t i;
     167        uint8_t *dp = (uint8_t *) data;
    160168
    161         while (true) {
    162                 sun4v_key_pressed(con);
    163                 thread_usleep(POLL_INTERVAL);
    164         }
     169        for (i = 0; i < size; i++)
     170                sun4v_con_putchar(con, dp[i]);
     171
     172        *nwr = size;
     173        return EOK;
    165174}
    166175
     
    169178    void *arg)
    170179{
    171         sun4v_con_t *con;
     180        sun4v_con_t *con = (sun4v_con_t *) ddf_dev_data_get(
     181            ddf_fun_get_dev((ddf_fun_t *) arg));
    172182
    173         /* Answer the IPC_M_CONNECT_ME_TO call. */
    174         async_answer_0(iid, EOK);
    175 
    176         con = (sun4v_con_t *)ddf_dev_data_get(ddf_fun_get_dev((ddf_fun_t *)arg));
    177 
    178         while (true) {
    179                 ipc_call_t call;
    180                 ipc_callid_t callid = async_get_call(&call);
    181                 sysarg_t method = IPC_GET_IMETHOD(call);
    182 
    183                 if (!method) {
    184                         /* The other side has hung up. */
    185                         async_answer_0(callid, EOK);
    186                         return;
    187                 }
    188 
    189                 async_sess_t *sess =
    190                     async_callback_receive_start(EXCHANGE_SERIALIZE, &call);
    191                 if (sess != NULL) {
    192                         if (con->client_sess == NULL) {
    193                                 con->client_sess = sess;
    194                                 async_answer_0(callid, EOK);
    195                         } else
    196                                 async_answer_0(callid, ELIMIT);
    197                 } else {
    198                         switch (method) {
    199                         case CHAR_WRITE_BYTE:
    200                                 ddf_msg(LVL_DEBUG, "Write %" PRIun " to device\n",
    201                                     IPC_GET_ARG1(call));
    202                                 sun4v_con_putchar(con, (uint8_t) IPC_GET_ARG1(call));
    203                                 async_answer_0(callid, EOK);
    204                                 break;
    205                         default:
    206                                 async_answer_0(callid, EINVAL);
    207                         }
    208                 }
    209         }
     183        chardev_conn(iid, icall, &con->cds);
    210184}
    211185
  • uspace/drv/char/sun4v-con/sun4v-con.h

    r74017ce r7a6065c  
    3838#include <async.h>
    3939#include <ddf/driver.h>
     40#include <io/chardev_srv.h>
    4041#include <loc.h>
    4142#include <stdint.h>
     
    5051        async_sess_t *client_sess;
    5152        ddf_dev_t *dev;
     53        chardev_srvs_t cds;
    5254        sun4v_con_res_t res;
    5355} sun4v_con_t;
  • uspace/lib/c/Makefile

    r74017ce r7a6065c  
    143143        generic/getopt.c \
    144144        generic/adt/checksum.c \
     145        generic/adt/circ_buf.c \
    145146        generic/adt/list.c \
    146147        generic/adt/hash_table.c \
     
    181182
    182183TEST_SOURCES = \
     184        test/adt/circ_buf.c \
    183185        test/fibril/timer.c \
    184186        test/main.c \
  • uspace/lib/c/test/main.c

    r74017ce r7a6065c  
    3232PCUT_INIT
    3333
     34PCUT_IMPORT(circ_buf);
    3435PCUT_IMPORT(fibril_timer);
    3536PCUT_IMPORT(odict);
  • uspace/srv/hid/input/port/chardev.c

    r74017ce r7a6065c  
    3535 */
    3636
    37 #include <ipc/char.h>
    3837#include <async.h>
     38#include <errno.h>
     39#include <fibril.h>
     40#include <io/chardev.h>
    3941#include <loc.h>
    40 #include <errno.h>
    4142#include <stdio.h>
    4243#include "../input.h"
     
    4445#include "../kbd.h"
    4546
    46 static void kbd_port_events(ipc_callid_t iid, ipc_call_t *icall, void *arg);
     47static int kbd_port_fibril(void *);
    4748
    4849static int chardev_port_init(kbd_dev_t *);
    49 static void chardev_port_write(uint8_t data);
     50static void chardev_port_write(uint8_t);
    5051
    5152kbd_port_ops_t chardev_port = {
     
    5657static kbd_dev_t *kbd_dev;
    5758static async_sess_t *dev_sess;
     59static chardev_t *chardev;
    5860
    5961/** List of devices to try connecting to. */
     
    7072{
    7173        service_id_t service_id;
    72         async_exch_t *exch;
    7374        unsigned int i;
     75        fid_t fid;
    7476        int rc;
    7577       
     
    9698        }
    9799       
    98         exch = async_exchange_begin(dev_sess);
    99         if (exch == NULL) {
    100                 printf("%s: Failed starting exchange with device\n", NAME);
     100        rc = chardev_open(dev_sess, &chardev);
     101        if (rc != EOK) {
     102                printf("%s: Failed opening character device\n", NAME);
    101103                async_hangup(dev_sess);
    102104                return ENOMEM;
    103105        }
    104106       
    105         port_id_t port;
    106         rc = async_create_callback_port(exch, INTERFACE_CHAR_CB, 0, 0,
    107             kbd_port_events, NULL, &port);
    108        
    109         async_exchange_end(exch);
    110        
    111         if (rc != 0) {
    112                 printf("%s: Failed to create callback from device\n", NAME);
     107        fid = fibril_create(kbd_port_fibril, NULL);
     108        if (fid == 0) {
     109                printf("%s: Failed creating fibril\n", NAME);
     110                chardev_close(chardev);
    113111                async_hangup(dev_sess);
    114                 return -1;
     112                return ENOMEM;
    115113        }
     114
     115        fibril_add_ready(fid);
    116116       
    117117        printf("%s: Found input device '%s'\n", NAME, in_devs[i]);
     
    121121static void chardev_port_write(uint8_t data)
    122122{
    123         async_exch_t *exch = async_exchange_begin(dev_sess);
    124         if (exch == NULL) {
    125                 printf("%s: Failed starting exchange with device\n", NAME);
     123        int rc;
     124        size_t nwr;
     125
     126        rc = chardev_write(chardev, &data, sizeof(data), &nwr);
     127        if (rc != EOK || nwr != sizeof(data)) {
     128                printf("%s: Failed writing to character device\n", NAME);
    126129                return;
    127         }
    128 
    129         async_msg_1(exch, CHAR_WRITE_BYTE, data);
    130         async_exchange_end(exch);
    131 }
    132 
    133 static void kbd_port_events(ipc_callid_t iid, ipc_call_t *icall, void *arg)
    134 {
    135         /* Ignore parameters, the connection is already opened */
    136         while (true) {
    137 
    138                 ipc_call_t call;
    139                 ipc_callid_t callid = async_get_call(&call);
    140                
    141                 if (!IPC_GET_IMETHOD(call)) {
    142                         /* TODO: Handle hangup */
    143                         return;
    144                 }
    145 
    146                 int retval = EOK;
    147 
    148                 switch (IPC_GET_IMETHOD(call)) {
    149                 case CHAR_NOTIF_BYTE:
    150                         kbd_push_data(kbd_dev, IPC_GET_ARG1(call));
    151                         break;
    152                 default:
    153                         retval = ENOENT;
    154                 }
    155                 async_answer_0(callid, retval);
    156130        }
    157131}
    158132
     133static int kbd_port_fibril(void *arg)
     134{
     135        int rc;
     136        size_t nread;
     137        uint8_t b;
     138
     139        while (true) {
     140                rc = chardev_read(chardev, &b, sizeof(b), &nread);
     141                if (rc != EOK || nread != sizeof(b)) {
     142                        printf("%s: Error reading data", NAME);
     143                        continue;
     144                }
     145
     146                kbd_push_data(kbd_dev, b);
     147        }
     148
     149        return 0;
     150}
    159151
    160152/**
  • uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.c

    r74017ce r7a6065c  
    2727 */
    2828
    29 /** @addtogroup driver_serial
    30  * @{
    31  */
    3229/**
    3330 * @file
     
    3734 */
    3835
     36#include <async.h>
    3937#include <ddi.h>
     38#include <errno.h>
     39#include <inttypes.h>
     40#include <io/chardev_srv.h>
    4041#include <loc.h>
    41 #include <ipc/char.h>
    42 #include <async.h>
    4342#include <stdio.h>
    4443#include <stdlib.h>
    4544#include <sysinfo.h>
    46 #include <errno.h>
    47 #include <inttypes.h>
    4845#include "s3c24xx_uart.h"
    4946
     
    7269static void s3c24xx_uart_sendb(s3c24xx_uart_t *, uint8_t);
    7370
     71static int s3c24xx_uart_read(chardev_srv_t *, void *, size_t, size_t *);
     72static int s3c24xx_uart_write(chardev_srv_t *, const void *, size_t, size_t *);
     73
     74static chardev_ops_t s3c24xx_uart_chardev_ops = {
     75        .read = s3c24xx_uart_read,
     76        .write = s3c24xx_uart_write
     77};
     78
    7479int main(int argc, char *argv[])
    7580{
    7681        printf("%s: S3C24xx on-chip UART driver\n", NAME);
    7782       
    78         async_set_fallback_port_handler(s3c24xx_uart_connection, NULL);
     83        async_set_fallback_port_handler(s3c24xx_uart_connection, uart);
    7984        int rc = loc_server_register(NAME);
    8085        if (rc != EOK) {
     
    111116    void *arg)
    112117{
    113         /* Answer the IPC_M_CONNECT_ME_TO call. */
    114         async_answer_0(iid, EOK);
    115        
    116         while (true) {
    117                 ipc_call_t call;
    118                 ipc_callid_t callid = async_get_call(&call);
    119                 sysarg_t method = IPC_GET_IMETHOD(call);
    120                
    121                 if (!method) {
    122                         /* The other side has hung up. */
    123                         async_answer_0(callid, EOK);
    124                         return;
    125                 }
    126                
    127                 async_sess_t *sess =
    128                     async_callback_receive_start(EXCHANGE_SERIALIZE, &call);
    129                 if (sess != NULL) {
    130                         if (uart->client_sess == NULL) {
    131                                 uart->client_sess = sess;
    132                                 async_answer_0(callid, EOK);
    133                         } else
    134                                 async_answer_0(callid, ELIMIT);
    135                 } else {
    136                         switch (method) {
    137                         case CHAR_WRITE_BYTE:
    138                                 printf(NAME ": write %" PRIun " to device\n",
    139                                     IPC_GET_ARG1(call));
    140                                 s3c24xx_uart_sendb(uart, (uint8_t) IPC_GET_ARG1(call));
    141                                 async_answer_0(callid, EOK);
    142                                 break;
    143                         default:
    144                                 async_answer_0(callid, EINVAL);
    145                         }
    146                 }
    147         }
    148 }
     118        s3c24xx_uart_t *uart = (s3c24xx_uart_t *) arg;
     119
     120        chardev_conn(iid, icall, &uart->cds);
     121}
     122
    149123
    150124static void s3c24xx_uart_irq_handler(ipc_callid_t iid, ipc_call_t *call,
    151125    void *arg)
    152126{
     127        int rc;
     128
    153129        (void) iid;
    154130        (void) call;
     
    159135                uint32_t status = pio_read_32(&uart->io->uerstat);
    160136
    161                 if (uart->client_sess != NULL) {
    162                         async_exch_t *exch = async_exchange_begin(uart->client_sess);
    163                         async_msg_1(exch, CHAR_NOTIF_BYTE, data);
    164                         async_exchange_end(exch);
    165                 }
     137                fibril_mutex_lock(&uart->buf_lock);
     138
     139                rc = circ_buf_push(&uart->cbuf, &data);
     140                if (rc != EOK)
     141                        printf(NAME ": Buffer overrun\n");
     142
     143                fibril_mutex_unlock(&uart->buf_lock);
     144                fibril_condvar_broadcast(&uart->buf_cv);
    166145
    167146                if (status != 0)
     
    176155        sysarg_t inr;
    177156
     157        circ_buf_init(&uart->cbuf, uart->buf, s3c24xx_uart_buf_size, 1);
     158        fibril_mutex_initialize(&uart->buf_lock);
     159        fibril_condvar_initialize(&uart->buf_cv);
     160
    178161        if (sysinfo_get_value("s3c24xx_uart.address.physical",
    179162            &uart->paddr) != EOK)
     
    188171
    189172        uart->io = vaddr;
    190         uart->client_sess = NULL;
    191173
    192174        printf(NAME ": device at physical address %p, inr %" PRIun ".\n",
     
    203185            pio_read_32(&uart->io->ucon) & ~UCON_RX_INT_LEVEL);
    204186
     187        chardev_srvs_init(&uart->cds);
     188        uart->cds.ops = &s3c24xx_uart_chardev_ops;
     189        uart->cds.sarg = uart;
     190
    205191        return EOK;
    206192}
     
    216202}
    217203
     204static int s3c24xx_uart_read(chardev_srv_t *srv, void *buf, size_t size,
     205    size_t *nread)
     206{
     207        s3c24xx_uart_t *uart = (s3c24xx_uart_t *) srv->srvs->sarg;
     208        size_t p;
     209        uint8_t *bp = (uint8_t *) buf;
     210        int rc;
     211
     212        fibril_mutex_lock(&uart->buf_lock);
     213
     214        while (circ_buf_nused(&uart->cbuf) == 0)
     215                fibril_condvar_wait(&uart->buf_cv, &uart->buf_lock);
     216
     217        p = 0;
     218        while (p < size) {
     219                rc = circ_buf_pop(&uart->cbuf, &bp[p]);
     220                if (rc != EOK)
     221                        break;
     222                ++p;
     223        }
     224
     225        fibril_mutex_unlock(&uart->buf_lock);
     226
     227        *nread = p;
     228        return EOK;
     229}
     230
     231static int s3c24xx_uart_write(chardev_srv_t *srv, const void *data, size_t size,
     232    size_t *nwr)
     233{
     234        s3c24xx_uart_t *uart = (s3c24xx_uart_t *) srv->srvs->sarg;
     235        size_t i;
     236        uint8_t *dp = (uint8_t *) data;
     237
     238        for (i = 0; i < size; i++)
     239                s3c24xx_uart_sendb(uart, dp[i]);
     240
     241        *nwr = size;
     242        return EOK;
     243}
     244
     245
    218246/** @}
    219247 */
  • uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.h

    r74017ce r7a6065c  
    3838#define S3C24XX_UART_H_
    3939
     40#include <adt/circ_buf.h>
     41#include <async.h>
     42#include <fibril_synch.h>
     43#include <io/chardev_srv.h>
    4044#include <stdint.h>
    41 #include <async.h>
    4245
    4346/** S3C24xx UART I/O */
     
    7679#define UFCON_FIFO_ENABLE               0x01
    7780
     81enum {
     82        s3c24xx_uart_buf_size = 64
     83};
    7884
    7985/** S3C24xx UART instance */
     
    8591        s3c24xx_uart_io_t *io;
    8692
    87         /** Callback session to the client */
    88         async_sess_t *client_sess;
     93        /** Character device service */
     94        chardev_srvs_t cds;
    8995
    9096        /** Service ID */
    9197        service_id_t service_id;
     98
     99        /** Circular buffer */
     100        circ_buf_t cbuf;
     101        /** Buffer */
     102        uint8_t buf[s3c24xx_uart_buf_size];
     103        /** Buffer lock */
     104        fibril_mutex_t buf_lock;
     105        /** Signal newly added data in buffer */
     106        fibril_condvar_t buf_cv;
    92107} s3c24xx_uart_t;
    93108
Note: See TracChangeset for help on using the changeset viewer.