Changeset 132ab5d1 in mainline for uspace/drv/char/msim-con/msim-con.c
- Timestamp:
- 2018-01-30T03:20:45Z (8 years ago)
- 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. - File:
-
- 1 edited
-
uspace/drv/char/msim-con/msim-con.c (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/char/msim-con/msim-con.c
r8bfb163 r132ab5d1 37 37 #include <ddi.h> 38 38 #include <errno.h> 39 #include <ipc/char.h> 40 #include <sysinfo.h> 39 #include <io/chardev_srv.h> 41 40 42 41 #include "msim-con.h" … … 44 43 static void msim_con_connection(ipc_callid_t, ipc_call_t *, void *); 45 44 46 static irq_pio_range_t msim_ranges[] = { 47 { 48 .base = 0, 49 .size = 1 50 } 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 51 51 }; 52 52 53 static irq_cmd_t msim_cmds [] = {53 static irq_cmd_t msim_cmds_proto[] = { 54 54 { 55 55 .cmd = CMD_PIO_READ_8, … … 62 62 }; 63 63 64 static 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 71 static void msim_irq_handler(ipc_callid_t iid, ipc_call_t *call, void *arg) 64 static void msim_irq_handler(ipc_call_t *call, void *arg) 72 65 { 73 66 msim_con_t *con = (msim_con_t *) arg; 74 67 uint8_t c; 68 int rc; 69 70 fibril_mutex_lock(&con->buf_lock); 75 71 76 72 c = IPC_GET_ARG2(*call); 77 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 }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); 83 79 } 84 80 85 81 /** Add msim console device. */ 86 int msim_con_add(msim_con_t *con )82 int msim_con_add(msim_con_t *con, msim_con_res_t *res) 87 83 { 88 84 ddf_fun_t *fun = NULL; 89 85 bool subscribed = false; 86 irq_cmd_t *msim_cmds = NULL; 90 87 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; 91 100 92 101 fun = ddf_fun_create(con->dev, fun_exposed, "a"); … … 97 106 } 98 107 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"); 111 goto error; 112 } 113 99 114 ddf_fun_set_conn_handler(fun, msim_con_connection); 100 115 101 sysarg_t paddr; 102 if (sysinfo_get_value("kbd.address.physical", &paddr) != EOK) { 103 rc = ENOENT; 104 goto error; 105 } 106 107 sysarg_t inr; 108 if (sysinfo_get_value("kbd.inr", &inr) != EOK) { 109 rc = ENOENT; 110 goto error; 111 } 112 113 msim_ranges[0].base = paddr; 114 msim_cmds[0].addr = (void *) paddr; 115 async_irq_subscribe(inr, msim_irq_handler, con, &msim_kbd); 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); 116 128 subscribed = true; 129 130 chardev_srvs_init(&con->cds); 131 con->cds.ops = &msim_con_chardev_ops; 132 con->cds.sarg = con; 117 133 118 134 rc = ddf_fun_bind(fun); … … 122 138 } 123 139 140 ddf_fun_add_to_category(fun, "console"); 141 124 142 return EOK; 125 143 error: 126 144 if (subscribed) 127 async_irq_unsubscribe( inr);145 async_irq_unsubscribe(res->irq); 128 146 if (fun != NULL) 129 147 ddf_fun_destroy(fun); 148 free(msim_cmds); 130 149 131 150 return rc; … … 146 165 static void msim_con_putchar(msim_con_t *con, uint8_t ch) 147 166 { 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; 148 211 } 149 212 … … 152 215 void *arg) 153 216 { 154 msim_con_t *con; 155 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 } 217 msim_con_t *con = (msim_con_t *) ddf_dev_data_get( 218 ddf_fun_get_dev((ddf_fun_t *) arg)); 219 220 chardev_conn(iid, icall, &con->cds); 193 221 } 194 222
Note:
See TracChangeset
for help on using the changeset viewer.
