Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.c

    r071a1ddb r24abb85d  
    2727 */
    2828
     29/** @addtogroup driver_serial
     30 * @{
     31 */
    2932/**
    3033 * @file
     
    3437 */
    3538
     39#include <ddi.h>
     40#include <loc.h>
     41#include <ipc/char.h>
    3642#include <async.h>
    37 #include <ddi.h>
    38 #include <errno.h>
    39 #include <inttypes.h>
    40 #include <io/chardev_srv.h>
    41 #include <loc.h>
    4243#include <stdio.h>
    4344#include <stdlib.h>
    4445#include <sysinfo.h>
     46#include <errno.h>
     47#include <inttypes.h>
    4548#include "s3c24xx_uart.h"
    4649
     
    6568
    6669static void s3c24xx_uart_connection(ipc_callid_t, ipc_call_t *, void *);
    67 static void s3c24xx_uart_irq_handler(ipc_call_t *, void *);
     70static void s3c24xx_uart_irq_handler(ipc_callid_t, ipc_call_t *, void *);
    6871static int s3c24xx_uart_init(s3c24xx_uart_t *);
    6972static void s3c24xx_uart_sendb(s3c24xx_uart_t *, uint8_t);
    7073
    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 
    7974int main(int argc, char *argv[])
    8075{
    8176        printf("%s: S3C24xx on-chip UART driver\n", NAME);
    8277       
    83         async_set_fallback_port_handler(s3c24xx_uart_connection, uart);
     78        async_set_fallback_port_handler(s3c24xx_uart_connection, NULL);
    8479        int rc = loc_server_register(NAME);
    8580        if (rc != EOK) {
     
    116111    void *arg)
    117112{
    118         s3c24xx_uart_t *uart = (s3c24xx_uart_t *) arg;
    119 
    120         chardev_conn(iid, icall, &uart->cds);
    121 }
    122 
    123 
    124 static void s3c24xx_uart_irq_handler(ipc_call_t *call, void *arg)
    125 {
    126         int rc;
    127 
     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}
     149
     150static void s3c24xx_uart_irq_handler(ipc_callid_t iid, ipc_call_t *call,
     151    void *arg)
     152{
     153        (void) iid;
    128154        (void) call;
    129155        (void) arg;
     
    133159                uint32_t status = pio_read_32(&uart->io->uerstat);
    134160
    135                 fibril_mutex_lock(&uart->buf_lock);
    136 
    137                 rc = circ_buf_push(&uart->cbuf, &data);
    138                 if (rc != EOK)
    139                         printf(NAME ": Buffer overrun\n");
    140 
    141                 fibril_mutex_unlock(&uart->buf_lock);
    142                 fibril_condvar_broadcast(&uart->buf_cv);
     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                }
    143166
    144167                if (status != 0)
     
    153176        sysarg_t inr;
    154177
    155         circ_buf_init(&uart->cbuf, uart->buf, s3c24xx_uart_buf_size, 1);
    156         fibril_mutex_initialize(&uart->buf_lock);
    157         fibril_condvar_initialize(&uart->buf_cv);
    158 
    159178        if (sysinfo_get_value("s3c24xx_uart.address.physical",
    160179            &uart->paddr) != EOK)
     
    169188
    170189        uart->io = vaddr;
     190        uart->client_sess = NULL;
    171191
    172192        printf(NAME ": device at physical address %p, inr %" PRIun ".\n",
    173193            (void *) uart->paddr, inr);
    174194
    175         async_irq_subscribe(inr, s3c24xx_uart_irq_handler, NULL, &uart_irq_code, NULL);
     195        async_irq_subscribe(inr, s3c24xx_uart_irq_handler, NULL, &uart_irq_code);
    176196
    177197        /* Enable FIFO, Tx trigger level: empty, Rx trigger level: 1 byte. */
     
    183203            pio_read_32(&uart->io->ucon) & ~UCON_RX_INT_LEVEL);
    184204
    185         chardev_srvs_init(&uart->cds);
    186         uart->cds.ops = &s3c24xx_uart_chardev_ops;
    187         uart->cds.sarg = uart;
    188 
    189205        return EOK;
    190206}
     
    200216}
    201217
    202 static int s3c24xx_uart_read(chardev_srv_t *srv, void *buf, size_t size,
    203     size_t *nread)
    204 {
    205         s3c24xx_uart_t *uart = (s3c24xx_uart_t *) srv->srvs->sarg;
    206         size_t p;
    207         uint8_t *bp = (uint8_t *) buf;
    208         int rc;
    209 
    210         fibril_mutex_lock(&uart->buf_lock);
    211 
    212         while (circ_buf_nused(&uart->cbuf) == 0)
    213                 fibril_condvar_wait(&uart->buf_cv, &uart->buf_lock);
    214 
    215         p = 0;
    216         while (p < size) {
    217                 rc = circ_buf_pop(&uart->cbuf, &bp[p]);
    218                 if (rc != EOK)
    219                         break;
    220                 ++p;
    221         }
    222 
    223         fibril_mutex_unlock(&uart->buf_lock);
    224 
    225         *nread = p;
    226         return EOK;
    227 }
    228 
    229 static int s3c24xx_uart_write(chardev_srv_t *srv, const void *data, size_t size,
    230     size_t *nwr)
    231 {
    232         s3c24xx_uart_t *uart = (s3c24xx_uart_t *) srv->srvs->sarg;
    233         size_t i;
    234         uint8_t *dp = (uint8_t *) data;
    235 
    236         for (i = 0; i < size; i++)
    237                 s3c24xx_uart_sendb(uart, dp[i]);
    238 
    239         *nwr = size;
    240         return EOK;
    241 }
    242 
    243 
    244218/** @}
    245219 */
Note: See TracChangeset for help on using the changeset viewer.