1 #include "libcflat.h" 2 #include "smp.h" 3 #include "asm/io.h" 4 #include "asm/page.h" 5 #include "vmalloc.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 /* IER: disable interrupts */ 44 outb(0x00, serial_iobase + 0x01); 45 /* LCR: 8 bits, no parity, one stop bit */ 46 outb(0x03, serial_iobase + 0x03); 47 /* FCR: disable FIFO queues */ 48 outb(0x00, serial_iobase + 0x02); 49 /* MCR: RTS, DTR on */ 50 outb(0x03, serial_iobase + 0x04); 51 } 52 53 static void print_serial(const char *buf) 54 { 55 unsigned long len = strlen(buf); 56 #ifdef USE_SERIAL 57 unsigned long i; 58 if (!serial_inited) { 59 serial_init(); 60 serial_inited = 1; 61 } 62 63 for (i = 0; i < len; i++) { 64 serial_outb(buf[i]); 65 } 66 #else 67 asm volatile ("rep/outsb" : "+S"(buf), "+c"(len) : "d"(0xf1)); 68 #endif 69 } 70 71 void puts(const char *s) 72 { 73 spin_lock(&lock); 74 print_serial(s); 75 spin_unlock(&lock); 76 } 77 78 void exit(int code) 79 { 80 #ifdef USE_SERIAL 81 static const char shutdown_str[8] = "Shutdown"; 82 int i; 83 84 /* test device exit (with status) */ 85 outl(code, 0xf4); 86 87 /* if that failed, try the Bochs poweroff port */ 88 for (i = 0; i < 8; i++) { 89 outb(shutdown_str[i], 0x8900); 90 } 91 #else 92 asm volatile("out %0, %1" : : "a"(code), "d"((short)0xf4)); 93 #endif 94 } 95 96 void __iomem *ioremap(phys_addr_t phys_addr, size_t size) 97 { 98 phys_addr_t base = phys_addr & PAGE_MASK; 99 phys_addr_t offset = phys_addr - base; 100 101 /* 102 * The kernel sets PTEs for an ioremap() with page cache disabled, 103 * but we do not do that right now. It would make sense that I/O 104 * mappings would be uncached - and may help us find bugs when we 105 * properly map that way. 106 */ 107 return vmap(phys_addr, size) + offset; 108 } 109