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 serial_inited = 1; 50 } 51 52 for (i = 0; i < len; i++) { 53 serial_outb(buf[i]); 54 } 55 #else 56 asm volatile ("rep/outsb" : "+S"(buf), "+c"(len) : "d"(0xf1)); 57 #endif 58 } 59 60 void puts(const char *s) 61 { 62 spin_lock(&lock); 63 print_serial(s); 64 spin_unlock(&lock); 65 } 66 67 void exit(int code) 68 { 69 #ifdef USE_SERIAL 70 static const char shutdown_str[8] = "Shutdown"; 71 int i; 72 73 /* test device exit (with status) */ 74 outl(code, 0xf4); 75 76 /* if that failed, try the Bochs poweroff port */ 77 for (i = 0; i < 8; i++) { 78 outb(shutdown_str[i], 0x8900); 79 } 80 #else 81 asm volatile("out %0, %1" : : "a"(code), "d"((short)0xf4)); 82 #endif 83 } 84