Changeset 132ab5d1 in mainline for uspace/drv/char/ski-con/ski-con.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/ski-con/ski-con.c

    r8bfb163 r132ab5d1  
    11/*
    22 * Copyright (c) 2005 Jakub Jermar
    3  * Copyright (c) 2011 Jiri Svoboda
     3 * Copyright (c) 2017 Jiri Svoboda
    44 * All rights reserved.
    55 *
     
    3131 */
    3232
     33#include <async.h>
    3334#include <ddf/driver.h>
    3435#include <ddf/log.h>
    3536#include <errno.h>
    36 #include <ipc/char.h>
     37#include <fibril.h>
     38#include <io/chardev.h>
    3739#include <stdint.h>
    3840#include <stdlib.h>
    39 #include <thread.h>
    4041#include <stdbool.h>
    4142
     
    4344
    4445#define SKI_GETCHAR             21
     46#define SKI_PUTCHAR             31
    4547
    4648#define POLL_INTERVAL           10000
    4749
    48 static void ski_con_thread_impl(void *arg);
     50static int ski_con_fibril(void *arg);
    4951static int32_t ski_con_getchar(void);
    5052static void ski_con_connection(ipc_callid_t, ipc_call_t *, void *);
    5153
     54static int ski_con_read(chardev_srv_t *, void *, size_t, size_t *);
     55static int ski_con_write(chardev_srv_t *, const void *, size_t, size_t *);
     56
     57static chardev_ops_t ski_con_chardev_ops = {
     58        .read = ski_con_read,
     59        .write = ski_con_write
     60};
     61
     62static void ski_con_putchar(ski_con_t *con, char ch); /* XXX */
     63
    5264/** Add ski console device. */
    5365int ski_con_add(ski_con_t *con)
    5466{
    55         thread_id_t tid;
     67        fid_t fid;
    5668        ddf_fun_t *fun = NULL;
    5769        bool bound = false;
    5870        int rc;
     71
     72        circ_buf_init(&con->cbuf, con->buf, ski_con_buf_size, 1);
     73        fibril_mutex_initialize(&con->buf_lock);
     74        fibril_condvar_initialize(&con->buf_cv);
    5975
    6076        fun = ddf_fun_create(con->dev, fun_exposed, "a");
     
    6783        ddf_fun_set_conn_handler(fun, ski_con_connection);
    6884
     85        chardev_srvs_init(&con->cds);
     86        con->cds.ops = &ski_con_chardev_ops;
     87        con->cds.sarg = con;
     88
    6989        rc = ddf_fun_bind(fun);
    7090        if (rc != EOK) {
     
    7393        }
    7494
     95        ddf_fun_add_to_category(fun, "console");
     96
    7597        bound = true;
    7698
    77         rc = thread_create(ski_con_thread_impl, con, "kbd_poll", &tid);
    78         if (rc != 0) {
    79                 return rc;
    80         }
    81 
     99        fid = fibril_create(ski_con_fibril, con);
     100        if (fid == 0) {
     101                ddf_msg(LVL_ERROR, "Error creating fibril.");
     102                rc = ENOMEM;
     103                goto error;
     104        }
     105
     106        fibril_add_ready(fid);
    82107        return EOK;
    83108error:
     
    102127}
    103128
    104 /** Thread to poll Ski for keypresses. */
    105 static void ski_con_thread_impl(void *arg)
     129/** Poll Ski for keypresses. */
     130static int ski_con_fibril(void *arg)
    106131{
    107132        int32_t c;
    108133        ski_con_t *con = (ski_con_t *) arg;
     134        int rc;
    109135
    110136        while (1) {
     
    114140                                break;
    115141
    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                         }
     142                        fibril_mutex_lock(&con->buf_lock);
     143
     144                        rc = circ_buf_push(&con->cbuf, &c);
     145                        if (rc != EOK)
     146                                ddf_msg(LVL_ERROR, "Buffer overrun");
     147
     148                        fibril_mutex_unlock(&con->buf_lock);
     149                        fibril_condvar_broadcast(&con->buf_cv);
    121150                }
    122151
    123                 thread_usleep(POLL_INTERVAL);
    124         }
     152                async_usleep(POLL_INTERVAL);
     153        }
     154
     155        return 0;
    125156}
    126157
     
    152183}
    153184
     185
     186/** Display character on ski debug console
     187 *
     188 * Use SSC (Simulator System Call) to
     189 * display character on debug console.
     190 *
     191 * @param c Character to be printed.
     192 *
     193 */
    154194static void ski_con_putchar(ski_con_t *con, char ch)
    155195{
    156        
     196        if (ch == '\n')
     197                ski_con_putchar(con, '\r');
     198
     199#ifdef UARCH_ia64
     200        asm volatile (
     201                "mov r15 = %0\n"
     202                "mov r32 = %1\n"   /* r32 is in0 */
     203                "break 0x80000\n"  /* modifies r8 */
     204                :
     205                : "i" (SKI_PUTCHAR), "r" (ch)
     206                : "r15", "in0", "r8"
     207        );
     208#else
     209        (void) ch;
     210#endif
     211}
     212
     213/** Read from Ski console device */
     214static int ski_con_read(chardev_srv_t *srv, void *buf, size_t size,
     215    size_t *nread)
     216{
     217        ski_con_t *con = (ski_con_t *) srv->srvs->sarg;
     218        size_t p;
     219        uint8_t *bp = (uint8_t *) buf;
     220        int rc;
     221
     222        fibril_mutex_lock(&con->buf_lock);
     223
     224        while (circ_buf_nused(&con->cbuf) == 0)
     225                fibril_condvar_wait(&con->buf_cv, &con->buf_lock);
     226
     227        p = 0;
     228        while (p < size) {
     229                rc = circ_buf_pop(&con->cbuf, &bp[p]);
     230                if (rc != EOK)
     231                        break;
     232                ++p;
     233        }
     234
     235        fibril_mutex_unlock(&con->buf_lock);
     236
     237        *nread = p;
     238        return EOK;
     239}
     240
     241/** Write to Ski console device */
     242static int ski_con_write(chardev_srv_t *srv, const void *data, size_t size,
     243    size_t *nwr)
     244{
     245        ski_con_t *con = (ski_con_t *) srv->srvs->sarg;
     246        size_t i;
     247        uint8_t *dp = (uint8_t *) data;
     248
     249        for (i = 0; i < size; i++)
     250                ski_con_putchar(con, dp[i]);
     251
     252        *nwr = size;
     253        return EOK;
    157254}
    158255
     
    161258    void *arg)
    162259{
    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         }
     260        ski_con_t *con = (ski_con_t *) ddf_dev_data_get(
     261            ddf_fun_get_dev((ddf_fun_t *) arg));
     262
     263        chardev_conn(iid, icall, &con->cds);
    202264}
    203265
Note: See TracChangeset for help on using the changeset viewer.