blob: e0661f14cea8a4185738ae0a8067a9db75c9e2f8 [file] [log] [blame]
Kevin O'Connor3471fdb2012-01-14 19:02:43 -05001// Standard VGA driver code
Kevin O'Connorc0c7df62009-05-17 18:11:33 -04002//
3// Copyright (C) 2009 Kevin O'Connor <kevin@koconnor.net>
4// Copyright (C) 2001-2008 the LGPL VGABios developers Team
5//
6// This file may be distributed under the terms of the GNU LGPLv3 license.
7
Kevin O'Connorc990f272011-12-31 16:00:54 -05008#include "biosvar.h" // GET_GLOBAL
Kevin O'Connor4ade5232013-09-18 21:41:48 -04009#include "farptr.h" // SET_FARVAR
10#include "stdvga.h" // stdvga_setup
Kevin O'Connorfa9c66a2013-09-14 19:10:40 -040011#include "string.h" // memset_far
Kevin O'Connor4ade5232013-09-18 21:41:48 -040012#include "vgabios.h" // struct vgamode_s
13#include "x86.h" // outb
Kevin O'Connorc0c7df62009-05-17 18:11:33 -040014
15
16/****************************************************************
17 * Attribute control
18 ****************************************************************/
19
Kevin O'Connora0ecb052009-05-18 23:34:00 -040020void
Kevin O'Connor88ca7412011-12-31 04:24:20 -050021stdvga_set_border_color(u8 color)
Kevin O'Connorc0c7df62009-05-17 18:11:33 -040022{
Kevin O'Connor8bc059e2009-05-17 21:19:36 -040023 u8 v1 = color & 0x0f;
24 if (v1 & 0x08)
25 v1 += 0x08;
Kevin O'Connor86d2e002012-01-14 22:17:07 -050026 stdvga_attr_write(0x00, v1);
Kevin O'Connorc0c7df62009-05-17 18:11:33 -040027
28 int i;
Kevin O'Connor86d2e002012-01-14 22:17:07 -050029 for (i = 1; i < 4; i++)
30 stdvga_attr_mask(i, 0x10, color & 0x10);
Kevin O'Connorc0c7df62009-05-17 18:11:33 -040031}
32
33void
Kevin O'Connor88ca7412011-12-31 04:24:20 -050034stdvga_set_overscan_border_color(u8 color)
Kevin O'Connorc0c7df62009-05-17 18:11:33 -040035{
Kevin O'Connor86d2e002012-01-14 22:17:07 -050036 stdvga_attr_write(0x11, color);
Kevin O'Connorc0c7df62009-05-17 18:11:33 -040037}
38
Kevin O'Connor8bc059e2009-05-17 21:19:36 -040039u8
Kevin O'Connor88ca7412011-12-31 04:24:20 -050040stdvga_get_overscan_border_color(void)
Kevin O'Connorc0c7df62009-05-17 18:11:33 -040041{
Kevin O'Connor86d2e002012-01-14 22:17:07 -050042 return stdvga_attr_read(0x11);
Kevin O'Connorc0c7df62009-05-17 18:11:33 -040043}
44
45void
Kevin O'Connor88ca7412011-12-31 04:24:20 -050046stdvga_set_palette(u8 palid)
Kevin O'Connorc0c7df62009-05-17 18:11:33 -040047{
Kevin O'Connorc0c7df62009-05-17 18:11:33 -040048 int i;
Kevin O'Connor86d2e002012-01-14 22:17:07 -050049 for (i = 1; i < 4; i++)
50 stdvga_attr_mask(i, 0x01, palid & 0x01);
Kevin O'Connorc0c7df62009-05-17 18:11:33 -040051}
52
53void
Kevin O'Connor88ca7412011-12-31 04:24:20 -050054stdvga_set_all_palette_reg(u16 seg, u8 *data_far)
Kevin O'Connorc0c7df62009-05-17 18:11:33 -040055{
Kevin O'Connorc0c7df62009-05-17 18:11:33 -040056 int i;
57 for (i = 0; i < 0x10; i++) {
Kevin O'Connor86d2e002012-01-14 22:17:07 -050058 stdvga_attr_write(i, GET_FARVAR(seg, *data_far));
Kevin O'Connorc0c7df62009-05-17 18:11:33 -040059 data_far++;
60 }
Kevin O'Connor86d2e002012-01-14 22:17:07 -050061 stdvga_attr_write(0x11, GET_FARVAR(seg, *data_far));
Kevin O'Connorc0c7df62009-05-17 18:11:33 -040062}
63
64void
Kevin O'Connor88ca7412011-12-31 04:24:20 -050065stdvga_get_all_palette_reg(u16 seg, u8 *data_far)
Kevin O'Connorc0c7df62009-05-17 18:11:33 -040066{
Kevin O'Connorc0c7df62009-05-17 18:11:33 -040067 int i;
68 for (i = 0; i < 0x10; i++) {
Kevin O'Connor86d2e002012-01-14 22:17:07 -050069 SET_FARVAR(seg, *data_far, stdvga_attr_read(i));
Kevin O'Connorc0c7df62009-05-17 18:11:33 -040070 data_far++;
71 }
Kevin O'Connor86d2e002012-01-14 22:17:07 -050072 SET_FARVAR(seg, *data_far, stdvga_attr_read(0x11));
Kevin O'Connorc0c7df62009-05-17 18:11:33 -040073}
74
75void
Kevin O'Connor88ca7412011-12-31 04:24:20 -050076stdvga_toggle_intensity(u8 flag)
Kevin O'Connorc0c7df62009-05-17 18:11:33 -040077{
Kevin O'Connor86d2e002012-01-14 22:17:07 -050078 stdvga_attr_mask(0x10, 0x08, (flag & 0x01) << 3);
Kevin O'Connorc0c7df62009-05-17 18:11:33 -040079}
80
81void
Kevin O'Connor88ca7412011-12-31 04:24:20 -050082stdvga_select_video_dac_color_page(u8 flag, u8 data)
Kevin O'Connorc0c7df62009-05-17 18:11:33 -040083{
Kevin O'Connor8bc059e2009-05-17 21:19:36 -040084 if (!(flag & 0x01)) {
85 // select paging mode
Kevin O'Connor86d2e002012-01-14 22:17:07 -050086 stdvga_attr_mask(0x10, 0x80, data << 7);
Kevin O'Connorc0c7df62009-05-17 18:11:33 -040087 return;
88 }
Kevin O'Connor8bc059e2009-05-17 21:19:36 -040089 // select page
Kevin O'Connor86d2e002012-01-14 22:17:07 -050090 u8 val = stdvga_attr_read(0x10);
Kevin O'Connorc0c7df62009-05-17 18:11:33 -040091 if (!(val & 0x80))
Kevin O'Connor8bc059e2009-05-17 21:19:36 -040092 data <<= 2;
93 data &= 0x0f;
Kevin O'Connor86d2e002012-01-14 22:17:07 -050094 stdvga_attr_write(0x14, data);
Kevin O'Connorc0c7df62009-05-17 18:11:33 -040095}
96
97void
Kevin O'Connor88ca7412011-12-31 04:24:20 -050098stdvga_read_video_dac_state(u8 *pmode, u8 *curpage)
Kevin O'Connorc0c7df62009-05-17 18:11:33 -040099{
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500100 u8 val1 = stdvga_attr_read(0x10) >> 7;
101 u8 val2 = stdvga_attr_read(0x14) & 0x0f;
Kevin O'Connorc0c7df62009-05-17 18:11:33 -0400102 if (!(val1 & 0x01))
103 val2 >>= 2;
Kevin O'Connor8bc059e2009-05-17 21:19:36 -0400104 *pmode = val1;
105 *curpage = val2;
Kevin O'Connorc0c7df62009-05-17 18:11:33 -0400106}
107
108
109/****************************************************************
110 * DAC control
111 ****************************************************************/
112
113void
Kevin O'Connor821d6b42011-12-31 18:19:22 -0500114stdvga_perform_gray_scale_summing(u16 start, u16 count)
115{
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500116 stdvga_attrindex_write(0x00);
Kevin O'Connor821d6b42011-12-31 18:19:22 -0500117 int i;
118 for (i = start; i < start+count; i++) {
119 u8 rgb[3];
Kevin O'Connor3471fdb2012-01-14 19:02:43 -0500120 stdvga_dac_read(GET_SEG(SS), rgb, i, 1);
Kevin O'Connor821d6b42011-12-31 18:19:22 -0500121
122 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
123 u16 intensity = ((77 * rgb[0] + 151 * rgb[1] + 28 * rgb[2]) + 0x80) >> 8;
124 if (intensity > 0x3f)
125 intensity = 0x3f;
Kevin O'Connor9cba2b32013-03-09 13:00:40 -0500126 rgb[0] = rgb[1] = rgb[2] = intensity;
Kevin O'Connor821d6b42011-12-31 18:19:22 -0500127
Kevin O'Connor3471fdb2012-01-14 19:02:43 -0500128 stdvga_dac_write(GET_SEG(SS), rgb, i, 1);
Kevin O'Connor821d6b42011-12-31 18:19:22 -0500129 }
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500130 stdvga_attrindex_write(0x20);
Kevin O'Connor821d6b42011-12-31 18:19:22 -0500131}
132
Kevin O'Connorc0c7df62009-05-17 18:11:33 -0400133
134/****************************************************************
135 * Memory control
136 ****************************************************************/
137
138void
Kevin O'Connor88ca7412011-12-31 04:24:20 -0500139stdvga_set_text_block_specifier(u8 spec)
Kevin O'Connorc0c7df62009-05-17 18:11:33 -0400140{
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500141 stdvga_sequ_write(0x03, spec);
Kevin O'Connorc0c7df62009-05-17 18:11:33 -0400142}
143
Kevin O'Connor160d34a2012-01-16 18:48:26 -0500144// Enable reads and writes to the given "plane" when in planar4 mode.
145void
146stdvga_planar4_plane(int plane)
147{
148 if (plane < 0) {
149 // Return to default mode (read plane0, write all planes)
150 stdvga_sequ_write(0x02, 0x0f);
151 stdvga_grdc_write(0x04, 0);
152 } else {
153 stdvga_sequ_write(0x02, 1<<plane);
154 stdvga_grdc_write(0x04, plane);
155 }
156}
157
Kevin O'Connor2bec7d62011-12-31 04:31:16 -0500158
159/****************************************************************
160 * Font loading
161 ****************************************************************/
162
163static void
Kevin O'Connor1ca05b02010-01-03 17:43:37 -0500164get_font_access(void)
Kevin O'Connorc0c7df62009-05-17 18:11:33 -0400165{
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500166 stdvga_sequ_write(0x00, 0x01);
167 stdvga_sequ_write(0x02, 0x04);
168 stdvga_sequ_write(0x04, 0x07);
169 stdvga_sequ_write(0x00, 0x03);
170 stdvga_grdc_write(0x04, 0x02);
171 stdvga_grdc_write(0x05, 0x00);
172 stdvga_grdc_write(0x06, 0x04);
Kevin O'Connorc0c7df62009-05-17 18:11:33 -0400173}
174
Kevin O'Connor2bec7d62011-12-31 04:31:16 -0500175static void
Kevin O'Connor1ca05b02010-01-03 17:43:37 -0500176release_font_access(void)
Kevin O'Connorc0c7df62009-05-17 18:11:33 -0400177{
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500178 stdvga_sequ_write(0x00, 0x01);
179 stdvga_sequ_write(0x02, 0x03);
180 stdvga_sequ_write(0x04, 0x03);
181 stdvga_sequ_write(0x00, 0x03);
182 u16 v = (stdvga_misc_read() & 0x01) ? 0x0e : 0x0a;
183 stdvga_grdc_write(0x06, v);
184 stdvga_grdc_write(0x04, 0x00);
185 stdvga_grdc_write(0x05, 0x10);
Kevin O'Connorc0c7df62009-05-17 18:11:33 -0400186}
187
Kevin O'Connor2bec7d62011-12-31 04:31:16 -0500188void
189stdvga_load_font(u16 seg, void *src_far, u16 count
190 , u16 start, u8 destflags, u8 fontsize)
191{
192 get_font_access();
193 u16 blockaddr = ((destflags & 0x03) << 14) + ((destflags & 0x04) << 11);
194 void *dest_far = (void*)(blockaddr + start*32);
195 u16 i;
196 for (i = 0; i < count; i++)
197 memcpy_far(SEG_GRAPH, dest_far + i*32
198 , seg, src_far + i*fontsize, fontsize);
199 release_font_access();
200}
201
Kevin O'Connorc0c7df62009-05-17 18:11:33 -0400202
203/****************************************************************
Kevin O'Connora0ecb052009-05-18 23:34:00 -0400204 * CRTC registers
205 ****************************************************************/
206
Kevin O'Connorc990f272011-12-31 16:00:54 -0500207u16
208stdvga_get_crtc(void)
Kevin O'Connora0ecb052009-05-18 23:34:00 -0400209{
Kevin O'Connor3471fdb2012-01-14 19:02:43 -0500210 if (stdvga_misc_read() & 1)
Kevin O'Connorc990f272011-12-31 16:00:54 -0500211 return VGAREG_VGA_CRTC_ADDRESS;
212 return VGAREG_MDA_CRTC_ADDRESS;
Kevin O'Connora0ecb052009-05-18 23:34:00 -0400213}
214
Kevin O'Connor68f56aa2013-09-10 10:41:33 -0400215// Ratio between system visible framebuffer ram and the actual videoram used.
Kevin O'Connor3876b532012-01-24 00:07:44 -0500216int
Kevin O'Connor68f56aa2013-09-10 10:41:33 -0400217stdvga_vram_ratio(struct vgamode_s *vmode_g)
Kevin O'Connor3876b532012-01-24 00:07:44 -0500218{
219 switch (GET_GLOBAL(vmode_g->memmodel)) {
220 case MM_TEXT:
221 return 2;
222 case MM_CGA:
Kevin O'Connor68f56aa2013-09-10 10:41:33 -0400223 return 4 / GET_GLOBAL(vmode_g->depth);
Kevin O'Connor3876b532012-01-24 00:07:44 -0500224 case MM_PLANAR:
Kevin O'Connor3876b532012-01-24 00:07:44 -0500225 return 4;
Kevin O'Connor68f56aa2013-09-10 10:41:33 -0400226 default:
227 return 1;
Kevin O'Connor3876b532012-01-24 00:07:44 -0500228 }
229}
230
Kevin O'Connora0ecb052009-05-18 23:34:00 -0400231void
Kevin O'Connor88ca7412011-12-31 04:24:20 -0500232stdvga_set_cursor_shape(u8 start, u8 end)
Kevin O'Connora0ecb052009-05-18 23:34:00 -0400233{
Kevin O'Connorc990f272011-12-31 16:00:54 -0500234 u16 crtc_addr = stdvga_get_crtc();
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500235 stdvga_crtc_write(crtc_addr, 0x0a, start);
236 stdvga_crtc_write(crtc_addr, 0x0b, end);
Kevin O'Connora0ecb052009-05-18 23:34:00 -0400237}
238
239void
Kevin O'Connor16920072012-01-27 22:59:46 -0500240stdvga_set_cursor_pos(int address)
Kevin O'Connora0ecb052009-05-18 23:34:00 -0400241{
Kevin O'Connorc990f272011-12-31 16:00:54 -0500242 u16 crtc_addr = stdvga_get_crtc();
Kevin O'Connor16920072012-01-27 22:59:46 -0500243 address /= 2; // Assume we're in text mode.
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500244 stdvga_crtc_write(crtc_addr, 0x0e, address >> 8);
245 stdvga_crtc_write(crtc_addr, 0x0f, address);
Kevin O'Connora0ecb052009-05-18 23:34:00 -0400246}
247
248void
Kevin O'Connor88ca7412011-12-31 04:24:20 -0500249stdvga_set_scan_lines(u8 lines)
Kevin O'Connora0ecb052009-05-18 23:34:00 -0400250{
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500251 stdvga_crtc_mask(stdvga_get_crtc(), 0x09, 0x1f, lines - 1);
Kevin O'Connora0ecb052009-05-18 23:34:00 -0400252}
253
254// Get vertical display end
255u16
Kevin O'Connor88ca7412011-12-31 04:24:20 -0500256stdvga_get_vde(void)
Kevin O'Connora0ecb052009-05-18 23:34:00 -0400257{
Kevin O'Connorc990f272011-12-31 16:00:54 -0500258 u16 crtc_addr = stdvga_get_crtc();
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500259 u16 vde = stdvga_crtc_read(crtc_addr, 0x12);
260 u8 ovl = stdvga_crtc_read(crtc_addr, 0x07);
Kevin O'Connora0ecb052009-05-18 23:34:00 -0400261 vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
262 return vde;
263}
264
Kevin O'Connor9961f992012-01-21 11:53:44 -0500265int
266stdvga_get_window(struct vgamode_s *vmode_g, int window)
267{
268 return -1;
269}
270
271int
272stdvga_set_window(struct vgamode_s *vmode_g, int window, int val)
273{
274 return -1;
275}
276
Kevin O'Connor3876b532012-01-24 00:07:44 -0500277int
278stdvga_get_linelength(struct vgamode_s *vmode_g)
279{
280 u8 val = stdvga_crtc_read(stdvga_get_crtc(), 0x13);
Kevin O'Connor68f56aa2013-09-10 10:41:33 -0400281 return val * 8 / stdvga_vram_ratio(vmode_g);
Kevin O'Connor3876b532012-01-24 00:07:44 -0500282}
283
284int
285stdvga_set_linelength(struct vgamode_s *vmode_g, int val)
286{
Kevin O'Connor68f56aa2013-09-10 10:41:33 -0400287 val = DIV_ROUND_UP(val * stdvga_vram_ratio(vmode_g), 8);
288 stdvga_crtc_write(stdvga_get_crtc(), 0x13, val);
Kevin O'Connor3876b532012-01-24 00:07:44 -0500289 return 0;
290}
291
Kevin O'Connord61fc532012-01-27 20:37:45 -0500292int
293stdvga_get_displaystart(struct vgamode_s *vmode_g)
294{
295 u16 crtc_addr = stdvga_get_crtc();
296 int addr = (stdvga_crtc_read(crtc_addr, 0x0c) << 8
297 | stdvga_crtc_read(crtc_addr, 0x0d));
Kevin O'Connor68f56aa2013-09-10 10:41:33 -0400298 return addr * 4 / stdvga_vram_ratio(vmode_g);
Kevin O'Connord61fc532012-01-27 20:37:45 -0500299}
300
301int
302stdvga_set_displaystart(struct vgamode_s *vmode_g, int val)
303{
304 u16 crtc_addr = stdvga_get_crtc();
Kevin O'Connor68f56aa2013-09-10 10:41:33 -0400305 val = val * stdvga_vram_ratio(vmode_g) / 4;
Kevin O'Connord61fc532012-01-27 20:37:45 -0500306 stdvga_crtc_write(crtc_addr, 0x0c, val >> 8);
307 stdvga_crtc_write(crtc_addr, 0x0d, val);
308 return 0;
309}
310
Kevin O'Connore737b172012-02-04 11:08:39 -0500311int
312stdvga_get_dacformat(struct vgamode_s *vmode_g)
313{
314 return -1;
315}
316
317int
318stdvga_set_dacformat(struct vgamode_s *vmode_g, int val)
319{
320 return -1;
321}
322
Kevin O'Connora0ecb052009-05-18 23:34:00 -0400323
324/****************************************************************
Kevin O'Connorf98bbf02012-01-27 23:09:02 -0500325 * Save/Restore state
Kevin O'Connorc0c7df62009-05-17 18:11:33 -0400326 ****************************************************************/
327
Kevin O'Connor9f857fc2012-02-04 11:59:02 -0500328struct saveVideoHardware {
329 u8 sequ_index;
330 u8 crtc_index;
331 u8 grdc_index;
332 u8 actl_index;
333 u8 feature;
334 u8 sequ_regs[4];
335 u8 sequ0;
336 u8 crtc_regs[25];
337 u8 actl_regs[20];
338 u8 grdc_regs[9];
339 u16 crtc_addr;
340 u8 plane_latch[4];
341};
342
343static void
344stdvga_save_hw_state(u16 seg, struct saveVideoHardware *info)
Kevin O'Connorca668642009-05-21 23:06:08 -0400345{
Kevin O'Connorc990f272011-12-31 16:00:54 -0500346 u16 crtc_addr = stdvga_get_crtc();
Kevin O'Connorca668642009-05-21 23:06:08 -0400347 SET_FARVAR(seg, info->sequ_index, inb(VGAREG_SEQU_ADDRESS));
348 SET_FARVAR(seg, info->crtc_index, inb(crtc_addr));
349 SET_FARVAR(seg, info->grdc_index, inb(VGAREG_GRDC_ADDRESS));
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500350 SET_FARVAR(seg, info->actl_index, stdvga_attrindex_read());
Kevin O'Connorca668642009-05-21 23:06:08 -0400351 SET_FARVAR(seg, info->feature, inb(VGAREG_READ_FEATURE_CTL));
352
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500353 int i;
354 for (i=0; i<4; i++)
355 SET_FARVAR(seg, info->sequ_regs[i], stdvga_sequ_read(i+1));
356 SET_FARVAR(seg, info->sequ0, stdvga_sequ_read(0));
Kevin O'Connorca668642009-05-21 23:06:08 -0400357
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500358 for (i=0; i<25; i++)
359 SET_FARVAR(seg, info->crtc_regs[i], stdvga_crtc_read(crtc_addr, i));
Kevin O'Connorca668642009-05-21 23:06:08 -0400360
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500361 for (i=0; i<20; i++)
362 SET_FARVAR(seg, info->actl_regs[i], stdvga_attr_read(i));
Kevin O'Connorca668642009-05-21 23:06:08 -0400363
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500364 for (i=0; i<9; i++)
365 SET_FARVAR(seg, info->grdc_regs[i], stdvga_grdc_read(i));
Kevin O'Connorca668642009-05-21 23:06:08 -0400366
367 SET_FARVAR(seg, info->crtc_addr, crtc_addr);
368
369 /* XXX: read plane latches */
370 for (i=0; i<4; i++)
371 SET_FARVAR(seg, info->plane_latch[i], 0);
372}
373
Kevin O'Connor9f857fc2012-02-04 11:59:02 -0500374static void
375stdvga_restore_hw_state(u16 seg, struct saveVideoHardware *info)
Kevin O'Connorca668642009-05-21 23:06:08 -0400376{
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500377 int i;
378 for (i=0; i<4; i++)
379 stdvga_sequ_write(i+1, GET_FARVAR(seg, info->sequ_regs[i]));
380 stdvga_sequ_write(0x00, GET_FARVAR(seg, info->sequ0));
Kevin O'Connorca668642009-05-21 23:06:08 -0400381
382 // Disable CRTC write protection
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500383 u16 crtc_addr = GET_FARVAR(seg, info->crtc_addr);
384 stdvga_crtc_write(crtc_addr, 0x11, 0x00);
Kevin O'Connorca668642009-05-21 23:06:08 -0400385 // Set CRTC regs
386 for (i=0; i<25; i++)
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500387 if (i != 0x11)
388 stdvga_crtc_write(crtc_addr, i, GET_FARVAR(seg, info->crtc_regs[i]));
Kevin O'Connorca668642009-05-21 23:06:08 -0400389 // select crtc base address
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500390 stdvga_misc_mask(0x01, crtc_addr == VGAREG_VGA_CRTC_ADDRESS ? 0x01 : 0x00);
Kevin O'Connorca668642009-05-21 23:06:08 -0400391
392 // enable write protection if needed
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500393 stdvga_crtc_write(crtc_addr, 0x11, GET_FARVAR(seg, info->crtc_regs[0x11]));
Kevin O'Connorca668642009-05-21 23:06:08 -0400394
395 // Set Attribute Ctl
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500396 for (i=0; i<20; i++)
397 stdvga_attr_write(i, GET_FARVAR(seg, info->actl_regs[i]));
398 stdvga_attrindex_write(GET_FARVAR(seg, info->actl_index));
Kevin O'Connorca668642009-05-21 23:06:08 -0400399
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500400 for (i=0; i<9; i++)
401 stdvga_grdc_write(i, GET_FARVAR(seg, info->grdc_regs[i]));
Kevin O'Connorca668642009-05-21 23:06:08 -0400402
403 outb(GET_FARVAR(seg, info->sequ_index), VGAREG_SEQU_ADDRESS);
404 outb(GET_FARVAR(seg, info->crtc_index), crtc_addr);
405 outb(GET_FARVAR(seg, info->grdc_index), VGAREG_GRDC_ADDRESS);
406 outb(GET_FARVAR(seg, info->feature), crtc_addr - 0x4 + 0xa);
407}
Kevin O'Connor124b6f72009-05-25 00:44:29 -0400408
Kevin O'Connor9f857fc2012-02-04 11:59:02 -0500409struct saveDACcolors {
410 u8 rwmode;
411 u8 peladdr;
412 u8 pelmask;
413 u8 dac[768];
414 u8 color_select;
415};
416
417static void
418stdvga_save_dac_state(u16 seg, struct saveDACcolors *info)
419{
420 /* XXX: check this */
421 SET_FARVAR(seg, info->rwmode, inb(VGAREG_DAC_STATE));
422 SET_FARVAR(seg, info->peladdr, inb(VGAREG_DAC_WRITE_ADDRESS));
423 SET_FARVAR(seg, info->pelmask, stdvga_pelmask_read());
424 stdvga_dac_read(seg, info->dac, 0, 256);
425 SET_FARVAR(seg, info->color_select, 0);
426}
427
428static void
429stdvga_restore_dac_state(u16 seg, struct saveDACcolors *info)
430{
431 stdvga_pelmask_write(GET_FARVAR(seg, info->pelmask));
432 stdvga_dac_write(seg, info->dac, 0, 256);
433 outb(GET_FARVAR(seg, info->peladdr), VGAREG_DAC_WRITE_ADDRESS);
434}
435
436int
437stdvga_size_state(int states)
438{
439 int size = 0;
440 if (states & 1)
441 size += sizeof(struct saveVideoHardware);
442 if (states & 2)
443 size += sizeof(struct saveBDAstate);
444 if (states & 4)
445 size += sizeof(struct saveDACcolors);
446 return size;
447}
448
449int
450stdvga_save_state(u16 seg, void *data, int states)
451{
452 if (states & 1) {
453 stdvga_save_hw_state(seg, data);
454 data += sizeof(struct saveVideoHardware);
455 }
456 if (states & 2) {
457 save_bda_state(seg, data);
458 data += sizeof(struct saveBDAstate);
459 }
460 if (states & 4)
461 stdvga_save_dac_state(seg, data);
462 return 0;
463}
464
465int
466stdvga_restore_state(u16 seg, void *data, int states)
467{
468 if (states & 1) {
469 stdvga_restore_hw_state(seg, data);
470 data += sizeof(struct saveVideoHardware);
471 }
472 if (states & 2) {
473 restore_bda_state(seg, data);
474 data += sizeof(struct saveBDAstate);
475 }
476 if (states & 4)
477 stdvga_restore_dac_state(seg, data);
478 return 0;
479}
480
Kevin O'Connor124b6f72009-05-25 00:44:29 -0400481
482/****************************************************************
483 * Misc
484 ****************************************************************/
485
486void
Kevin O'Connor88ca7412011-12-31 04:24:20 -0500487stdvga_enable_video_addressing(u8 disable)
Kevin O'Connor124b6f72009-05-25 00:44:29 -0400488{
489 u8 v = (disable & 1) ? 0x00 : 0x02;
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500490 stdvga_misc_mask(0x02, v);
Kevin O'Connor124b6f72009-05-25 00:44:29 -0400491}
492
Kevin O'Connor161d2012011-12-31 19:42:21 -0500493int
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500494stdvga_setup(void)
Kevin O'Connor124b6f72009-05-25 00:44:29 -0400495{
496 // switch to color mode and enable CPU access 480 lines
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500497 stdvga_misc_write(0xc3);
Kevin O'Connor124b6f72009-05-25 00:44:29 -0400498 // more than 64k 3C4/04
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500499 stdvga_sequ_write(0x04, 0x02);
Kevin O'Connor161d2012011-12-31 19:42:21 -0500500
501 return 0;
Kevin O'Connor124b6f72009-05-25 00:44:29 -0400502}