Ignore:
File:
1 edited

Legend:

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

    r56fd7cf rc7235d40  
    5858#include <ops/char_dev.h>
    5959
     60#include <devman.h>
    6061#include <ns.h>
     62#include <ipc/devman.h>
    6163#include <ipc/services.h>
    6264#include <ipc/irc.h>
     
    8082/** Interrupt ID Register definition. */
    8183#define NS8250_IID_ACTIVE       (1 << 0)
    82 #define NS8250_IID_CAUSE_MASK 0x0e
    83 #define NS8250_IID_CAUSE_RXSTATUS 0x06
    8484
    8585/** FIFO Control Register definition. */
     
    125125#define NS8250_MSR_SIGNALS      (NS8250_MSR_CTS | NS8250_MSR_DSR \
    126126    | NS8250_MSR_RI | NS8250_MSR_DCD)
     127
     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))
    127133
    128134/** The number of bits of one data unit send by the serial port. */
     
    173179        /** The fibril mutex for synchronizing the access to the device. */
    174180        fibril_mutex_t mutex;
    175         /** Indicates that some data has become available */
    176         fibril_condvar_t input_buffer_available;
    177181        /** True if device is removed. */
    178182        bool removed;
    179183} ns8250_t;
    180184
    181 /** Obtain soft-state structure from device node */
    182 static ns8250_t *dev_ns8250(ddf_dev_t *dev)
    183 {
    184         return ddf_dev_data_get(dev);
    185 }
    186 
    187 /** Obtain soft-state structure from function node */
    188 static ns8250_t *fun_ns8250(ddf_fun_t *fun)
    189 {
    190         return dev_ns8250(ddf_fun_get_dev(fun));
    191 }
    192 
    193185/** Find out if there is some incomming data available on the serial port.
    194186 *
     
    245237static int ns8250_read(ddf_fun_t *fun, char *buf, size_t count)
    246238{
    247         ns8250_t *ns = fun_ns8250(fun);
    248         int ret = 0;
    249        
    250         if (count == 0) return 0;
     239        ns8250_t *ns = NS8250(fun);
     240        int ret = EOK;
    251241       
    252242        fibril_mutex_lock(&ns->mutex);
    253         while (buf_is_empty(&ns->input_buffer))
    254                 fibril_condvar_wait(&ns->input_buffer_available, &ns->mutex);
    255243        while (!buf_is_empty(&ns->input_buffer) && (size_t)ret < count) {
    256244                buf[ret] = (char)buf_pop_front(&ns->input_buffer);
     
    283271static int ns8250_write(ddf_fun_t *fun, char *buf, size_t count)
    284272{
    285         ns8250_t *ns = fun_ns8250(fun);
     273        ns8250_t *ns = NS8250(fun);
    286274        size_t idx;
    287275       
     
    321309static void ns8250_dev_cleanup(ns8250_t *ns)
    322310{
     311        if (ns->dev->parent_sess) {
     312                async_hangup(ns->dev->parent_sess);
     313                ns->dev->parent_sess = NULL;
     314        }
    323315}
    324316
     
    330322static bool ns8250_pio_enable(ns8250_t *ns)
    331323{
    332         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);
    333325       
    334326        /* Gain control over port's registers. */
     
    336328            (void **) &ns->port)) {
    337329                ddf_msg(LVL_ERROR, "Cannot map the port %#" PRIx32
    338                     " for device %s.", ns->io_addr, ddf_dev_get_name(ns->dev));
     330                    " for device %s.", ns->io_addr, ns->dev->name);
    339331                return false;
    340332        }
     
    352344static bool ns8250_dev_probe(ns8250_t *ns)
    353345{
    354         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);
    355347       
    356348        bool res = true;
     
    372364        if (!res) {
    373365                ddf_msg(LVL_DEBUG, "Device %s is not present.",
    374                     ddf_dev_get_name(ns->dev));
     366                    ns->dev->name);
    375367        }
    376368       
     
    385377static int ns8250_dev_initialize(ns8250_t *ns)
    386378{
    387         async_sess_t *parent_sess;
     379        ddf_msg(LVL_DEBUG, "ns8250_dev_initialize %s", ns->dev->name);
     380       
    388381        int ret = EOK;
    389        
    390         ddf_msg(LVL_DEBUG, "ns8250_dev_initialize %s", ddf_dev_get_name(ns->dev));
    391382       
    392383        hw_resource_list_t hw_resources;
     
    394385       
    395386        /* Connect to the parent's driver. */
    396         parent_sess = ddf_dev_parent_sess_create(ns->dev, EXCHANGE_SERIALIZE);
    397         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) {
    398390                ddf_msg(LVL_ERROR, "Failed to connect to parent driver of "
    399                     "device %s.", ddf_dev_get_name(ns->dev));
     391                    "device %s.", ns->dev->name);
    400392                ret = ENOENT;
    401393                goto failed;
     
    403395       
    404396        /* Get hw resources. */
    405         ret = hw_res_get_resource_list(parent_sess, &hw_resources);
     397        ret = hw_res_get_resource_list(ns->dev->parent_sess, &hw_resources);
    406398        if (ret != EOK) {
    407399                ddf_msg(LVL_ERROR, "Failed to get HW resources for device "
    408                     "%s.", ddf_dev_get_name(ns->dev));
     400                    "%s.", ns->dev->name);
    409401                goto failed;
    410402        }
     
    422414                        irq = true;
    423415                        ddf_msg(LVL_NOTE, "Device %s was asigned irq = 0x%x.",
    424                             ddf_dev_get_name(ns->dev), ns->irq);
     416                            ns->dev->name, ns->irq);
    425417                        break;
    426418                       
     
    429421                        if (res->res.io_range.size < REG_COUNT) {
    430422                                ddf_msg(LVL_ERROR, "I/O range assigned to "
    431                                     "device %s is too small.", ddf_dev_get_name(ns->dev));
     423                                    "device %s is too small.", ns->dev->name);
    432424                                ret = ELIMIT;
    433425                                goto failed;
     
    435427                        ioport = true;
    436428                        ddf_msg(LVL_NOTE, "Device %s was asigned I/O address = "
    437                             "0x%x.", ddf_dev_get_name(ns->dev), ns->io_addr);
     429                            "0x%x.", ns->dev->name, ns->io_addr);
    438430                        break;
    439431                       
     
    445437        if (!irq || !ioport) {
    446438                ddf_msg(LVL_ERROR, "Missing HW resource(s) for device %s.",
    447                     ddf_dev_get_name(ns->dev));
     439                    ns->dev->name);
    448440                ret = ENOENT;
    449441                goto failed;
     
    468460{
    469461        /* Interrupt when data received. */
    470         pio_write_8(&regs->ier, NS8250_IER_RXREADY | NS8250_IER_RXSTATUS);
     462        pio_write_8(&regs->ier, NS8250_IER_RXREADY);
    471463        pio_write_8(&regs->mcr, NS8250_MCR_DTR | NS8250_MCR_RTS
    472464            | NS8250_MCR_OUT2);
     
    507499        async_exchange_end(exch);
    508500
    509         /* Read LSR to clear possible previous LSR interrupt */
    510         pio_read_8(&ns->regs->lsr);
    511 
    512501        /* Enable interrupt on the serial port. */
    513502        ns8250_port_interrupts_enable(ns->regs);
     
    613602        *parity = ((val >> NS8250_LCR_PARITY) & 7);
    614603       
    615         /* Silence warnings */
    616         *word_length = 0;
    617 
    618604        switch (val & 3) {
    619605        case WORD_LENGTH_5:
     
    709695        /* 8 bits, no parity, two stop bits. */
    710696        ns8250_port_set_com_props(ns->regs, SERIAL_NO_PARITY, 8, 2);
    711         /*
    712          * Enable FIFO, clear them, with 4-byte threshold for greater
    713          * reliability.
    714          */
     697        /* Enable FIFO, clear them, with 14-byte threshold. */
    715698        pio_write_8(&ns->regs->iid, NS8250_FCR_FIFOENABLE
    716             | NS8250_FCR_RXFIFORESET | NS8250_FCR_TXFIFORESET
    717             | NS8250_FCR_RXTRIGGERLOW);
     699            | NS8250_FCR_RXFIFORESET | NS8250_FCR_TXFIFORESET 
     700            | NS8250_FCR_RXTRIGGERLOW | NS8250_FCR_RXTRIGGERHI);
    718701        /*
    719702         * RTS/DSR set (Request to Send and Data Terminal Ready lines enabled),
     
    748731        bool cont = true;
    749732       
    750         fibril_mutex_lock(&ns->mutex);
    751733        while (cont) {
     734                fibril_mutex_lock(&ns->mutex);
     735               
    752736                cont = ns8250_received(regs);
    753737                if (cont) {
     
    755739                       
    756740                        if (ns->client_connected) {
    757                                 bool buf_was_empty = buf_is_empty(&ns->input_buffer);
    758741                                if (!buf_push_back(&ns->input_buffer, val)) {
    759742                                        ddf_msg(LVL_WARN, "Buffer overflow on "
    760                                             "%s.", ddf_dev_get_name(ns->dev));
    761                                         break;
     743                                            "%s.", ns->dev->name);
    762744                                } else {
    763745                                        ddf_msg(LVL_DEBUG2, "Character %c saved "
    764746                                            "to the buffer of %s.",
    765                                             val, ddf_dev_get_name(ns->dev));
    766                                         if (buf_was_empty)
    767                                                 fibril_condvar_broadcast(&ns->input_buffer_available);
     747                                            val, ns->dev->name);
    768748                                }
    769749                        }
    770750                }
    771         }
    772         fibril_mutex_unlock(&ns->mutex);
    773         fibril_yield();
     751               
     752                fibril_mutex_unlock(&ns->mutex);
     753                fibril_yield();
     754        }
    774755}
    775756
    776757/** The interrupt handler.
    777758 *
    778  * The serial port is initialized to interrupt when some data come or line
    779  * status register changes, so the interrupt is handled by reading the incoming
    780  * 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.
    781761 *
    782762 * @param dev           The serial port device.
     
    785765    ipc_call_t *icall)
    786766{
    787         ns8250_t *ns = dev_ns8250(dev);
    788 
    789         uint8_t iir = pio_read_8(&ns->regs->iid);
    790         if ((iir & NS8250_IID_CAUSE_MASK) == NS8250_IID_CAUSE_RXSTATUS) {
    791                 uint8_t lsr = pio_read_8(&ns->regs->lsr);
    792                 if (lsr & NS8250_LSR_OE) {
    793                         ddf_msg(LVL_WARN, "Overrun error on %s", ddf_dev_get_name(ns->dev));
    794                 }
    795         }
    796        
    797         ns8250_read_from_device(ns);
     767        ns8250_read_from_device(NS8250_FROM_DEV(dev));
    798768}
    799769
     
    831801       
    832802        ddf_msg(LVL_DEBUG, "ns8250_dev_add %s (handle = %d)",
    833             ddf_dev_get_name(dev), (int) ddf_dev_get_handle(dev));
     803            dev->name, (int) dev->handle);
    834804       
    835805        /* Allocate soft-state for the device */
     
    841811       
    842812        fibril_mutex_initialize(&ns->mutex);
    843         fibril_condvar_initialize(&ns->input_buffer_available);
    844813        ns->dev = dev;
    845814       
     
    886855       
    887856        /* Set device operations. */
    888         ddf_fun_set_ops(fun, &ns8250_dev_ops);
     857        fun->ops = &ns8250_dev_ops;
    889858        rc = ddf_fun_bind(fun);
    890859        if (rc != EOK) {
     
    898867       
    899868        ddf_msg(LVL_NOTE, "Device %s successfully initialized.",
    900             ddf_dev_get_name(dev));
     869            dev->name);
    901870       
    902871        return EOK;
     
    911880static int ns8250_dev_remove(ddf_dev_t *dev)
    912881{
    913         ns8250_t *ns = dev_ns8250(dev);
     882        ns8250_t *ns = NS8250_FROM_DEV(dev);
    914883        int rc;
    915884       
     
    945914static int ns8250_open(ddf_fun_t *fun)
    946915{
    947         ns8250_t *ns = fun_ns8250(fun);
     916        ns8250_t *ns = NS8250(fun);
    948917        int res;
    949918       
     
    971940static void ns8250_close(ddf_fun_t *fun)
    972941{
    973         ns8250_t *data = fun_ns8250(fun);
     942        ns8250_t *data = (ns8250_t *) fun->dev->driver_data;
    974943       
    975944        fibril_mutex_lock(&data->mutex);
     
    996965    unsigned int *word_length, unsigned int* stop_bits)
    997966{
    998         ns8250_t *data = dev_ns8250(dev);
     967        ns8250_t *data = (ns8250_t *) dev->driver_data;
    999968        ns8250_regs_t *regs = data->regs;
    1000969       
     
    1027996            stop_bits);
    1028997       
    1029         ns8250_t *data = dev_ns8250(dev);
     998        ns8250_t *data = (ns8250_t *) dev->driver_data;
    1030999        ns8250_regs_t *regs = data->regs;
    10311000        int ret;
     
    10561025        switch (method) {
    10571026        case SERIAL_GET_COM_PROPS:
    1058                 ns8250_get_props(ddf_fun_get_dev(fun), &baud_rate, &parity, &word_length,
     1027                ns8250_get_props(fun->dev, &baud_rate, &parity, &word_length,
    10591028                    &stop_bits);
    10601029                async_answer_4(callid, EOK, baud_rate, parity, word_length,
     
    10671036                word_length = IPC_GET_ARG3(*call);
    10681037                stop_bits = IPC_GET_ARG4(*call);
    1069                 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,
    10701039                    stop_bits);
    10711040                async_answer_0(callid, ret);
     
    10841053static void ns8250_init(void)
    10851054{
    1086         ddf_log_init(NAME, LVL_WARN);
     1055        ddf_log_init(NAME, LVL_ERROR);
    10871056       
    10881057        ns8250_dev_ops.open = &ns8250_open;
Note: See TracChangeset for help on using the changeset viewer.