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