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