f4eb723b1f58be784538474dceb890d0e56512df
[eightysix] / kern / src / vid.c
1 #include <string.h>
2 #include "vid.h"
3 #include "asmutil.h"
4
5 #define CRTC_ADDR_PORT  (iobase | 4)
6 #define CRTC_DATA_PORT  (iobase | 5)
7
8 /* CRTC registers */
9 #define CRTC_START_H    0x0c
10 #define CRTC_START_L    0x0d
11 #define CRTC_CURPOS_H   0x0e
12 #define CRTC_CURPOS_L   0x0f
13
14 static void detect_video(void);
15 static int detect_vgainfo(void);
16 static int detect_egainfo(void);
17 static void detect_eqlist(void);
18 static void crtc_write(int reg, unsigned char val);
19
20 //struct console con_vid = { con_clear, con_putc, 0 };
21
22 static uint16_t __far *vmem;
23 static int iobase;
24
25 static uint16_t cur_attr;
26 static int cur_x, cur_y;
27 static int cur_scroll;
28 static int mono;
29
30 void vid_init(void)
31 {
32         detect_video();
33         if(mono) {
34                 vmem = MK_FP(0xb000, 0);
35                 iobase = 0x3b0;
36         } else {
37                 vmem = MK_FP(0xb800, 0);
38                 iobase = 0x3d0;
39         }
40
41         vid_reset();
42 }
43
44 static void detect_video(void)
45 {
46         mono = 0;
47         vid_type = VID_UNK;
48
49         if(detect_vgainfo() == 0) {
50                 return;
51         }
52         if(detect_egainfo() == 0) {
53                 return;
54         }
55         detect_eqlist();
56 }
57
58 static int detect_vgainfo(void)
59 {
60         union regs regs;
61
62         regs.w.ax = 0x1a00;
63         int86(0x10, &regs, &regs);
64         if(regs.h.al != 0x1a) {
65                 return -1;
66         }
67
68         switch(regs.h.bl) {
69         case 1:
70                 vid_type = VID_MDA;
71                 mono = 1;
72                 break;
73         case 2:
74                 vid_type = VID_CGA;
75                 break;
76         case 4:
77                 vid_type = VID_EGA;
78                 break;
79         case 5:
80                 vid_type = VID_EGA;
81                 mono = 1;
82                 break;
83         case 6:
84                 vid_type = VID_PGA;
85                 break;
86         case 7:
87                 vid_type = VID_VGA;
88                 mono = 1;
89                 break;
90         case 8:
91                 vid_type = VID_VGA;
92                 break;
93         case 0xa:
94         case 0xc:
95                 vid_type = VID_MCGA;
96                 break;
97         case 0xb:
98                 vid_type = VID_MCGA;
99                 mono = 1;
100                 break;
101         default:
102                 return -1;
103         }
104         return 0;
105 }
106
107 static int detect_egainfo(void)
108 {
109         union regs regs;
110
111         regs.w.ax = 0x1200;
112         regs.w.bx = 0xff10;
113         int86(0x10, &regs, &regs);
114         if(regs.h.bh == 0xff) {
115                 return -1;
116         }
117
118         vid_type = VID_EGA;
119         mono = regs.h.bh;
120         return 0;
121 }
122
123 static void detect_eqlist(void)
124 {
125         union regs regs;
126
127         int86(0x11, &regs, &regs);
128         switch(regs.w.ax & 0x30) {
129         case 0:
130                 vid_type = VID_EGA;
131                 break;
132
133         case 0x10:
134         case 0x20:
135                 vid_type = VID_CGA;
136                 break;
137
138         case 0x30:
139                 vid_type = VID_MDA;
140                 mono = 1;
141                 break;
142         }
143 }
144
145 void vid_reset(void)
146 {
147         vid_fgcolor(WHITE);
148         vid_bgcolor(BLACK);
149         vid_scroll(0);
150         vid_setcursor(0, 0);
151         fmemset(vmem, 0, 80 * 25 * 2);
152 }
153
154 void vid_clearline(int row)
155 {
156         int i;
157         uint16_t __far *ptr;
158
159         row += cur_scroll;
160
161         ptr = vmem + row * 80;
162         for(i=0; i<80; i++) {
163                 ptr[i] = cur_attr;
164         }
165
166         if(row - 32 >= 0) {
167                 /* write a copy to wrap-around future scrolling */
168                 ptr -= 80 * 32;
169                 for(i=0; i<80; i++) {
170                         ptr[i] = cur_attr;
171                 }
172         }
173 }
174
175 void vid_clear(void)
176 {
177         int i;
178         for(i=0; i<25; i++) {
179                 vid_clearline(i);
180         }
181 }
182
183 void vid_scroll(int line)
184 {
185         int offs;
186         cur_scroll = line & 0x1f;
187         offs = cur_scroll * 80;
188         crtc_write(CRTC_START_H, offs >> 8);
189         crtc_write(CRTC_START_L, offs);
190 }
191
192 void vid_setcursor(int x, int y)
193 {
194         int loc = (y + cur_scroll) * 80 + x;
195         cur_x = x;
196         cur_y = y;
197         crtc_write(CRTC_CURPOS_H, loc >> 8);
198         crtc_write(CRTC_CURPOS_L, loc);
199 }
200
201 void vid_fgcolor(int color)
202 {
203         cur_attr = (cur_attr & 0xf0) | color;
204 }
205
206 void vid_bgcolor(int color)
207 {
208         cur_attr = (cur_attr & 0x0f) | (color << 4);
209 }
210
211 void vid_glyph(int x, int y, int c, int attr)
212 {
213         uint16_t __far *ptr;
214         uint16_t val = (c & 0xff) | attr;
215
216         y += cur_scroll;
217
218         ptr = vmem + y * 80 + x;
219         *ptr = val;
220
221         if(y - 32 >= 0) {
222                 /* write a copy to wrap-around future scrolling */
223                 ptr -= 80 * 32;
224                 *ptr = val;
225         }
226 }
227
228 void vid_text(int x, int y, const char *s, int attr)
229 {
230         int len = 0;
231         uint16_t __far *ptr;
232
233         y += cur_scroll;
234
235         ptr = vmem + y * 80 + x;
236         while(*s) {
237                 *ptr++ = (*s++ & 0xff) | attr;
238                 len++;
239         }
240
241         if(y - 32 >= 0) {
242                 /* write a copy to wrap-around future scrolling */
243                 ptr -= 80 * 32 + len;
244                 s -= len;
245                 while(*s) {
246                         *ptr++ = (*s++ & 0xff) | attr;
247                 }
248         }
249 }
250
251 static void crtc_write(int reg, unsigned char val)
252 {
253         outp(CRTC_ADDR_PORT, reg);
254         outp(CRTC_DATA_PORT, val);
255 }