source: mainline/uspace/drv/char/msim-con/msim-con.c@ 43ba118

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 43ba118 was 984a9ba, checked in by Martin Decky <martin@…>, 7 years ago

do not expose the call capability handler from the async framework

Keep the call capability handler encapsulated within the async framework
and do not expose it explicitly via its API. Use the pointer to
ipc_call_t as the sole object identifying an IPC call in the code that
uses the async framework.

This plugs a major leak in the abstraction and also simplifies both the
async framework (slightly) and all IPC servers.

  • Property mode set to 100644
File size: 5.6 KB
Line 
1/*
2 * Copyright (c) 2006 Josef Cejka
3 * Copyright (c) 2011 Jiri Svoboda
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @file
31 * @brief Msim console driver.
32 */
33
34#include <async.h>
35#include <ddf/driver.h>
36#include <ddf/log.h>
37#include <ddi.h>
38#include <errno.h>
39#include <io/chardev_srv.h>
40
41#include "msim-con.h"
42
43static void msim_con_connection(ipc_call_t *, void *);
44
45static errno_t msim_con_read(chardev_srv_t *, void *, size_t, size_t *);
46static errno_t 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};
52
53static irq_cmd_t msim_cmds_proto[] = {
54 {
55 .cmd = CMD_PIO_READ_8,
56 .addr = (void *) 0, /* will be patched in run-time */
57 .dstarg = 2
58 },
59 {
60 .cmd = CMD_ACCEPT
61 }
62};
63
64static void msim_irq_handler(ipc_call_t *call, void *arg)
65{
66 msim_con_t *con = (msim_con_t *) arg;
67 uint8_t c;
68 errno_t rc;
69
70 fibril_mutex_lock(&con->buf_lock);
71
72 c = IPC_GET_ARG2(*call);
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);
79}
80
81/** Add msim console device. */
82errno_t msim_con_add(msim_con_t *con, msim_con_res_t *res)
83{
84 ddf_fun_t *fun = NULL;
85 irq_cmd_t *msim_cmds = NULL;
86 errno_t rc;
87
88 circ_buf_init(&con->cbuf, con->buf, msim_con_buf_size, 1);
89 fibril_mutex_initialize(&con->buf_lock);
90 fibril_condvar_initialize(&con->buf_cv);
91
92 con->irq_handle = CAP_NIL;
93
94 msim_cmds = malloc(sizeof(msim_cmds_proto));
95 if (msim_cmds == NULL) {
96 rc = ENOMEM;
97 goto error;
98 }
99
100 con->res = *res;
101
102 fun = ddf_fun_create(con->dev, fun_exposed, "a");
103 if (fun == NULL) {
104 ddf_msg(LVL_ERROR, "Error creating function 'a'.");
105 rc = ENOMEM;
106 goto error;
107 }
108
109 rc = pio_enable((void *)res->base, 1, (void **) &con->out_reg);
110 if (rc != EOK) {
111 ddf_msg(LVL_ERROR, "Error enabling I/O");
112 goto error;
113 }
114
115 ddf_fun_set_conn_handler(fun, msim_con_connection);
116
117 con->irq_range[0].base = res->base;
118 con->irq_range[0].size = 1;
119
120 memcpy(msim_cmds, msim_cmds_proto, sizeof(msim_cmds_proto));
121 msim_cmds[0].addr = (void *) res->base;
122
123 con->irq_code.rangecount = 1;
124 con->irq_code.ranges = con->irq_range;
125 con->irq_code.cmdcount = sizeof(msim_cmds_proto) / sizeof(irq_cmd_t);
126 con->irq_code.cmds = msim_cmds;
127
128 rc = async_irq_subscribe(res->irq, msim_irq_handler, con,
129 &con->irq_code, &con->irq_handle);
130 if (rc != EOK) {
131 ddf_msg(LVL_ERROR, "Error registering IRQ code.");
132 goto error;
133 }
134
135 chardev_srvs_init(&con->cds);
136 con->cds.ops = &msim_con_chardev_ops;
137 con->cds.sarg = con;
138
139 rc = ddf_fun_bind(fun);
140 if (rc != EOK) {
141 ddf_msg(LVL_ERROR, "Error binding function 'a'.");
142 goto error;
143 }
144
145 ddf_fun_add_to_category(fun, "console");
146
147 return EOK;
148error:
149 if (CAP_HANDLE_VALID(con->irq_handle))
150 async_irq_unsubscribe(con->irq_handle);
151 if (fun != NULL)
152 ddf_fun_destroy(fun);
153 free(msim_cmds);
154
155 return rc;
156}
157
158/** Remove msim console device */
159errno_t msim_con_remove(msim_con_t *con)
160{
161 return ENOTSUP;
162}
163
164/** Msim console device gone */
165errno_t msim_con_gone(msim_con_t *con)
166{
167 return ENOTSUP;
168}
169
170static void msim_con_putchar(msim_con_t *con, uint8_t ch)
171{
172 pio_write_8(con->out_reg, ch);
173}
174
175/** Read from msim console device */
176static errno_t msim_con_read(chardev_srv_t *srv, void *buf, size_t size,
177 size_t *nread)
178{
179 msim_con_t *con = (msim_con_t *) srv->srvs->sarg;
180 size_t p;
181 uint8_t *bp = (uint8_t *) buf;
182 errno_t rc;
183
184 fibril_mutex_lock(&con->buf_lock);
185
186 while (circ_buf_nused(&con->cbuf) == 0)
187 fibril_condvar_wait(&con->buf_cv, &con->buf_lock);
188
189 p = 0;
190 while (p < size) {
191 rc = circ_buf_pop(&con->cbuf, &bp[p]);
192 if (rc != EOK)
193 break;
194 ++p;
195 }
196
197 fibril_mutex_unlock(&con->buf_lock);
198
199 *nread = p;
200 return EOK;
201}
202
203/** Write to msim console device */
204static errno_t msim_con_write(chardev_srv_t *srv, const void *data, size_t size,
205 size_t *nwr)
206{
207 msim_con_t *con = (msim_con_t *) srv->srvs->sarg;
208 size_t i;
209 uint8_t *dp = (uint8_t *) data;
210
211 for (i = 0; i < size; i++)
212 msim_con_putchar(con, dp[i]);
213
214 *nwr = size;
215 return EOK;
216}
217
218/** Character device connection handler. */
219static void msim_con_connection(ipc_call_t *icall, void *arg)
220{
221 msim_con_t *con = (msim_con_t *) ddf_dev_data_get(
222 ddf_fun_get_dev((ddf_fun_t *) arg));
223
224 chardev_conn(icall, &con->cds);
225}
226
227/** @}
228 */
Note: See TracBrowser for help on using the repository browser.