1 #include "libcflat.h" 2 #include "smp.h" 3 #include "io.h" 4 #ifndef USE_SERIAL 5 #define USE_SERIAL 6 #endif 7 8 static struct spinlock lock; 9 static int serial_iobase = 0x3f8; 10 static int serial_inited = 0; 11 12 static void serial_outb(char ch) 13 { 14 u8 lsr; 15 16 do { 17 lsr = inb(serial_iobase + 0x05); 18 } while (!(lsr & 0x20)); 19 20 outb(ch, serial_iobase + 0x00); 21 } 22 23 static void serial_init(void) 24 { 25 u8 lcr; 26 27 /* set DLAB */ 28 lcr = inb(serial_iobase + 0x03); 29 lcr |= 0x80; 30 outb(lcr, serial_iobase + 0x03); 31 32 /* set baud rate to 115200 */ 33 outb(0x01, serial_iobase + 0x00); 34 outb(0x00, serial_iobase + 0x01); 35 36 /* clear DLAB */ 37 lcr = inb(serial_iobase + 0x03); 38 lcr &= ~0x80; 39 outb(lcr, serial_iobase + 0x03); 40 } 41 42 static void print_serial(const char *buf) 43 { 44 unsigned long len = strlen(buf); 45 #ifdef USE_SERIAL 46 unsigned long i; 47 if (!serial_inited) { 48 serial_init(); 49 } 50 51 for (i = 0; i < len; i++) { 52 serial_outb(buf[i]); 53 } 54 #else 55 asm volatile ("rep/outsb" : "+S"(buf), "+c"(len) : "d"(0xf1)); 56 #endif 57 } 58 59 void puts(const char *s) 60 { 61 spin_lock(&lock); 62 print_serial(s); 63 spin_unlock(&lock); 64 } 65 66 void exit(int code) 67 { 68 #ifdef USE_SERIAL 69 static const char shutdown_str[8] = "Shutdown"; 70 int i; 71 72 /* test device exit (with status) */ 73 outl(code, 0xf4); 74 75 /* if that failed, try the Bochs poweroff port */ 76 for (i = 0; i < 8; i++) { 77 outb(shutdown_str[i], 0x8900); 78 } 79 #else 80 asm volatile("out %0, %1" : : "a"(code), "d"((short)0xf4)); 81 #endif 82 } 83