blob: ae6c0be394af26f30b4f27e80c5066a48dd9ef52 [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'Connorf98bbf02012-01-27 23:09:02 -05008#include "vgabios.h" // struct vgamode_s
Kevin O'Connor88ca7412011-12-31 04:24:20 -05009#include "stdvga.h" // stdvga_init
Kevin O'Connorc0c7df62009-05-17 18:11:33 -040010#include "ioport.h" // outb
Kevin O'Connorc0c7df62009-05-17 18:11:33 -040011#include "farptr.h" // SET_FARVAR
Kevin O'Connorc990f272011-12-31 16:00:54 -050012#include "biosvar.h" // GET_GLOBAL
Kevin O'Connor2bec7d62011-12-31 04:31:16 -050013#include "util.h" // memcpy_far
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;
126
Kevin O'Connor3471fdb2012-01-14 19:02:43 -0500127 stdvga_dac_write(GET_SEG(SS), rgb, i, 1);
Kevin O'Connor821d6b42011-12-31 18:19:22 -0500128 }
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500129 stdvga_attrindex_write(0x20);
Kevin O'Connor821d6b42011-12-31 18:19:22 -0500130}
131
Kevin O'Connorc0c7df62009-05-17 18:11:33 -0400132
133/****************************************************************
134 * Memory control
135 ****************************************************************/
136
137void
Kevin O'Connor88ca7412011-12-31 04:24:20 -0500138stdvga_set_text_block_specifier(u8 spec)
Kevin O'Connorc0c7df62009-05-17 18:11:33 -0400139{
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500140 stdvga_sequ_write(0x03, spec);
Kevin O'Connorc0c7df62009-05-17 18:11:33 -0400141}
142
Kevin O'Connor160d34a2012-01-16 18:48:26 -0500143// Enable reads and writes to the given "plane" when in planar4 mode.
144void
145stdvga_planar4_plane(int plane)
146{
147 if (plane < 0) {
148 // Return to default mode (read plane0, write all planes)
149 stdvga_sequ_write(0x02, 0x0f);
150 stdvga_grdc_write(0x04, 0);
151 } else {
152 stdvga_sequ_write(0x02, 1<<plane);
153 stdvga_grdc_write(0x04, plane);
154 }
155}
156
Kevin O'Connor2bec7d62011-12-31 04:31:16 -0500157
158/****************************************************************
159 * Font loading
160 ****************************************************************/
161
162static void
Kevin O'Connor1ca05b02010-01-03 17:43:37 -0500163get_font_access(void)
Kevin O'Connorc0c7df62009-05-17 18:11:33 -0400164{
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500165 stdvga_sequ_write(0x00, 0x01);
166 stdvga_sequ_write(0x02, 0x04);
167 stdvga_sequ_write(0x04, 0x07);
168 stdvga_sequ_write(0x00, 0x03);
169 stdvga_grdc_write(0x04, 0x02);
170 stdvga_grdc_write(0x05, 0x00);
171 stdvga_grdc_write(0x06, 0x04);
Kevin O'Connorc0c7df62009-05-17 18:11:33 -0400172}
173
Kevin O'Connor2bec7d62011-12-31 04:31:16 -0500174static void
Kevin O'Connor1ca05b02010-01-03 17:43:37 -0500175release_font_access(void)
Kevin O'Connorc0c7df62009-05-17 18:11:33 -0400176{
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500177 stdvga_sequ_write(0x00, 0x01);
178 stdvga_sequ_write(0x02, 0x03);
179 stdvga_sequ_write(0x04, 0x03);
180 stdvga_sequ_write(0x00, 0x03);
181 u16 v = (stdvga_misc_read() & 0x01) ? 0x0e : 0x0a;
182 stdvga_grdc_write(0x06, v);
183 stdvga_grdc_write(0x04, 0x00);
184 stdvga_grdc_write(0x05, 0x10);
Kevin O'Connorc0c7df62009-05-17 18:11:33 -0400185}
186
Kevin O'Connor2bec7d62011-12-31 04:31:16 -0500187void
188stdvga_load_font(u16 seg, void *src_far, u16 count
189 , u16 start, u8 destflags, u8 fontsize)
190{
191 get_font_access();
192 u16 blockaddr = ((destflags & 0x03) << 14) + ((destflags & 0x04) << 11);
193 void *dest_far = (void*)(blockaddr + start*32);
194 u16 i;
195 for (i = 0; i < count; i++)
196 memcpy_far(SEG_GRAPH, dest_far + i*32
197 , seg, src_far + i*fontsize, fontsize);
198 release_font_access();
199}
200
Kevin O'Connorc0c7df62009-05-17 18:11:33 -0400201
202/****************************************************************
Kevin O'Connora0ecb052009-05-18 23:34:00 -0400203 * CRTC registers
204 ****************************************************************/
205
Kevin O'Connorc990f272011-12-31 16:00:54 -0500206u16
207stdvga_get_crtc(void)
Kevin O'Connora0ecb052009-05-18 23:34:00 -0400208{
Kevin O'Connor3471fdb2012-01-14 19:02:43 -0500209 if (stdvga_misc_read() & 1)
Kevin O'Connorc990f272011-12-31 16:00:54 -0500210 return VGAREG_VGA_CRTC_ADDRESS;
211 return VGAREG_MDA_CRTC_ADDRESS;
Kevin O'Connora0ecb052009-05-18 23:34:00 -0400212}
213
Kevin O'Connor3876b532012-01-24 00:07:44 -0500214// Return the multiplication factor needed for the vga offset register.
215int
216stdvga_bpp_factor(struct vgamode_s *vmode_g)
217{
218 switch (GET_GLOBAL(vmode_g->memmodel)) {
219 case MM_TEXT:
220 return 2;
221 case MM_CGA:
222 return GET_GLOBAL(vmode_g->depth);
223 case MM_PLANAR:
224 return 1;
225 default:
226 return 4;
227 }
228}
229
Kevin O'Connora0ecb052009-05-18 23:34:00 -0400230void
Kevin O'Connor88ca7412011-12-31 04:24:20 -0500231stdvga_set_cursor_shape(u8 start, u8 end)
Kevin O'Connora0ecb052009-05-18 23:34:00 -0400232{
Kevin O'Connorc990f272011-12-31 16:00:54 -0500233 u16 crtc_addr = stdvga_get_crtc();
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500234 stdvga_crtc_write(crtc_addr, 0x0a, start);
235 stdvga_crtc_write(crtc_addr, 0x0b, end);
Kevin O'Connora0ecb052009-05-18 23:34:00 -0400236}
237
238void
Kevin O'Connor16920072012-01-27 22:59:46 -0500239stdvga_set_cursor_pos(int address)
Kevin O'Connora0ecb052009-05-18 23:34:00 -0400240{
Kevin O'Connorc990f272011-12-31 16:00:54 -0500241 u16 crtc_addr = stdvga_get_crtc();
Kevin O'Connor16920072012-01-27 22:59:46 -0500242 address /= 2; // Assume we're in text mode.
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500243 stdvga_crtc_write(crtc_addr, 0x0e, address >> 8);
244 stdvga_crtc_write(crtc_addr, 0x0f, address);
Kevin O'Connora0ecb052009-05-18 23:34:00 -0400245}
246
247void
Kevin O'Connor88ca7412011-12-31 04:24:20 -0500248stdvga_set_scan_lines(u8 lines)
Kevin O'Connora0ecb052009-05-18 23:34:00 -0400249{
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500250 stdvga_crtc_mask(stdvga_get_crtc(), 0x09, 0x1f, lines - 1);
Kevin O'Connora0ecb052009-05-18 23:34:00 -0400251}
252
253// Get vertical display end
254u16
Kevin O'Connor88ca7412011-12-31 04:24:20 -0500255stdvga_get_vde(void)
Kevin O'Connora0ecb052009-05-18 23:34:00 -0400256{
Kevin O'Connorc990f272011-12-31 16:00:54 -0500257 u16 crtc_addr = stdvga_get_crtc();
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500258 u16 vde = stdvga_crtc_read(crtc_addr, 0x12);
259 u8 ovl = stdvga_crtc_read(crtc_addr, 0x07);
Kevin O'Connora0ecb052009-05-18 23:34:00 -0400260 vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
261 return vde;
262}
263
Kevin O'Connor9961f992012-01-21 11:53:44 -0500264int
265stdvga_get_window(struct vgamode_s *vmode_g, int window)
266{
267 return -1;
268}
269
270int
271stdvga_set_window(struct vgamode_s *vmode_g, int window, int val)
272{
273 return -1;
274}
275
Kevin O'Connor3876b532012-01-24 00:07:44 -0500276int
277stdvga_get_linelength(struct vgamode_s *vmode_g)
278{
279 u8 val = stdvga_crtc_read(stdvga_get_crtc(), 0x13);
280 return val * stdvga_bpp_factor(vmode_g) * 2;
281}
282
283int
284stdvga_set_linelength(struct vgamode_s *vmode_g, int val)
285{
286 int factor = stdvga_bpp_factor(vmode_g) * 2;
287 stdvga_crtc_write(stdvga_get_crtc(), 0x13, DIV_ROUND_UP(val, factor));
288 return 0;
289}
290
Kevin O'Connord61fc532012-01-27 20:37:45 -0500291int
292stdvga_get_displaystart(struct vgamode_s *vmode_g)
293{
294 u16 crtc_addr = stdvga_get_crtc();
295 int addr = (stdvga_crtc_read(crtc_addr, 0x0c) << 8
296 | stdvga_crtc_read(crtc_addr, 0x0d));
297 return addr * stdvga_bpp_factor(vmode_g);
298}
299
300int
301stdvga_set_displaystart(struct vgamode_s *vmode_g, int val)
302{
303 u16 crtc_addr = stdvga_get_crtc();
304 val /= stdvga_bpp_factor(vmode_g);
305 stdvga_crtc_write(crtc_addr, 0x0c, val >> 8);
306 stdvga_crtc_write(crtc_addr, 0x0d, val);
307 return 0;
308}
309
Kevin O'Connore737b172012-02-04 11:08:39 -0500310int
311stdvga_get_dacformat(struct vgamode_s *vmode_g)
312{
313 return -1;
314}
315
316int
317stdvga_set_dacformat(struct vgamode_s *vmode_g, int val)
318{
319 return -1;
320}
321
Kevin O'Connora0ecb052009-05-18 23:34:00 -0400322
323/****************************************************************
Kevin O'Connorf98bbf02012-01-27 23:09:02 -0500324 * Save/Restore state
Kevin O'Connorc0c7df62009-05-17 18:11:33 -0400325 ****************************************************************/
326
Kevin O'Connor9f857fc2012-02-04 11:59:02 -0500327struct saveVideoHardware {
328 u8 sequ_index;
329 u8 crtc_index;
330 u8 grdc_index;
331 u8 actl_index;
332 u8 feature;
333 u8 sequ_regs[4];
334 u8 sequ0;
335 u8 crtc_regs[25];
336 u8 actl_regs[20];
337 u8 grdc_regs[9];
338 u16 crtc_addr;
339 u8 plane_latch[4];
340};
341
342static void
343stdvga_save_hw_state(u16 seg, struct saveVideoHardware *info)
Kevin O'Connorca668642009-05-21 23:06:08 -0400344{
Kevin O'Connorc990f272011-12-31 16:00:54 -0500345 u16 crtc_addr = stdvga_get_crtc();
Kevin O'Connorca668642009-05-21 23:06:08 -0400346 SET_FARVAR(seg, info->sequ_index, inb(VGAREG_SEQU_ADDRESS));
347 SET_FARVAR(seg, info->crtc_index, inb(crtc_addr));
348 SET_FARVAR(seg, info->grdc_index, inb(VGAREG_GRDC_ADDRESS));
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500349 SET_FARVAR(seg, info->actl_index, stdvga_attrindex_read());
Kevin O'Connorca668642009-05-21 23:06:08 -0400350 SET_FARVAR(seg, info->feature, inb(VGAREG_READ_FEATURE_CTL));
351
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500352 int i;
353 for (i=0; i<4; i++)
354 SET_FARVAR(seg, info->sequ_regs[i], stdvga_sequ_read(i+1));
355 SET_FARVAR(seg, info->sequ0, stdvga_sequ_read(0));
Kevin O'Connorca668642009-05-21 23:06:08 -0400356
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500357 for (i=0; i<25; i++)
358 SET_FARVAR(seg, info->crtc_regs[i], stdvga_crtc_read(crtc_addr, i));
Kevin O'Connorca668642009-05-21 23:06:08 -0400359
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500360 for (i=0; i<20; i++)
361 SET_FARVAR(seg, info->actl_regs[i], stdvga_attr_read(i));
Kevin O'Connorca668642009-05-21 23:06:08 -0400362
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500363 for (i=0; i<9; i++)
364 SET_FARVAR(seg, info->grdc_regs[i], stdvga_grdc_read(i));
Kevin O'Connorca668642009-05-21 23:06:08 -0400365
366 SET_FARVAR(seg, info->crtc_addr, crtc_addr);
367
368 /* XXX: read plane latches */
369 for (i=0; i<4; i++)
370 SET_FARVAR(seg, info->plane_latch[i], 0);
371}
372
Kevin O'Connor9f857fc2012-02-04 11:59:02 -0500373static void
374stdvga_restore_hw_state(u16 seg, struct saveVideoHardware *info)
Kevin O'Connorca668642009-05-21 23:06:08 -0400375{
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500376 int i;
377 for (i=0; i<4; i++)
378 stdvga_sequ_write(i+1, GET_FARVAR(seg, info->sequ_regs[i]));
379 stdvga_sequ_write(0x00, GET_FARVAR(seg, info->sequ0));
Kevin O'Connorca668642009-05-21 23:06:08 -0400380
381 // Disable CRTC write protection
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500382 u16 crtc_addr = GET_FARVAR(seg, info->crtc_addr);
383 stdvga_crtc_write(crtc_addr, 0x11, 0x00);
Kevin O'Connorca668642009-05-21 23:06:08 -0400384 // Set CRTC regs
385 for (i=0; i<25; i++)
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500386 if (i != 0x11)
387 stdvga_crtc_write(crtc_addr, i, GET_FARVAR(seg, info->crtc_regs[i]));
Kevin O'Connorca668642009-05-21 23:06:08 -0400388 // select crtc base address
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500389 stdvga_misc_mask(0x01, crtc_addr == VGAREG_VGA_CRTC_ADDRESS ? 0x01 : 0x00);
Kevin O'Connorca668642009-05-21 23:06:08 -0400390
391 // enable write protection if needed
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500392 stdvga_crtc_write(crtc_addr, 0x11, GET_FARVAR(seg, info->crtc_regs[0x11]));
Kevin O'Connorca668642009-05-21 23:06:08 -0400393
394 // Set Attribute Ctl
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500395 for (i=0; i<20; i++)
396 stdvga_attr_write(i, GET_FARVAR(seg, info->actl_regs[i]));
397 stdvga_attrindex_write(GET_FARVAR(seg, info->actl_index));
Kevin O'Connorca668642009-05-21 23:06:08 -0400398
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500399 for (i=0; i<9; i++)
400 stdvga_grdc_write(i, GET_FARVAR(seg, info->grdc_regs[i]));
Kevin O'Connorca668642009-05-21 23:06:08 -0400401
402 outb(GET_FARVAR(seg, info->sequ_index), VGAREG_SEQU_ADDRESS);
403 outb(GET_FARVAR(seg, info->crtc_index), crtc_addr);
404 outb(GET_FARVAR(seg, info->grdc_index), VGAREG_GRDC_ADDRESS);
405 outb(GET_FARVAR(seg, info->feature), crtc_addr - 0x4 + 0xa);
406}
Kevin O'Connor124b6f72009-05-25 00:44:29 -0400407
Kevin O'Connor9f857fc2012-02-04 11:59:02 -0500408struct saveDACcolors {
409 u8 rwmode;
410 u8 peladdr;
411 u8 pelmask;
412 u8 dac[768];
413 u8 color_select;
414};
415
416static void
417stdvga_save_dac_state(u16 seg, struct saveDACcolors *info)
418{
419 /* XXX: check this */
420 SET_FARVAR(seg, info->rwmode, inb(VGAREG_DAC_STATE));
421 SET_FARVAR(seg, info->peladdr, inb(VGAREG_DAC_WRITE_ADDRESS));
422 SET_FARVAR(seg, info->pelmask, stdvga_pelmask_read());
423 stdvga_dac_read(seg, info->dac, 0, 256);
424 SET_FARVAR(seg, info->color_select, 0);
425}
426
427static void
428stdvga_restore_dac_state(u16 seg, struct saveDACcolors *info)
429{
430 stdvga_pelmask_write(GET_FARVAR(seg, info->pelmask));
431 stdvga_dac_write(seg, info->dac, 0, 256);
432 outb(GET_FARVAR(seg, info->peladdr), VGAREG_DAC_WRITE_ADDRESS);
433}
434
435int
436stdvga_size_state(int states)
437{
438 int size = 0;
439 if (states & 1)
440 size += sizeof(struct saveVideoHardware);
441 if (states & 2)
442 size += sizeof(struct saveBDAstate);
443 if (states & 4)
444 size += sizeof(struct saveDACcolors);
445 return size;
446}
447
448int
449stdvga_save_state(u16 seg, void *data, int states)
450{
451 if (states & 1) {
452 stdvga_save_hw_state(seg, data);
453 data += sizeof(struct saveVideoHardware);
454 }
455 if (states & 2) {
456 save_bda_state(seg, data);
457 data += sizeof(struct saveBDAstate);
458 }
459 if (states & 4)
460 stdvga_save_dac_state(seg, data);
461 return 0;
462}
463
464int
465stdvga_restore_state(u16 seg, void *data, int states)
466{
467 if (states & 1) {
468 stdvga_restore_hw_state(seg, data);
469 data += sizeof(struct saveVideoHardware);
470 }
471 if (states & 2) {
472 restore_bda_state(seg, data);
473 data += sizeof(struct saveBDAstate);
474 }
475 if (states & 4)
476 stdvga_restore_dac_state(seg, data);
477 return 0;
478}
479
Kevin O'Connor124b6f72009-05-25 00:44:29 -0400480
481/****************************************************************
482 * Misc
483 ****************************************************************/
484
485void
Kevin O'Connor88ca7412011-12-31 04:24:20 -0500486stdvga_enable_video_addressing(u8 disable)
Kevin O'Connor124b6f72009-05-25 00:44:29 -0400487{
488 u8 v = (disable & 1) ? 0x00 : 0x02;
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500489 stdvga_misc_mask(0x02, v);
Kevin O'Connor124b6f72009-05-25 00:44:29 -0400490}
491
Kevin O'Connor161d2012011-12-31 19:42:21 -0500492int
Kevin O'Connor88ca7412011-12-31 04:24:20 -0500493stdvga_init(void)
Kevin O'Connor124b6f72009-05-25 00:44:29 -0400494{
495 // switch to color mode and enable CPU access 480 lines
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500496 stdvga_misc_write(0xc3);
Kevin O'Connor124b6f72009-05-25 00:44:29 -0400497 // more than 64k 3C4/04
Kevin O'Connor86d2e002012-01-14 22:17:07 -0500498 stdvga_sequ_write(0x04, 0x02);
Kevin O'Connor161d2012011-12-31 19:42:21 -0500499
500 return 0;
Kevin O'Connor124b6f72009-05-25 00:44:29 -0400501}