Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /* -*- linux-c -*- ------------------------------------------------------- *
0003  *
0004  *   Copyright (C) 1991, 1992 Linus Torvalds
0005  *   Copyright 2007 rPath, Inc. - All Rights Reserved
0006  *   Copyright 2009 Intel Corporation; author H. Peter Anvin
0007  *
0008  * ----------------------------------------------------------------------- */
0009 
0010 /*
0011  * Very simple screen and serial I/O
0012  */
0013 
0014 #include "boot.h"
0015 
0016 int early_serial_base;
0017 
0018 #define XMTRDY          0x20
0019 
0020 #define TXR             0       /*  Transmit register (WRITE) */
0021 #define LSR             5       /*  Line Status               */
0022 
0023 /*
0024  * These functions are in .inittext so they can be used to signal
0025  * error during initialization.
0026  */
0027 
0028 static void __section(".inittext") serial_putchar(int ch)
0029 {
0030     unsigned timeout = 0xffff;
0031 
0032     while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout)
0033         cpu_relax();
0034 
0035     outb(ch, early_serial_base + TXR);
0036 }
0037 
0038 static void __section(".inittext") bios_putchar(int ch)
0039 {
0040     struct biosregs ireg;
0041 
0042     initregs(&ireg);
0043     ireg.bx = 0x0007;
0044     ireg.cx = 0x0001;
0045     ireg.ah = 0x0e;
0046     ireg.al = ch;
0047     intcall(0x10, &ireg, NULL);
0048 }
0049 
0050 void __section(".inittext") putchar(int ch)
0051 {
0052     if (ch == '\n')
0053         putchar('\r');  /* \n -> \r\n */
0054 
0055     bios_putchar(ch);
0056 
0057     if (early_serial_base != 0)
0058         serial_putchar(ch);
0059 }
0060 
0061 void __section(".inittext") puts(const char *str)
0062 {
0063     while (*str)
0064         putchar(*str++);
0065 }
0066 
0067 /*
0068  * Read the CMOS clock through the BIOS, and return the
0069  * seconds in BCD.
0070  */
0071 
0072 static u8 gettime(void)
0073 {
0074     struct biosregs ireg, oreg;
0075 
0076     initregs(&ireg);
0077     ireg.ah = 0x02;
0078     intcall(0x1a, &ireg, &oreg);
0079 
0080     return oreg.dh;
0081 }
0082 
0083 /*
0084  * Read from the keyboard
0085  */
0086 int getchar(void)
0087 {
0088     struct biosregs ireg, oreg;
0089 
0090     initregs(&ireg);
0091     /* ireg.ah = 0x00; */
0092     intcall(0x16, &ireg, &oreg);
0093 
0094     return oreg.al;
0095 }
0096 
0097 static int kbd_pending(void)
0098 {
0099     struct biosregs ireg, oreg;
0100 
0101     initregs(&ireg);
0102     ireg.ah = 0x01;
0103     intcall(0x16, &ireg, &oreg);
0104 
0105     return !(oreg.eflags & X86_EFLAGS_ZF);
0106 }
0107 
0108 void kbd_flush(void)
0109 {
0110     for (;;) {
0111         if (!kbd_pending())
0112             break;
0113         getchar();
0114     }
0115 }
0116 
0117 int getchar_timeout(void)
0118 {
0119     int cnt = 30;
0120     int t0, t1;
0121 
0122     t0 = gettime();
0123 
0124     while (cnt) {
0125         if (kbd_pending())
0126             return getchar();
0127 
0128         t1 = gettime();
0129         if (t0 != t1) {
0130             cnt--;
0131             t0 = t1;
0132         }
0133     }
0134 
0135     return 0;       /* Timeout! */
0136 }
0137