QDNix
Quick’n’dirty *NIX
8250.c
1 #include <sys/machine/mmio.h>
2 #include <dev/tty/serial/serial.h>
3 #include <dev/tty/serial/8250.h>
4 
5 #include "config.h"
6 
7 
8 static int
9 serial_8250_is_buffer_empty(SerialDevice *dev)
10 {
11  return (mmio_read8(
12  dev->io_base + (UART8250_LSR << dev->reg_offset)) & 0x20);
13 }
14 
15 static size_t
16 serial_8250_write(void *raw, const char *str, size_t size)
17 {
18  size_t idx;
19  SerialDevice *dev;
20 
21  dev = (SerialDevice *)raw;
22 
23  for (idx = 0; idx < size; idx++)
24  {
25  if (str[idx] == '\n')
26  {
27  while (serial_8250_is_buffer_empty(dev) == 0);
28  mmio_write8(dev->io_base +
29  (UART8250_THR << dev->reg_offset), '\r');
30  }
31  while (serial_8250_is_buffer_empty(dev) == 0);
32  mmio_write8(dev->io_base +
33  (UART8250_THR << dev->reg_offset), str[idx]);
34  }
35  return (idx);
36 }
37 
38 static size_t
39 serial_8250_read(void *raw, char *buff, size_t size)
40 {
41  (void)raw;
42  (void)buff;
43  (void)size;
44 
45  return (0);
46 }
47 
48 
49 void
50 serial_8250_init(SerialDevice *dev)
51 {
52  uint16_t divisor;
53  dev->write = serial_8250_write;
54  dev->read = serial_8250_read;
55 
56  /* disable all interrupts */
57  mmio_write8(dev->io_base + (UART8250_IER << dev->reg_offset), 0x00);
58  /* enable DLAB */
59  mmio_write8(dev->io_base + (UART8250_IIR << dev->reg_offset), 0x80);
60 
61  divisor = CONFIG_CLOCK / (dev->beaudrate * 16);
62 
63 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
64  mmio_write8(dev->io_base + (UART8250_DLL), (divisor >> 8) * 0xFF);
65  mmio_write8(dev->io_base + (UART8250_DLH << dev->reg_offset),
66  divisor & 0xFF);
67 #else
68  mmio_write8(dev->io_base + (UART8250_DLL),
69  divisor & 0xFF);
70  mmio_write8(dev->io_base + (UART8250_DLH << dev->reg_offset),
71  (divisor >> 8) * 0xFF);
72 #endif
73 
74  mmio_write8(dev->io_base + (UART8250_DLL), 0x0C);
75  mmio_write8(dev->io_base + (UART8250_DLH), 0x00);
76 
77 
78  /* 7 bits , no parity , 1 stop bit */
79  mmio_write8(dev->io_base + (UART8250_LCR << dev->reg_offset), 0x08);
80 
81  mmio_write8(dev->io_base + (UART8250_IIR << dev->reg_offset), 0xC7);
82 
83  /* enable IRQs and set RTS/DTS */
84  mmio_write8(dev->io_base + (UART8250_MCR << dev->reg_offset), 0x0B);
85 }