|
|
1.1 root 1: // VGA bios implementation
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:
9: // TODO:
10: // * review correctness of converted asm by comparing with RBIL
11: //
12: // * convert vbe/clext code
13:
14: #include "bregs.h" // struct bregs
15: #include "biosvar.h" // GET_BDA
16: #include "util.h" // memset
17: #include "vgatables.h" // find_vga_entry
18:
19: // XXX
20: #define CONFIG_VBE 0
21: #define CONFIG_CIRRUS 0
22:
23: // XXX
24: #define DEBUG_VGA_POST 1
25: #define DEBUG_VGA_10 3
26:
27: #define SET_VGA(var, val) SET_FARVAR(get_global_seg(), (var), (val))
28:
29:
30: /****************************************************************
31: * Helper functions
32: ****************************************************************/
33:
34: static inline void
35: call16_vgaint(u32 eax, u32 ebx)
36: {
37: asm volatile(
38: "int $0x10\n"
39: "cli\n"
40: "cld"
41: :
42: : "a"(eax), "b"(ebx)
43: : "cc", "memory");
44: }
45:
46: static void
47: perform_gray_scale_summing(u16 start, u16 count)
48: {
49: vgahw_screen_disable();
50: int i;
51: for (i = start; i < start+count; i++) {
52: u8 rgb[3];
53: vgahw_get_dac_regs(GET_SEG(SS), rgb, i, 1);
54:
55: // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
56: u16 intensity = ((77 * rgb[0] + 151 * rgb[1] + 28 * rgb[2]) + 0x80) >> 8;
57: if (intensity > 0x3f)
58: intensity = 0x3f;
59:
60: vgahw_set_dac_regs(GET_SEG(SS), rgb, i, 1);
61: }
62: vgahw_screen_enable();
63: }
64:
65: static void
66: set_cursor_shape(u8 start, u8 end)
67: {
68: start &= 0x3f;
69: end &= 0x1f;
70:
71: u16 curs = (start << 8) + end;
72: SET_BDA(cursor_type, curs);
73:
74: u8 modeset_ctl = GET_BDA(modeset_ctl);
75: u16 cheight = GET_BDA(char_height);
76: if ((modeset_ctl & 0x01) && (cheight > 8) && (end < 8) && (start < 0x20)) {
77: if (end != (start + 1))
78: start = ((start + 1) * cheight / 8) - 1;
79: else
80: start = ((end + 1) * cheight / 8) - 2;
81: end = ((end + 1) * cheight / 8) - 1;
82: }
83: vgahw_set_cursor_shape(start, end);
84: }
85:
86: static u16
87: get_cursor_shape(u8 page)
88: {
89: if (page > 7)
90: return 0;
91: // FIXME should handle VGA 14/16 lines
92: return GET_BDA(cursor_type);
93: }
94:
95: static void
96: set_cursor_pos(struct cursorpos cp)
97: {
98: // Should not happen...
99: if (cp.page > 7)
100: return;
101:
102: // Bios cursor pos
103: SET_BDA(cursor_pos[cp.page], (cp.y << 8) | cp.x);
104:
105: // Set the hardware cursor
106: u8 current = GET_BDA(video_page);
107: if (cp.page != current)
108: return;
109:
110: // Get the dimensions
111: u16 nbcols = GET_BDA(video_cols);
112: u16 nbrows = GET_BDA(video_rows) + 1;
113:
114: // Calculate the address knowing nbcols nbrows and page num
115: u16 address = (SCREEN_IO_START(nbcols, nbrows, cp.page)
116: + cp.x + cp.y * nbcols);
117:
118: vgahw_set_cursor_pos(address);
119: }
120:
121: static struct cursorpos
122: get_cursor_pos(u8 page)
123: {
124: if (page == 0xff)
125: // special case - use current page
126: page = GET_BDA(video_page);
127: if (page > 7) {
128: struct cursorpos cp = { 0, 0, 0xfe };
129: return cp;
130: }
131: // FIXME should handle VGA 14/16 lines
132: u16 xy = GET_BDA(cursor_pos[page]);
133: struct cursorpos cp = {xy, xy>>8, page};
134: return cp;
135: }
136:
137: static void
138: set_active_page(u8 page)
139: {
140: if (page > 7)
141: return;
142:
143: // Get the mode
144: struct vgamode_s *vmode_g = find_vga_entry(GET_BDA(video_mode));
145: if (!vmode_g)
146: return;
147:
148: // Get pos curs pos for the right page
149: struct cursorpos cp = get_cursor_pos(page);
150:
151: u16 address;
152: if (GET_GLOBAL(vmode_g->memmodel) & TEXT) {
153: // Get the dimensions
154: u16 nbcols = GET_BDA(video_cols);
155: u16 nbrows = GET_BDA(video_rows) + 1;
156:
157: // Calculate the address knowing nbcols nbrows and page num
158: address = SCREEN_MEM_START(nbcols, nbrows, page);
159: SET_BDA(video_pagestart, address);
160:
161: // Start address
162: address = SCREEN_IO_START(nbcols, nbrows, page);
163: } else {
164: struct VideoParam_s *vparam_g = GET_GLOBAL(vmode_g->vparam);
165: address = page * GET_GLOBAL(vparam_g->slength);
166: }
167:
168: vgahw_set_active_page(address);
169:
170: // And change the BIOS page
171: SET_BDA(video_page, page);
172:
173: dprintf(1, "Set active page %02x address %04x\n", page, address);
174:
175: // Display the cursor, now the page is active
176: set_cursor_pos(cp);
177: }
178:
179: static void
180: set_scan_lines(u8 lines)
181: {
182: vgahw_set_scan_lines(lines);
183: if (lines == 8)
184: set_cursor_shape(0x06, 0x07);
185: else
186: set_cursor_shape(lines - 4, lines - 3);
187: SET_BDA(char_height, lines);
188: u16 vde = vgahw_get_vde();
189: u8 rows = vde / lines;
190: SET_BDA(video_rows, rows - 1);
191: u16 cols = GET_BDA(video_cols);
192: SET_BDA(video_pagesize, rows * cols * 2);
193: }
194:
195:
196: /****************************************************************
197: * Character writing
198: ****************************************************************/
199:
200: // Scroll the screen one line. This function is designed to be called
201: // tail-recursive to reduce stack usage.
202: static void noinline
203: scroll_one(u16 nbrows, u16 nbcols, u8 page)
204: {
205: struct cursorpos ul = {0, 0, page};
206: struct cursorpos lr = {nbcols-1, nbrows-1, page};
207: vgafb_scroll(1, -1, ul, lr);
208: }
209:
210: // Write a character to the screen at a given position. Implement
211: // special characters and scroll the screen if necessary.
212: static void
213: write_teletype(struct cursorpos *pcp, struct carattr ca)
214: {
215: struct cursorpos cp = *pcp;
216:
217: // Get the dimensions
218: u16 nbrows = GET_BDA(video_rows) + 1;
219: u16 nbcols = GET_BDA(video_cols);
220:
221: switch (ca.car) {
222: case 7:
223: //FIXME should beep
224: break;
225: case 8:
226: if (cp.x > 0)
227: cp.x--;
228: break;
229: case '\r':
230: cp.x = 0;
231: break;
232: case '\n':
233: cp.y++;
234: break;
235: case '\t':
236: do {
237: struct carattr dummyca = {' ', ca.attr, ca.use_attr};
238: vgafb_write_char(cp, dummyca);
239: cp.x++;
240: } while (cp.x < nbcols && cp.x % 8);
241: break;
242: default:
243: vgafb_write_char(cp, ca);
244: cp.x++;
245: }
246:
247: // Do we need to wrap ?
248: if (cp.x == nbcols) {
249: cp.x = 0;
250: cp.y++;
251: }
252: // Do we need to scroll ?
253: if (cp.y < nbrows) {
254: *pcp = cp;
255: return;
256: }
257: // Scroll screen
258: cp.y--;
259: *pcp = cp;
260: scroll_one(nbrows, nbcols, cp.page);
261: }
262:
263: // Write out a buffer of alternating characters and attributes.
264: static void
265: write_attr_string(struct cursorpos *pcp, u16 count, u16 seg, u8 *offset_far)
266: {
267: while (count--) {
268: u8 car = GET_FARVAR(seg, *offset_far);
269: offset_far++;
270: u8 attr = GET_FARVAR(seg, *offset_far);
271: offset_far++;
272:
273: struct carattr ca = {car, attr, 1};
274: write_teletype(pcp, ca);
275: }
276: }
277:
278: // Write out a buffer of characters.
279: static void
280: write_string(struct cursorpos *pcp, u8 attr, u16 count, u16 seg, u8 *offset_far)
281: {
282: while (count--) {
283: u8 car = GET_FARVAR(seg, *offset_far);
284: offset_far++;
285:
286: struct carattr ca = {car, attr, 1};
287: write_teletype(pcp, ca);
288: }
289: }
290:
291:
292: /****************************************************************
293: * Save and restore bda state
294: ****************************************************************/
295:
296: static void
297: save_bda_state(u16 seg, struct saveBDAstate *info)
298: {
299: SET_FARVAR(seg, info->video_mode, GET_BDA(video_mode));
300: SET_FARVAR(seg, info->video_cols, GET_BDA(video_cols));
301: SET_FARVAR(seg, info->video_pagesize, GET_BDA(video_pagesize));
302: SET_FARVAR(seg, info->crtc_address, GET_BDA(crtc_address));
303: SET_FARVAR(seg, info->video_rows, GET_BDA(video_rows));
304: SET_FARVAR(seg, info->char_height, GET_BDA(char_height));
305: SET_FARVAR(seg, info->video_ctl, GET_BDA(video_ctl));
306: SET_FARVAR(seg, info->video_switches, GET_BDA(video_switches));
307: SET_FARVAR(seg, info->modeset_ctl, GET_BDA(modeset_ctl));
308: SET_FARVAR(seg, info->cursor_type, GET_BDA(cursor_type));
309: u16 i;
310: for (i=0; i<8; i++)
311: SET_FARVAR(seg, info->cursor_pos[i], GET_BDA(cursor_pos[i]));
312: SET_FARVAR(seg, info->video_pagestart, GET_BDA(video_pagestart));
313: SET_FARVAR(seg, info->video_page, GET_BDA(video_page));
314: /* current font */
315: SET_FARVAR(seg, info->font0, GET_IVT(0x1f));
316: SET_FARVAR(seg, info->font1, GET_IVT(0x43));
317: }
318:
319: static void
320: restore_bda_state(u16 seg, struct saveBDAstate *info)
321: {
322: SET_BDA(video_mode, GET_FARVAR(seg, info->video_mode));
323: SET_BDA(video_cols, GET_FARVAR(seg, info->video_cols));
324: SET_BDA(video_pagesize, GET_FARVAR(seg, info->video_pagesize));
325: SET_BDA(crtc_address, GET_FARVAR(seg, info->crtc_address));
326: SET_BDA(video_rows, GET_FARVAR(seg, info->video_rows));
327: SET_BDA(char_height, GET_FARVAR(seg, info->char_height));
328: SET_BDA(video_ctl, GET_FARVAR(seg, info->video_ctl));
329: SET_BDA(video_switches, GET_FARVAR(seg, info->video_switches));
330: SET_BDA(modeset_ctl, GET_FARVAR(seg, info->modeset_ctl));
331: SET_BDA(cursor_type, GET_FARVAR(seg, info->cursor_type));
332: u16 i;
333: for (i = 0; i < 8; i++)
334: SET_BDA(cursor_pos[i], GET_FARVAR(seg, info->cursor_pos[i]));
335: SET_BDA(video_pagestart, GET_FARVAR(seg, info->video_pagestart));
336: SET_BDA(video_page, GET_FARVAR(seg, info->video_page));
337: /* current font */
338: SET_IVT(0x1f, GET_FARVAR(seg, info->font0));
339: SET_IVT(0x43, GET_FARVAR(seg, info->font1));
340: }
341:
342:
343: /****************************************************************
344: * VGA int 10 handler
345: ****************************************************************/
346:
347: // set video mode
348: static void
349: handle_1000(struct bregs *regs)
350: {
351: u8 noclearmem = regs->al & 0x80;
352: u8 mode = regs->al & 0x7f;
353:
354: // Set regs->al
355: if (mode > 7)
356: regs->al = 0x20;
357: else if (mode == 6)
358: regs->al = 0x3f;
359: else
360: regs->al = 0x30;
361:
362: if (CONFIG_CIRRUS)
363: cirrus_set_video_mode(mode);
364:
365: if (CONFIG_VBE)
366: if (vbe_has_vbe_display())
367: dispi_set_enable(VBE_DISPI_DISABLED);
368:
369: // find the entry in the video modes
370: struct vgamode_s *vmode_g = find_vga_entry(mode);
371: dprintf(1, "mode search %02x found %p\n", mode, vmode_g);
372: if (!vmode_g)
373: return;
374:
375: // Read the bios mode set control
376: u8 modeset_ctl = GET_BDA(modeset_ctl);
377:
378: // Then we know the number of lines
379: // FIXME
380:
381: // if palette loading (bit 3 of modeset ctl = 0)
382: if ((modeset_ctl & 0x08) == 0) { // Set the PEL mask
383: vgahw_set_pel_mask(GET_GLOBAL(vmode_g->pelmask));
384:
385: // From which palette
386: u8 *palette_g = GET_GLOBAL(vmode_g->dac);
387: u16 palsize = GET_GLOBAL(vmode_g->dacsize) / 3;
388:
389: // Always 256*3 values
390: vgahw_set_dac_regs(get_global_seg(), palette_g, 0, palsize);
391: u16 i;
392: for (i = palsize; i < 0x0100; i++) {
393: static u8 rgb[3] VAR16;
394: vgahw_set_dac_regs(get_global_seg(), rgb, i, 1);
395: }
396:
397: if ((modeset_ctl & 0x02) == 0x02)
398: perform_gray_scale_summing(0x00, 0x100);
399: }
400:
401: struct VideoParam_s *vparam_g = GET_GLOBAL(vmode_g->vparam);
402: vgahw_set_mode(vparam_g);
403:
404: if (noclearmem == 0x00)
405: clear_screen(vmode_g);
406:
407: // Set CRTC address VGA or MDA
408: u16 crtc_addr = VGAREG_VGA_CRTC_ADDRESS;
409: if (GET_GLOBAL(vmode_g->memmodel) == MTEXT)
410: crtc_addr = VGAREG_MDA_CRTC_ADDRESS;
411:
412: // Set the BIOS mem
413: u16 cheight = GET_GLOBAL(vparam_g->cheight);
414: SET_BDA(video_mode, mode);
415: SET_BDA(video_cols, GET_GLOBAL(vparam_g->twidth));
416: SET_BDA(video_pagesize, GET_GLOBAL(vparam_g->slength));
417: SET_BDA(crtc_address, crtc_addr);
418: SET_BDA(video_rows, GET_GLOBAL(vparam_g->theightm1));
419: SET_BDA(char_height, cheight);
420: SET_BDA(video_ctl, (0x60 | noclearmem));
421: SET_BDA(video_switches, 0xF9);
422: SET_BDA(modeset_ctl, GET_BDA(modeset_ctl) & 0x7f);
423:
424: // FIXME We nearly have the good tables. to be reworked
425: SET_BDA(dcc_index, 0x08); // 8 is VGA should be ok for now
426: SET_BDA(video_savetable
427: , SEGOFF(get_global_seg(), (u32)video_save_pointer_table));
428:
429: // FIXME
430: SET_BDA(video_msr, 0x00); // Unavailable on vanilla vga, but...
431: SET_BDA(video_pal, 0x00); // Unavailable on vanilla vga, but...
432:
433: // Set cursor shape
434: if (GET_GLOBAL(vmode_g->memmodel) & TEXT)
435: set_cursor_shape(0x06, 0x07);
436: // Set cursor pos for page 0..7
437: int i;
438: for (i = 0; i < 8; i++) {
439: struct cursorpos cp = {0, 0, i};
440: set_cursor_pos(cp);
441: }
442:
443: // Set active page 0
444: set_active_page(0x00);
445:
446: // Write the fonts in memory
447: if (GET_GLOBAL(vmode_g->memmodel) & TEXT) {
448: call16_vgaint(0x1104, 0);
449: call16_vgaint(0x1103, 0);
450: }
451: // Set the ints 0x1F and 0x43
452: SET_IVT(0x1f, SEGOFF(get_global_seg(), (u32)&vgafont8[128 * 8]));
453:
454: switch (cheight) {
455: case 8:
456: SET_IVT(0x43, SEGOFF(get_global_seg(), (u32)vgafont8));
457: break;
458: case 14:
459: SET_IVT(0x43, SEGOFF(get_global_seg(), (u32)vgafont14));
460: break;
461: case 16:
462: SET_IVT(0x43, SEGOFF(get_global_seg(), (u32)vgafont16));
463: break;
464: }
465: }
466:
467: static void
468: handle_1001(struct bregs *regs)
469: {
470: set_cursor_shape(regs->ch, regs->cl);
471: }
472:
473: static void
474: handle_1002(struct bregs *regs)
475: {
476: struct cursorpos cp = {regs->dl, regs->dh, regs->bh};
477: set_cursor_pos(cp);
478: }
479:
480: static void
481: handle_1003(struct bregs *regs)
482: {
483: regs->cx = get_cursor_shape(regs->bh);
484: struct cursorpos cp = get_cursor_pos(regs->bh);
485: regs->dl = cp.x;
486: regs->dh = cp.y;
487: }
488:
489: // Read light pen pos (unimplemented)
490: static void
491: handle_1004(struct bregs *regs)
492: {
493: debug_stub(regs);
494: regs->ax = regs->bx = regs->cx = regs->dx = 0;
495: }
496:
497: static void
498: handle_1005(struct bregs *regs)
499: {
500: set_active_page(regs->al);
501: }
502:
503: static void
504: verify_scroll(struct bregs *regs, int dir)
505: {
506: u8 page = GET_BDA(video_page);
507: struct cursorpos ul = {regs->cl, regs->ch, page};
508: struct cursorpos lr = {regs->dl, regs->dh, page};
509:
510: u16 nbrows = GET_BDA(video_rows) + 1;
511: if (lr.y >= nbrows)
512: lr.y = nbrows - 1;
513: u16 nbcols = GET_BDA(video_cols);
514: if (lr.x >= nbcols)
515: lr.x = nbcols - 1;
516:
517: if (ul.x > lr.x || ul.y > lr.y)
518: return;
519:
520: u16 nblines = regs->al;
521: if (!nblines || nblines > lr.y - ul.y + 1)
522: nblines = lr.y - ul.y + 1;
523:
524: vgafb_scroll(dir * nblines, regs->bh, ul, lr);
525: }
526:
527: static void
528: handle_1006(struct bregs *regs)
529: {
530: verify_scroll(regs, 1);
531: }
532:
533: static void
534: handle_1007(struct bregs *regs)
535: {
536: verify_scroll(regs, -1);
537: }
538:
539: static void
540: handle_1008(struct bregs *regs)
541: {
542: struct carattr ca = vgafb_read_char(get_cursor_pos(regs->bh));
543: regs->al = ca.car;
544: regs->ah = ca.attr;
545: }
546:
547: static void noinline
548: write_chars(u8 page, struct carattr ca, u16 count)
549: {
550: struct cursorpos cp = get_cursor_pos(page);
551: while (count--) {
552: vgafb_write_char(cp, ca);
553: cp.x++;
554: }
555: }
556:
557: static void
558: handle_1009(struct bregs *regs)
559: {
560: struct carattr ca = {regs->al, regs->bl, 1};
561: write_chars(regs->bh, ca, regs->cx);
562: }
563:
564: static void
565: handle_100a(struct bregs *regs)
566: {
567: struct carattr ca = {regs->al, regs->bl, 0};
568: write_chars(regs->bh, ca, regs->cx);
569: }
570:
571:
572: static void
573: handle_100b00(struct bregs *regs)
574: {
575: vgahw_set_border_color(regs->bl);
576: }
577:
578: static void
579: handle_100b01(struct bregs *regs)
580: {
581: vgahw_set_palette(regs->bl);
582: }
583:
584: static void
585: handle_100bXX(struct bregs *regs)
586: {
587: debug_stub(regs);
588: }
589:
590: static void
591: handle_100b(struct bregs *regs)
592: {
593: switch (regs->bh) {
594: case 0x00: handle_100b00(regs); break;
595: case 0x01: handle_100b01(regs); break;
596: default: handle_100bXX(regs); break;
597: }
598: }
599:
600:
601: static void
602: handle_100c(struct bregs *regs)
603: {
604: // XXX - page (regs->bh) is unused
605: vgafb_write_pixel(regs->al, regs->cx, regs->dx);
606: }
607:
608: static void
609: handle_100d(struct bregs *regs)
610: {
611: // XXX - page (regs->bh) is unused
612: regs->al = vgafb_read_pixel(regs->cx, regs->dx);
613: }
614:
615: static void noinline
616: handle_100e(struct bregs *regs)
617: {
618: // Ralf Brown Interrupt list is WRONG on bh(page)
619: // We do output only on the current page !
620: struct carattr ca = {regs->al, regs->bl, 0};
621: struct cursorpos cp = get_cursor_pos(0xff);
622: write_teletype(&cp, ca);
623: set_cursor_pos(cp);
624: }
625:
626: static void
627: handle_100f(struct bregs *regs)
628: {
629: regs->bh = GET_BDA(video_page);
630: regs->al = GET_BDA(video_mode) | (GET_BDA(video_ctl) & 0x80);
631: regs->ah = GET_BDA(video_cols);
632: }
633:
634:
635: static void
636: handle_101000(struct bregs *regs)
637: {
638: if (regs->bl > 0x14)
639: return;
640: vgahw_set_single_palette_reg(regs->bl, regs->bh);
641: }
642:
643: static void
644: handle_101001(struct bregs *regs)
645: {
646: vgahw_set_overscan_border_color(regs->bh);
647: }
648:
649: static void
650: handle_101002(struct bregs *regs)
651: {
652: vgahw_set_all_palette_reg(regs->es, (u8*)(regs->dx + 0));
653: }
654:
655: static void
656: handle_101003(struct bregs *regs)
657: {
658: vgahw_toggle_intensity(regs->bl);
659: }
660:
661: static void
662: handle_101007(struct bregs *regs)
663: {
664: if (regs->bl > 0x14)
665: return;
666: regs->bh = vgahw_get_single_palette_reg(regs->bl);
667: }
668:
669: static void
670: handle_101008(struct bregs *regs)
671: {
672: regs->bh = vgahw_get_overscan_border_color(regs);
673: }
674:
675: static void
676: handle_101009(struct bregs *regs)
677: {
678: vgahw_get_all_palette_reg(regs->es, (u8*)(regs->dx + 0));
679: }
680:
681: static void noinline
682: handle_101010(struct bregs *regs)
683: {
684: u8 rgb[3] = {regs->dh, regs->ch, regs->cl};
685: vgahw_set_dac_regs(GET_SEG(SS), rgb, regs->bx, 1);
686: }
687:
688: static void
689: handle_101012(struct bregs *regs)
690: {
691: vgahw_set_dac_regs(regs->es, (u8*)(regs->dx + 0), regs->bx, regs->cx);
692: }
693:
694: static void
695: handle_101013(struct bregs *regs)
696: {
697: vgahw_select_video_dac_color_page(regs->bl, regs->bh);
698: }
699:
700: static void noinline
701: handle_101015(struct bregs *regs)
702: {
703: u8 rgb[3];
704: vgahw_get_dac_regs(GET_SEG(SS), rgb, regs->bx, 1);
705: regs->dh = rgb[0];
706: regs->ch = rgb[1];
707: regs->cl = rgb[2];
708: }
709:
710: static void
711: handle_101017(struct bregs *regs)
712: {
713: vgahw_get_dac_regs(regs->es, (u8*)(regs->dx + 0), regs->bx, regs->cx);
714: }
715:
716: static void
717: handle_101018(struct bregs *regs)
718: {
719: vgahw_set_pel_mask(regs->bl);
720: }
721:
722: static void
723: handle_101019(struct bregs *regs)
724: {
725: regs->bl = vgahw_get_pel_mask();
726: }
727:
728: static void
729: handle_10101a(struct bregs *regs)
730: {
731: vgahw_read_video_dac_state(®s->bl, ®s->bh);
732: }
733:
734: static void
735: handle_10101b(struct bregs *regs)
736: {
737: perform_gray_scale_summing(regs->bx, regs->cx);
738: }
739:
740: static void
741: handle_1010XX(struct bregs *regs)
742: {
743: debug_stub(regs);
744: }
745:
746: static void
747: handle_1010(struct bregs *regs)
748: {
749: switch (regs->al) {
750: case 0x00: handle_101000(regs); break;
751: case 0x01: handle_101001(regs); break;
752: case 0x02: handle_101002(regs); break;
753: case 0x03: handle_101003(regs); break;
754: case 0x07: handle_101007(regs); break;
755: case 0x08: handle_101008(regs); break;
756: case 0x09: handle_101009(regs); break;
757: case 0x10: handle_101010(regs); break;
758: case 0x12: handle_101012(regs); break;
759: case 0x13: handle_101013(regs); break;
760: case 0x15: handle_101015(regs); break;
761: case 0x17: handle_101017(regs); break;
762: case 0x18: handle_101018(regs); break;
763: case 0x19: handle_101019(regs); break;
764: case 0x1a: handle_10101a(regs); break;
765: case 0x1b: handle_10101b(regs); break;
766: default: handle_1010XX(regs); break;
767: }
768: }
769:
770:
771: static void
772: handle_101100(struct bregs *regs)
773: {
774: vgafb_load_font(regs->es, (void*)(regs->bp+0), regs->cx
775: , regs->dx, regs->bl, regs->bh);
776: }
777:
778: static void
779: handle_101101(struct bregs *regs)
780: {
781: vgafb_load_font(get_global_seg(), vgafont14, 0x100, 0, regs->bl, 14);
782: }
783:
784: static void
785: handle_101102(struct bregs *regs)
786: {
787: vgafb_load_font(get_global_seg(), vgafont8, 0x100, 0, regs->bl, 8);
788: }
789:
790: static void
791: handle_101103(struct bregs *regs)
792: {
793: vgahw_set_text_block_specifier(regs->bl);
794: }
795:
796: static void
797: handle_101104(struct bregs *regs)
798: {
799: vgafb_load_font(get_global_seg(), vgafont16, 0x100, 0, regs->bl, 16);
800: }
801:
802: static void
803: handle_101110(struct bregs *regs)
804: {
805: vgafb_load_font(regs->es, (void*)(regs->bp+0), regs->cx
806: , regs->dx, regs->bl, regs->bh);
807: set_scan_lines(regs->bh);
808: }
809:
810: static void
811: handle_101111(struct bregs *regs)
812: {
813: vgafb_load_font(get_global_seg(), vgafont14, 0x100, 0, regs->bl, 14);
814: set_scan_lines(14);
815: }
816:
817: static void
818: handle_101112(struct bregs *regs)
819: {
820: vgafb_load_font(get_global_seg(), vgafont8, 0x100, 0, regs->bl, 8);
821: set_scan_lines(8);
822: }
823:
824: static void
825: handle_101114(struct bregs *regs)
826: {
827: vgafb_load_font(get_global_seg(), vgafont16, 0x100, 0, regs->bl, 16);
828: set_scan_lines(16);
829: }
830:
831: static void
832: handle_101130(struct bregs *regs)
833: {
834: switch (regs->bh) {
835: case 0x00: {
836: u32 segoff = GET_IVT(0x1f).segoff;
837: regs->es = segoff >> 16;
838: regs->bp = segoff;
839: break;
840: }
841: case 0x01: {
842: u32 segoff = GET_IVT(0x43).segoff;
843: regs->es = segoff >> 16;
844: regs->bp = segoff;
845: break;
846: }
847: case 0x02:
848: regs->es = get_global_seg();
849: regs->bp = (u32)vgafont14;
850: break;
851: case 0x03:
852: regs->es = get_global_seg();
853: regs->bp = (u32)vgafont8;
854: break;
855: case 0x04:
856: regs->es = get_global_seg();
857: regs->bp = (u32)vgafont8 + 128 * 8;
858: break;
859: case 0x05:
860: regs->es = get_global_seg();
861: regs->bp = (u32)vgafont14alt;
862: break;
863: case 0x06:
864: regs->es = get_global_seg();
865: regs->bp = (u32)vgafont16;
866: break;
867: case 0x07:
868: regs->es = get_global_seg();
869: regs->bp = (u32)vgafont16alt;
870: break;
871: default:
872: dprintf(1, "Get font info BH(%02x) was discarded\n", regs->bh);
873: return;
874: }
875: // Set byte/char of on screen font
876: regs->cx = GET_BDA(char_height) & 0xff;
877:
878: // Set Highest char row
879: regs->dx = GET_BDA(video_rows);
880: }
881:
882: static void
883: handle_1011XX(struct bregs *regs)
884: {
885: debug_stub(regs);
886: }
887:
888: static void
889: handle_1011(struct bregs *regs)
890: {
891: switch (regs->al) {
892: case 0x00: handle_101100(regs); break;
893: case 0x01: handle_101101(regs); break;
894: case 0x02: handle_101102(regs); break;
895: case 0x03: handle_101103(regs); break;
896: case 0x04: handle_101104(regs); break;
897: case 0x10: handle_101110(regs); break;
898: case 0x11: handle_101111(regs); break;
899: case 0x12: handle_101112(regs); break;
900: case 0x14: handle_101114(regs); break;
901: case 0x30: handle_101130(regs); break;
902: default: handle_1011XX(regs); break;
903: }
904: }
905:
906:
907: static void
908: handle_101210(struct bregs *regs)
909: {
910: u16 crtc_addr = GET_BDA(crtc_address);
911: if (crtc_addr == VGAREG_MDA_CRTC_ADDRESS)
912: regs->bx = 0x0103;
913: else
914: regs->bx = 0x0003;
915: regs->cx = GET_BDA(video_switches) & 0x0f;
916: }
917:
918: static void
919: handle_101230(struct bregs *regs)
920: {
921: u8 mctl = GET_BDA(modeset_ctl);
922: u8 vswt = GET_BDA(video_switches);
923: switch (regs->al) {
924: case 0x00:
925: // 200 lines
926: mctl = (mctl & ~0x10) | 0x80;
927: vswt = (vswt & ~0x0f) | 0x08;
928: break;
929: case 0x01:
930: // 350 lines
931: mctl &= ~0x90;
932: vswt = (vswt & ~0x0f) | 0x09;
933: break;
934: case 0x02:
935: // 400 lines
936: mctl = (mctl & ~0x80) | 0x10;
937: vswt = (vswt & ~0x0f) | 0x09;
938: break;
939: default:
940: dprintf(1, "Select vert res (%02x) was discarded\n", regs->al);
941: break;
942: }
943: SET_BDA(modeset_ctl, mctl);
944: SET_BDA(video_switches, vswt);
945: regs->al = 0x12;
946: }
947:
948: static void
949: handle_101231(struct bregs *regs)
950: {
951: u8 v = (regs->al & 0x01) << 3;
952: u8 mctl = GET_BDA(video_ctl) & ~0x08;
953: SET_BDA(video_ctl, mctl | v);
954: regs->al = 0x12;
955: }
956:
957: static void
958: handle_101232(struct bregs *regs)
959: {
960: vgahw_enable_video_addressing(regs->al);
961: regs->al = 0x12;
962: }
963:
964: static void
965: handle_101233(struct bregs *regs)
966: {
967: u8 v = ((regs->al << 1) & 0x02) ^ 0x02;
968: u8 v2 = GET_BDA(modeset_ctl) & ~0x02;
969: SET_BDA(modeset_ctl, v | v2);
970: regs->al = 0x12;
971: }
972:
973: static void
974: handle_101234(struct bregs *regs)
975: {
976: u8 v = (regs->al & 0x01) ^ 0x01;
977: u8 v2 = GET_BDA(modeset_ctl) & ~0x01;
978: SET_BDA(modeset_ctl, v | v2);
979: regs->al = 0x12;
980: }
981:
982: static void
983: handle_101235(struct bregs *regs)
984: {
985: debug_stub(regs);
986: regs->al = 0x12;
987: }
988:
989: static void
990: handle_101236(struct bregs *regs)
991: {
992: debug_stub(regs);
993: regs->al = 0x12;
994: }
995:
996: static void
997: handle_1012XX(struct bregs *regs)
998: {
999: debug_stub(regs);
1000: }
1001:
1002: static void
1003: handle_1012(struct bregs *regs)
1004: {
1005: switch (regs->bl) {
1006: case 0x10: handle_101210(regs); break;
1007: case 0x30: handle_101230(regs); break;
1008: case 0x31: handle_101231(regs); break;
1009: case 0x32: handle_101232(regs); break;
1010: case 0x33: handle_101233(regs); break;
1011: case 0x34: handle_101234(regs); break;
1012: case 0x35: handle_101235(regs); break;
1013: case 0x36: handle_101236(regs); break;
1014: default: handle_1012XX(regs); break;
1015: }
1016:
1017: // XXX - cirrus has 1280, 1281, 1282, 1285, 129a, 12a0, 12a1, 12a2, 12ae
1018: }
1019:
1020:
1021: // Write string
1022: static void noinline
1023: handle_1013(struct bregs *regs)
1024: {
1025: struct cursorpos cp = {regs->dl, regs->dh, regs->bh};
1026: // if row=0xff special case : use current cursor position
1027: if (cp.y == 0xff)
1028: cp = get_cursor_pos(cp.page);
1029: u8 flag = regs->al;
1030: if (flag & 2)
1031: write_attr_string(&cp, regs->cx, regs->es, (void*)(regs->bp + 0));
1032: else
1033: write_string(&cp, regs->bl, regs->cx, regs->es, (void*)(regs->bp + 0));
1034:
1035: if (flag & 1)
1036: set_cursor_pos(cp);
1037: }
1038:
1039:
1040: static void
1041: handle_101a00(struct bregs *regs)
1042: {
1043: regs->bx = GET_BDA(dcc_index);
1044: regs->al = 0x1a;
1045: }
1046:
1047: static void
1048: handle_101a01(struct bregs *regs)
1049: {
1050: SET_BDA(dcc_index, regs->bl);
1051: dprintf(1, "Alternate Display code (%02x) was discarded\n", regs->bh);
1052: regs->al = 0x1a;
1053: }
1054:
1055: static void
1056: handle_101aXX(struct bregs *regs)
1057: {
1058: debug_stub(regs);
1059: }
1060:
1061: static void
1062: handle_101a(struct bregs *regs)
1063: {
1064: switch (regs->al) {
1065: case 0x00: handle_101a00(regs); break;
1066: case 0x01: handle_101a01(regs); break;
1067: default: handle_101aXX(regs); break;
1068: }
1069: }
1070:
1071:
1072: struct funcInfo {
1073: u16 static_functionality_off;
1074: u16 static_functionality_seg;
1075: u8 bda_0x49[30];
1076: u8 bda_0x84[3];
1077: u8 dcc_index;
1078: u8 dcc_alt;
1079: u16 colors;
1080: u8 pages;
1081: u8 scan_lines;
1082: u8 primary_char;
1083: u8 secondar_char;
1084: u8 misc;
1085: u8 non_vga_mode;
1086: u8 reserved_2f[2];
1087: u8 video_mem;
1088: u8 save_flags;
1089: u8 disp_info;
1090: u8 reserved_34[12];
1091: };
1092:
1093: static void
1094: handle_101b(struct bregs *regs)
1095: {
1096: u16 seg = regs->es;
1097: struct funcInfo *info = (void*)(regs->di+0);
1098: memset_far(seg, info, 0, sizeof(*info));
1099: // Address of static functionality table
1100: SET_FARVAR(seg, info->static_functionality_off, (u32)static_functionality);
1101: SET_FARVAR(seg, info->static_functionality_seg, get_global_seg());
1102:
1103: // Hard coded copy from BIOS area. Should it be cleaner ?
1104: memcpy_far(seg, info->bda_0x49, SEG_BDA, (void*)0x49
1105: , sizeof(info->bda_0x49));
1106: memcpy_far(seg, info->bda_0x84, SEG_BDA, (void*)0x84
1107: , sizeof(info->bda_0x84));
1108:
1109: SET_FARVAR(seg, info->dcc_index, GET_BDA(dcc_index));
1110: SET_FARVAR(seg, info->colors, 16);
1111: SET_FARVAR(seg, info->pages, 8);
1112: SET_FARVAR(seg, info->scan_lines, 2);
1113: SET_FARVAR(seg, info->video_mem, 3);
1114: regs->al = 0x1B;
1115: }
1116:
1117:
1118: static void
1119: handle_101c00(struct bregs *regs)
1120: {
1121: u16 flags = regs->cx;
1122: u16 size = 0;
1123: if (flags & 1)
1124: size += sizeof(struct saveVideoHardware);
1125: if (flags & 2)
1126: size += sizeof(struct saveBDAstate);
1127: if (flags & 4)
1128: size += sizeof(struct saveDACcolors);
1129: regs->bx = size;
1130: regs->al = 0x1c;
1131: }
1132:
1133: static void
1134: handle_101c01(struct bregs *regs)
1135: {
1136: u16 flags = regs->cx;
1137: u16 seg = regs->es;
1138: void *data = (void*)(regs->bx+0);
1139: if (flags & 1) {
1140: vgahw_save_state(seg, data);
1141: data += sizeof(struct saveVideoHardware);
1142: }
1143: if (flags & 2) {
1144: save_bda_state(seg, data);
1145: data += sizeof(struct saveBDAstate);
1146: }
1147: if (flags & 4)
1148: vgahw_save_dac_state(seg, data);
1149: regs->al = 0x1c;
1150: }
1151:
1152: static void
1153: handle_101c02(struct bregs *regs)
1154: {
1155: u16 flags = regs->cx;
1156: u16 seg = regs->es;
1157: void *data = (void*)(regs->bx+0);
1158: if (flags & 1) {
1159: vgahw_restore_state(seg, data);
1160: data += sizeof(struct saveVideoHardware);
1161: }
1162: if (flags & 2) {
1163: restore_bda_state(seg, data);
1164: data += sizeof(struct saveBDAstate);
1165: }
1166: if (flags & 4)
1167: vgahw_restore_dac_state(seg, data);
1168: regs->al = 0x1c;
1169: }
1170:
1171: static void
1172: handle_101cXX(struct bregs *regs)
1173: {
1174: debug_stub(regs);
1175: }
1176:
1177: static void
1178: handle_101c(struct bregs *regs)
1179: {
1180: switch (regs->al) {
1181: case 0x00: handle_101c00(regs); break;
1182: case 0x01: handle_101c01(regs); break;
1183: case 0x02: handle_101c02(regs); break;
1184: default: handle_101cXX(regs); break;
1185: }
1186: }
1187:
1188:
1189: static void
1190: handle_104f00(struct bregs *regs)
1191: {
1192: // XXX - vbe_biosfn_return_controller_information(&AX,ES,DI);
1193: // XXX - OR cirrus_vesa_00h
1194: }
1195:
1196: static void
1197: handle_104f01(struct bregs *regs)
1198: {
1199: // XXX - vbe_biosfn_return_mode_information(&AX,CX,ES,DI);
1200: // XXX - OR cirrus_vesa_01h
1201: }
1202:
1203: static void
1204: handle_104f02(struct bregs *regs)
1205: {
1206: // XXX - vbe_biosfn_set_mode(&AX,BX,ES,DI);
1207: // XXX - OR cirrus_vesa_02h
1208: }
1209:
1210: static void
1211: handle_104f03(struct bregs *regs)
1212: {
1213: // XXX - vbe_biosfn_return_current_mode
1214: // XXX - OR cirrus_vesa_03h
1215: }
1216:
1217: static void
1218: handle_104f04(struct bregs *regs)
1219: {
1220: // XXX - vbe_biosfn_save_restore_state(&AX, CX, DX, ES, &BX);
1221: }
1222:
1223: static void
1224: handle_104f05(struct bregs *regs)
1225: {
1226: // XXX - vbe_biosfn_display_window_control
1227: // XXX - OR cirrus_vesa_05h
1228: }
1229:
1230: static void
1231: handle_104f06(struct bregs *regs)
1232: {
1233: // XXX - vbe_biosfn_set_get_logical_scan_line_length
1234: // XXX - OR cirrus_vesa_06h
1235: }
1236:
1237: static void
1238: handle_104f07(struct bregs *regs)
1239: {
1240: // XXX - vbe_biosfn_set_get_display_start
1241: // XXX - OR cirrus_vesa_07h
1242: }
1243:
1244: static void
1245: handle_104f08(struct bregs *regs)
1246: {
1247: // XXX - vbe_biosfn_set_get_dac_palette_format
1248: }
1249:
1250: static void
1251: handle_104f0a(struct bregs *regs)
1252: {
1253: // XXX - vbe_biosfn_return_protected_mode_interface
1254: }
1255:
1256: static void
1257: handle_104fXX(struct bregs *regs)
1258: {
1259: debug_stub(regs);
1260: regs->ax = 0x0100;
1261: }
1262:
1263: static void
1264: handle_104f(struct bregs *regs)
1265: {
1266: if (! CONFIG_VBE || !vbe_has_vbe_display()) {
1267: handle_104fXX(regs);
1268: return;
1269: }
1270:
1271: switch (regs->al) {
1272: case 0x00: handle_104f00(regs); break;
1273: case 0x01: handle_104f01(regs); break;
1274: case 0x02: handle_104f02(regs); break;
1275: case 0x03: handle_104f03(regs); break;
1276: case 0x04: handle_104f04(regs); break;
1277: case 0x05: handle_104f05(regs); break;
1278: case 0x06: handle_104f06(regs); break;
1279: case 0x07: handle_104f07(regs); break;
1280: case 0x08: handle_104f08(regs); break;
1281: case 0x0a: handle_104f0a(regs); break;
1282: default: handle_104fXX(regs); break;
1283: }
1284: }
1285:
1286:
1287: static void
1288: handle_10XX(struct bregs *regs)
1289: {
1290: debug_stub(regs);
1291: }
1292:
1293: // INT 10h Video Support Service Entry Point
1294: void VISIBLE16
1295: handle_10(struct bregs *regs)
1296: {
1297: debug_enter(regs, DEBUG_VGA_10);
1298: switch (regs->ah) {
1299: case 0x00: handle_1000(regs); break;
1300: case 0x01: handle_1001(regs); break;
1301: case 0x02: handle_1002(regs); break;
1302: case 0x03: handle_1003(regs); break;
1303: case 0x04: handle_1004(regs); break;
1304: case 0x05: handle_1005(regs); break;
1305: case 0x06: handle_1006(regs); break;
1306: case 0x07: handle_1007(regs); break;
1307: case 0x08: handle_1008(regs); break;
1308: case 0x09: handle_1009(regs); break;
1309: case 0x0a: handle_100a(regs); break;
1310: case 0x0b: handle_100b(regs); break;
1311: case 0x0c: handle_100c(regs); break;
1312: case 0x0d: handle_100d(regs); break;
1313: case 0x0e: handle_100e(regs); break;
1314: case 0x0f: handle_100f(regs); break;
1315: case 0x10: handle_1010(regs); break;
1316: case 0x11: handle_1011(regs); break;
1317: case 0x12: handle_1012(regs); break;
1318: case 0x13: handle_1013(regs); break;
1319: case 0x1a: handle_101a(regs); break;
1320: case 0x1b: handle_101b(regs); break;
1321: case 0x1c: handle_101c(regs); break;
1322: case 0x4f: handle_104f(regs); break;
1323: default: handle_10XX(regs); break;
1324: }
1325: }
1326:
1327:
1328: /****************************************************************
1329: * VGA post
1330: ****************************************************************/
1331:
1332: static void
1333: init_bios_area()
1334: {
1335: // init detected hardware BIOS Area
1336: // set 80x25 color (not clear from RBIL but usual)
1337: u16 eqf = GET_BDA(equipment_list_flags);
1338: SET_BDA(equipment_list_flags, (eqf & 0xffcf) | 0x20);
1339:
1340: // Just for the first int10 find its children
1341:
1342: // the default char height
1343: SET_BDA(char_height, 0x10);
1344:
1345: // Clear the screen
1346: SET_BDA(video_ctl, 0x60);
1347:
1348: // Set the basic screen we have
1349: SET_BDA(video_switches, 0xf9);
1350:
1351: // Set the basic modeset options
1352: SET_BDA(modeset_ctl, 0x51);
1353:
1354: // Set the default MSR
1355: SET_BDA(video_msr, 0x09);
1356: }
1357:
1358: void VISIBLE16
1359: vga_post(struct bregs *regs)
1360: {
1361: debug_enter(regs, DEBUG_VGA_POST);
1362:
1363: vgahw_init();
1364:
1365: init_bios_area();
1366:
1367: if (CONFIG_VBE)
1368: vbe_init();
1369:
1370: extern void entry_10(void);
1371: SET_IVT(0x10, SEGOFF(get_global_seg(), (u32)entry_10));
1372:
1373: if (CONFIG_CIRRUS)
1374: cirrus_init();
1375:
1376: // XXX - clear screen and display info
1377:
1378: // XXX: fill it
1379: SET_VGA(video_save_pointer_table[0], (u32)video_param_table);
1380: SET_VGA(video_save_pointer_table[1], get_global_seg());
1381:
1382: // Fixup checksum
1383: extern u8 _rom_header_size, _rom_header_checksum;
1384: SET_VGA(_rom_header_checksum, 0);
1385: u8 sum = -checksum_far(get_global_seg(), 0, _rom_header_size * 512);
1386: SET_VGA(_rom_header_checksum, sum);
1387: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.