Ignore:
File:
1 edited

Legend:

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

    r4510e06 rc7235d40  
    4040#include <stdio.h>
    4141#include <errno.h>
    42 #include <stdbool.h>
     42#include <bool.h>
    4343#include <fibril_synch.h>
    4444#include <stdlib.h>
     
    5151#include <sys/stat.h>
    5252#include <ddi.h>
     53#include <libarch/ddi.h>
    5354
    5455#include <ddf/driver.h>
     
    5758#include <ops/char_dev.h>
    5859
     60#include <devman.h>
    5961#include <ns.h>
     62#include <ipc/devman.h>
    6063#include <ipc/services.h>
    6164#include <ipc/irc.h>
     
    7982/** Interrupt ID Register definition. */
    8083#define NS8250_IID_ACTIVE       (1 << 0)
    81 #define NS8250_IID_CAUSE_MASK 0x0e
    82 #define NS8250_IID_CAUSE_RXSTATUS 0x06
    8384
    8485/** FIFO Control Register definition. */
     
    125126    | NS8250_MSR_RI | NS8250_MSR_DCD)
    126127
     128/** Obtain soft-state structure from function node */
     129#define NS8250(fnode) ((ns8250_t *) ((fnode)->dev->driver_data))
     130
     131/** Obtain soft-state structure from device node */
     132#define NS8250_FROM_DEV(dnode) ((ns8250_t *) ((dnode)->driver_data))
     133
    127134/** The number of bits of one data unit send by the serial port. */
    128135typedef enum {
     
    160167        /** I/O registers **/
    161168        ns8250_regs_t *regs;
    162         /** Are there any clients connected to the device? */
    163         unsigned client_connections;
     169        /** Is there any client conntected to the device? */
     170        bool client_connected;
    164171        /** The irq assigned to this device. */
    165172        int irq;
     
    168175        /** The i/o port used to access the serial ports registers. */
    169176        ioport8_t *port;
    170         /** The buffer for incoming data. */
     177        /** The buffer for incomming data. */
    171178        cyclic_buffer_t input_buffer;
    172179        /** The fibril mutex for synchronizing the access to the device. */
    173180        fibril_mutex_t mutex;
    174         /** Indicates that some data has become available */
    175         fibril_condvar_t input_buffer_available;
    176181        /** True if device is removed. */
    177182        bool removed;
    178183} ns8250_t;
    179184
    180 /** Obtain soft-state structure from device node */
    181 static ns8250_t *dev_ns8250(ddf_dev_t *dev)
    182 {
    183         return ddf_dev_data_get(dev);
    184 }
    185 
    186 /** Obtain soft-state structure from function node */
    187 static ns8250_t *fun_ns8250(ddf_fun_t *fun)
    188 {
    189         return dev_ns8250(ddf_fun_get_dev(fun));
    190 }
    191 
    192 /** Find out if there is some incoming data available on the serial port.
     185/** Find out if there is some incomming data available on the serial port.
    193186 *
    194187 * @param port          The base address of the serial port device's ports.
     
    244237static int ns8250_read(ddf_fun_t *fun, char *buf, size_t count)
    245238{
    246         ns8250_t *ns = fun_ns8250(fun);
    247         int ret = 0;
    248        
    249         if (count == 0) return 0;
     239        ns8250_t *ns = NS8250(fun);
     240        int ret = EOK;
    250241       
    251242        fibril_mutex_lock(&ns->mutex);
    252         while (buf_is_empty(&ns->input_buffer))
    253                 fibril_condvar_wait(&ns->input_buffer_available, &ns->mutex);
    254243        while (!buf_is_empty(&ns->input_buffer) && (size_t)ret < count) {
    255244                buf[ret] = (char)buf_pop_front(&ns->input_buffer);
     
    282271static int ns8250_write(ddf_fun_t *fun, char *buf, size_t count)
    283272{
    284         ns8250_t *ns = fun_ns8250(fun);
     273        ns8250_t *ns = NS8250(fun);
    285274        size_t idx;
    286275       
     
    320309static void ns8250_dev_cleanup(ns8250_t *ns)
    321310{
     311        if (ns->dev->parent_sess) {
     312                async_hangup(ns->dev->parent_sess);
     313                ns->dev->parent_sess = NULL;
     314        }
    322315}
    323316
     
    329322static bool ns8250_pio_enable(ns8250_t *ns)
    330323{
    331         ddf_msg(LVL_DEBUG, "ns8250_pio_enable %s", ddf_dev_get_name(ns->dev));
     324        ddf_msg(LVL_DEBUG, "ns8250_pio_enable %s", ns->dev->name);
    332325       
    333326        /* Gain control over port's registers. */
     
    335328            (void **) &ns->port)) {
    336329                ddf_msg(LVL_ERROR, "Cannot map the port %#" PRIx32
    337                     " for device %s.", ns->io_addr, ddf_dev_get_name(ns->dev));
     330                    " for device %s.", ns->io_addr, ns->dev->name);
    338331                return false;
    339332        }
     
    351344static bool ns8250_dev_probe(ns8250_t *ns)
    352345{
    353         ddf_msg(LVL_DEBUG, "ns8250_dev_probe %s", ddf_dev_get_name(ns->dev));
     346        ddf_msg(LVL_DEBUG, "ns8250_dev_probe %s", ns->dev->name);
    354347       
    355348        bool res = true;
     
    371364        if (!res) {
    372365                ddf_msg(LVL_DEBUG, "Device %s is not present.",
    373                     ddf_dev_get_name(ns->dev));
     366                    ns->dev->name);
    374367        }
    375368       
     
    384377static int ns8250_dev_initialize(ns8250_t *ns)
    385378{
    386         async_sess_t *parent_sess;
     379        ddf_msg(LVL_DEBUG, "ns8250_dev_initialize %s", ns->dev->name);
     380       
    387381        int ret = EOK;
    388        
    389         ddf_msg(LVL_DEBUG, "ns8250_dev_initialize %s", ddf_dev_get_name(ns->dev));
    390382       
    391383        hw_resource_list_t hw_resources;
     
    393385       
    394386        /* Connect to the parent's driver. */
    395         parent_sess = ddf_dev_parent_sess_create(ns->dev, EXCHANGE_SERIALIZE);
    396         if (parent_sess == NULL) {
     387        ns->dev->parent_sess = devman_parent_device_connect(EXCHANGE_SERIALIZE,
     388            ns->dev->handle, IPC_FLAG_BLOCKING);
     389        if (!ns->dev->parent_sess) {
    397390                ddf_msg(LVL_ERROR, "Failed to connect to parent driver of "
    398                     "device %s.", ddf_dev_get_name(ns->dev));
     391                    "device %s.", ns->dev->name);
    399392                ret = ENOENT;
    400393                goto failed;
     
    402395       
    403396        /* Get hw resources. */
    404         ret = hw_res_get_resource_list(parent_sess, &hw_resources);
     397        ret = hw_res_get_resource_list(ns->dev->parent_sess, &hw_resources);
    405398        if (ret != EOK) {
    406399                ddf_msg(LVL_ERROR, "Failed to get HW resources for device "
    407                     "%s.", ddf_dev_get_name(ns->dev));
     400                    "%s.", ns->dev->name);
    408401                goto failed;
    409402        }
     
    421414                        irq = true;
    422415                        ddf_msg(LVL_NOTE, "Device %s was asigned irq = 0x%x.",
    423                             ddf_dev_get_name(ns->dev), ns->irq);
     416                            ns->dev->name, ns->irq);
    424417                        break;
    425418                       
     
    428421                        if (res->res.io_range.size < REG_COUNT) {
    429422                                ddf_msg(LVL_ERROR, "I/O range assigned to "
    430                                     "device %s is too small.", ddf_dev_get_name(ns->dev));
     423                                    "device %s is too small.", ns->dev->name);
    431424                                ret = ELIMIT;
    432425                                goto failed;
     
    434427                        ioport = true;
    435428                        ddf_msg(LVL_NOTE, "Device %s was asigned I/O address = "
    436                             "0x%x.", ddf_dev_get_name(ns->dev), ns->io_addr);
     429                            "0x%x.", ns->dev->name, ns->io_addr);
    437430                        break;
    438431                       
     
    444437        if (!irq || !ioport) {
    445438                ddf_msg(LVL_ERROR, "Missing HW resource(s) for device %s.",
    446                     ddf_dev_get_name(ns->dev));
     439                    ns->dev->name);
    447440                ret = ENOENT;
    448441                goto failed;
     
    467460{
    468461        /* Interrupt when data received. */
    469         pio_write_8(&regs->ier, NS8250_IER_RXREADY | NS8250_IER_RXSTATUS);
     462        pio_write_8(&regs->ier, NS8250_IER_RXREADY);
    470463        pio_write_8(&regs->mcr, NS8250_MCR_DTR | NS8250_MCR_RTS
    471464            | NS8250_MCR_OUT2);
     
    506499        async_exchange_end(exch);
    507500
    508         /* Read LSR to clear possible previous LSR interrupt */
    509         pio_read_8(&ns->regs->lsr);
    510 
    511501        /* Enable interrupt on the serial port. */
    512502        ns8250_port_interrupts_enable(ns->regs);
     
    612602        *parity = ((val >> NS8250_LCR_PARITY) & 7);
    613603       
    614         /* Silence warnings */
    615         *word_length = 0;
    616 
    617604        switch (val & 3) {
    618605        case WORD_LENGTH_5:
     
    708695        /* 8 bits, no parity, two stop bits. */
    709696        ns8250_port_set_com_props(ns->regs, SERIAL_NO_PARITY, 8, 2);
    710         /*
    711          * Enable FIFO, clear them, with 4-byte threshold for greater
    712          * reliability.
    713          */
     697        /* Enable FIFO, clear them, with 14-byte threshold. */
    714698        pio_write_8(&ns->regs->iid, NS8250_FCR_FIFOENABLE
    715             | NS8250_FCR_RXFIFORESET | NS8250_FCR_TXFIFORESET
    716             | NS8250_FCR_RXTRIGGERLOW);
     699            | NS8250_FCR_RXFIFORESET | NS8250_FCR_TXFIFORESET 
     700            | NS8250_FCR_RXTRIGGERLOW | NS8250_FCR_RXTRIGGERHI);
    717701        /*
    718702         * RTS/DSR set (Request to Send and Data Terminal Ready lines enabled),
     
    747731        bool cont = true;
    748732       
    749         fibril_mutex_lock(&ns->mutex);
    750733        while (cont) {
     734                fibril_mutex_lock(&ns->mutex);
     735               
    751736                cont = ns8250_received(regs);
    752737                if (cont) {
    753738                        uint8_t val = ns8250_read_8(regs);
    754739                       
    755                         if (ns->client_connections > 0) {
    756                                 bool buf_was_empty = buf_is_empty(&ns->input_buffer);
     740                        if (ns->client_connected) {
    757741                                if (!buf_push_back(&ns->input_buffer, val)) {
    758742                                        ddf_msg(LVL_WARN, "Buffer overflow on "
    759                                             "%s.", ddf_dev_get_name(ns->dev));
    760                                         break;
     743                                            "%s.", ns->dev->name);
    761744                                } else {
    762745                                        ddf_msg(LVL_DEBUG2, "Character %c saved "
    763746                                            "to the buffer of %s.",
    764                                             val, ddf_dev_get_name(ns->dev));
    765                                         if (buf_was_empty)
    766                                                 fibril_condvar_broadcast(&ns->input_buffer_available);
     747                                            val, ns->dev->name);
    767748                                }
    768749                        }
    769750                }
    770         }
    771         fibril_mutex_unlock(&ns->mutex);
    772         fibril_yield();
     751               
     752                fibril_mutex_unlock(&ns->mutex);
     753                fibril_yield();
     754        }
    773755}
    774756
    775757/** The interrupt handler.
    776758 *
    777  * The serial port is initialized to interrupt when some data come or line
    778  * status register changes, so the interrupt is handled by reading the incoming
    779  * data and reading the line status register.
     759 * The serial port is initialized to interrupt when some data come, so the
     760 * interrupt is handled by reading the incomming data.
    780761 *
    781762 * @param dev           The serial port device.
     
    784765    ipc_call_t *icall)
    785766{
    786         ns8250_t *ns = dev_ns8250(dev);
    787 
    788         uint8_t iir = pio_read_8(&ns->regs->iid);
    789         if ((iir & NS8250_IID_CAUSE_MASK) == NS8250_IID_CAUSE_RXSTATUS) {
    790                 uint8_t lsr = pio_read_8(&ns->regs->lsr);
    791                 if (lsr & NS8250_LSR_OE) {
    792                         ddf_msg(LVL_WARN, "Overrun error on %s", ddf_dev_get_name(ns->dev));
    793                 }
    794         }
    795        
    796         ns8250_read_from_device(ns);
     767        ns8250_read_from_device(NS8250_FROM_DEV(dev));
    797768}
    798769
     
    830801       
    831802        ddf_msg(LVL_DEBUG, "ns8250_dev_add %s (handle = %d)",
    832             ddf_dev_get_name(dev), (int) ddf_dev_get_handle(dev));
     803            dev->name, (int) dev->handle);
    833804       
    834805        /* Allocate soft-state for the device */
     
    840811       
    841812        fibril_mutex_initialize(&ns->mutex);
    842         fibril_condvar_initialize(&ns->input_buffer_available);
    843813        ns->dev = dev;
    844814       
     
    885855       
    886856        /* Set device operations. */
    887         ddf_fun_set_ops(fun, &ns8250_dev_ops);
     857        fun->ops = &ns8250_dev_ops;
    888858        rc = ddf_fun_bind(fun);
    889859        if (rc != EOK) {
     
    897867       
    898868        ddf_msg(LVL_NOTE, "Device %s successfully initialized.",
    899             ddf_dev_get_name(dev));
     869            dev->name);
    900870       
    901871        return EOK;
     
    910880static int ns8250_dev_remove(ddf_dev_t *dev)
    911881{
    912         ns8250_t *ns = dev_ns8250(dev);
     882        ns8250_t *ns = NS8250_FROM_DEV(dev);
    913883        int rc;
    914884       
    915885        fibril_mutex_lock(&ns->mutex);
    916                 if (ns->client_connections > 0) {
     886        if (ns->client_connected) {
    917887                fibril_mutex_unlock(&ns->mutex);
    918888                return EBUSY;
     
    944914static int ns8250_open(ddf_fun_t *fun)
    945915{
    946         ns8250_t *ns = fun_ns8250(fun);
     916        ns8250_t *ns = NS8250(fun);
    947917        int res;
    948918       
    949919        fibril_mutex_lock(&ns->mutex);
    950         if (ns->removed) {
     920        if (ns->client_connected) {
     921                res = ELIMIT;
     922        } else if (ns->removed) {
    951923                res = ENXIO;
    952924        } else {
    953925                res = EOK;
    954                 ns->client_connections++;
     926                ns->client_connected = true;
    955927        }
    956928        fibril_mutex_unlock(&ns->mutex);
     
    968940static void ns8250_close(ddf_fun_t *fun)
    969941{
    970         ns8250_t *data = fun_ns8250(fun);
     942        ns8250_t *data = (ns8250_t *) fun->dev->driver_data;
    971943       
    972944        fibril_mutex_lock(&data->mutex);
    973945       
    974         assert(data->client_connections > 0);
    975        
    976         if (!(--data->client_connections))
    977                 buf_clear(&data->input_buffer);
     946        assert(data->client_connected);
     947       
     948        data->client_connected = false;
     949        buf_clear(&data->input_buffer);
    978950       
    979951        fibril_mutex_unlock(&data->mutex);
     
    993965    unsigned int *word_length, unsigned int* stop_bits)
    994966{
    995         ns8250_t *data = dev_ns8250(dev);
     967        ns8250_t *data = (ns8250_t *) dev->driver_data;
    996968        ns8250_regs_t *regs = data->regs;
    997969       
     
    1024996            stop_bits);
    1025997       
    1026         ns8250_t *data = dev_ns8250(dev);
     998        ns8250_t *data = (ns8250_t *) dev->driver_data;
    1027999        ns8250_regs_t *regs = data->regs;
    10281000        int ret;
     
    10531025        switch (method) {
    10541026        case SERIAL_GET_COM_PROPS:
    1055                 ns8250_get_props(ddf_fun_get_dev(fun), &baud_rate, &parity, &word_length,
     1027                ns8250_get_props(fun->dev, &baud_rate, &parity, &word_length,
    10561028                    &stop_bits);
    10571029                async_answer_4(callid, EOK, baud_rate, parity, word_length,
     
    10641036                word_length = IPC_GET_ARG3(*call);
    10651037                stop_bits = IPC_GET_ARG4(*call);
    1066                 ret = ns8250_set_props(ddf_fun_get_dev(fun), baud_rate, parity, word_length,
     1038                ret = ns8250_set_props(fun->dev, baud_rate, parity, word_length,
    10671039                    stop_bits);
    10681040                async_answer_0(callid, ret);
     
    10811053static void ns8250_init(void)
    10821054{
    1083         ddf_log_init(NAME);
     1055        ddf_log_init(NAME, LVL_ERROR);
    10841056       
    10851057        ns8250_dev_ops.open = &ns8250_open;
Note: See TracChangeset for help on using the changeset viewer.