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