aboutsummaryrefslogtreecommitdiffstats
path: root/memdump/serial.c
blob: 902dcc3d7e86789595a0710a7bae3530ed8b15ea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include "mystuff.h"
#include "ymsend.h"
#include "io.h"

enum {
  THR = 0,
  RBR = 0,
  DLL = 0,
  DLM = 1,
  IER = 1,
  IIR = 2,
  FCR = 2,
  LCR = 3,
  MCR = 4,
  LSR = 5,
  MSR = 6,
  SCR = 7,
};

int serial_init(struct serial_if *sif)
{
  uint16_t port = sif->port;
  uint8_t dll, dlm, lcr;

  /* Set 115200n81 */
  outb(0x83, port+LCR);
  outb(0x01, port+DLL);
  outb(0x00, port+DLM);
  (void)inb(port+IER);		/* Synchronize */
  dll = inb(port+DLL);
  dlm = inb(port+DLM);
  lcr = inb(port+LCR);
  outb(0x03, port+LCR);
  (void)inb(port+IER);		/* Synchronize */

  if (dll != 0x01 || dlm != 0x00 || lcr != 0x83)
    return -1;			/* This doesn't look like a serial port */

  /* Disable interrupts */
  outb(port+IER, 0);

  /* Enable 16550A FIFOs if available */
  outb(port+FCR, 0x01);		/* Enable FIFO */
  (void)inb(port+IER);		/* Synchronize */
  if (inb(port+IIR) < 0xc0)
    outb(port+FCR, 0x00);	/* Disable FIFOs if non-functional */
  (void)inb(port+IER);		/* Synchronize */

  return 0;
}

void serial_write(struct serial_if *sif, const void *data, size_t n)
{
  uint16_t port = sif->port;
  const char *p = data;
  uint8_t lsr;

  while (n--) {
    do {
      lsr = inb(port+LSR);
    } while (!(lsr & 0x20));

    outb(*p++, port+THR);
  }
}

void serial_read(struct serial_if *sif, void *data, size_t n)
{
  uint16_t port = sif->port;
  char *p = data;
  uint8_t lsr;

  while (n--) {
    do {
      lsr = inb(port+LSR);
    } while (!(lsr & 0x01));

    *p++ = inb(port+RBR);
  }
}