File: serial.c

package info (click to toggle)
syslinux 2:4.05+dfsg-6+deb7u1
  • links: PTS
  • area: main
  • in suites: wheezy
  • size: 25,684 kB
  • sloc: ansic: 276,159; asm: 9,973; pascal: 9,907; perl: 3,492; makefile: 1,736; sh: 626; python: 266; xml: 39
file content (83 lines) | stat: -rw-r--r-- 1,631 bytes parent folder | download | duplicates (2)
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
81
82
83
#include <stdbool.h>
#include <stdio.h>

#include "mystuff.h"
#include "file.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);
    }
}