Changeset 7a6065c in mainline for uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.c
- Timestamp:
- 2017-11-23T11:56:31Z (6 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 221176c1
- Parents:
- 74017ce
- git-author:
- Jiri Svoboda <jiri@…> (2017-11-22 19:55:36)
- git-committer:
- Jiri Svoboda <jiri@…> (2017-11-23 11:56:31)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.c
r74017ce r7a6065c 27 27 */ 28 28 29 /** @addtogroup driver_serial30 * @{31 */32 29 /** 33 30 * @file … … 37 34 */ 38 35 36 #include <async.h> 39 37 #include <ddi.h> 38 #include <errno.h> 39 #include <inttypes.h> 40 #include <io/chardev_srv.h> 40 41 #include <loc.h> 41 #include <ipc/char.h>42 #include <async.h>43 42 #include <stdio.h> 44 43 #include <stdlib.h> 45 44 #include <sysinfo.h> 46 #include <errno.h>47 #include <inttypes.h>48 45 #include "s3c24xx_uart.h" 49 46 … … 72 69 static void s3c24xx_uart_sendb(s3c24xx_uart_t *, uint8_t); 73 70 71 static int s3c24xx_uart_read(chardev_srv_t *, void *, size_t, size_t *); 72 static int s3c24xx_uart_write(chardev_srv_t *, const void *, size_t, size_t *); 73 74 static chardev_ops_t s3c24xx_uart_chardev_ops = { 75 .read = s3c24xx_uart_read, 76 .write = s3c24xx_uart_write 77 }; 78 74 79 int main(int argc, char *argv[]) 75 80 { 76 81 printf("%s: S3C24xx on-chip UART driver\n", NAME); 77 82 78 async_set_fallback_port_handler(s3c24xx_uart_connection, NULL);83 async_set_fallback_port_handler(s3c24xx_uart_connection, uart); 79 84 int rc = loc_server_register(NAME); 80 85 if (rc != EOK) { … … 111 116 void *arg) 112 117 { 113 /* Answer the IPC_M_CONNECT_ME_TO call. */ 114 async_answer_0(iid, EOK); 115 116 while (true) { 117 ipc_call_t call; 118 ipc_callid_t callid = async_get_call(&call); 119 sysarg_t method = IPC_GET_IMETHOD(call); 120 121 if (!method) { 122 /* The other side has hung up. */ 123 async_answer_0(callid, EOK); 124 return; 125 } 126 127 async_sess_t *sess = 128 async_callback_receive_start(EXCHANGE_SERIALIZE, &call); 129 if (sess != NULL) { 130 if (uart->client_sess == NULL) { 131 uart->client_sess = sess; 132 async_answer_0(callid, EOK); 133 } else 134 async_answer_0(callid, ELIMIT); 135 } else { 136 switch (method) { 137 case CHAR_WRITE_BYTE: 138 printf(NAME ": write %" PRIun " to device\n", 139 IPC_GET_ARG1(call)); 140 s3c24xx_uart_sendb(uart, (uint8_t) IPC_GET_ARG1(call)); 141 async_answer_0(callid, EOK); 142 break; 143 default: 144 async_answer_0(callid, EINVAL); 145 } 146 } 147 } 148 } 118 s3c24xx_uart_t *uart = (s3c24xx_uart_t *) arg; 119 120 chardev_conn(iid, icall, &uart->cds); 121 } 122 149 123 150 124 static void s3c24xx_uart_irq_handler(ipc_callid_t iid, ipc_call_t *call, 151 125 void *arg) 152 126 { 127 int rc; 128 153 129 (void) iid; 154 130 (void) call; … … 159 135 uint32_t status = pio_read_32(&uart->io->uerstat); 160 136 161 if (uart->client_sess != NULL) { 162 async_exch_t *exch = async_exchange_begin(uart->client_sess); 163 async_msg_1(exch, CHAR_NOTIF_BYTE, data); 164 async_exchange_end(exch); 165 } 137 fibril_mutex_lock(&uart->buf_lock); 138 139 rc = circ_buf_push(&uart->cbuf, &data); 140 if (rc != EOK) 141 printf(NAME ": Buffer overrun\n"); 142 143 fibril_mutex_unlock(&uart->buf_lock); 144 fibril_condvar_broadcast(&uart->buf_cv); 166 145 167 146 if (status != 0) … … 176 155 sysarg_t inr; 177 156 157 circ_buf_init(&uart->cbuf, uart->buf, s3c24xx_uart_buf_size, 1); 158 fibril_mutex_initialize(&uart->buf_lock); 159 fibril_condvar_initialize(&uart->buf_cv); 160 178 161 if (sysinfo_get_value("s3c24xx_uart.address.physical", 179 162 &uart->paddr) != EOK) … … 188 171 189 172 uart->io = vaddr; 190 uart->client_sess = NULL;191 173 192 174 printf(NAME ": device at physical address %p, inr %" PRIun ".\n", … … 203 185 pio_read_32(&uart->io->ucon) & ~UCON_RX_INT_LEVEL); 204 186 187 chardev_srvs_init(&uart->cds); 188 uart->cds.ops = &s3c24xx_uart_chardev_ops; 189 uart->cds.sarg = uart; 190 205 191 return EOK; 206 192 } … … 216 202 } 217 203 204 static int s3c24xx_uart_read(chardev_srv_t *srv, void *buf, size_t size, 205 size_t *nread) 206 { 207 s3c24xx_uart_t *uart = (s3c24xx_uart_t *) srv->srvs->sarg; 208 size_t p; 209 uint8_t *bp = (uint8_t *) buf; 210 int rc; 211 212 fibril_mutex_lock(&uart->buf_lock); 213 214 while (circ_buf_nused(&uart->cbuf) == 0) 215 fibril_condvar_wait(&uart->buf_cv, &uart->buf_lock); 216 217 p = 0; 218 while (p < size) { 219 rc = circ_buf_pop(&uart->cbuf, &bp[p]); 220 if (rc != EOK) 221 break; 222 ++p; 223 } 224 225 fibril_mutex_unlock(&uart->buf_lock); 226 227 *nread = p; 228 return EOK; 229 } 230 231 static int s3c24xx_uart_write(chardev_srv_t *srv, const void *data, size_t size, 232 size_t *nwr) 233 { 234 s3c24xx_uart_t *uart = (s3c24xx_uart_t *) srv->srvs->sarg; 235 size_t i; 236 uint8_t *dp = (uint8_t *) data; 237 238 for (i = 0; i < size; i++) 239 s3c24xx_uart_sendb(uart, dp[i]); 240 241 *nwr = size; 242 return EOK; 243 } 244 245 218 246 /** @} 219 247 */
Note:
See TracChangeset
for help on using the changeset viewer.