1
2 #include <stdbool.h>
3 #include <stdint.h>
4
5 #include <sys/spinlock.h>
6 #include <sys/kmem.h>
7 #include <sys/thread.h>
8
9 #include "console.h"
10 #include "x86/vgacons.h"
11 #include "x86/sercons.h"
12 #include "x86/debugcons.h"
13
14 Spinlock consoleLock;
15 Console consoles;
16
17 /*
18 * Initialize console devices for debugging purposes. At this point interrupts
19 * and device state is not initialized.
20 */
21 void
Console_Init()22 Console_Init()
23 {
24 VGA_Init();
25 Serial_Init();
26 DebugConsole_Init();
27
28 Console_Puts("Castor Operating System\n");
29
30 Spinlock_Init(&consoleLock, "Console Lock", SPINLOCK_TYPE_NORMAL);
31
32 Spinlock_Init(&consoles.keyLock, "Console Keyboard Lock", SPINLOCK_TYPE_NORMAL);
33 consoles.nextKey = 0;
34 consoles.lastKey = 0;
35 }
36
37 /*
38 * Setup interrupts and input devices that may not be ready
39 */
40 void
Console_LateInit()41 Console_LateInit()
42 {
43 Serial_LateInit();
44 }
45
46 char
Console_Getc()47 Console_Getc()
48 {
49 while (1) {
50 Spinlock_Lock(&consoles.keyLock);
51 if (consoles.nextKey != consoles.lastKey) {
52 char key = consoles.keyBuf[consoles.nextKey];
53 consoles.nextKey = (consoles.nextKey + 1) % CONSOLE_KEYBUF_MAXLEN;
54 Spinlock_Unlock(&consoles.keyLock);
55 return key;
56 }
57 Spinlock_Unlock(&consoles.keyLock);
58
59 // Support serial debugging if interrupts are disabled
60 if (Serial_HasData()) {
61 char key = Serial_Getc();
62 switch (key) {
63 case '\r':
64 return '\n';
65 case 0x7f:
66 return '\b';
67 default:
68 return key;
69 }
70 }
71 }
72 }
73
74 void
Console_EnqueueKey(char key)75 Console_EnqueueKey(char key)
76 {
77 Spinlock_Lock(&consoles.keyLock);
78 if (((consoles.lastKey + 1) % CONSOLE_KEYBUF_MAXLEN) == consoles.lastKey) {
79 Spinlock_Unlock(&consoles.keyLock);
80 return;
81 }
82 consoles.keyBuf[consoles.lastKey] = key;
83 consoles.lastKey = (consoles.lastKey + 1) % CONSOLE_KEYBUF_MAXLEN;
84 Spinlock_Unlock(&consoles.keyLock);
85 }
86
87 void
Console_Gets(char * str,size_t n)88 Console_Gets(char *str, size_t n)
89 {
90 int i;
91
92 for (i = 0; i < (n - 1); i++)
93 {
94 char ch = Console_Getc();
95 if (ch == '\b') {
96 if (i > 0) {
97 Console_Putc(ch);
98 i--;
99 }
100 i--;
101 continue;
102 }
103 if (ch == '\n') {
104 Console_Putc('\n');
105 str[i] = '\0';
106 return;
107 }
108 if (ch == '\r') {
109 Console_Putc('\n');
110 str[i] = '\0';
111 return;
112 }
113 if (ch == '\t') {
114 Console_Putc('\t');
115 str[i] = '\t';
116 continue;
117 }
118 if (ch < 0x20)
119 {
120 // Unprintable character
121 continue;
122 }
123 Console_Putc(ch);
124 str[i] = ch;
125 }
126
127 str[i+1] = '\0';
128 }
129
130 void
Console_Putc(char ch)131 Console_Putc(char ch)
132 {
133 Spinlock_Lock(&consoleLock);
134 VGA_Putc(ch);
135 Serial_Putc(ch);
136 DebugConsole_Putc(ch);
137 Spinlock_Unlock(&consoleLock);
138 }
139
140 void
Console_Puts(const char * str)141 Console_Puts(const char *str)
142 {
143 Spinlock_Lock(&consoleLock);
144 VGA_Puts(str);
145 Serial_Puts(str);
146 DebugConsole_Puts(str);
147 Spinlock_Unlock(&consoleLock);
148 }
149
150 int
Console_Read(Handle * handle,void * buf,uint64_t off,uint64_t len)151 Console_Read(Handle *handle, void *buf, uint64_t off, uint64_t len)
152 {
153 uintptr_t b = (uintptr_t)buf;
154 uint64_t i;
155
156 for (i = 0; i < len; i++)
157 {
158 char c = Console_Getc();
159 Console_Putc(c);
160 Copy_Out(&c, b+i, 1);
161 }
162
163 return len;
164 }
165
166 int
Console_Write(Handle * handle,void * buf,uint64_t off,uint64_t len)167 Console_Write(Handle *handle, void *buf, uint64_t off, uint64_t len)
168 {
169 int i;
170 uintptr_t b = (uintptr_t)buf;
171 char kbuf[512];
172 uint64_t nbytes = 0;
173
174 while (len > nbytes) {
175 uint64_t chunksz = len > 512 ? 512 : len;
176 Copy_In(b + nbytes, &kbuf, chunksz);
177 nbytes += chunksz;
178
179 for (i = 0; i < chunksz; i++)
180 Console_Putc(kbuf[i]);
181 }
182
183 return nbytes;
184 }
185
186 int
Console_Flush(Handle * handle)187 Console_Flush(Handle *handle)
188 {
189 return 0;
190 }
191
192 int
Console_Close(Handle * handle)193 Console_Close(Handle *handle)
194 {
195 Handle_Free(handle);
196 return 0;
197 }
198
199 Handle *
Console_OpenHandle()200 Console_OpenHandle()
201 {
202 Handle *handle = Handle_Alloc();
203 if (!handle)
204 return NULL;
205
206 handle->read = &Console_Read;
207 handle->write = &Console_Write;
208 handle->flush = &Console_Flush;
209 handle->close = &Console_Close;
210
211 return handle;
212 }
213
214