xref: /kvm-unit-tests/lib/x86/io.c (revision 0f54b9b2875b155b02e60904cd21d394fd86e94f)
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