17d36db35SAvi Kivity #include "libcflat.h" 27d36db35SAvi Kivity #include "smp.h" 328fb1a86SLucas Meneghel Rodrigues #include "io.h" 428fb1a86SLucas Meneghel Rodrigues #ifndef USE_SERIAL 528fb1a86SLucas Meneghel Rodrigues #define USE_SERIAL 6ac1690b2SAvi Kivity #endif 77d36db35SAvi Kivity 87d36db35SAvi Kivity static struct spinlock lock; 928fb1a86SLucas Meneghel Rodrigues static int serial_iobase = 0x3f8; 1028fb1a86SLucas Meneghel Rodrigues static int serial_inited = 0; 1128fb1a86SLucas Meneghel Rodrigues 1228fb1a86SLucas Meneghel Rodrigues static void serial_outb(char ch) 1328fb1a86SLucas Meneghel Rodrigues { 1428fb1a86SLucas Meneghel Rodrigues u8 lsr; 1528fb1a86SLucas Meneghel Rodrigues 1628fb1a86SLucas Meneghel Rodrigues do { 1728fb1a86SLucas Meneghel Rodrigues lsr = inb(serial_iobase + 0x05); 1828fb1a86SLucas Meneghel Rodrigues } while (!(lsr & 0x20)); 1928fb1a86SLucas Meneghel Rodrigues 2028fb1a86SLucas Meneghel Rodrigues outb(ch, serial_iobase + 0x00); 2128fb1a86SLucas Meneghel Rodrigues } 2228fb1a86SLucas Meneghel Rodrigues 2328fb1a86SLucas Meneghel Rodrigues static void serial_init(void) 2428fb1a86SLucas Meneghel Rodrigues { 2528fb1a86SLucas Meneghel Rodrigues u8 lcr; 2628fb1a86SLucas Meneghel Rodrigues 2728fb1a86SLucas Meneghel Rodrigues /* set DLAB */ 2828fb1a86SLucas Meneghel Rodrigues lcr = inb(serial_iobase + 0x03); 2928fb1a86SLucas Meneghel Rodrigues lcr |= 0x80; 3028fb1a86SLucas Meneghel Rodrigues outb(lcr, serial_iobase + 0x03); 3128fb1a86SLucas Meneghel Rodrigues 3228fb1a86SLucas Meneghel Rodrigues /* set baud rate to 115200 */ 3328fb1a86SLucas Meneghel Rodrigues outb(0x01, serial_iobase + 0x00); 3428fb1a86SLucas Meneghel Rodrigues outb(0x00, serial_iobase + 0x01); 3528fb1a86SLucas Meneghel Rodrigues 3628fb1a86SLucas Meneghel Rodrigues /* clear DLAB */ 3728fb1a86SLucas Meneghel Rodrigues lcr = inb(serial_iobase + 0x03); 3828fb1a86SLucas Meneghel Rodrigues lcr &= ~0x80; 3928fb1a86SLucas Meneghel Rodrigues outb(lcr, serial_iobase + 0x03); 4028fb1a86SLucas Meneghel Rodrigues } 417d36db35SAvi Kivity 427d36db35SAvi Kivity static void print_serial(const char *buf) 437d36db35SAvi Kivity { 447d36db35SAvi Kivity unsigned long len = strlen(buf); 4528fb1a86SLucas Meneghel Rodrigues #ifdef USE_SERIAL 4628fb1a86SLucas Meneghel Rodrigues unsigned long i; 4728fb1a86SLucas Meneghel Rodrigues if (!serial_inited) { 4828fb1a86SLucas Meneghel Rodrigues serial_init(); 49*0f54b9b2SPaolo Bonzini serial_inited = 1; 5028fb1a86SLucas Meneghel Rodrigues } 517d36db35SAvi Kivity 5228fb1a86SLucas Meneghel Rodrigues for (i = 0; i < len; i++) { 5328fb1a86SLucas Meneghel Rodrigues serial_outb(buf[i]); 5428fb1a86SLucas Meneghel Rodrigues } 5528fb1a86SLucas Meneghel Rodrigues #else 567d36db35SAvi Kivity asm volatile ("rep/outsb" : "+S"(buf), "+c"(len) : "d"(0xf1)); 5728fb1a86SLucas Meneghel Rodrigues #endif 587d36db35SAvi Kivity } 597d36db35SAvi Kivity 607d36db35SAvi Kivity void puts(const char *s) 617d36db35SAvi Kivity { 627d36db35SAvi Kivity spin_lock(&lock); 637d36db35SAvi Kivity print_serial(s); 647d36db35SAvi Kivity spin_unlock(&lock); 657d36db35SAvi Kivity } 667d36db35SAvi Kivity 677d36db35SAvi Kivity void exit(int code) 687d36db35SAvi Kivity { 6928fb1a86SLucas Meneghel Rodrigues #ifdef USE_SERIAL 7028fb1a86SLucas Meneghel Rodrigues static const char shutdown_str[8] = "Shutdown"; 7128fb1a86SLucas Meneghel Rodrigues int i; 7228fb1a86SLucas Meneghel Rodrigues 7328fb1a86SLucas Meneghel Rodrigues /* test device exit (with status) */ 7428fb1a86SLucas Meneghel Rodrigues outl(code, 0xf4); 7528fb1a86SLucas Meneghel Rodrigues 7628fb1a86SLucas Meneghel Rodrigues /* if that failed, try the Bochs poweroff port */ 7728fb1a86SLucas Meneghel Rodrigues for (i = 0; i < 8; i++) { 7828fb1a86SLucas Meneghel Rodrigues outb(shutdown_str[i], 0x8900); 7928fb1a86SLucas Meneghel Rodrigues } 8028fb1a86SLucas Meneghel Rodrigues #else 817d36db35SAvi Kivity asm volatile("out %0, %1" : : "a"(code), "d"((short)0xf4)); 8228fb1a86SLucas Meneghel Rodrigues #endif 837d36db35SAvi Kivity } 84