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