1 #include "libcflat.h" 2 #include "vm.h" 3 #include "smp.h" 4 #include "asm/io.h" 5 #include "asm/page.h" 6 #ifndef USE_SERIAL 7 #define USE_SERIAL 8 #endif 9 10 static struct spinlock lock; 11 static int serial_iobase = 0x3f8; 12 static int serial_inited = 0; 13 14 static void serial_outb(char ch) 15 { 16 u8 lsr; 17 18 do { 19 lsr = inb(serial_iobase + 0x05); 20 } while (!(lsr & 0x20)); 21 22 outb(ch, serial_iobase + 0x00); 23 } 24 25 static void serial_init(void) 26 { 27 u8 lcr; 28 29 /* set DLAB */ 30 lcr = inb(serial_iobase + 0x03); 31 lcr |= 0x80; 32 outb(lcr, serial_iobase + 0x03); 33 34 /* set baud rate to 115200 */ 35 outb(0x01, serial_iobase + 0x00); 36 outb(0x00, serial_iobase + 0x01); 37 38 /* clear DLAB */ 39 lcr = inb(serial_iobase + 0x03); 40 lcr &= ~0x80; 41 outb(lcr, serial_iobase + 0x03); 42 } 43 44 static void print_serial(const char *buf) 45 { 46 unsigned long len = strlen(buf); 47 #ifdef USE_SERIAL 48 unsigned long i; 49 if (!serial_inited) { 50 serial_init(); 51 serial_inited = 1; 52 } 53 54 for (i = 0; i < len; i++) { 55 serial_outb(buf[i]); 56 } 57 #else 58 asm volatile ("rep/outsb" : "+S"(buf), "+c"(len) : "d"(0xf1)); 59 #endif 60 } 61 62 void puts(const char *s) 63 { 64 spin_lock(&lock); 65 print_serial(s); 66 spin_unlock(&lock); 67 } 68 69 void exit(int code) 70 { 71 #ifdef USE_SERIAL 72 static const char shutdown_str[8] = "Shutdown"; 73 int i; 74 75 /* test device exit (with status) */ 76 outl(code, 0xf4); 77 78 /* if that failed, try the Bochs poweroff port */ 79 for (i = 0; i < 8; i++) { 80 outb(shutdown_str[i], 0x8900); 81 } 82 #else 83 asm volatile("out %0, %1" : : "a"(code), "d"((short)0xf4)); 84 #endif 85 } 86 87 void __iomem *ioremap(phys_addr_t phys_addr, size_t size) 88 { 89 phys_addr_t base = phys_addr & PAGE_MASK; 90 phys_addr_t offset = phys_addr - base; 91 92 /* 93 * The kernel sets PTEs for an ioremap() with page cache disabled, 94 * but we do not do that right now. It would make sense that I/O 95 * mappings would be uncached - and may help us find bugs when we 96 * properly map that way. 97 */ 98 return vmap(phys_addr, size) + offset; 99 } 100