Initial code release
[external/syslinux.git] / com32 / lib / vdprintf.c
1 /*
2  * vdprintf.c
3  */
4
5 #include <stdio.h>
6 #include <string.h>
7 #include <stdarg.h>
8 #include <unistd.h>
9 #include <inttypes.h>
10 #include <sys/io.h>
11 #include <sys/cpu.h>
12
13 #undef DEBUG
14 #define DEBUG 1
15 #include <dprintf.h>
16
17 #define BUFFER_SIZE     4096
18
19 enum serial_port_regs {
20     THR = 0,
21     RBR = 0,
22     DLL = 0,
23     DLM = 1,
24     IER = 1,
25     IIR = 2,
26     FCR = 2,
27     LCR = 3,
28     MCR = 4,
29     LSR = 5,
30     MSR = 6,
31     SCR = 7,
32 };
33
34 #ifndef DEBUG_PORT
35 # define DEBUG_PORT 0x03f8      /* I/O base address */
36 #endif
37
38 static const uint16_t debug_base = DEBUG_PORT;
39
40 static void debug_putc(char c)
41 {
42     if (c == '\n')
43         debug_putc('\r');
44
45     while ((inb(debug_base + LSR) & 0x20) == 0)
46         cpu_relax();
47     outb(c, debug_base + THR);
48 }
49
50 void vdprintf(const char *format, va_list ap)
51 {
52     int rv;
53     char buffer[BUFFER_SIZE];
54     char *p;
55     static bool debug_init = false;
56     static bool debug_ok   = false;
57
58     rv = vsnprintf(buffer, BUFFER_SIZE, format, ap);
59
60     if (rv < 0)
61         return;
62
63     if (rv > BUFFER_SIZE - 1)
64         rv = BUFFER_SIZE - 1;
65
66     /*
67      * This unconditionally outputs to a serial port at 0x3f8 regardless of
68      * if one is enabled or not (this means we don't have to enable the real
69      * serial console and therefore get conflicting output.)
70      */
71     if (__unlikely(!debug_init)) {
72         uint8_t dll, dlm, lcr;
73
74         debug_init = true;
75
76         cli();
77
78         /* Initialize the serial port to 115200 n81 with FIFOs enabled */
79         outb(0x83, debug_base + LCR);
80         outb(0x01, debug_base + DLL);
81         outb(0x00, debug_base + DLM);
82         (void)inb(debug_base + IER);    /* Synchronize */
83         dll = inb(debug_base + DLL);
84         dlm = inb(debug_base + DLM);
85         lcr = inb(debug_base + LCR);
86         
87         outb(0x03, debug_base + LCR);
88         (void)inb(debug_base + IER);    /* Synchronize */
89
90         outb(0x00, debug_base + IER);
91         (void)inb(debug_base + IER);    /* Synchronize */
92
93         sti();
94
95         if (dll != 0x01 || dlm != 0x00 || lcr != 0x83) {
96             /* No serial port present */
97             return;
98         }
99
100         outb(0x01, debug_base + FCR);
101         (void)inb(debug_base + IER);    /* Synchronize */
102         if (inb(debug_base + IIR) < 0xc0) {
103             outb(0x00, debug_base + FCR); /* Disable non-functional FIFOs */
104             (void)inb(debug_base + IER);        /* Synchronize */
105         }
106
107         debug_ok = true;
108     }
109
110     if (!debug_ok)
111         return;
112
113     p = buffer;
114     while (rv--)
115         debug_putc(*p++);
116 }