2 pcboot - bootable PC demo/game kernel
3 Copyright (C) 2018 John Tsiombikas <nuclear@member.fsf.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY, without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>.
29 #define TEXT_ADDR ((char*)0xb8000)
31 #define CRTC_ADDR 0x3d4
32 #define CRTC_DATA 0x3d5
34 #define CRTC_REG_CURSTART 0x0a
35 #define CRTC_REG_CUREND 0x0b
36 #define CRTC_REG_START_H 0x0c
37 #define CRTC_REG_START_L 0x0d
38 #define CRTC_REG_CURLOC_H 0x0e
39 #define CRTC_REG_CURLOC_L 0x0f
41 #define VMEM_CHAR(c, attr) \
42 ((uint16_t)(c) | ((uint16_t)(attr) << 8))
44 static void scroll(void);
45 static void crtc_cursor(int x, int y);
46 static void crtc_setstart(int y);
47 static inline unsigned char crtc_read(int reg);
48 static inline void crtc_write(int reg, unsigned char val);
49 static inline void crtc_write_bits(int reg, unsigned char val, unsigned char mask);
51 extern int cursor_x, cursor_y;
52 static unsigned char txattr = 0x07;
53 static int start_line;
58 ser_open(0, 9600, SER_8N1);
64 crtc_cursor(cursor_x, cursor_y);
66 printf("curloc: %x %x\n", (unsigned int)crtc_read(CRTC_REG_CURLOC_H),
67 (unsigned int)crtc_read(CRTC_REG_CURLOC_L));
68 printf("curstart: %x\n", (unsigned int)crtc_read(CRTC_REG_CURSTART));
69 printf("curend: %x\n", (unsigned int)crtc_read(CRTC_REG_CUREND));
76 void con_show_cursor(int show)
79 unsigned char val = show ? 0 : 0x20;
81 crtc_write_bits(CRTC_REG_CURSTART, val, 0x20);
85 void con_cursor(int x, int y)
94 void con_fgcolor(int c)
96 txattr = (txattr & 0xf0) | c;
99 void con_bgcolor(int c)
101 txattr = (txattr & 0x0f) | (c << 4);
107 memset(TEXT_ADDR, 0, NCOLS * NROWS * 2);
112 cursor_x = cursor_y = 0;
117 static inline void linefeed(void)
119 if(++cursor_y >= NROWS) {
125 void con_putchar(int c)
135 crtc_cursor(cursor_x, cursor_y);
139 cursor_x = (cursor_x & 0x7) + 8;
140 if(cursor_x >= NCOLS) {
144 crtc_cursor(cursor_x, cursor_y);
148 ptr = (uint16_t*)TEXT_ADDR;
149 ptr[(cursor_y + start_line) * NCOLS + cursor_x] = VMEM_CHAR(c, txattr);
151 if(++cursor_x >= NCOLS) {
155 crtc_cursor(cursor_x, cursor_y);
164 static void scroll(void)
168 if(++start_line > VIRT_ROWS - NROWS) {
169 /* The bottom of the visible range reached the end of our text buffer.
170 * Copy the rest of the lines to the top and reset start_line.
172 memcpy(TEXT_ADDR, TEXT_ADDR + start_line * NCOLS, (NROWS - 1) * NCOLS * 2);
176 /* clear the next line that will be revealed by scrolling */
177 new_line = start_line + NROWS - 1;
178 memset16(TEXT_ADDR + new_line * NCOLS * 2, VMEM_CHAR(' ', txattr), NCOLS);
179 crtc_setstart(start_line);
182 static void crtc_cursor(int x, int y)
186 addr = (y + start_line) * NCOLS + x;
188 crtc_write(CRTC_REG_CURLOC_L, addr);
189 crtc_write(CRTC_REG_CURLOC_H, addr >> 8);
192 static void crtc_setstart(int y)
194 unsigned int addr = y * NCOLS;
196 crtc_write(CRTC_REG_START_L, addr);
197 crtc_write(CRTC_REG_START_H, addr >> 8);
200 static inline unsigned char crtc_read(int reg)
202 outb(reg, CRTC_ADDR);
203 return inb(CRTC_DATA);
206 static inline void crtc_write(int reg, unsigned char val)
208 outb(reg, CRTC_ADDR);
209 outb(val, CRTC_DATA);
212 static inline void crtc_write_bits(int reg, unsigned char val, unsigned char mask)
215 outb(reg, CRTC_ADDR);
216 prev = inb(CRTC_DATA);
217 val = (prev & ~mask) | (val & mask);
218 outb(val, CRTC_DATA);