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