1/**
2 * \file
3 * \brief Text-mode video console output driver.
4 */
5
6/*
7 * Copyright (c) 2007, 2008, 2010, ETH Zurich.
8 * All rights reserved.
9 *
10 * This file is distributed under the terms in the attached LICENSE file.
11 * If you do not find this file, copies can be found by writing to:
12 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
13 */
14
15#include <kernel.h>
16#include <string.h>
17#include <x86.h>
18#include <arch/x86/conio.h>
19
20#define COLS        80                  ///< Number of columns on screen
21#define LINES       25                 ///< Number of lines on screen
22#define CHAR_ATTR   7                   ///< Attribute of plain text characters
23#define VIDEO_LEN   (COLS * LINES * 2)  ///< Size of video memory
24#define TAB_WIDTH   8                   ///< Tab-stop width
25
26// Cursor X/Y position and attribute
27static int xpos = 0, ypos = 0, attribute = CHAR_ATTR;
28// Pointer to video memory
29static uint8_t * COUNT(VIDEO_LEN) video
30     = (uint8_t * COUNT(VIDEO_LEN)) TC(VIDEO_MEM);
31static int use_conio = 1;
32
33/**
34 * \brief Clear the screen and reset cursor.
35 */
36void conio_cls(void)
37{
38    if (use_conio && CPU_IS_M5_SIMULATOR) {
39        use_conio = 0;
40    } else {
41        memset(video, 0, LINES * COLS * 2);
42        xpos = ypos = 0;
43    }
44}
45
46/**
47 * \brief Relocate video memory to new location.
48 *
49 * This function relocates the start of the video memory to the
50 * virtual address 'newaddr'.
51 *
52 * \param newaddr       Address of start of new video memory.
53 */
54void conio_relocate_vidmem(lvaddr_t newaddr)
55{
56    video = (uint8_t *)newaddr;
57}
58
59/**
60 * \brief Feed the screen page by one line.
61 */
62static void page_feed(void)
63{
64    memmove(video, video + COLS * 2, (LINES - 1) * COLS * 2);
65    memset(video + (LINES - 1) * COLS * 2, 0, COLS * 2);
66}
67
68/**
69 * \brief Put the character 'c' on the screen.
70 *
71 * \param c     Character to print on the screen.
72 */
73void conio_putchar(char c)
74{
75    if (use_conio) {
76        uint8_t *vidptr;
77
78        // Handle carriage return character
79        if (c == '\r') {
80        carriage:
81          xpos = 0;
82          return;
83        }
84
85        // Handle newline character
86        if (c == '\n') {
87        newline:
88          if (ypos < LINES - 1) {
89            ypos++;
90          } else {
91            page_feed();
92          }
93          goto carriage;
94        }
95
96        // Handle backspace character
97        if (c == '\b') {
98          xpos--;
99          return;
100        }
101
102        // Handle tab-stop character
103        if (c == '\t') {
104          while(xpos % TAB_WIDTH != 0)
105            xpos++;
106
107          return;
108        }
109
110        vidptr = video + (xpos + ypos * COLS) * 2;
111        *vidptr = c & 0xff;
112        *(vidptr + 1) = attribute;
113
114        xpos++;
115        if (xpos >= COLS) {
116          goto newline;
117        }
118    }
119}
120