]> pd.if.org Git - zos/blob - tty.c
add a readme with a public domain note
[zos] / tty.c
1 #include <stddef.h>
2 #include <stdint.h>
3  
4 #include "tty.h"
5
6 #include "kernel.h"
7 #include "interrupt.h"
8 #include "ioport.h"
9
10 #include "string.h"
11
12 #include <mem.h>
13
14 #define make_color(fg, bg) (fg | bg << 4)
15 #define make_vga(ch, color) ((uint16_t)(ch & 0xff | color << 8))
16  
17 #define VGA_WIDTH  80
18 #define VGA_HEIGHT 25
19  
20 static struct virtual_console {
21         int row, column;
22         uint8_t color;
23
24 } con;
25
26 struct terminal terminal = { 0 };
27
28 static void clear() {
29         int i;
30         uint16_t blank = make_vga(' ', terminal.color);
31         for (i=0; i < VGA_WIDTH * VGA_HEIGHT; i++) {
32                 terminal.vmem[i] = blank;
33         }
34 }
35
36 static void scroll(int lines) {
37         uint16_t *base, *offset;
38         uint16_t blank;
39         int i;
40
41         base = terminal.vmem;
42         offset = base + VGA_WIDTH * lines;
43         memmove(base, offset, (VGA_WIDTH * VGA_HEIGHT - lines) * 2);
44
45         offset = base + (VGA_WIDTH * VGA_HEIGHT - lines);
46         blank = make_vga(' ', terminal.color);
47         for (i=0; i < VGA_WIDTH * lines; i++) {
48                 offset[i] = blank;
49         }
50 }
51  
52 static void putentryat(int c, uint8_t color, size_t x, size_t y) {
53         size_t index = y * VGA_WIDTH + x;
54         terminal.vmem[index] = make_vga(c, color);
55 }
56  
57 static void putchar(int c) {
58         if (terminal.escape) {
59                 switch(c) {
60
61                 }
62
63                 return;
64         }
65
66         switch (c) {
67                 case '\n':
68                         terminal.column = 0;
69                         if (++terminal.row == VGA_HEIGHT) {
70                                 terminal.row = VGA_HEIGHT-1;
71                                 scroll(1);
72                         }
73                         break;
74                 case '\r':
75                         terminal.column = 0;
76                         break;
77                 default:
78                         putentryat(c, terminal.color, terminal.column, terminal.row);
79                         terminal.column++;
80                         break;
81         }
82
83         if (terminal.column == VGA_WIDTH) {
84                 terminal.column = 0;
85                 if (++terminal.row == VGA_HEIGHT) {
86                         terminal.row = VGA_HEIGHT-1;
87                         scroll(1);
88                 }
89         }
90 }
91
92 static void setcursor(int row, int col) {
93         uint16_t position = (row*VGA_WIDTH) + col;
94
95         /* cursor low port to vga index register */
96         outport8(0x3D4, 0x0F);
97         outport8(0x3D5, (unsigned char)(position&0xFF));
98         /* cursor high port to vga index register */
99         outport8(0x3D4, 0x0E);
100         outport8(0x3D5, (unsigned char )((position>>8)&0xFF));
101 }
102
103 static void updcursor() {
104         setcursor(terminal.row, terminal.column);
105 }
106  
107 static void writestring(const char *data) {
108         size_t i = 0;
109
110         while (data[i]) {
111                 putchar(data[i++]);
112         }
113         updcursor();
114 }
115
116 void terminal_initialize() {
117         terminal.putchar = putchar;
118         terminal.clear = clear;
119         terminal.scroll = scroll;
120         terminal.writestring = writestring;
121         terminal.vc = &con;
122         terminal.vmem = (uint16_t *) (0xb8000 + _asm_physmap);
123         terminal.update_cursor = updcursor;
124
125         terminal.row = 0;
126         terminal.column = 0;
127         updcursor();
128
129         terminal.color = make_color(VGA_LIGHT_GREY, VGA_BLACK);
130
131         clear();
132 }