Ignore:
File:
1 edited

Legend:

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

    r071a1ddb r7aa94304  
    3737#include <ddi.h>
    3838#include <errno.h>
    39 #include <io/chardev_srv.h>
     39#include <ipc/char.h>
     40#include <sysinfo.h>
    4041
    4142#include "msim-con.h"
     
    4344static void msim_con_connection(ipc_callid_t, ipc_call_t *, void *);
    4445
    45 static int msim_con_read(chardev_srv_t *, void *, size_t, size_t *);
    46 static int msim_con_write(chardev_srv_t *, const void *, size_t, size_t *);
    47 
    48 static chardev_ops_t msim_con_chardev_ops = {
    49         .read = msim_con_read,
    50         .write = msim_con_write
     46static irq_pio_range_t msim_ranges[] = {
     47        {
     48                .base = 0,
     49                .size = 1
     50        }
    5151};
    5252
    53 static irq_cmd_t msim_cmds_proto[] = {
     53static irq_cmd_t msim_cmds[] = {
    5454        {
    5555                .cmd = CMD_PIO_READ_8,
     
    6262};
    6363
    64 static void msim_irq_handler(ipc_call_t *call, void *arg)
     64static irq_code_t msim_kbd = {
     65        sizeof(msim_ranges) / sizeof(irq_pio_range_t),
     66        msim_ranges,
     67        sizeof(msim_cmds) / sizeof(irq_cmd_t),
     68        msim_cmds
     69};
     70
     71static void msim_irq_handler(ipc_callid_t iid, ipc_call_t *call, void *arg)
    6572{
    6673        msim_con_t *con = (msim_con_t *) arg;
    6774        uint8_t c;
    68         int rc;
    69 
    70         fibril_mutex_lock(&con->buf_lock);
    7175
    7276        c = IPC_GET_ARG2(*call);
    73         rc = circ_buf_push(&con->cbuf, &c);
    74         if (rc != EOK)
    75                 ddf_msg(LVL_ERROR, "Buffer overrun");
    7677
    77         fibril_mutex_unlock(&con->buf_lock);
    78         fibril_condvar_broadcast(&con->buf_cv);
     78        if (con->client_sess != NULL) {
     79                async_exch_t *exch = async_exchange_begin(con->client_sess);
     80                async_msg_1(exch, CHAR_NOTIF_BYTE, c);
     81                async_exchange_end(exch);
     82        }
    7983}
    8084
    8185/** Add msim console device. */
    82 int msim_con_add(msim_con_t *con, msim_con_res_t *res)
     86int msim_con_add(msim_con_t *con)
    8387{
    8488        ddf_fun_t *fun = NULL;
    8589        bool subscribed = false;
    86         irq_cmd_t *msim_cmds = NULL;
    8790        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);
    92 
    93         msim_cmds = malloc(sizeof(msim_cmds_proto));
    94         if (msim_cmds == NULL) {
    95                 rc = ENOMEM;
    96                 goto error;
    97         }
    98 
    99         con->res = *res;
    10091
    10192        fun = ddf_fun_create(con->dev, fun_exposed, "a");
     
    10697        }
    10798
    108         rc = pio_enable((void *)res->base, 1, (void **) &con->out_reg);
    109         if (rc != EOK) {
    110                 ddf_msg(LVL_ERROR, "Error enabling I/O");
     99        ddf_fun_set_conn_handler(fun, msim_con_connection);
     100
     101        sysarg_t paddr;
     102        if (sysinfo_get_value("kbd.address.physical", &paddr) != EOK) {
     103                rc = ENOENT;
    111104                goto error;
    112105        }
    113106
    114         ddf_fun_set_conn_handler(fun, msim_con_connection);
     107        sysarg_t inr;
     108        if (sysinfo_get_value("kbd.inr", &inr) != EOK) {
     109                rc = ENOENT;
     110                goto error;
     111        }
    115112
    116         con->irq_range[0].base = res->base;
    117         con->irq_range[0].size = 1;
    118 
    119         memcpy(msim_cmds, msim_cmds_proto, sizeof(msim_cmds_proto));
    120         msim_cmds[0].addr = (void *) res->base;
    121 
    122         con->irq_code.rangecount = 1;
    123         con->irq_code.ranges = con->irq_range;
    124         con->irq_code.cmdcount = sizeof(msim_cmds_proto) / sizeof(irq_cmd_t);
    125         con->irq_code.cmds = msim_cmds;
    126 
    127         async_irq_subscribe(res->irq, msim_irq_handler, con, &con->irq_code, NULL);
     113        msim_ranges[0].base = paddr;
     114        msim_cmds[0].addr = (void *) paddr;
     115        async_irq_subscribe(inr, msim_irq_handler, con, &msim_kbd);
    128116        subscribed = true;
    129 
    130         chardev_srvs_init(&con->cds);
    131         con->cds.ops = &msim_con_chardev_ops;
    132         con->cds.sarg = con;
    133117
    134118        rc = ddf_fun_bind(fun);
     
    138122        }
    139123
    140         ddf_fun_add_to_category(fun, "console");
    141 
    142124        return EOK;
    143125error:
    144126        if (subscribed)
    145                 async_irq_unsubscribe(res->irq);
     127                async_irq_unsubscribe(inr);
    146128        if (fun != NULL)
    147129                ddf_fun_destroy(fun);
    148         free(msim_cmds);
    149130
    150131        return rc;
     
    165146static void msim_con_putchar(msim_con_t *con, uint8_t ch)
    166147{
    167         pio_write_8(con->out_reg, ch);
    168 }
    169 
    170 /** Read from msim console device */
    171 static int msim_con_read(chardev_srv_t *srv, void *buf, size_t size,
    172     size_t *nread)
    173 {
    174         msim_con_t *con = (msim_con_t *) srv->srvs->sarg;
    175         size_t p;
    176         uint8_t *bp = (uint8_t *) buf;
    177         int rc;
    178 
    179         fibril_mutex_lock(&con->buf_lock);
    180 
    181         while (circ_buf_nused(&con->cbuf) == 0)
    182                 fibril_condvar_wait(&con->buf_cv, &con->buf_lock);
    183 
    184         p = 0;
    185         while (p < size) {
    186                 rc = circ_buf_pop(&con->cbuf, &bp[p]);
    187                 if (rc != EOK)
    188                         break;
    189                 ++p;
    190         }
    191 
    192         fibril_mutex_unlock(&con->buf_lock);
    193 
    194         *nread = p;
    195         return EOK;
    196 }
    197 
    198 /** Write to msim console device */
    199 static int msim_con_write(chardev_srv_t *srv, const void *data, size_t size,
    200     size_t *nwr)
    201 {
    202         msim_con_t *con = (msim_con_t *) srv->srvs->sarg;
    203         size_t i;
    204         uint8_t *dp = (uint8_t *) data;
    205 
    206         for (i = 0; i < size; i++)
    207                 msim_con_putchar(con, dp[i]);
    208 
    209         *nwr = size;
    210         return EOK;
    211148}
    212149
     
    215152    void *arg)
    216153{
    217         msim_con_t *con = (msim_con_t *) ddf_dev_data_get(
    218             ddf_fun_get_dev((ddf_fun_t *) arg));
     154        msim_con_t *con;
    219155
    220         chardev_conn(iid, icall, &con->cds);
     156        /* Answer the IPC_M_CONNECT_ME_TO call. */
     157        async_answer_0(iid, EOK);
     158
     159        con = (msim_con_t *)ddf_dev_data_get(ddf_fun_get_dev((ddf_fun_t *)arg));
     160
     161        while (true) {
     162                ipc_call_t call;
     163                ipc_callid_t callid = async_get_call(&call);
     164                sysarg_t method = IPC_GET_IMETHOD(call);
     165
     166                if (!method) {
     167                        /* The other side has hung up. */
     168                        async_answer_0(callid, EOK);
     169                        return;
     170                }
     171
     172                async_sess_t *sess =
     173                    async_callback_receive_start(EXCHANGE_SERIALIZE, &call);
     174                if (sess != NULL) {
     175                        if (con->client_sess == NULL) {
     176                                con->client_sess = sess;
     177                                async_answer_0(callid, EOK);
     178                        } else
     179                                async_answer_0(callid, ELIMIT);
     180                } else {
     181                        switch (method) {
     182                        case CHAR_WRITE_BYTE:
     183                                ddf_msg(LVL_DEBUG, "Write %" PRIun " to device\n",
     184                                    IPC_GET_ARG1(call));
     185                                msim_con_putchar(con, (uint8_t) IPC_GET_ARG1(call));
     186                                async_answer_0(callid, EOK);
     187                                break;
     188                        default:
     189                                async_answer_0(callid, EINVAL);
     190                        }
     191                }
     192        }
    221193}
    222194
Note: See TracChangeset for help on using the changeset viewer.