Changes in uspace/drv/char/msim-con/msim-con.c [071a1ddb:7aa94304] in mainline
- 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
r071a1ddb r7aa94304 37 37 #include <ddi.h> 38 38 #include <errno.h> 39 #include <io/chardev_srv.h> 39 #include <ipc/char.h> 40 #include <sysinfo.h> 40 41 41 42 #include "msim-con.h" … … 43 44 static void msim_con_connection(ipc_callid_t, ipc_call_t *, void *); 44 45 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 46 static irq_pio_range_t msim_ranges[] = { 47 { 48 .base = 0, 49 .size = 1 50 } 51 51 }; 52 52 53 static irq_cmd_t msim_cmds _proto[] = {53 static irq_cmd_t msim_cmds[] = { 54 54 { 55 55 .cmd = CMD_PIO_READ_8, … … 62 62 }; 63 63 64 static void msim_irq_handler(ipc_call_t *call, void *arg) 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) 65 72 { 66 73 msim_con_t *con = (msim_con_t *) arg; 67 74 uint8_t c; 68 int rc;69 70 fibril_mutex_lock(&con->buf_lock);71 75 72 76 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 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 } 79 83 } 80 84 81 85 /** Add msim console device. */ 82 int msim_con_add(msim_con_t *con , msim_con_res_t *res)86 int msim_con_add(msim_con_t *con) 83 87 { 84 88 ddf_fun_t *fun = NULL; 85 89 bool subscribed = false; 86 irq_cmd_t *msim_cmds = NULL;87 90 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;100 91 101 92 fun = ddf_fun_create(con->dev, fun_exposed, "a"); … … 106 97 } 107 98 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; 111 104 goto error; 112 105 } 113 106 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 } 115 112 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); 128 116 subscribed = true; 129 130 chardev_srvs_init(&con->cds);131 con->cds.ops = &msim_con_chardev_ops;132 con->cds.sarg = con;133 117 134 118 rc = ddf_fun_bind(fun); … … 138 122 } 139 123 140 ddf_fun_add_to_category(fun, "console");141 142 124 return EOK; 143 125 error: 144 126 if (subscribed) 145 async_irq_unsubscribe( res->irq);127 async_irq_unsubscribe(inr); 146 128 if (fun != NULL) 147 129 ddf_fun_destroy(fun); 148 free(msim_cmds);149 130 150 131 return rc; … … 165 146 static void msim_con_putchar(msim_con_t *con, uint8_t ch) 166 147 { 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;211 148 } 212 149 … … 215 152 void *arg) 216 153 { 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; 219 155 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 } 221 193 } 222 194
Note:
See TracChangeset
for help on using the changeset viewer.
