Ignore:
File:
1 edited

Legend:

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

    rc7235d40 r128c78b  
    7474#define DLAB_MASK (1 << 7)
    7575
    76 /** Interrupt Enable Register definition. */
    77 #define NS8250_IER_RXREADY      (1 << 0)
    78 #define NS8250_IER_THRE         (1 << 1)
    79 #define NS8250_IER_RXSTATUS     (1 << 2)
    80 #define NS8250_IER_MODEM_STATUS (1 << 3)
    81 
    82 /** Interrupt ID Register definition. */
    83 #define NS8250_IID_ACTIVE       (1 << 0)
    84 
    85 /** FIFO Control Register definition. */
    86 #define NS8250_FCR_FIFOENABLE   (1 << 0)
    87 #define NS8250_FCR_RXFIFORESET  (1 << 1)
    88 #define NS8250_FCR_TXFIFORESET  (1 << 2)
    89 #define NS8250_FCR_DMAMODE      (1 << 3)
    90 #define NS8250_FCR_RXTRIGGERLOW (1 << 6)
    91 #define NS8250_FCR_RXTRIGGERHI  (1 << 7)
    92 
    93 /** Line Control Register definition. */
    94 #define NS8250_LCR_STOPBITS     (1 << 2)
    95 #define NS8250_LCR_PARITY       (1 << 3)
    96 #define NS8250_LCR_SENDBREAK    (1 << 6)
    97 #define NS8250_LCR_DLAB         (1 << 7)
    98 
    99 /** Modem Control Register definition. */
    100 #define NS8250_MCR_DTR          (1 << 0)
    101 #define NS8250_MCR_RTS          (1 << 1)
    102 #define NS8250_MCR_OUT1         (1 << 2)
    103 #define NS8250_MCR_OUT2         (1 << 3)
    104 #define NS8250_MCR_LOOPBACK     (1 << 4)
    105 #define NS8250_MCR_ALL          (0x1f)
    106 
    107 /** Line Status Register definition. */
    108 #define NS8250_LSR_RXREADY      (1 << 0)
    109 #define NS8250_LSR_OE           (1 << 1)
    110 #define NS8250_LSR_PE           (1 << 2)
    111 #define NS8250_LSR_FE           (1 << 3)
    112 #define NS8250_LSR_BREAK        (1 << 4)
    113 #define NS8250_LSR_THRE         (1 << 5)
    114 #define NS8250_LSR_TSE          (1 << 6)
    115 
    116 /** Modem Status Register definition. */
    117 #define NS8250_MSR_DELTACTS     (1 << 0)
    118 #define NS8250_MSR_DELTADSR     (1 << 1)
    119 #define NS8250_MSR_RITRAILING   (1 << 2)
    120 #define NS8250_MSR_DELTADCD     (1 << 3)
    121 #define NS8250_MSR_CTS          (1 << 4)
    122 #define NS8250_MSR_DSR          (1 << 5)
    123 #define NS8250_MSR_RI           (1 << 6)
    124 #define NS8250_MSR_DCD          (1 << 7)
    125 #define NS8250_MSR_SIGNALS      (NS8250_MSR_CTS | NS8250_MSR_DSR \
    126     | NS8250_MSR_RI | NS8250_MSR_DCD)
    127 
    12876/** Obtain soft-state structure from function node */
    12977#define NS8250(fnode) ((ns8250_t *) ((fnode)->dev->driver_data))
     
    14896} stop_bit_t;
    14997
    150 /** 8250 UART registers layout. */
    151 typedef struct {
    152         ioport8_t data;         /**< Data register. */
    153         ioport8_t ier;          /**< Interrupt Enable Reg. */
    154         ioport8_t iid;          /**< Interrupt ID Reg. */
    155         ioport8_t lcr;          /**< Line Control Reg. */
    156         ioport8_t mcr;          /**< Modem Control Reg. */
    157         ioport8_t lsr;          /**< Line Status Reg. */
    158         ioport8_t msr;          /**< Modem Status Reg. */
    159 } ns8250_regs_t;
    160 
    16198/** The driver data for the serial port devices. */
    16299typedef struct ns8250 {
     
    165102        /** DDF function node */
    166103        ddf_fun_t *fun;
    167         /** I/O registers **/
    168         ns8250_regs_t *regs;
    169104        /** Is there any client conntected to the device? */
    170105        bool client_connected;
     
    189124 *                      otherwise.
    190125 */
    191 static bool ns8250_received(ns8250_regs_t *regs)
    192 {
    193         return (pio_read_8(&regs->lsr) & NS8250_LSR_RXREADY) != 0;
     126static bool ns8250_received(ioport8_t *port)
     127{
     128        return (pio_read_8(port + 5) & 1) != 0;
    194129}
    195130
     
    199134 * @return              The data read.
    200135 */
    201 static uint8_t ns8250_read_8(ns8250_regs_t *regs)
    202 {
    203         return pio_read_8(&regs->data);
     136static uint8_t ns8250_read_8(ioport8_t *port)
     137{
     138        return pio_read_8(port);
    204139}
    205140
     
    208143 * @param port          The base address of the serial port device's ports.
    209144 */
    210 static bool is_transmit_empty(ns8250_regs_t *regs)
    211 {
    212         return (pio_read_8(&regs->lsr) & NS8250_LSR_THRE) != 0;
     145static bool is_transmit_empty(ioport8_t *port)
     146{
     147        return (pio_read_8(port + 5) & 0x20) != 0;
    213148}
    214149
     
    218153 * @param c             The character to be written to the serial port device.
    219154 */
    220 static void ns8250_write_8(ns8250_regs_t *regs, uint8_t c)
    221 {
    222         while (!is_transmit_empty(regs))
     155static void ns8250_write_8(ioport8_t *port, uint8_t c)
     156{
     157        while (!is_transmit_empty(port))
    223158                ;
    224159       
    225         pio_write_8(&regs->data, c);
     160        pio_write_8(port, c);
    226161}
    227162
     
    258193{
    259194        fibril_mutex_lock(&ns->mutex);
    260         ns8250_write_8(ns->regs, c);
     195        ns8250_write_8(ns->port, c);
    261196        fibril_mutex_unlock(&ns->mutex);
    262197}
     
    277212                ns8250_putchar(ns, (uint8_t) buf[idx]);
    278213       
    279         return count;
     214        return 0;
    280215}
    281216
     
    288223};
    289224
    290 static int ns8250_dev_add(ddf_dev_t *dev);
     225static int ns8250_add_device(ddf_dev_t *dev);
    291226static int ns8250_dev_remove(ddf_dev_t *dev);
    292227
    293228/** The serial port device driver's standard operations. */
    294229static driver_ops_t ns8250_ops = {
    295         .dev_add = &ns8250_dev_add,
     230        .add_device = &ns8250_add_device,
    296231        .dev_remove = &ns8250_dev_remove
    297232};
     
    331266                return false;
    332267        }
    333 
    334         ns->regs = (ns8250_regs_t *)ns->port;
    335268       
    336269        return true;
     
    346279        ddf_msg(LVL_DEBUG, "ns8250_dev_probe %s", ns->dev->name);
    347280       
     281        ioport8_t *port_addr = ns->port;
    348282        bool res = true;
    349283        uint8_t olddata;
    350284       
    351         olddata = pio_read_8(&ns->regs->mcr);
    352        
    353         pio_write_8(&ns->regs->mcr, NS8250_MCR_LOOPBACK);
    354         if (pio_read_8(&ns->regs->msr) & NS8250_MSR_SIGNALS)
     285        olddata = pio_read_8(port_addr + 4);
     286       
     287        pio_write_8(port_addr + 4, 0x10);
     288        if (pio_read_8(port_addr + 6) & 0xf0)
    355289                res = false;
    356290       
    357         pio_write_8(&ns->regs->mcr, NS8250_MCR_ALL);
    358         if ((pio_read_8(&ns->regs->msr) & NS8250_MSR_SIGNALS)
    359             != NS8250_MSR_SIGNALS)
     291        pio_write_8(port_addr + 4, 0x1f);
     292        if ((pio_read_8(port_addr + 6) & 0xf0) != 0xf0)
    360293                res = false;
    361294       
    362         pio_write_8(&ns->regs->mcr, olddata);
     295        pio_write_8(port_addr + 4, olddata);
    363296       
    364297        if (!res) {
     
    457390 * @param port          The base address of the serial port device's ports.
    458391 */
    459 static inline void ns8250_port_interrupts_enable(ns8250_regs_t *regs)
    460 {
    461         /* Interrupt when data received. */
    462         pio_write_8(&regs->ier, NS8250_IER_RXREADY);
    463         pio_write_8(&regs->mcr, NS8250_MCR_DTR | NS8250_MCR_RTS
    464             | NS8250_MCR_OUT2);
     392static inline void ns8250_port_interrupts_enable(ioport8_t *port)
     393{
     394        pio_write_8(port + 1, 0x1);     /* Interrupt when data received. */
     395        pio_write_8(port + 4, 0xB);
    465396}
    466397
     
    469400 * @param port          The base address of the serial port device's ports
    470401 */
    471 static inline void ns8250_port_interrupts_disable(ns8250_regs_t *regs)
    472 {
    473         pio_write_8(&regs->ier, 0x0);   /* Disable all interrupts. */
     402static inline void ns8250_port_interrupts_disable(ioport8_t *port)
     403{
     404        pio_write_8(port + 1, 0x0);     /* Disable all interrupts. */
    474405}
    475406
     
    500431
    501432        /* Enable interrupt on the serial port. */
    502         ns8250_port_interrupts_enable(ns->regs);
     433        ns8250_port_interrupts_enable(ns->port);
    503434       
    504435        return EOK;
     
    512443 * @param port          The base address of the serial port device's ports.
    513444 */
    514 static inline void enable_dlab(ns8250_regs_t *regs)
    515 {
    516         uint8_t val = pio_read_8(&regs->lcr);
    517         pio_write_8(&regs->lcr, val | NS8250_LCR_DLAB);
     445static inline void enable_dlab(ioport8_t *port)
     446{
     447        uint8_t val = pio_read_8(port + 3);
     448        pio_write_8(port + 3, val | DLAB_MASK);
    518449}
    519450
     
    522453 * @param port          The base address of the serial port device's ports.
    523454 */
    524 static inline void clear_dlab(ns8250_regs_t *regs)
    525 {
    526         uint8_t val = pio_read_8(&regs->lcr);
    527         pio_write_8(&regs->lcr, val & (~NS8250_LCR_DLAB));
     455static inline void clear_dlab(ioport8_t *port)
     456{
     457        uint8_t val = pio_read_8(port + 3);
     458        pio_write_8(port + 3, val & (~DLAB_MASK));
    528459}
    529460
     
    535466 *                      if the specified baud_rate is not valid).
    536467 */
    537 static int ns8250_port_set_baud_rate(ns8250_regs_t *regs, unsigned int baud_rate)
     468static int ns8250_port_set_baud_rate(ioport8_t *port, unsigned int baud_rate)
    538469{
    539470        uint16_t divisor;
     
    551482       
    552483        /* Enable DLAB to be able to access baud rate divisor. */
    553         enable_dlab(regs);
     484        enable_dlab(port);
    554485       
    555486        /* Set divisor low byte. */
    556         pio_write_8(&regs->data, div_low);
     487        pio_write_8(port + 0, div_low);
    557488        /* Set divisor high byte. */
    558         pio_write_8(&regs->ier, div_high);
    559        
    560         clear_dlab(regs);
     489        pio_write_8(port + 1, div_high);
     490       
     491        clear_dlab(port);
    561492       
    562493        return EOK;
     
    568499 * @param baud_rate     The ouput parameter to which the baud rate is stored.
    569500 */
    570 static unsigned int ns8250_port_get_baud_rate(ns8250_regs_t *regs)
     501static unsigned int ns8250_port_get_baud_rate(ioport8_t *port)
    571502{
    572503        uint16_t divisor;
     
    574505       
    575506        /* Enable DLAB to be able to access baud rate divisor. */
    576         enable_dlab(regs);
     507        enable_dlab(port);
    577508       
    578509        /* Get divisor low byte. */
    579         div_low = pio_read_8(&regs->data);
     510        div_low = pio_read_8(port + 0);
    580511        /* Get divisor high byte. */
    581         div_high = pio_read_8(&regs->ier);
    582        
    583         clear_dlab(regs);
     512        div_high = pio_read_8(port + 1);
     513       
     514        clear_dlab(port);
    584515       
    585516        divisor = (div_high << 8) | div_low;
     
    594525 * @param stop_bits     The number of stop bits used (one or two).
    595526 */
    596 static void ns8250_port_get_com_props(ns8250_regs_t *regs, unsigned int *parity,
     527static void ns8250_port_get_com_props(ioport8_t *port, unsigned int *parity,
    597528    unsigned int *word_length, unsigned int *stop_bits)
    598529{
    599530        uint8_t val;
    600531       
    601         val = pio_read_8(&regs->lcr);
    602         *parity = ((val >> NS8250_LCR_PARITY) & 7);
     532        val = pio_read_8(port + 3);
     533        *parity = ((val >> 3) & 7);
    603534       
    604535        switch (val & 3) {
     
    617548        }
    618549       
    619         if ((val >> NS8250_LCR_STOPBITS) & 1)
     550        if ((val >> 2) & 1)
    620551                *stop_bits = 2;
    621552        else
     
    631562 *                      is invalid.
    632563 */
    633 static int ns8250_port_set_com_props(ns8250_regs_t *regs, unsigned int parity,
     564static int ns8250_port_set_com_props(ioport8_t *port, unsigned int parity,
    634565    unsigned int word_length, unsigned int stop_bits)
    635566{
     
    655586        switch (stop_bits) {
    656587        case 1:
    657                 val |= ONE_STOP_BIT << NS8250_LCR_STOPBITS;
     588                val |= ONE_STOP_BIT << 2;
    658589                break;
    659590        case 2:
    660                 val |= TWO_STOP_BITS << NS8250_LCR_STOPBITS;
     591                val |= TWO_STOP_BITS << 2;
    661592                break;
    662593        default:
     
    670601        case SERIAL_MARK_PARITY:
    671602        case SERIAL_SPACE_PARITY:
    672                 val |= parity << NS8250_LCR_PARITY;
     603                val |= parity << 3;
    673604                break;
    674605        default:
     
    676607        }
    677608       
    678         pio_write_8(&regs->lcr, val);
     609        pio_write_8(port + 3, val);
    679610       
    680611        return EOK;
     
    689620static void ns8250_initialize_port(ns8250_t *ns)
    690621{
     622        ioport8_t *port = ns->port;
     623       
    691624        /* Disable interrupts. */
    692         ns8250_port_interrupts_disable(ns->regs);
     625        ns8250_port_interrupts_disable(port);
    693626        /* Set baud rate. */
    694         ns8250_port_set_baud_rate(ns->regs, 38400);
     627        ns8250_port_set_baud_rate(port, 38400);
    695628        /* 8 bits, no parity, two stop bits. */
    696         ns8250_port_set_com_props(ns->regs, SERIAL_NO_PARITY, 8, 2);
     629        ns8250_port_set_com_props(port, SERIAL_NO_PARITY, 8, 2);
    697630        /* Enable FIFO, clear them, with 14-byte threshold. */
    698         pio_write_8(&ns->regs->iid, NS8250_FCR_FIFOENABLE
    699             | NS8250_FCR_RXFIFORESET | NS8250_FCR_TXFIFORESET
    700             | NS8250_FCR_RXTRIGGERLOW | NS8250_FCR_RXTRIGGERHI);
     631        pio_write_8(port + 2, 0xC7);
    701632        /*
    702633         * RTS/DSR set (Request to Send and Data Terminal Ready lines enabled),
    703634         * Aux Output2 set - needed for interrupts.
    704635         */
    705         pio_write_8(&ns->regs->mcr, NS8250_MCR_DTR | NS8250_MCR_RTS
    706             | NS8250_MCR_OUT2);
     636        pio_write_8(port + 4, 0x0B);
    707637}
    708638
     
    714644{
    715645        /* Disable FIFO */
    716         pio_write_8(&ns->regs->iid, 0x00);
     646        pio_write_8(ns->port + 2, 0x00);
    717647        /* Disable DTR, RTS, OUT1, OUT2 (int. enable) */
    718         pio_write_8(&ns->regs->mcr, 0x00);
     648        pio_write_8(ns->port + 4, 0x00);
    719649        /* Disable all interrupts from the port */
    720         ns8250_port_interrupts_disable(ns->regs);
     650        ns8250_port_interrupts_disable(ns->port);
    721651}
    722652
     
    728658static void ns8250_read_from_device(ns8250_t *ns)
    729659{
    730         ns8250_regs_t *regs = ns->regs;
     660        ioport8_t *port = ns->port;
    731661        bool cont = true;
    732662       
     
    734664                fibril_mutex_lock(&ns->mutex);
    735665               
    736                 cont = ns8250_received(regs);
     666                cont = ns8250_received(port);
    737667                if (cont) {
    738                         uint8_t val = ns8250_read_8(regs);
     668                        uint8_t val = ns8250_read_8(port);
    739669                       
    740670                        if (ns->client_connected) {
     
    787717}
    788718
    789 /** The dev_add callback method of the serial port driver.
     719/** The add_device callback method of the serial port driver.
    790720 *
    791721 * Probe and initialize the newly added device.
     
    793723 * @param dev           The serial port device.
    794724 */
    795 static int ns8250_dev_add(ddf_dev_t *dev)
     725static int ns8250_add_device(ddf_dev_t *dev)
    796726{
    797727        ns8250_t *ns = NULL;
     
    800730        int rc;
    801731       
    802         ddf_msg(LVL_DEBUG, "ns8250_dev_add %s (handle = %d)",
     732        ddf_msg(LVL_DEBUG, "ns8250_add_device %s (handle = %d)",
    803733            dev->name, (int) dev->handle);
    804734       
     
    966896{
    967897        ns8250_t *data = (ns8250_t *) dev->driver_data;
    968         ns8250_regs_t *regs = data->regs;
     898        ioport8_t *port = data->port;
    969899       
    970900        fibril_mutex_lock(&data->mutex);
    971         ns8250_port_interrupts_disable(regs);
    972         *baud_rate = ns8250_port_get_baud_rate(regs);
    973         ns8250_port_get_com_props(regs, parity, word_length, stop_bits);
    974         ns8250_port_interrupts_enable(regs);
     901        ns8250_port_interrupts_disable(port);
     902        *baud_rate = ns8250_port_get_baud_rate(port);
     903        ns8250_port_get_com_props(port, parity, word_length, stop_bits);
     904        ns8250_port_interrupts_enable(port);
    975905        fibril_mutex_unlock(&data->mutex);
    976906       
     
    997927       
    998928        ns8250_t *data = (ns8250_t *) dev->driver_data;
    999         ns8250_regs_t *regs = data->regs;
     929        ioport8_t *port = data->port;
    1000930        int ret;
    1001931       
    1002932        fibril_mutex_lock(&data->mutex);
    1003         ns8250_port_interrupts_disable(regs);
    1004         ret = ns8250_port_set_baud_rate(regs, baud_rate);
     933        ns8250_port_interrupts_disable(port);
     934        ret = ns8250_port_set_baud_rate(port, baud_rate);
    1005935        if (ret == EOK)
    1006                 ret = ns8250_port_set_com_props(regs, parity, word_length, stop_bits);
    1007         ns8250_port_interrupts_enable(regs);
     936                ret = ns8250_port_set_com_props(port, parity, word_length, stop_bits);
     937        ns8250_port_interrupts_enable(port);
    1008938        fibril_mutex_unlock(&data->mutex);
    1009939       
Note: See TracChangeset for help on using the changeset viewer.