Ignore:
File:
1 edited

Legend:

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

    r1dc4a5e r128c78b  
    5959
    6060#include <devman.h>
     61#include <ns.h>
    6162#include <ipc/devman.h>
     63#include <ipc/services.h>
     64#include <ipc/irc.h>
    6265#include <device/hw_res.h>
    6366#include <ipc/serial_ctl.h>
     
    111114        /** The fibril mutex for synchronizing the access to the device. */
    112115        fibril_mutex_t mutex;
     116        /** True if device is removed. */
     117        bool removed;
    113118} ns8250_t;
    114 
    115 /** Create per-device soft-state structure.
    116  *
    117  * @return      Pointer to soft-state structure.
    118  */
    119 static ns8250_t *ns8250_new(void)
    120 {
    121         ns8250_t *ns;
    122        
    123         ns = (ns8250_t *) calloc(1, sizeof(ns8250_t));
    124         if (ns == NULL)
    125                 return NULL;
    126        
    127         fibril_mutex_initialize(&ns->mutex);
    128         return ns;
    129 }
    130 
    131 /** Delete soft-state structure.
    132  *
    133  * @param ns    The driver data structure.
    134  */
    135 static void ns8250_delete(ns8250_t *ns)
    136 {
    137         assert(ns != NULL);
    138         free(ns);
    139 }
    140119
    141120/** Find out if there is some incomming data available on the serial port.
     
    245224
    246225static int ns8250_add_device(ddf_dev_t *dev);
     226static int ns8250_dev_remove(ddf_dev_t *dev);
    247227
    248228/** The serial port device driver's standard operations. */
    249229static driver_ops_t ns8250_ops = {
    250         .add_device = &ns8250_add_device
     230        .add_device = &ns8250_add_device,
     231        .dev_remove = &ns8250_dev_remove
    251232};
    252233
     
    431412static int ns8250_interrupt_enable(ns8250_t *ns)
    432413{
     414        /*
     415         * Enable interrupt using IRC service.
     416         * TODO: This is a temporary solution until the device framework
     417         * takes care of this itself.
     418         */
     419        async_sess_t *irc_sess = service_connect_blocking(EXCHANGE_SERIALIZE,
     420            SERVICE_IRC, 0, 0);
     421        if (!irc_sess) {
     422                return EIO;
     423        }
     424
     425        async_exch_t *exch = async_exchange_begin(irc_sess);
     426        if (!exch) {
     427                return EIO;
     428        }
     429        async_msg_1(exch, IRC_ENABLE_INTERRUPT, ns->irq);
     430        async_exchange_end(exch);
     431
    433432        /* Enable interrupt on the serial port. */
    434433        ns8250_port_interrupts_enable(ns->port);
     
    636635         */
    637636        pio_write_8(port + 4, 0x0B);
     637}
     638
     639/** Deinitialize the serial port device.
     640 *
     641 * @param ns            Serial port device
     642 */
     643static void ns8250_port_cleanup(ns8250_t *ns)
     644{
     645        /* Disable FIFO */
     646        pio_write_8(ns->port + 2, 0x00);
     647        /* Disable DTR, RTS, OUT1, OUT2 (int. enable) */
     648        pio_write_8(ns->port + 4, 0x00);
     649        /* Disable all interrupts from the port */
     650        ns8250_port_interrupts_disable(ns->port);
    638651}
    639652
     
    721734       
    722735        /* Allocate soft-state for the device */
    723         ns = ns8250_new();
     736        ns = ddf_dev_data_alloc(dev, sizeof(ns8250_t));
    724737        if (ns == NULL) {
    725738                rc = ENOMEM;
     
    727740        }
    728741       
     742        fibril_mutex_initialize(&ns->mutex);
    729743        ns->dev = dev;
    730         dev->driver_data = ns;
    731744       
    732745        rc = ns8250_dev_initialize(ns);
     
    792805        if (need_cleanup)
    793806                ns8250_dev_cleanup(ns);
    794         if (ns != NULL)
    795                 ns8250_delete(ns);
    796807        return rc;
     808}
     809
     810static int ns8250_dev_remove(ddf_dev_t *dev)
     811{
     812        ns8250_t *ns = NS8250_FROM_DEV(dev);
     813        int rc;
     814       
     815        fibril_mutex_lock(&ns->mutex);
     816        if (ns->client_connected) {
     817                fibril_mutex_unlock(&ns->mutex);
     818                return EBUSY;
     819        }
     820        ns->removed = true;
     821        fibril_mutex_unlock(&ns->mutex);
     822       
     823        rc = ddf_fun_unbind(ns->fun);
     824        if (rc != EOK) {
     825                ddf_msg(LVL_ERROR, "Failed to unbind function.");
     826                return rc;
     827        }
     828       
     829        ddf_fun_destroy(ns->fun);
     830       
     831        ns8250_port_cleanup(ns);
     832        ns8250_unregister_interrupt_handler(ns);
     833        ns8250_dev_cleanup(ns);
     834        return EOK;
    797835}
    798836
     
    806844static int ns8250_open(ddf_fun_t *fun)
    807845{
    808         ns8250_t *data = (ns8250_t *) fun->dev->driver_data;
     846        ns8250_t *ns = NS8250(fun);
    809847        int res;
    810848       
    811         fibril_mutex_lock(&data->mutex);
    812         if (data->client_connected) {
     849        fibril_mutex_lock(&ns->mutex);
     850        if (ns->client_connected) {
    813851                res = ELIMIT;
     852        } else if (ns->removed) {
     853                res = ENXIO;
    814854        } else {
    815855                res = EOK;
    816                 data->client_connected = true;
    817         }
    818         fibril_mutex_unlock(&data->mutex);
     856                ns->client_connected = true;
     857        }
     858        fibril_mutex_unlock(&ns->mutex);
    819859       
    820860        return res;
Note: See TracChangeset for help on using the changeset viewer.