Changeset b224a3e in mainline for uspace/drv/char/ns8250/ns8250.c


Ignore:
Timestamp:
2012-08-15T23:55:32Z (12 years ago)
Author:
Sean Bartell <wingedtachikoma@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
681a985
Parents:
71b0d4d4 (diff), b8b742e (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.
Message:

Merge mainline changes

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/char/ns8250/ns8250.c

    r71b0d4d4 rb224a3e  
    8282/** Interrupt ID Register definition. */
    8383#define NS8250_IID_ACTIVE       (1 << 0)
     84#define NS8250_IID_CAUSE_MASK 0x0e
     85#define NS8250_IID_CAUSE_RXSTATUS 0x06
    8486
    8587/** FIFO Control Register definition. */
     
    179181        /** The fibril mutex for synchronizing the access to the device. */
    180182        fibril_mutex_t mutex;
     183        /** Indicates that some data has become available */
     184        fibril_condvar_t input_buffer_available;
    181185        /** True if device is removed. */
    182186        bool removed;
     
    238242{
    239243        ns8250_t *ns = NS8250(fun);
    240         int ret = EOK;
     244        int ret = 0;
     245       
     246        if (count == 0) return 0;
    241247       
    242248        fibril_mutex_lock(&ns->mutex);
     249        while (buf_is_empty(&ns->input_buffer))
     250                fibril_condvar_wait(&ns->input_buffer_available, &ns->mutex);
    243251        while (!buf_is_empty(&ns->input_buffer) && (size_t)ret < count) {
    244252                buf[ret] = (char)buf_pop_front(&ns->input_buffer);
     
    460468{
    461469        /* Interrupt when data received. */
    462         pio_write_8(&regs->ier, NS8250_IER_RXREADY);
     470        pio_write_8(&regs->ier, NS8250_IER_RXREADY | NS8250_IER_RXSTATUS);
    463471        pio_write_8(&regs->mcr, NS8250_MCR_DTR | NS8250_MCR_RTS
    464472            | NS8250_MCR_OUT2);
     
    499507        async_exchange_end(exch);
    500508
     509        /* Read LSR to clear possible previous LSR interrupt */
     510        pio_read_8(&ns->regs->lsr);
     511
    501512        /* Enable interrupt on the serial port. */
    502513        ns8250_port_interrupts_enable(ns->regs);
     
    695706        /* 8 bits, no parity, two stop bits. */
    696707        ns8250_port_set_com_props(ns->regs, SERIAL_NO_PARITY, 8, 2);
    697         /* Enable FIFO, clear them, with 14-byte threshold. */
     708        /*
     709         * Enable FIFO, clear them, with 4-byte threshold for greater
     710         * reliability.
     711         */
    698712        pio_write_8(&ns->regs->iid, NS8250_FCR_FIFOENABLE
    699             | NS8250_FCR_RXFIFORESET | NS8250_FCR_TXFIFORESET 
    700             | NS8250_FCR_RXTRIGGERLOW | NS8250_FCR_RXTRIGGERHI);
     713            | NS8250_FCR_RXFIFORESET | NS8250_FCR_TXFIFORESET
     714            | NS8250_FCR_RXTRIGGERLOW);
    701715        /*
    702716         * RTS/DSR set (Request to Send and Data Terminal Ready lines enabled),
     
    731745        bool cont = true;
    732746       
     747        fibril_mutex_lock(&ns->mutex);
    733748        while (cont) {
    734                 fibril_mutex_lock(&ns->mutex);
    735                
    736749                cont = ns8250_received(regs);
    737750                if (cont) {
     
    739752                       
    740753                        if (ns->client_connected) {
     754                                bool buf_was_empty = buf_is_empty(&ns->input_buffer);
    741755                                if (!buf_push_back(&ns->input_buffer, val)) {
    742756                                        ddf_msg(LVL_WARN, "Buffer overflow on "
    743757                                            "%s.", ns->dev->name);
     758                                        break;
    744759                                } else {
    745760                                        ddf_msg(LVL_DEBUG2, "Character %c saved "
    746761                                            "to the buffer of %s.",
    747762                                            val, ns->dev->name);
     763                                        if (buf_was_empty)
     764                                                fibril_condvar_broadcast(&ns->input_buffer_available);
    748765                                }
    749766                        }
    750767                }
    751                
    752                 fibril_mutex_unlock(&ns->mutex);
    753                 fibril_yield();
    754         }
     768        }
     769        fibril_mutex_unlock(&ns->mutex);
     770        fibril_yield();
    755771}
    756772
    757773/** The interrupt handler.
    758774 *
    759  * The serial port is initialized to interrupt when some data come, so the
    760  * interrupt is handled by reading the incomming data.
     775 * The serial port is initialized to interrupt when some data come or line
     776 * status register changes, so the interrupt is handled by reading the incoming
     777 * data and reading the line status register.
    761778 *
    762779 * @param dev           The serial port device.
     
    765782    ipc_call_t *icall)
    766783{
    767         ns8250_read_from_device(NS8250_FROM_DEV(dev));
     784        ns8250_t *ns = NS8250_FROM_DEV(dev);
     785
     786        uint8_t iir = pio_read_8(&ns->regs->iid);
     787        if ((iir & NS8250_IID_CAUSE_MASK) == NS8250_IID_CAUSE_RXSTATUS) {
     788                uint8_t lsr = pio_read_8(&ns->regs->lsr);
     789                if (lsr & NS8250_LSR_OE) {
     790                        ddf_msg(LVL_WARN, "Overrun error on %s", ns->dev->name);
     791                }
     792        }
     793       
     794        ns8250_read_from_device(ns);
    768795}
    769796
     
    811838       
    812839        fibril_mutex_initialize(&ns->mutex);
     840        fibril_condvar_initialize(&ns->input_buffer_available);
    813841        ns->dev = dev;
    814842       
     
    10531081static void ns8250_init(void)
    10541082{
    1055         ddf_log_init(NAME, LVL_ERROR);
     1083        ddf_log_init(NAME, LVL_WARN);
    10561084       
    10571085        ns8250_dev_ops.open = &ns8250_open;
Note: See TracChangeset for help on using the changeset viewer.