|
|
1.1 root 1: // VGA io port access
2: //
3: // Copyright (C) 2009 Kevin O'Connor <[email protected]>
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:
8: #include "ioport.h" // outb
9: #include "farptr.h" // SET_FARVAR
10: #include "biosvar.h" // GET_BDA
11: #include "vgatables.h" // VGAREG_*
12:
13: // TODO
14: // * replace direct in/out calls with wrapper functions
15:
16:
17: /****************************************************************
18: * Attribute control
19: ****************************************************************/
20:
21: void
1.1.1.2 ! root 22: vgahw_screen_disable(void)
1.1 root 23: {
24: inb(VGAREG_ACTL_RESET);
25: outb(0x00, VGAREG_ACTL_ADDRESS);
26: }
27:
28: void
1.1.1.2 ! root 29: vgahw_screen_enable(void)
1.1 root 30: {
31: inb(VGAREG_ACTL_RESET);
32: outb(0x20, VGAREG_ACTL_ADDRESS);
33: }
34:
35: void
36: vgahw_set_border_color(u8 color)
37: {
38: inb(VGAREG_ACTL_RESET);
39: outb(0x00, VGAREG_ACTL_ADDRESS);
40: u8 v1 = color & 0x0f;
41: if (v1 & 0x08)
42: v1 += 0x08;
43: outb(v1, VGAREG_ACTL_WRITE_DATA);
44:
45: u8 v2 = color & 0x10;
46: int i;
47: for (i = 1; i < 4; i++) {
48: outb(i, VGAREG_ACTL_ADDRESS);
49:
50: u8 cur = inb(VGAREG_ACTL_READ_DATA);
51: cur &= 0xef;
52: cur |= v2;
53: outb(cur, VGAREG_ACTL_WRITE_DATA);
54: }
55: outb(0x20, VGAREG_ACTL_ADDRESS);
56: }
57:
58: void
59: vgahw_set_overscan_border_color(u8 color)
60: {
61: inb(VGAREG_ACTL_RESET);
62: outb(0x11, VGAREG_ACTL_ADDRESS);
63: outb(color, VGAREG_ACTL_WRITE_DATA);
64: outb(0x20, VGAREG_ACTL_ADDRESS);
65: }
66:
67: u8
1.1.1.2 ! root 68: vgahw_get_overscan_border_color(void)
1.1 root 69: {
70: inb(VGAREG_ACTL_RESET);
71: outb(0x11, VGAREG_ACTL_ADDRESS);
72: u8 v = inb(VGAREG_ACTL_READ_DATA);
73: inb(VGAREG_ACTL_RESET);
74: outb(0x20, VGAREG_ACTL_ADDRESS);
75: return v;
76: }
77:
78: void
79: vgahw_set_palette(u8 palid)
80: {
81: inb(VGAREG_ACTL_RESET);
82: palid &= 0x01;
83: int i;
84: for (i = 1; i < 4; i++) {
85: outb(i, VGAREG_ACTL_ADDRESS);
86:
87: u8 v = inb(VGAREG_ACTL_READ_DATA);
88: v &= 0xfe;
89: v |= palid;
90: outb(v, VGAREG_ACTL_WRITE_DATA);
91: }
92: outb(0x20, VGAREG_ACTL_ADDRESS);
93: }
94:
95: void
96: vgahw_set_single_palette_reg(u8 reg, u8 val)
97: {
98: inb(VGAREG_ACTL_RESET);
99: outb(reg, VGAREG_ACTL_ADDRESS);
100: outb(val, VGAREG_ACTL_WRITE_DATA);
101: outb(0x20, VGAREG_ACTL_ADDRESS);
102: }
103:
104: u8
105: vgahw_get_single_palette_reg(u8 reg)
106: {
107: inb(VGAREG_ACTL_RESET);
108: outb(reg, VGAREG_ACTL_ADDRESS);
109: u8 v = inb(VGAREG_ACTL_READ_DATA);
110: inb(VGAREG_ACTL_RESET);
111: outb(0x20, VGAREG_ACTL_ADDRESS);
112: return v;
113: }
114:
115: void
116: vgahw_set_all_palette_reg(u16 seg, u8 *data_far)
117: {
118: inb(VGAREG_ACTL_RESET);
119: int i;
120: for (i = 0; i < 0x10; i++) {
121: outb(i, VGAREG_ACTL_ADDRESS);
122: u8 val = GET_FARVAR(seg, *data_far);
123: outb(val, VGAREG_ACTL_WRITE_DATA);
124: data_far++;
125: }
126: outb(0x11, VGAREG_ACTL_ADDRESS);
127: outb(GET_FARVAR(seg, *data_far), VGAREG_ACTL_WRITE_DATA);
128: outb(0x20, VGAREG_ACTL_ADDRESS);
129: }
130:
131: void
132: vgahw_get_all_palette_reg(u16 seg, u8 *data_far)
133: {
134: int i;
135: for (i = 0; i < 0x10; i++) {
136: inb(VGAREG_ACTL_RESET);
137: outb(i, VGAREG_ACTL_ADDRESS);
138: SET_FARVAR(seg, *data_far, inb(VGAREG_ACTL_READ_DATA));
139: data_far++;
140: }
141: inb(VGAREG_ACTL_RESET);
142: outb(0x11, VGAREG_ACTL_ADDRESS);
143: SET_FARVAR(seg, *data_far, inb(VGAREG_ACTL_READ_DATA));
144: inb(VGAREG_ACTL_RESET);
145: outb(0x20, VGAREG_ACTL_ADDRESS);
146: }
147:
148: void
149: vgahw_toggle_intensity(u8 flag)
150: {
151: inb(VGAREG_ACTL_RESET);
152: outb(0x10, VGAREG_ACTL_ADDRESS);
153: u8 val = (inb(VGAREG_ACTL_READ_DATA) & 0xf7) | ((flag & 0x01) << 3);
154: outb(val, VGAREG_ACTL_WRITE_DATA);
155: outb(0x20, VGAREG_ACTL_ADDRESS);
156: }
157:
158: void
159: vgahw_select_video_dac_color_page(u8 flag, u8 data)
160: {
161: inb(VGAREG_ACTL_RESET);
162: outb(0x10, VGAREG_ACTL_ADDRESS);
163: u8 val = inb(VGAREG_ACTL_READ_DATA);
164: if (!(flag & 0x01)) {
165: // select paging mode
166: val = (val & 0x7f) | (data << 7);
167: outb(val, VGAREG_ACTL_WRITE_DATA);
168: outb(0x20, VGAREG_ACTL_ADDRESS);
169: return;
170: }
171: // select page
172: inb(VGAREG_ACTL_RESET);
173: outb(0x14, VGAREG_ACTL_ADDRESS);
174: if (!(val & 0x80))
175: data <<= 2;
176: data &= 0x0f;
177: outb(data, VGAREG_ACTL_WRITE_DATA);
178: outb(0x20, VGAREG_ACTL_ADDRESS);
179: }
180:
181: void
182: vgahw_read_video_dac_state(u8 *pmode, u8 *curpage)
183: {
184: inb(VGAREG_ACTL_RESET);
185: outb(0x10, VGAREG_ACTL_ADDRESS);
186: u8 val1 = inb(VGAREG_ACTL_READ_DATA) >> 7;
187:
188: inb(VGAREG_ACTL_RESET);
189: outb(0x14, VGAREG_ACTL_ADDRESS);
190: u8 val2 = inb(VGAREG_ACTL_READ_DATA) & 0x0f;
191: if (!(val1 & 0x01))
192: val2 >>= 2;
193:
194: inb(VGAREG_ACTL_RESET);
195: outb(0x20, VGAREG_ACTL_ADDRESS);
196:
197: *pmode = val1;
198: *curpage = val2;
199: }
200:
201:
202: /****************************************************************
203: * DAC control
204: ****************************************************************/
205:
206: void
207: vgahw_set_dac_regs(u16 seg, u8 *data_far, u8 start, int count)
208: {
209: outb(start, VGAREG_DAC_WRITE_ADDRESS);
210: while (count) {
211: outb(GET_FARVAR(seg, *data_far), VGAREG_DAC_DATA);
212: data_far++;
213: outb(GET_FARVAR(seg, *data_far), VGAREG_DAC_DATA);
214: data_far++;
215: outb(GET_FARVAR(seg, *data_far), VGAREG_DAC_DATA);
216: data_far++;
217: count--;
218: }
219: }
220:
221: void
222: vgahw_get_dac_regs(u16 seg, u8 *data_far, u8 start, int count)
223: {
224: outb(start, VGAREG_DAC_READ_ADDRESS);
225: while (count) {
226: SET_FARVAR(seg, *data_far, inb(VGAREG_DAC_DATA));
227: data_far++;
228: SET_FARVAR(seg, *data_far, inb(VGAREG_DAC_DATA));
229: data_far++;
230: SET_FARVAR(seg, *data_far, inb(VGAREG_DAC_DATA));
231: data_far++;
232: count--;
233: }
234: }
235:
236: void
237: vgahw_set_pel_mask(u8 val)
238: {
239: outb(val, VGAREG_PEL_MASK);
240: }
241:
242: u8
1.1.1.2 ! root 243: vgahw_get_pel_mask(void)
1.1 root 244: {
245: return inb(VGAREG_PEL_MASK);
246: }
247:
248: void
249: vgahw_save_dac_state(u16 seg, struct saveDACcolors *info)
250: {
251: /* XXX: check this */
252: SET_FARVAR(seg, info->rwmode, inb(VGAREG_DAC_STATE));
253: SET_FARVAR(seg, info->peladdr, inb(VGAREG_DAC_WRITE_ADDRESS));
254: SET_FARVAR(seg, info->pelmask, inb(VGAREG_PEL_MASK));
255: vgahw_get_dac_regs(seg, info->dac, 0, 256);
256: SET_FARVAR(seg, info->color_select, 0);
257: }
258:
259: void
260: vgahw_restore_dac_state(u16 seg, struct saveDACcolors *info)
261: {
262: outb(GET_FARVAR(seg, info->pelmask), VGAREG_PEL_MASK);
263: vgahw_set_dac_regs(seg, info->dac, 0, 256);
264: outb(GET_FARVAR(seg, info->peladdr), VGAREG_DAC_WRITE_ADDRESS);
265: }
266:
267:
268: /****************************************************************
269: * Memory control
270: ****************************************************************/
271:
272: void
273: vgahw_sequ_write(u8 index, u8 value)
274: {
275: outw((value<<8) | index, VGAREG_SEQU_ADDRESS);
276: }
277:
278: void
279: vgahw_grdc_write(u8 index, u8 value)
280: {
281: outw((value<<8) | index, VGAREG_GRDC_ADDRESS);
282: }
283:
284: void
285: vgahw_set_text_block_specifier(u8 spec)
286: {
287: outw((spec << 8) | 0x03, VGAREG_SEQU_ADDRESS);
288: }
289:
290: void
1.1.1.2 ! root 291: get_font_access(void)
1.1 root 292: {
293: outw(0x0100, VGAREG_SEQU_ADDRESS);
294: outw(0x0402, VGAREG_SEQU_ADDRESS);
295: outw(0x0704, VGAREG_SEQU_ADDRESS);
296: outw(0x0300, VGAREG_SEQU_ADDRESS);
297: outw(0x0204, VGAREG_GRDC_ADDRESS);
298: outw(0x0005, VGAREG_GRDC_ADDRESS);
299: outw(0x0406, VGAREG_GRDC_ADDRESS);
300: }
301:
302: void
1.1.1.2 ! root 303: release_font_access(void)
1.1 root 304: {
305: outw(0x0100, VGAREG_SEQU_ADDRESS);
306: outw(0x0302, VGAREG_SEQU_ADDRESS);
307: outw(0x0304, VGAREG_SEQU_ADDRESS);
308: outw(0x0300, VGAREG_SEQU_ADDRESS);
309: u16 v = (inw(VGAREG_READ_MISC_OUTPUT) & 0x01) ? 0x0e : 0x0a;
310: outw((v << 8) | 0x06, VGAREG_GRDC_ADDRESS);
311: outw(0x0004, VGAREG_GRDC_ADDRESS);
312: outw(0x1005, VGAREG_GRDC_ADDRESS);
313: }
314:
315:
316: /****************************************************************
317: * CRTC registers
318: ****************************************************************/
319:
320: static u16
1.1.1.2 ! root 321: get_crtc(void)
1.1 root 322: {
323: return GET_BDA(crtc_address);
324: }
325:
326: void
327: vgahw_set_cursor_shape(u8 start, u8 end)
328: {
329: u16 crtc_addr = get_crtc();
330: outb(0x0a, crtc_addr);
331: outb(start, crtc_addr + 1);
332: outb(0x0b, crtc_addr);
333: outb(end, crtc_addr + 1);
334: }
335:
336: void
337: vgahw_set_active_page(u16 address)
338: {
339: u16 crtc_addr = get_crtc();
340: outb(0x0c, crtc_addr);
341: outb((address & 0xff00) >> 8, crtc_addr + 1);
342: outb(0x0d, crtc_addr);
343: outb(address & 0x00ff, crtc_addr + 1);
344: }
345:
346: void
347: vgahw_set_cursor_pos(u16 address)
348: {
349: u16 crtc_addr = get_crtc();
350: outb(0x0e, crtc_addr);
351: outb((address & 0xff00) >> 8, crtc_addr + 1);
352: outb(0x0f, crtc_addr);
353: outb(address & 0x00ff, crtc_addr + 1);
354: }
355:
356: void
357: vgahw_set_scan_lines(u8 lines)
358: {
359: u16 crtc_addr = get_crtc();
360: outb(0x09, crtc_addr);
361: u8 crtc_r9 = inb(crtc_addr + 1);
362: crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1);
363: outb(crtc_r9, crtc_addr + 1);
364: }
365:
366: // Get vertical display end
367: u16
1.1.1.2 ! root 368: vgahw_get_vde(void)
1.1 root 369: {
370: u16 crtc_addr = get_crtc();
371: outb(0x12, crtc_addr);
372: u16 vde = inb(crtc_addr + 1);
373: outb(0x07, crtc_addr);
374: u8 ovl = inb(crtc_addr + 1);
375: vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
376: return vde;
377: }
378:
379:
380: /****************************************************************
381: * Save/Restore/Set state
382: ****************************************************************/
383:
384: void
385: vgahw_save_state(u16 seg, struct saveVideoHardware *info)
386: {
387: u16 crtc_addr = get_crtc();
388: SET_FARVAR(seg, info->sequ_index, inb(VGAREG_SEQU_ADDRESS));
389: SET_FARVAR(seg, info->crtc_index, inb(crtc_addr));
390: SET_FARVAR(seg, info->grdc_index, inb(VGAREG_GRDC_ADDRESS));
391: inb(VGAREG_ACTL_RESET);
392: u16 ar_index = inb(VGAREG_ACTL_ADDRESS);
393: SET_FARVAR(seg, info->actl_index, ar_index);
394: SET_FARVAR(seg, info->feature, inb(VGAREG_READ_FEATURE_CTL));
395:
396: u16 i;
397: for (i=0; i<4; i++) {
398: outb(i+1, VGAREG_SEQU_ADDRESS);
399: SET_FARVAR(seg, info->sequ_regs[i], inb(VGAREG_SEQU_DATA));
400: }
401: outb(0, VGAREG_SEQU_ADDRESS);
402: SET_FARVAR(seg, info->sequ0, inb(VGAREG_SEQU_DATA));
403:
404: for (i=0; i<25; i++) {
405: outb(i, crtc_addr);
406: SET_FARVAR(seg, info->crtc_regs[i], inb(crtc_addr + 1));
407: }
408:
409: for (i=0; i<20; i++) {
410: inb(VGAREG_ACTL_RESET);
411: outb(i | (ar_index & 0x20), VGAREG_ACTL_ADDRESS);
412: SET_FARVAR(seg, info->actl_regs[i], inb(VGAREG_ACTL_READ_DATA));
413: }
414: inb(VGAREG_ACTL_RESET);
415:
416: for (i=0; i<9; i++) {
417: outb(i, VGAREG_GRDC_ADDRESS);
418: SET_FARVAR(seg, info->grdc_regs[i], inb(VGAREG_GRDC_DATA));
419: }
420:
421: SET_FARVAR(seg, info->crtc_addr, crtc_addr);
422:
423: /* XXX: read plane latches */
424: for (i=0; i<4; i++)
425: SET_FARVAR(seg, info->plane_latch[i], 0);
426: }
427:
428: void
429: vgahw_restore_state(u16 seg, struct saveVideoHardware *info)
430: {
431: // Reset Attribute Ctl flip-flop
432: inb(VGAREG_ACTL_RESET);
433:
434: u16 crtc_addr = GET_FARVAR(seg, info->crtc_addr);
435:
436: u16 i;
437: for (i=0; i<4; i++) {
438: outb(i+1, VGAREG_SEQU_ADDRESS);
439: outb(GET_FARVAR(seg, info->sequ_regs[i]), VGAREG_SEQU_DATA);
440: }
441: outb(0, VGAREG_SEQU_ADDRESS);
442: outb(GET_FARVAR(seg, info->sequ0), VGAREG_SEQU_DATA);
443:
444: // Disable CRTC write protection
445: outw(0x0011, crtc_addr);
446: // Set CRTC regs
447: for (i=0; i<25; i++)
448: if (i != 0x11) {
449: outb(i, crtc_addr);
450: outb(GET_FARVAR(seg, info->crtc_regs[i]), crtc_addr + 1);
451: }
452: // select crtc base address
453: u16 v = inb(VGAREG_READ_MISC_OUTPUT) & ~0x01;
454: if (crtc_addr == VGAREG_VGA_CRTC_ADDRESS)
455: v |= 0x01;
456: outb(v, VGAREG_WRITE_MISC_OUTPUT);
457:
458: // enable write protection if needed
459: outb(0x11, crtc_addr);
460: outb(GET_FARVAR(seg, info->crtc_regs[0x11]), crtc_addr + 1);
461:
462: // Set Attribute Ctl
463: u16 ar_index = GET_FARVAR(seg, info->actl_index);
464: inb(VGAREG_ACTL_RESET);
465: for (i=0; i<20; i++) {
466: outb(i | (ar_index & 0x20), VGAREG_ACTL_ADDRESS);
467: outb(GET_FARVAR(seg, info->actl_regs[i]), VGAREG_ACTL_WRITE_DATA);
468: }
469: outb(ar_index, VGAREG_ACTL_ADDRESS);
470: inb(VGAREG_ACTL_RESET);
471:
472: for (i=0; i<9; i++) {
473: outb(i, VGAREG_GRDC_ADDRESS);
474: outb(GET_FARVAR(seg, info->grdc_regs[i]), VGAREG_GRDC_DATA);
475: }
476:
477: outb(GET_FARVAR(seg, info->sequ_index), VGAREG_SEQU_ADDRESS);
478: outb(GET_FARVAR(seg, info->crtc_index), crtc_addr);
479: outb(GET_FARVAR(seg, info->grdc_index), VGAREG_GRDC_ADDRESS);
480: outb(GET_FARVAR(seg, info->feature), crtc_addr - 0x4 + 0xa);
481: }
482:
483: void
484: vgahw_set_mode(struct VideoParam_s *vparam_g)
485: {
486: // Reset Attribute Ctl flip-flop
487: inb(VGAREG_ACTL_RESET);
488:
489: // Set Attribute Ctl
490: u16 i;
491: for (i = 0; i <= 0x13; i++) {
492: outb(i, VGAREG_ACTL_ADDRESS);
493: outb(GET_GLOBAL(vparam_g->actl_regs[i]), VGAREG_ACTL_WRITE_DATA);
494: }
495: outb(0x14, VGAREG_ACTL_ADDRESS);
496: outb(0x00, VGAREG_ACTL_WRITE_DATA);
497:
498: // Set Sequencer Ctl
499: outb(0, VGAREG_SEQU_ADDRESS);
500: outb(0x03, VGAREG_SEQU_DATA);
501: for (i = 1; i <= 4; i++) {
502: outb(i, VGAREG_SEQU_ADDRESS);
503: outb(GET_GLOBAL(vparam_g->sequ_regs[i - 1]), VGAREG_SEQU_DATA);
504: }
505:
506: // Set Grafx Ctl
507: for (i = 0; i <= 8; i++) {
508: outb(i, VGAREG_GRDC_ADDRESS);
509: outb(GET_GLOBAL(vparam_g->grdc_regs[i]), VGAREG_GRDC_DATA);
510: }
511:
512: // Set CRTC address VGA or MDA
513: u8 miscreg = GET_GLOBAL(vparam_g->miscreg);
514: u16 crtc_addr = VGAREG_VGA_CRTC_ADDRESS;
515: if (!(miscreg & 1))
516: crtc_addr = VGAREG_MDA_CRTC_ADDRESS;
517:
518: // Disable CRTC write protection
519: outw(0x0011, crtc_addr);
520: // Set CRTC regs
521: for (i = 0; i <= 0x18; i++) {
522: outb(i, crtc_addr);
523: outb(GET_GLOBAL(vparam_g->crtc_regs[i]), crtc_addr + 1);
524: }
525:
526: // Set the misc register
527: outb(miscreg, VGAREG_WRITE_MISC_OUTPUT);
528:
529: // Enable video
530: outb(0x20, VGAREG_ACTL_ADDRESS);
531: inb(VGAREG_ACTL_RESET);
532: }
533:
534:
535: /****************************************************************
536: * Misc
537: ****************************************************************/
538:
539: void
540: vgahw_enable_video_addressing(u8 disable)
541: {
542: u8 v = (disable & 1) ? 0x00 : 0x02;
543: u8 v2 = inb(VGAREG_READ_MISC_OUTPUT) & ~0x02;
544: outb(v | v2, VGAREG_WRITE_MISC_OUTPUT);
545: }
546:
547: void
1.1.1.2 ! root 548: vgahw_init(void)
1.1 root 549: {
550: // switch to color mode and enable CPU access 480 lines
551: outb(0xc3, VGAREG_WRITE_MISC_OUTPUT);
552: // more than 64k 3C4/04
553: outb(0x04, VGAREG_SEQU_ADDRESS);
554: outb(0x02, VGAREG_SEQU_DATA);
555: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.