io.c 2.1 KB

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