blob: 5a9d2e9e771de582552302038a249a1ae1436d5a (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
/*
* con.c
*
* Basic VGA text console. Implements printk().
*/
#include <asm/io.h>
#include <kernel/tty.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#define COLS 80
#define ROWS 25
/* internal function prototypes */
static void con_write(void);
struct tty_struct tty_con = {
.init = NULL,
.write = &con_write
};
static uint8_t *vram = (uint8_t*) 0xB8000;
static int pos;
static inline void cursorpos(int pos) {
outb(0x3D4, 0x0E);
outb(0x3D5, (uint8_t) ((pos >> 9) & 0xFF));
outb(0x3D4, 0x0F);
outb(0x3D5, (uint8_t) ((pos >> 1) & 0xFF));
}
/* scrolls the console up one line */
static void scroll_up(void) {
int n = (COLS * (ROWS - 1)) << 1;
uint8_t *p = vram;
while(n--) {
*p = p[COLS << 1];
p++;
}
p = (uint8_t*) (vram + (COLS * (ROWS - 1) << 1));
n = COLS;
while(n--) {
*p = ' ';
p += 2;
}
pos -= COLS << 1;
cursorpos(pos);
}
/* clear the console and reset the cursor to the starting position */
void con_clear(void) {
int n = COLS * ROWS;
uint8_t *p = vram;
while(n--) {
*(p++) = 0x20;
*(p++) = 0x07;
}
pos = 0;
cursorpos(0);
}
/* must be called before any console output */
void con_init(void) {
/* clear the console */
con_clear();
}
/* write a zero-terminated string to console */
static int con_puts(char *s) {
uint8_t *p = &vram[pos];
while(*s) {
if(*s == '\n') {
pos = (int) (p - vram);
pos = ((pos / (COLS << 1)) + 1) * (COLS << 1);
p = &vram[pos];
s++;
} else {
*p = *(s++);
p += 2;
}
pos = (int) (p - vram);
if(pos >= (COLS * ROWS) << 1)
scroll_up();
}
/* update the cursor position */
cursorpos(pos);
/* this always succeeds */
return 0;
}
/* same as con_puts() but deals with bytes rather than strings */
static void con_write(void) {
char c;
int copied = 0;
uint8_t *p = &vram[pos];
struct tty_queue *q = &tty_con.wqueue;
while(q->pread != q->pwrite) {
c = q->buf[q->pread];
if(c == '\n') {
pos = (int) (p - vram);
pos = ((pos / (COLS << 1)) + 1) * (COLS << 1);
p = &vram[pos];
} else {
*p = c;
p += 2;
}
q->pread = (q->pread + 1) % TTY_BUF_SIZE;
copied = 1;
pos = (int) (p - vram);
if(pos >= (COLS * ROWS) << 1)
scroll_up();
}
/* update the cursor position */
cursorpos(pos);
if(copied)
wake_up(&q->waiting);
}
int printk(char *fmt, ...) {
int ret;
char buf[1024];
va_list ap;
va_start(ap, fmt);
ret = vsprintf(buf, fmt, ap);
va_end(ap);
con_puts(buf);
return ret;
}
|