Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset ec16831 in mainline


Ignore:
Timestamp:
2021-08-04T18:52:58Z (2 months ago)
Author:
Marek Benc <dusxmt@…>
Parents:
a977e37
git-author:
Marek Benc <dusxmt@…> (2021-06-23 20:56:38)
git-committer:
Marek Benc <dusxmt@…> (2021-08-04 18:52:58)
Message:

Configure NS16550 transmission format settings on initialization on PCs.

Currently, the NS116550 serial line controller is left with its
settings as it was left by the boot firmware and/or bootloader.
On my computer, this was an invalid configuration, and it left me
with a really slow booting system, since each output character
had to go through the full timeout loop in ns16550_sendb().

This patch adds the necessary bit and register descriptions to configure
the baud rate and transmission settings, as well as configuring them on
post-SMP initialization on ia32 and amd64, currently with values matching
the ns8250 userspace character device driver (38400 baud, 8-bit words,
2 stop bits, no parity).

This could perhaps be changed to be adjustable with a kernel command-line
argument, or through the configuration system.

This change does not affect emulators, since those largely ignore these
settings.

Location:
kernel
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/amd64/src/amd64.c

    ra977e37 rec16831  
    224224            ns16550_out_ptr);
    225225        if (ns16550_instance) {
     226                ns16550_format_set(ns16550_instance, 38400,
     227                    LCR_PARITY_NONE | LCR_STOP_BIT_TWO | LCR_WORD_LEN_8);
    226228#ifdef CONFIG_NS16550
    227229                srln_instance_t *srln_instance = srln_init();
  • kernel/arch/ia32/src/ia32.c

    ra977e37 rec16831  
    209209            ns16550_out_ptr);
    210210        if (ns16550_instance) {
     211                ns16550_format_set(ns16550_instance, 38400,
     212                    LCR_PARITY_NONE | LCR_STOP_BIT_TWO | LCR_WORD_LEN_8);
    211213#ifdef CONFIG_NS16550
    212214                srln_instance_t *srln_instance = srln_init();
  • kernel/genarch/include/genarch/drivers/ns16550/ns16550.h

    ra977e37 rec16831  
    4343#include <console/chardev.h>
    4444
    45 #define IER_ERBFI  0x01  /** Enable Receive Buffer Full Interrupt. */
     45#define NS156440_CLOCK    115200 /** Internal clock speed, max. baud rate. */
    4646
    47 #define LCR_DLAB   0x80  /** Divisor Latch Access bit. */
     47#define IER_ERBFI         0x01   /** Enable Receive Buffer Full Interrupt. */
     48#define MCR_OUT2          0x08   /** OUT2. */
    4849
    49 #define MCR_OUT2   0x08  /** OUT2. */
     50#define LCR_DLAB          0x80   /** Divisor Latch Access bit. */
     51#define LCR_SBE           0x40   /** RS-232 Break Signal bit. */
     52
     53#define LCR_PARITY_NONE   0x00   /** No parity bit. */
     54#define LCR_PARITY_ODD    0x08   /** Odd parity. */
     55#define LCR_PARITY_EVEN   0x18   /** Even parity. */
     56#define LCR_PARITY_MARK   0x28   /** Parity bit always one. */
     57#define LCR_PARITY_SPACE  0x38   /** Parity bit always zero. */
     58
     59#define LCR_STOP_BIT_ONE  0x00   /** One stop bit. */
     60#define LCR_STOP_BIT_TWO  0x04   /** Two stop bits. */
     61
     62#define LCR_WORD_LEN_5    0x00   /** 5-bit word length. */
     63#define LCR_WORD_LEN_6    0x01   /** 6-bit word length. */
     64#define LCR_WORD_LEN_7    0x02   /** 7-bit word length. */
     65#define LCR_WORD_LEN_8    0x03   /** 8-bit word length. */
    5066
    5167/** NS16550 registers. */
     
    5369        NS16550_REG_RBR = 0,  /**< Receiver Buffer Register (read). */
    5470        NS16550_REG_THR = 0,  /**< Transmitter Holder Register (write). */
     71        NS16550_REG_DLL = 0,  /**< Baud rate divisor latch low byte (write). */
    5572        NS16550_REG_IER = 1,  /**< Interrupt Enable Register. */
     73        NS16550_REG_DLH = 1,  /**< Baud rate divisor latch high byte (write). */
    5674        NS16550_REG_IIR = 2,  /**< Interrupt Ident Register (read). */
    5775        NS16550_REG_FCR = 2,  /**< FIFO control register (write). */
     
    7391extern ns16550_instance_t *ns16550_init(ioport8_t *, unsigned, inr_t, cir_t,
    7492    void *, outdev_t **);
     93extern void ns16550_format_set(ns16550_instance_t *, unsigned, uint8_t);
    7594extern void ns16550_wire(ns16550_instance_t *, indev_t *);
    7695
  • kernel/genarch/src/drivers/ns16550/ns16550.c

    ra977e37 rec16831  
    132132};
    133133
     134/** Configure ns16550 transmission format.
     135 *
     136 * @param instance   NS 16550 driver instance.
     137 * @param baud_rate  Transmission speed in bits per second, also known as baud,
     138 *                   maximum value is 115200.
     139 * @param lcr_format Line Control Register configuration bits, as defined by
     140 *                   the @c LCR_ macros.  These configure the word width,
     141 *                   parity type, and stop bit count.
     142 */
     143void ns16550_format_set(ns16550_instance_t *instance,
     144    unsigned baud_rate, uint8_t lcr_format)
     145{
     146        uint16_t divisor;
     147
     148        divisor = (uint16_t)(NS156440_CLOCK / baud_rate);
     149        if (divisor == 0)
     150                divisor = 1;  /* Avoid division by zero. */
     151
     152        ns16550_reg_write(instance, NS16550_REG_LCR, LCR_DLAB);
     153        ns16550_reg_write(instance, NS16550_REG_DLL, divisor & 0xFF);
     154        ns16550_reg_write(instance, NS16550_REG_DLH, (divisor >> 8) & 0xFF);
     155        ns16550_reg_write(instance, NS16550_REG_LCR, lcr_format & ~LCR_DLAB);
     156}
     157
    134158/** Initialize ns16550.
    135159 *
Note: See TracChangeset for help on using the changeset viewer.