Reorganization, comments.
[pintos-anon] / src / devices / vga.c
1 #include "vga.h"
2 #include <stdint.h>
3 #include <stddef.h>
4 #include "io.h"
5 #include "lib.h"
6 #include "mmu.h"
7
8 /* VGA text screen support.  See [FREEVGA] for more information. */
9
10 /* Number of columns and rows on the text display. */
11 #define COL_CNT 80
12 #define ROW_CNT 25
13
14 /* Current cursor position.  (0,0) is in the upper left corner of
15    the display. */
16 static size_t cx, cy;
17
18 /* Attribute value for gray text on a black background. */
19 #define GRAY_ON_BLACK 0x07
20
21 /* Framebuffer.  See [FREEVGA] under "VGA Text Mode Operation".
22    The character at (x,y) is fb[y][x][0].
23    The attribute at (x,y) is fb[y][x][1]. */
24 static uint8_t (*fb)[COL_CNT][2];
25
26 static void clear_row (size_t y);
27 static void cls (void);
28 static void newline (void);
29 static void move_cursor (void);
30
31 /* Initializes the VGA text display and clears the screen. */
32 void
33 vga_init (void)
34 {
35   fb = ptov (0xb8000);
36   cls ();
37 }
38
39 /* Writes C to the VGA text display, interpreting control
40    characters in the conventional ways. */
41 void
42 vga_putc (int c)
43 {
44   switch (c) 
45     {
46     case '\n':
47       newline ();
48       break;
49
50     case '\f':
51       cls ();
52       break;
53
54     case '\b':
55       if (cx > 0)
56         cx--;
57       break;
58       
59     case '\r':
60       cx = 0;
61       break;
62
63     case '\t':
64       cx = ROUND_UP (cx + 1, 8);
65       if (cx >= COL_CNT)
66         newline ();
67       break;
68       
69     default:
70       fb[cy][cx][0] = c;
71       fb[cy][cx][1] = GRAY_ON_BLACK;
72       if (++cx >= COL_CNT)
73         newline ();
74       break;
75     }
76
77   /* Update cursor position. */
78   move_cursor ();
79 }
80 \f
81 /* Clears the screen and moves the cursor to the upper left. */
82 static void
83 cls (void)
84 {
85   size_t y;
86
87   for (y = 0; y < ROW_CNT; y++)
88     clear_row (y);
89
90   cx = cy = 0;
91   move_cursor ();
92 }
93
94 /* Clears row Y to spaces. */
95 static void
96 clear_row (size_t y) 
97 {
98   size_t x;
99
100   for (x = 0; x < COL_CNT; x++)
101     {
102       fb[y][x][0] = ' ';
103       fb[y][x][1] = GRAY_ON_BLACK;
104     }
105 }
106
107 /* Advances the cursor to the first column in the next line on
108    the screen.  If the cursor is already on the last line on the
109    screen, scrolls the screen upward one line. */
110 static void
111 newline (void)
112 {
113   cx = 0;
114   cy++;
115   if (cy >= ROW_CNT)
116     {
117       cy = ROW_CNT - 1;
118       memmove (&fb[0], &fb[1], sizeof fb[0] * (ROW_CNT - 1));
119       clear_row (ROW_CNT - 1);
120     }
121 }
122
123 /* Moves the hardware cursor to (cx,cy). */
124 static void
125 move_cursor (void) 
126 {
127   /* See [FREEVGA] under "Manipulating the Text-mode Cursor". */
128   uint16_t cp = cx + COL_CNT * cy;
129   outw (0x3d4, 0x0e | (cp & 0xff00));
130   outw (0x3d4, 0x0f | (cp << 8));
131 }
132