linux/arch/x86/boot/tty.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/* -*- linux-c -*- ------------------------------------------------------- *
   3 *
   4 *   Copyright (C) 1991, 1992 Linus Torvalds
   5 *   Copyright 2007 rPath, Inc. - All Rights Reserved
   6 *   Copyright 2009 Intel Corporation; author H. Peter Anvin
   7 *
   8 * ----------------------------------------------------------------------- */
   9
  10/*
  11 * Very simple screen and serial I/O
  12 */
  13
  14#include "boot.h"
  15
  16int early_serial_base;
  17
  18#define XMTRDY          0x20
  19
  20#define TXR             0       /*  Transmit register (WRITE) */
  21#define LSR             5       /*  Line Status               */
  22
  23/*
  24 * These functions are in .inittext so they can be used to signal
  25 * error during initialization.
  26 */
  27
  28static void __section(".inittext") serial_putchar(int ch)
  29{
  30        unsigned timeout = 0xffff;
  31
  32        while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout)
  33                cpu_relax();
  34
  35        outb(ch, early_serial_base + TXR);
  36}
  37
  38static void __section(".inittext") bios_putchar(int ch)
  39{
  40        struct biosregs ireg;
  41
  42        initregs(&ireg);
  43        ireg.bx = 0x0007;
  44        ireg.cx = 0x0001;
  45        ireg.ah = 0x0e;
  46        ireg.al = ch;
  47        intcall(0x10, &ireg, NULL);
  48}
  49
  50void __section(".inittext") putchar(int ch)
  51{
  52        if (ch == '\n')
  53                putchar('\r');  /* \n -> \r\n */
  54
  55        bios_putchar(ch);
  56
  57        if (early_serial_base != 0)
  58                serial_putchar(ch);
  59}
  60
  61void __section(".inittext") puts(const char *str)
  62{
  63        while (*str)
  64                putchar(*str++);
  65}
  66
  67/*
  68 * Read the CMOS clock through the BIOS, and return the
  69 * seconds in BCD.
  70 */
  71
  72static u8 gettime(void)
  73{
  74        struct biosregs ireg, oreg;
  75
  76        initregs(&ireg);
  77        ireg.ah = 0x02;
  78        intcall(0x1a, &ireg, &oreg);
  79
  80        return oreg.dh;
  81}
  82
  83/*
  84 * Read from the keyboard
  85 */
  86int getchar(void)
  87{
  88        struct biosregs ireg, oreg;
  89
  90        initregs(&ireg);
  91        /* ireg.ah = 0x00; */
  92        intcall(0x16, &ireg, &oreg);
  93
  94        return oreg.al;
  95}
  96
  97static int kbd_pending(void)
  98{
  99        struct biosregs ireg, oreg;
 100
 101        initregs(&ireg);
 102        ireg.ah = 0x01;
 103        intcall(0x16, &ireg, &oreg);
 104
 105        return !(oreg.eflags & X86_EFLAGS_ZF);
 106}
 107
 108void kbd_flush(void)
 109{
 110        for (;;) {
 111                if (!kbd_pending())
 112                        break;
 113                getchar();
 114        }
 115}
 116
 117int getchar_timeout(void)
 118{
 119        int cnt = 30;
 120        int t0, t1;
 121
 122        t0 = gettime();
 123
 124        while (cnt) {
 125                if (kbd_pending())
 126                        return getchar();
 127
 128                t1 = gettime();
 129                if (t0 != t1) {
 130                        cnt--;
 131                        t0 = t1;
 132                }
 133        }
 134
 135        return 0;               /* Timeout! */
 136}
 137
 138