VirtualBox

source: vbox/trunk/src/VBox/Devices/Graphics/BIOS/vgabios.c@ 52493

最後變更 在這個檔案從52493是 51154,由 vboxsync 提交於 11 年 前

VGABIOS: Requests to set mode 7 must set mode 0 instead.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 60.6 KB
 
1// ============================================================================================
2/*
3 * vgabios.c
4 */
5// ============================================================================================
6//
7// Copyright (C) 2001,2002 the LGPL VGABios developers Team
8//
9// This library is free software; you can redistribute it and/or
10// modify it under the terms of the GNU Lesser General Public
11// License as published by the Free Software Foundation; either
12// version 2 of the License, or (at your option) any later version.
13//
14// This library is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17// Lesser General Public License for more details.
18//
19// You should have received a copy of the GNU Lesser General Public
20// License along with this library; if not, write to the Free Software
21// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22//
23// ============================================================================================
24//
25// This VGA Bios is specific to the plex86/bochs Emulated VGA card.
26// You can NOT drive any physical vga card with it.
27//
28// ============================================================================================
29//
30// This file contains code ripped from :
31// - rombios.c of plex86
32//
33// This VGA Bios contains fonts from :
34// - fntcol16.zip (c) by Joseph Gil avalable at :
35// ftp://ftp.simtel.net/pub/simtelnet/msdos/screen/fntcol16.zip
36// These fonts are public domain
37//
38// This VGA Bios is based on information taken from :
39// - Kevin Lawton's vga card emulation for bochs/plex86
40// - Ralf Brown's interrupts list available at http://www.cs.cmu.edu/afs/cs/user/ralf/pub/WWW/files.html
41// - Finn Thogersons' VGADOC4b available at http://home.worldonline.dk/~finth/
42// - Michael Abrash's Graphics Programming Black Book
43// - Francois Gervais' book "programmation des cartes graphiques cga-ega-vga" edited by sybex
44// - DOSEMU 1.0.1 source code for several tables values and formulas
45//
46// Thanks for patches, comments and ideas to :
47// - [email protected]
48//
49// ============================================================================================
50
51
52/*
53 * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
54 * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
55 * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
56 * a choice of LGPL license versions is made available with the language indicating
57 * that LGPLv2 or any later version may be used, or where a choice of which version
58 * of the LGPL is applied is otherwise unspecified.
59 */
60
61#include <inttypes.h>
62#include "vgabios.h"
63
64#ifdef VBE
65#include "vbe.h"
66#endif
67
68#include "inlines.h"
69
70/* Declares */
71extern void vgabios_int10_handler(void);
72#pragma aux vgabios_int10_handler "*";
73
74// Output
75void __cdecl unimplemented(void);
76void __cdecl unknown(void);
77
78static uint8_t find_vga_entry();
79
80#ifdef VBE
81extern uint16_t __cdecl vbe_has_vbe_display(void);
82extern void vbe_init(void);
83#endif
84
85void set_int_vector(uint8_t int_vec, void *offset)
86{
87 void __far * __far *ivt = 0;
88
89 ivt[int_vec] = 0xC000 :> offset;
90}
91
92//@todo!!
93#if 0
94
95vgabios_name:
96#ifdef VBOX
97.ascii "VirtualBox VGA BIOS"
98#else
99.ascii "Plex86/Bochs VGABios"
100#endif
101.ascii " "
102.byte 0x00
103
104#ifndef VBOX
105vgabios_version:
106#ifndef VGABIOS_VERS
107.ascii "current-cvs"
108#else
109.ascii VGABIOS_VERS
110#endif
111.ascii " "
112
113vgabios_date:
114.ascii VGABIOS_DATE
115.byte 0x0a,0x0d
116.byte 0x00
117#endif
118
119#ifndef VBOX
120char vgabios_copyright[] = "(C) 2003 the LGPL VGABios developers Team\r\n";
121char vgabios_license[] = "This VGA/VBE Bios is released under the GNU LGPL\r\n\r\n";
122char vgabios_website[] = "Please visit :\r\n" \
123 " . http://www.plex86.org\r\n" \
124 " . http://bochs.sourceforge.net\r\n" \
125 " . http://www.nongnu.org/vgabios\r\n\r\n"
126#endif
127
128#endif
129
130extern void set_mode(int mode);
131#pragma aux set_mode = \
132 "xor ah, ah" \
133 "int 10h" \
134 parm [ax];
135
136char msg_vga_init[] = "Oracle VM VirtualBox Version " VBOX_VERSION_STRING " VGA BIOS\r\n";
137
138/*
139 * Boot time harware inits
140 */
141void init_vga_card(void)
142{
143 /* Switch to color mode and enable CPU access 480 lines. */
144 outb(0x3C2, 0xC3);
145 /* More than 64k 3C4/04. */
146 //@todo: 16-bit write
147 outb(0x3C4, 0x04);
148 outb(0x3C5, 0x02);
149
150#ifdef DEBUG_VGA
151 printf(msg_vga_init);
152#endif
153}
154
155#include "vgatables.h"
156#include "vgadefs.h"
157
158// --------------------------------------------------------------------------------------------
159/*
160 * Boot time bios area inits
161 */
162void init_bios_area(void)
163{
164 uint8_t __far *bda;
165
166 bda = 0x40 :> 0;
167
168 /* Indicate 80x25 color was detected. */
169 bda[BIOSMEM_INITIAL_MODE] = (bda[BIOSMEM_INITIAL_MODE] & 0xcf) | 0x20;
170 /* Just for the first int10 find its children. */
171
172 /* The default char height. */
173 bda[BIOSMEM_CHAR_HEIGHT] = 16;
174 /* Clear the screen. */
175 bda[BIOSMEM_VIDEO_CTL] = 0x60;
176 /* Set the basic screen we have. */
177 bda[BIOSMEM_SWITCHES] = 0xf9;
178 /* Set the basic mode set options. */
179 bda[BIOSMEM_MODESET_CTL] = 0x51;
180 /* Set the default MSR. */
181 bda[BIOSMEM_CURRENT_MSR] = 0x09;
182}
183
184void __far *video_save_pointer_table[7] = {
185 &video_param_table
186};
187
188// ============================================================================================
189//
190// Init Entry point
191//
192// ============================================================================================
193void __far __cdecl vgabios_init_func(void)
194{
195 init_vga_card();
196 init_bios_area();
197#ifdef VBE
198 vbe_init();
199#endif
200 set_int_vector(0x10, vgabios_int10_handler);
201#ifdef CIRRUS
202 cirrus_init();
203#endif
204
205#ifndef VBOX
206 display_splash_screen();
207
208 // init video mode and clear the screen
209 // @@AS: Do not remove this init, because it will break VESA graphics
210 set_mode(3);
211
212 display_info();
213
214#ifdef VBE
215 vbe_display_info();
216#endif
217
218#ifdef CIRRUS
219 cirrus_display_info();
220#endif
221
222#else /* VBOX */
223
224//#ifdef DEBUG_bird
225 /* Init video mode and clear the screen */
226 set_mode(3);
227//#endif
228#endif /* VBOX */
229}
230
231#include "vgafonts.h"
232
233#ifndef VBOX
234// --------------------------------------------------------------------------------------------
235/*
236 * Boot time Splash screen
237 */
238static void display_splash_screen()
239{
240}
241
242// --------------------------------------------------------------------------------------------
243/*
244 * Tell who we are
245 */
246
247static void display_string(void)
248{
249 // Get length of string
250ASM_START
251 mov ax,ds
252 mov es,ax
253 mov di,si
254 xor cx,cx
255 not cx
256 xor al,al
257 cld
258 repne
259 scasb
260 not cx
261 dec cx
262 push cx
263
264 mov ax,#0x0300
265 mov bx,#0x0000
266 int #0x10
267
268 pop cx
269 mov ax,#0x1301
270 mov bx,#0x000b
271 mov bp,si
272 int #0x10
273ASM_END
274}
275
276static void display_info(void)
277{
278 display_string(vgabios_name);
279 display_string(vgabios_version);
280 display_string(vgabios_copyright);
281 display_string(vgabios_license);
282 display_string(vgabios_website);
283}
284
285#endif
286
287// --------------------------------------------------------------------------------------------
288#ifdef VGA_DEBUG
289void __cdecl int10_debugmsg(uint16_t DI, uint16_t SI, uint16_t BP, uint16_t SP, uint16_t BX,
290 uint16_t DX, uint16_t CX, uint16_t AX, uint16_t DS, uint16_t ES, uint16_t FLAGS)
291{
292 /* Function 0Eh is write char and would generate way too much output. */
293 if (GET_AH() != 0x0E)
294 printf("vgabios call ah%02x al%02x bx%04x cx%04x dx%04x\n", GET_AH(), GET_AL(), BX, CX, DX);
295}
296#endif
297
298static void vga_get_cursor_pos(uint8_t page, uint16_t STACK_BASED *scans, uint16_t STACK_BASED *loc)
299{
300 if (page > 7) {
301 *scans = 0;
302 *loc = 0;
303 } else {
304 // FIXME should handle VGA 14/16 lines
305 *scans = read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE);
306 *loc = read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_POS + page * 2);
307 }
308}
309
310
311static void vga_read_char_attr(uint8_t page, uint16_t STACK_BASED *chr_atr)
312{
313 uint8_t xcurs, ycurs, mode, line;
314 uint16_t nbcols, nbrows, address;
315 uint16_t cursor, dummy;
316
317 // Get the mode
318 mode = read_byte(BIOSMEM_SEG, BIOSMEM_CURRENT_MODE);
319 line = find_vga_entry(mode);
320 if (line == 0xFF)
321 return;
322
323 // Get the cursor pos for the page
324 vga_get_cursor_pos(page, &dummy, &cursor);
325 xcurs = cursor & 0x00ff;
326 ycurs = (cursor & 0xff00) >> 8;
327
328 // Get the dimensions
329 nbrows = read_byte(BIOSMEM_SEG, BIOSMEM_NB_ROWS) + 1;
330 nbcols = read_word(BIOSMEM_SEG, BIOSMEM_NB_COLS);
331
332 if (vga_modes[line].class == TEXT) {
333 // Compute the address
334 address = SCREEN_MEM_START(nbcols, nbrows, page) + (xcurs + ycurs * nbcols) * 2;
335 *chr_atr = read_word(vga_modes[line].sstart, address);
336 } else {
337 //@todo: graphics modes (not so easy - or useful!)
338#ifdef VGA_DEBUG
339 unimplemented();
340#endif
341 }
342}
343
344static void vga_get_font_info (uint16_t func, uint16_t STACK_BASED *u_seg, uint16_t STACK_BASED *u_ofs,
345 uint16_t STACK_BASED *c_height, uint16_t STACK_BASED *max_row)
346{
347 void __far *ptr;
348
349 switch (func) {
350 case 0x00:
351 ptr = (void __far *)read_dword(0x00, 0x1f * 4);
352 break;
353 case 0x01:
354 ptr = (void __far *)read_dword(0x00, 0x43 * 4);
355 break;
356 case 0x02:
357 ptr = 0xC000 :> vgafont14;
358 break;
359 case 0x03:
360 ptr = 0xC000 :> vgafont8;
361 break;
362 case 0x04:
363 ptr = 0xC000 :> (vgafont8 + 128 * 8);
364 break;
365 case 0x05:
366 ptr = 0xC000 :> vgafont14alt;
367 break;
368 case 0x06:
369 ptr = 0xC000 :> vgafont16;
370 break;
371 case 0x07:
372 ptr = 0xC000 :> vgafont16alt;
373 break;
374 default:
375#ifdef VGA_DEBUG
376 printf("Get font info subfn(%02x) not implemented\n", func);
377#endif
378 return;
379 }
380 /* Split the far pointer and write it back. */
381 *u_ofs = (uint16_t)ptr;
382 *u_seg = (uint32_t)ptr >> 16;
383
384 /* The character height (effectively bytes per glyph). */
385 *c_height = read_byte(BIOSMEM_SEG, BIOSMEM_CHAR_HEIGHT);
386
387 /* The highest row number. */
388 *max_row = read_byte(BIOSMEM_SEG, BIOSMEM_NB_ROWS);
389}
390
391static void vga_read_pixel(uint8_t page, uint16_t col, uint16_t row, uint16_t STACK_BASED *pixel)
392{
393 uint8_t mode, line, mask, attr, data, i;
394 uint16_t addr;
395
396 /* Determine current mode characteristics. */
397 mode = read_byte(BIOSMEM_SEG, BIOSMEM_CURRENT_MODE);
398 line = find_vga_entry(mode);
399 if (line == 0xFF)
400 return;
401 if (vga_modes[line].class == TEXT)
402 return;
403
404 /* Read data depending on memory model. */
405 switch (vga_modes[line].memmodel) {
406 case PLANAR4:
407 case PLANAR1:
408 addr = col / 8 + row * read_word(BIOSMEM_SEG, BIOSMEM_NB_COLS);
409 mask = 0x80 >> (col & 0x07);
410 attr = 0x00;
411 for (i = 0; i < 4; i++) {
412 outw(VGAREG_GRDC_ADDRESS, (i << 8) | 0x04);
413 data = read_byte(0xa000,addr) & mask;
414 if (data > 0)
415 attr |= (0x01 << i);
416 }
417 break;
418 case CGA:
419 addr = (col >> 2) + (row >> 1) * 80;
420 if (row & 1)
421 addr += 0x2000;
422 data = read_byte(0xb800, addr);
423 if (vga_modes[line].pixbits == 2)
424 attr = (data >> ((3 - (col & 0x03)) * 2)) & 0x03;
425 else
426 attr = (data >> (7 - (col & 0x07))) & 0x01;
427 break;
428 case LINEAR8:
429 addr = col + row * (read_word(BIOSMEM_SEG, BIOSMEM_NB_COLS) * 8);
430 attr = read_byte(0xa000, addr);
431 break;
432 default:
433#ifdef VGA_DEBUG
434 unimplemented();
435#endif
436 attr = 0;
437 }
438 *(uint8_t STACK_BASED *)pixel = attr;
439}
440
441
442
443// --------------------------------------------------------------------------------------------
444/*static*/ void biosfn_perform_gray_scale_summing(uint16_t start, uint16_t count)
445{uint8_t r,g,b;
446 uint16_t i;
447 uint16_t index;
448
449 inb(VGAREG_ACTL_RESET);
450 outb(VGAREG_ACTL_ADDRESS,0x00);
451
452 for( index = 0; index < count; index++ )
453 {
454 // set read address and switch to read mode
455 outb(VGAREG_DAC_READ_ADDRESS,start);
456 // get 6-bit wide RGB data values
457 r=inb( VGAREG_DAC_DATA );
458 g=inb( VGAREG_DAC_DATA );
459 b=inb( VGAREG_DAC_DATA );
460
461 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
462 i = ( ( 77*r + 151*g + 28*b ) + 0x80 ) >> 8;
463
464 if(i>0x3f)i=0x3f;
465
466 // set write address and switch to write mode
467 outb(VGAREG_DAC_WRITE_ADDRESS,start);
468 // write new intensity value
469 outb( VGAREG_DAC_DATA, i&0xff );
470 outb( VGAREG_DAC_DATA, i&0xff );
471 outb( VGAREG_DAC_DATA, i&0xff );
472 start++;
473 }
474 inb(VGAREG_ACTL_RESET);
475 outb(VGAREG_ACTL_ADDRESS,0x20);
476#ifdef VBOX
477 inb(VGAREG_ACTL_RESET);
478#endif /* VBOX */
479}
480
481// --------------------------------------------------------------------------------------------
482static void biosfn_set_cursor_shape(uint8_t CH, uint8_t CL)
483{uint16_t cheight,curs,crtc_addr;
484 uint8_t modeset_ctl;
485
486 CH&=0x3f;
487 CL&=0x1f;
488
489 curs=(CH<<8)+CL;
490 write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE,curs);
491
492 modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
493 cheight = read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT);
494 if((modeset_ctl&0x01) && (cheight>8) && (CL<8) && (CH<0x20))
495 {
496 if(CL!=(CH+1))
497 {
498 CH = ((CH+1) * cheight / 8) -1;
499 }
500 else
501 {
502 CH = ((CL+1) * cheight / 8) - 2;
503 }
504 CL = ((CL+1) * cheight / 8) - 1;
505 }
506
507 // CTRC regs 0x0a and 0x0b
508 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
509 outb(crtc_addr,0x0a);
510 outb(crtc_addr+1,CH);
511 outb(crtc_addr,0x0b);
512 outb(crtc_addr+1,CL);
513}
514
515// --------------------------------------------------------------------------------------------
516static void biosfn_set_cursor_pos (uint8_t page, uint16_t cursor)
517{
518 uint8_t xcurs,ycurs,current;
519 uint16_t nbcols,nbrows,address,crtc_addr;
520
521 // Should not happen...
522 if(page>7)return;
523
524 // Bios cursor pos
525 write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*page, cursor);
526
527 // Set the hardware cursor
528 current=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
529 if(page==current)
530 {
531 // Get the dimensions
532 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
533 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
534
535 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
536
537 // Calculate the address knowing nbcols nbrows and page num
538 address=SCREEN_IO_START(nbcols,nbrows,page)+xcurs+ycurs*nbcols;
539
540 // CRTC regs 0x0e and 0x0f
541 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
542 outb(crtc_addr,0x0e);
543 outb(crtc_addr+1,(address&0xff00)>>8);
544 outb(crtc_addr,0x0f);
545 outb(crtc_addr+1,address&0x00ff);
546 }
547}
548
549// --------------------------------------------------------------------------------------------
550static void biosfn_set_active_page(uint8_t page)
551{
552 uint16_t cursor,dummy,crtc_addr;
553 uint16_t nbcols,nbrows,address;
554 uint8_t mode,line;
555
556 if(page>7)return;
557
558 // Get the mode
559 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
560 line=find_vga_entry(mode);
561 if(line==0xFF)return;
562
563 // Get pos curs pos for the right page
564 vga_get_cursor_pos(page,&dummy,&cursor);
565
566 if(vga_modes[line].class==TEXT)
567 {
568 // Get the dimensions
569 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
570 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
571
572 // Calculate the address knowing nbcols nbrows and page num
573 address=SCREEN_MEM_START(nbcols,nbrows,page);
574 write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START,address);
575
576 // Start address
577 address=SCREEN_IO_START(nbcols,nbrows,page);
578 }
579 else
580 {
581 address = page * (*(uint16_t *)&video_param_table[line_to_vpti[line]].slength_l);
582 }
583
584 // CRTC regs 0x0c and 0x0d
585 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
586 outb(crtc_addr,0x0c);
587 outb(crtc_addr+1,(address&0xff00)>>8);
588 outb(crtc_addr,0x0d);
589 outb(crtc_addr+1,address&0x00ff);
590
591 // And change the BIOS page
592 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE,page);
593
594#ifdef VGA_DEBUG
595 printf("Set active page %02x address %04x\n",page,address);
596#endif
597
598 // Display the cursor, now the page is active
599 biosfn_set_cursor_pos(page,cursor);
600}
601
602//@todo: Evaluate whether executing INT 10h is the right thing here
603extern void vga_font_set(uint8_t function, uint8_t data);
604#pragma aux vga_font_set = \
605 "mov ah, 11h" \
606 "int 10h" \
607 parm [al] [bl];
608
609// ============================================================================================
610//
611// BIOS functions
612//
613// ============================================================================================
614
615void biosfn_set_video_mode(uint8_t mode)
616{// mode: Bit 7 is 1 if no clear screen
617
618 // Should we clear the screen ?
619 uint8_t noclearmem=mode&0x80;
620 uint8_t line,mmask,*palette,vpti;
621 uint16_t i,twidth,theightm1,cheight;
622 uint8_t modeset_ctl,video_ctl,vga_switches;
623 uint16_t crtc_addr;
624
625#ifdef VBE
626 if (vbe_has_vbe_display()) {
627 // Force controller into VGA mode
628 outb(VGAREG_SEQU_ADDRESS,7);
629 outb(VGAREG_SEQU_DATA,0x00);
630 }
631#endif // def VBE
632
633 // The real mode
634 mode=mode&0x7f;
635
636 // Display switching is not supported, and mono monitors aren't either.
637 // Requests to set mode 7 (mono) must set mode 0 instead (color).
638 if (mode == 7)
639 mode = 0;
640
641 // find the entry in the video modes
642 line=find_vga_entry(mode);
643
644#ifdef VGA_DEBUG
645 printf("mode search %02x found line %02x\n",mode,line);
646#endif
647
648 if(line==0xFF)
649 return;
650
651 vpti=line_to_vpti[line];
652 twidth=video_param_table[vpti].twidth;
653 theightm1=video_param_table[vpti].theightm1;
654 cheight=video_param_table[vpti].cheight;
655
656 // Read the bios vga control
657 video_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
658
659 // Read the bios vga switches
660 vga_switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
661
662 // Read the bios mode set control
663 modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
664
665 // Then we know the number of lines
666// FIXME
667
668 // if palette loading (bit 3 of modeset ctl = 0)
669 if((modeset_ctl&0x08)==0)
670 {// Set the PEL mask
671 outb(VGAREG_PEL_MASK,vga_modes[line].pelmask);
672
673 // Set the whole dac always, from 0
674 outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
675
676 // From which palette
677 switch(vga_modes[line].dacmodel)
678 {case 0:
679 palette=&palette0[0];
680 break;
681 case 1:
682 palette=&palette1[0];
683 break;
684 case 2:
685 palette=&palette2[0];
686 break;
687 case 3:
688 palette=&palette3[0];
689 break;
690 }
691 // Always 256*3 values
692 for(i=0;i<0x0100;i++)
693 {if(i<=dac_regs[vga_modes[line].dacmodel])
694 {outb(VGAREG_DAC_DATA,palette[(i*3)+0]);
695 outb(VGAREG_DAC_DATA,palette[(i*3)+1]);
696 outb(VGAREG_DAC_DATA,palette[(i*3)+2]);
697 }
698 else
699 {outb(VGAREG_DAC_DATA,0);
700 outb(VGAREG_DAC_DATA,0);
701 outb(VGAREG_DAC_DATA,0);
702 }
703 }
704 if((modeset_ctl&0x02)==0x02)
705 {
706 biosfn_perform_gray_scale_summing(0x00, 0x100);
707 }
708 }
709
710 // Reset Attribute Ctl flip-flop
711 inb(VGAREG_ACTL_RESET);
712
713 // Set Attribute Ctl
714 for(i=0;i<=0x13;i++)
715 {outb(VGAREG_ACTL_ADDRESS,i);
716 outb(VGAREG_ACTL_WRITE_DATA,video_param_table[vpti].actl_regs[i]);
717 }
718 outb(VGAREG_ACTL_ADDRESS,0x14);
719 outb(VGAREG_ACTL_WRITE_DATA,0x00);
720
721 // Set Sequencer Ctl
722 outb(VGAREG_SEQU_ADDRESS,0);
723 outb(VGAREG_SEQU_DATA,0x03);
724 for(i=1;i<=4;i++)
725 {outb(VGAREG_SEQU_ADDRESS,i);
726 outb(VGAREG_SEQU_DATA,video_param_table[vpti].sequ_regs[i - 1]);
727 }
728
729 // Set Grafx Ctl
730 for(i=0;i<=8;i++)
731 {outb(VGAREG_GRDC_ADDRESS,i);
732 outb(VGAREG_GRDC_DATA,video_param_table[vpti].grdc_regs[i]);
733 }
734
735 // Set CRTC address VGA or MDA
736 crtc_addr=vga_modes[line].memmodel==MTEXT?VGAREG_MDA_CRTC_ADDRESS:VGAREG_VGA_CRTC_ADDRESS;
737
738 // Disable CRTC write protection
739 outw(crtc_addr,0x0011);
740 // Set CRTC regs
741 for(i=0;i<=0x18;i++)
742 {outb(crtc_addr,i);
743 outb(crtc_addr+1,video_param_table[vpti].crtc_regs[i]);
744 }
745
746 // Set the misc register
747 outb(VGAREG_WRITE_MISC_OUTPUT,video_param_table[vpti].miscreg);
748
749 // Enable video
750 outb(VGAREG_ACTL_ADDRESS,0x20);
751 inb(VGAREG_ACTL_RESET);
752
753 if(noclearmem==0x00)
754 {
755 if(vga_modes[line].class==TEXT)
756 {
757 memsetw(vga_modes[line].sstart,0,0x0720,0x4000); // 32k
758 }
759 else
760 {
761 if(mode<0x0d)
762 {
763 memsetw(vga_modes[line].sstart,0,0x0000,0x4000); // 32k
764 }
765 else
766 {
767 outb( VGAREG_SEQU_ADDRESS, 0x02 );
768 mmask = inb( VGAREG_SEQU_DATA );
769 outb( VGAREG_SEQU_DATA, 0x0f ); // all planes
770 memsetw(vga_modes[line].sstart,0,0x0000,0x8000); // 64k
771 outb( VGAREG_SEQU_DATA, mmask );
772 }
773 }
774 }
775
776 // Set the BIOS mem
777 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,mode);
778 write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS,twidth);
779 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE,*(uint16_t *)&video_param_table[vpti].slength_l);
780 write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS,crtc_addr);
781 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS,theightm1);
782 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,cheight);
783 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|noclearmem));
784 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,0xF9);
785 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x7f);
786
787 // FIXME We nearly have the good tables. to be reworked
788 write_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,0x08); // 8 is VGA should be ok for now
789 write_dword(BIOSMEM_SEG,BIOSMEM_VS_POINTER, (uint32_t)(void __far *)video_save_pointer_table);
790
791 // FIXME
792 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x00); // Unavailable on vanilla vga, but...
793 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x00); // Unavailable on vanilla vga, but...
794
795 // Set cursor shape
796 if(vga_modes[line].class==TEXT)
797 {
798 biosfn_set_cursor_shape(0x06,0x07);
799 }
800
801 // Set cursor pos for page 0..7
802 for(i=0;i<8;i++)
803 biosfn_set_cursor_pos(i,0x0000);
804
805 // Set active page 0
806 biosfn_set_active_page(0x00);
807
808 // Write the fonts in memory
809 if(vga_modes[line].class==TEXT)
810 {
811 vga_font_set(0x04, 0); /* Load 8x16 font into page 0. */
812 vga_font_set(0x03, 0); /* Select font page mode 0. */
813 }
814
815 // Set the ints 0x1F and 0x43
816 set_int_vector(0x1f, vgafont8+128*8);
817
818 switch(cheight)
819 {case 8:
820 set_int_vector(0x43, vgafont8);
821 break;
822 case 14:
823 set_int_vector(0x43, vgafont14);
824 break;
825 case 16:
826 set_int_vector(0x43, vgafont16);
827 break;
828 }
829}
830
831// --------------------------------------------------------------------------------------------
832static void vgamem_copy_pl4(uint8_t xstart, uint8_t ysrc, uint8_t ydest,
833 uint8_t cols, uint8_t nbcols, uint8_t cheight)
834{
835 uint16_t src,dest;
836 uint8_t i;
837
838 src=ysrc*cheight*nbcols+xstart;
839 dest=ydest*cheight*nbcols+xstart;
840 outw(VGAREG_GRDC_ADDRESS, 0x0105);
841 for(i=0;i<cheight;i++)
842 {
843 memcpyb(0xa000,dest+i*nbcols,0xa000,src+i*nbcols,cols);
844 }
845 outw(VGAREG_GRDC_ADDRESS, 0x0005);
846}
847
848// --------------------------------------------------------------------------------------------
849static void vgamem_fill_pl4(uint8_t xstart, uint8_t ystart, uint8_t cols,
850 uint8_t nbcols, uint8_t cheight, uint8_t attr)
851{
852 uint16_t dest;
853 uint8_t i;
854
855 dest=ystart*cheight*nbcols+xstart;
856 outw(VGAREG_GRDC_ADDRESS, 0x0205);
857 for(i=0;i<cheight;i++)
858 {
859 memsetb(0xa000,dest+i*nbcols,attr,cols);
860 }
861 outw(VGAREG_GRDC_ADDRESS, 0x0005);
862}
863
864// --------------------------------------------------------------------------------------------
865static void vgamem_copy_cga(uint8_t xstart, uint8_t ysrc, uint8_t ydest,
866 uint8_t cols, uint8_t nbcols, uint8_t cheight)
867{
868 uint16_t src,dest;
869 uint8_t i;
870
871 src=((ysrc*cheight*nbcols)>>1)+xstart;
872 dest=((ydest*cheight*nbcols)>>1)+xstart;
873 for(i=0;i<cheight;i++)
874 {
875 if (i & 1)
876 memcpyb(0xb800,0x2000+dest+(i>>1)*nbcols,0xb800,0x2000+src+(i>>1)*nbcols,cols);
877 else
878 memcpyb(0xb800,dest+(i>>1)*nbcols,0xb800,src+(i>>1)*nbcols,cols);
879 }
880}
881
882// --------------------------------------------------------------------------------------------
883static void vgamem_fill_cga(uint8_t xstart, uint8_t ystart, uint8_t cols,
884 uint8_t nbcols, uint8_t cheight, uint8_t attr)
885{
886 uint16_t dest;
887 uint8_t i;
888
889 dest=((ystart*cheight*nbcols)>>1)+xstart;
890 for(i=0;i<cheight;i++)
891 {
892 if (i & 1)
893 memsetb(0xb800,0x2000+dest+(i>>1)*nbcols,attr,cols);
894 else
895 memsetb(0xb800,dest+(i>>1)*nbcols,attr,cols);
896 }
897}
898
899// --------------------------------------------------------------------------------------------
900static void biosfn_scroll(uint8_t nblines, uint8_t attr, uint8_t rul, uint8_t cul,
901 uint8_t rlr, uint8_t clr, uint8_t page, uint8_t dir)
902{
903 // page == 0xFF if current
904
905 uint8_t mode,line,cheight,bpp,cols;
906 uint16_t nbcols,nbrows,i;
907 uint16_t address;
908
909 if(rul>rlr)return;
910 if(cul>clr)return;
911
912 // Get the mode
913 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
914 line=find_vga_entry(mode);
915 if(line==0xFF)return;
916
917 // Get the dimensions
918 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
919 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
920
921 // Get the current page
922 if(page==0xFF)
923 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
924
925 if(rlr>=nbrows)rlr=nbrows-1;
926 if(clr>=nbcols)clr=nbcols-1;
927 if(nblines>nbrows)nblines=0;
928 cols=clr-cul+1;
929
930 if(vga_modes[line].class==TEXT)
931 {
932 // Compute the address
933 address=SCREEN_MEM_START(nbcols,nbrows,page);
934#ifdef VGA_DEBUG
935 printf("Scroll, address %04x (%04x %04x %02x)\n",address,nbrows,nbcols,page);
936#endif
937
938 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
939 {
940 memsetw(vga_modes[line].sstart,address,(uint16_t)attr*0x100+' ',nbrows*nbcols);
941 }
942 else
943 {// if Scroll up
944 if(dir==SCROLL_UP)
945 {for(i=rul;i<=rlr;i++)
946 {
947 if((i+nblines>rlr)||(nblines==0))
948 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(uint16_t)attr*0x100+' ',cols);
949 else
950 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i+nblines)*nbcols+cul)*2,cols);
951 }
952 }
953 else
954 {for(i=rlr;i>=rul;i--)
955 {
956 if((i<rul+nblines)||(nblines==0))
957 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(uint16_t)attr*0x100+' ',cols);
958 else
959 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i-nblines)*nbcols+cul)*2,cols);
960 if (i>rlr) break;
961 }
962 }
963 }
964 }
965 else
966 {
967 // FIXME gfx mode not complete
968 cheight=video_param_table[line_to_vpti[line]].cheight;
969 switch(vga_modes[line].memmodel)
970 {
971 case PLANAR4:
972 case PLANAR1:
973 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
974 {
975 outw(VGAREG_GRDC_ADDRESS, 0x0205);
976 memsetb(vga_modes[line].sstart,0,attr,nbrows*nbcols*cheight);
977 outw(VGAREG_GRDC_ADDRESS, 0x0005);
978 }
979 else
980 {// if Scroll up
981 if(dir==SCROLL_UP)
982 {for(i=rul;i<=rlr;i++)
983 {
984 if((i+nblines>rlr)||(nblines==0))
985 vgamem_fill_pl4(cul,i,cols,nbcols,cheight,attr);
986 else
987 vgamem_copy_pl4(cul,i+nblines,i,cols,nbcols,cheight);
988 }
989 }
990 else
991 {for(i=rlr;i>=rul;i--)
992 {
993 if((i<rul+nblines)||(nblines==0))
994 vgamem_fill_pl4(cul,i,cols,nbcols,cheight,attr);
995 else
996 vgamem_copy_pl4(cul,i,i-nblines,cols,nbcols,cheight);
997 if (i>rlr) break;
998 }
999 }
1000 }
1001 break;
1002 case CGA:
1003 bpp=vga_modes[line].pixbits;
1004 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1005 {
1006 memsetb(vga_modes[line].sstart,0,attr,nbrows*nbcols*cheight*bpp);
1007 }
1008 else
1009 {
1010 if(bpp==2)
1011 {
1012 cul<<=1;
1013 cols<<=1;
1014 nbcols<<=1;
1015 }
1016 // if Scroll up
1017 if(dir==SCROLL_UP)
1018 {for(i=rul;i<=rlr;i++)
1019 {
1020 if((i+nblines>rlr)||(nblines==0))
1021 vgamem_fill_cga(cul,i,cols,nbcols,cheight,attr);
1022 else
1023 vgamem_copy_cga(cul,i+nblines,i,cols,nbcols,cheight);
1024 }
1025 }
1026 else
1027 {for(i=rlr;i>=rul;i--)
1028 {
1029 if((i<rul+nblines)||(nblines==0))
1030 vgamem_fill_cga(cul,i,cols,nbcols,cheight,attr);
1031 else
1032 vgamem_copy_cga(cul,i,i-nblines,cols,nbcols,cheight);
1033 if (i>rlr) break;
1034 }
1035 }
1036 }
1037 break;
1038#ifdef VGA_DEBUG
1039 default:
1040 printf("Scroll in graphics mode ");
1041 unimplemented();
1042#endif
1043 }
1044 }
1045}
1046
1047// --------------------------------------------------------------------------------------------
1048static void write_gfx_char_pl4(uint8_t car, uint8_t attr, uint8_t xcurs,
1049 uint8_t ycurs, uint8_t nbcols, uint8_t cheight)
1050{
1051 uint8_t i,j,mask;
1052 uint8_t *fdata;
1053 uint16_t addr,dest,src;
1054
1055 switch(cheight)
1056 {case 14:
1057 fdata = &vgafont14;
1058 break;
1059 case 16:
1060 fdata = &vgafont16;
1061 break;
1062 default:
1063 fdata = &vgafont8;
1064 }
1065 addr=xcurs+ycurs*cheight*nbcols;
1066 src = car * cheight;
1067 outw(VGAREG_SEQU_ADDRESS, 0x0f02);
1068 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1069 if(attr&0x80)
1070 {
1071 outw(VGAREG_GRDC_ADDRESS, 0x1803);
1072 }
1073 else
1074 {
1075 outw(VGAREG_GRDC_ADDRESS, 0x0003);
1076 }
1077 for(i=0;i<cheight;i++)
1078 {
1079 dest=addr+i*nbcols;
1080 for(j=0;j<8;j++)
1081 {
1082 mask=0x80>>j;
1083 outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08);
1084 read_byte(0xa000,dest);
1085 if(fdata[src+i]&mask)
1086 {
1087 write_byte(0xa000,dest,attr&0x0f);
1088 }
1089 else
1090 {
1091 write_byte(0xa000,dest,0x00);
1092 }
1093 }
1094 }
1095 outw(VGAREG_GRDC_ADDRESS, 0xff08);
1096 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1097 outw(VGAREG_GRDC_ADDRESS, 0x0003);
1098}
1099
1100// --------------------------------------------------------------------------------------------
1101static void write_gfx_char_cga(uint8_t car, uint8_t attr, uint8_t xcurs,
1102 uint8_t ycurs, uint8_t nbcols, uint8_t bpp)
1103{
1104 uint8_t i,j,mask,data;
1105 uint8_t *fdata;
1106 uint16_t addr,dest,src;
1107
1108 fdata = &vgafont8;
1109 addr=(xcurs*bpp)+ycurs*320;
1110 src = car * 8;
1111 for(i=0;i<8;i++)
1112 {
1113 dest=addr+(i>>1)*80;
1114 if (i & 1) dest += 0x2000;
1115 mask = 0x80;
1116 if (bpp == 1)
1117 {
1118 if (attr & 0x80)
1119 {
1120 data = read_byte(0xb800,dest);
1121 }
1122 else
1123 {
1124 data = 0x00;
1125 }
1126 for(j=0;j<8;j++)
1127 {
1128 if (fdata[src+i] & mask)
1129 {
1130 if (attr & 0x80)
1131 {
1132 data ^= (attr & 0x01) << (7-j);
1133 }
1134 else
1135 {
1136 data |= (attr & 0x01) << (7-j);
1137 }
1138 }
1139 mask >>= 1;
1140 }
1141 write_byte(0xb800,dest,data);
1142 }
1143 else
1144 {
1145 while (mask > 0)
1146 {
1147 if (attr & 0x80)
1148 {
1149 data = read_byte(0xb800,dest);
1150 }
1151 else
1152 {
1153 data = 0x00;
1154 }
1155 for(j=0;j<4;j++)
1156 {
1157 if (fdata[src+i] & mask)
1158 {
1159 if (attr & 0x80)
1160 {
1161 data ^= (attr & 0x03) << ((3-j)*2);
1162 }
1163 else
1164 {
1165 data |= (attr & 0x03) << ((3-j)*2);
1166 }
1167 }
1168 mask >>= 1;
1169 }
1170 write_byte(0xb800,dest,data);
1171 dest += 1;
1172 }
1173 }
1174 }
1175}
1176
1177// --------------------------------------------------------------------------------------------
1178static void write_gfx_char_lin(uint8_t car, uint8_t attr, uint8_t xcurs,
1179 uint8_t ycurs, uint8_t nbcols)
1180{
1181 uint8_t i,j,mask,data;
1182 uint8_t *fdata;
1183 uint16_t addr,dest,src;
1184
1185 fdata = &vgafont8;
1186 addr=xcurs*8+ycurs*nbcols*64;
1187 src = car * 8;
1188 for(i=0;i<8;i++)
1189 {
1190 dest=addr+i*nbcols*8;
1191 mask = 0x80;
1192 for(j=0;j<8;j++)
1193 {
1194 data = 0x00;
1195 if (fdata[src+i] & mask)
1196 {
1197 data = attr;
1198 }
1199 write_byte(0xa000,dest+j,data);
1200 mask >>= 1;
1201 }
1202 }
1203}
1204
1205// --------------------------------------------------------------------------------------------
1206static void biosfn_write_char_attr(uint8_t car, uint8_t page, uint8_t attr, uint16_t count)
1207{
1208 uint8_t cheight,xcurs,ycurs,mode,line,bpp;
1209 uint16_t nbcols,nbrows,address;
1210 uint16_t cursor,dummy;
1211
1212 // Get the mode
1213 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1214 line=find_vga_entry(mode);
1215 if(line==0xFF)return;
1216
1217 // Get the cursor pos for the page
1218 vga_get_cursor_pos(page,&dummy,&cursor);
1219 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1220
1221 // Get the dimensions
1222 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1223 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1224
1225 if(vga_modes[line].class==TEXT)
1226 {
1227 // Compute the address
1228 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1229
1230 dummy=((uint16_t)attr<<8)+car;
1231 memsetw(vga_modes[line].sstart,address,dummy,count);
1232 }
1233 else
1234 {
1235 // FIXME gfx mode not complete
1236 cheight=video_param_table[line_to_vpti[line]].cheight;
1237 bpp=vga_modes[line].pixbits;
1238 while((count-->0) && (xcurs<nbcols))
1239 {
1240 switch(vga_modes[line].memmodel)
1241 {
1242 case PLANAR4:
1243 case PLANAR1:
1244 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1245 break;
1246 case CGA:
1247 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1248 break;
1249 case LINEAR8:
1250 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1251 break;
1252#ifdef VGA_DEBUG
1253 default:
1254 unimplemented();
1255#endif
1256 }
1257 xcurs++;
1258 }
1259 }
1260}
1261
1262// --------------------------------------------------------------------------------------------
1263static void biosfn_write_char_only(uint8_t car, uint8_t page, uint8_t attr, uint16_t count)
1264{
1265 uint8_t cheight,xcurs,ycurs,mode,line,bpp;
1266 uint16_t nbcols,nbrows,address;
1267 uint16_t cursor,dummy;
1268
1269 // Get the mode
1270 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1271 line=find_vga_entry(mode);
1272 if(line==0xFF)return;
1273
1274 // Get the cursor pos for the page
1275 vga_get_cursor_pos(page,&dummy,&cursor);
1276 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1277
1278 // Get the dimensions
1279 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1280 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1281
1282 if(vga_modes[line].class==TEXT)
1283 {
1284 // Compute the address
1285 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1286
1287 while(count-->0)
1288 {write_byte(vga_modes[line].sstart,address,car);
1289 address+=2;
1290 }
1291 }
1292 else
1293 {
1294 // FIXME gfx mode not complete
1295 cheight=video_param_table[line_to_vpti[line]].cheight;
1296 bpp=vga_modes[line].pixbits;
1297 while((count-->0) && (xcurs<nbcols))
1298 {
1299 switch(vga_modes[line].memmodel)
1300 {
1301 case PLANAR4:
1302 case PLANAR1:
1303 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1304 break;
1305 case CGA:
1306 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1307 break;
1308 case LINEAR8:
1309 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1310 break;
1311#ifdef VGA_DEBUG
1312 default:
1313 unimplemented();
1314#endif
1315 }
1316 xcurs++;
1317 }
1318 }
1319}
1320
1321// --------------------------------------------------------------------------------------------
1322static void biosfn_write_pixel(uint8_t BH, uint8_t AL, uint16_t CX, uint16_t DX)
1323{
1324 uint8_t mode,line,mask,attr,data;
1325 uint16_t addr;
1326
1327 // Get the mode
1328 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1329 line=find_vga_entry(mode);
1330 if(line==0xFF)return;
1331 if(vga_modes[line].class==TEXT)return;
1332
1333 switch(vga_modes[line].memmodel)
1334 {
1335 case PLANAR4:
1336 case PLANAR1:
1337 addr = CX/8+DX*read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1338 mask = 0x80 >> (CX & 0x07);
1339 outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08);
1340 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1341 data = read_byte(0xa000,addr);
1342 if (AL & 0x80)
1343 {
1344 outw(VGAREG_GRDC_ADDRESS, 0x1803);
1345 }
1346 write_byte(0xa000,addr,AL);
1347 outw(VGAREG_GRDC_ADDRESS, 0xff08);
1348 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1349 outw(VGAREG_GRDC_ADDRESS, 0x0003);
1350 break;
1351 case CGA:
1352 if(vga_modes[line].pixbits==2)
1353 {
1354 addr=(CX>>2)+(DX>>1)*80;
1355 }
1356 else
1357 {
1358 addr=(CX>>3)+(DX>>1)*80;
1359 }
1360 if (DX & 1) addr += 0x2000;
1361 data = read_byte(0xb800,addr);
1362 if(vga_modes[line].pixbits==2)
1363 {
1364 attr = (AL & 0x03) << ((3 - (CX & 0x03)) * 2);
1365 mask = 0x03 << ((3 - (CX & 0x03)) * 2);
1366 }
1367 else
1368 {
1369 attr = (AL & 0x01) << (7 - (CX & 0x07));
1370 mask = 0x01 << (7 - (CX & 0x07));
1371 }
1372 if (AL & 0x80)
1373 {
1374 data ^= attr;
1375 }
1376 else
1377 {
1378 data &= ~mask;
1379 data |= attr;
1380 }
1381 write_byte(0xb800,addr,data);
1382 break;
1383 case LINEAR8:
1384 addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
1385 write_byte(0xa000,addr,AL);
1386 break;
1387#ifdef VGA_DEBUG
1388 default:
1389 unimplemented();
1390#endif
1391 }
1392}
1393
1394// --------------------------------------------------------------------------------------------
1395static void biosfn_write_teletype(uint8_t car, uint8_t page, uint8_t attr, uint8_t flag)
1396{// flag = WITH_ATTR / NO_ATTR
1397
1398 uint8_t cheight,xcurs,ycurs,mode,line,bpp;
1399 uint16_t nbcols,nbrows,address;
1400 uint16_t cursor,dummy;
1401
1402 // special case if page is 0xff, use current page
1403 if(page==0xff)
1404 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1405
1406 // Get the mode
1407 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1408 line=find_vga_entry(mode);
1409 if(line==0xFF)return;
1410
1411 // Get the cursor pos for the page
1412 vga_get_cursor_pos(page,&dummy,&cursor);
1413 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1414
1415 // Get the dimensions
1416 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1417 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1418
1419 switch(car)
1420 {
1421 case '\a': // ASCII 0x07, BEL
1422 //FIXME should beep
1423 break;
1424
1425 case '\b': // ASCII 0x08, BS
1426 if(xcurs>0)xcurs--;
1427 break;
1428
1429 case '\n': // ASCII 0x0A, LF
1430 ycurs++;
1431 break;
1432
1433 case '\r': // ASCII 0x0D, CR
1434 xcurs=0;
1435 break;
1436
1437 default:
1438
1439 if(vga_modes[line].class==TEXT)
1440 {
1441 // Compute the address
1442 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1443
1444 // Write the char
1445 write_byte(vga_modes[line].sstart,address,car);
1446
1447 if(flag==WITH_ATTR)
1448 write_byte(vga_modes[line].sstart,address+1,attr);
1449 }
1450 else
1451 {
1452 // FIXME gfx mode not complete
1453 cheight=video_param_table[line_to_vpti[line]].cheight;
1454 bpp=vga_modes[line].pixbits;
1455 switch(vga_modes[line].memmodel)
1456 {
1457 case PLANAR4:
1458 case PLANAR1:
1459 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1460 break;
1461 case CGA:
1462 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1463 break;
1464 case LINEAR8:
1465 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1466 break;
1467#ifdef VGA_DEBUG
1468 default:
1469 unimplemented();
1470#endif
1471 }
1472 }
1473 xcurs++;
1474 // Do we need to wrap ?
1475 if(xcurs==nbcols)
1476 {xcurs=0;
1477 ycurs++;
1478 }
1479 }
1480
1481 // Do we need to scroll ?
1482 if(ycurs==nbrows)
1483 {
1484 if(vga_modes[line].class==TEXT)
1485 {
1486 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+(ycurs-1)*nbcols)*2;
1487 attr=read_byte(vga_modes[line].sstart,address+1);
1488 biosfn_scroll(0x01,attr,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
1489 }
1490 else
1491 {
1492 biosfn_scroll(0x01,0x00,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
1493 }
1494 ycurs-=1;
1495 }
1496
1497 // Set the cursor for the page
1498 cursor=ycurs; cursor<<=8; cursor+=xcurs;
1499 biosfn_set_cursor_pos(page,cursor);
1500}
1501
1502// --------------------------------------------------------------------------------------------
1503static void get_font_access(void)
1504{
1505 outw(VGAREG_SEQU_ADDRESS, 0x0100);
1506 outw(VGAREG_SEQU_ADDRESS, 0x0402);
1507 outw(VGAREG_SEQU_ADDRESS, 0x0704);
1508 outw(VGAREG_SEQU_ADDRESS, 0x0300);
1509 outw(VGAREG_GRDC_ADDRESS, 0x0204);
1510 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1511 outw(VGAREG_GRDC_ADDRESS, 0x0406);
1512}
1513
1514static void release_font_access(void)
1515{
1516 outw(VGAREG_SEQU_ADDRESS, 0x0100);
1517 outw(VGAREG_SEQU_ADDRESS, 0x0302);
1518 outw(VGAREG_SEQU_ADDRESS, 0x0304);
1519 outw(VGAREG_SEQU_ADDRESS, 0x0300);
1520 outw(VGAREG_GRDC_ADDRESS, (((0x0a | ((inb(VGAREG_READ_MISC_OUTPUT) & 0x01) << 2)) << 8) | 0x06));
1521 outw(VGAREG_GRDC_ADDRESS, 0x0004);
1522 outw(VGAREG_GRDC_ADDRESS, 0x1005);
1523}
1524
1525static void set_scan_lines(uint8_t lines)
1526{
1527 uint16_t crtc_addr,cols,vde;
1528 uint8_t crtc_r9,ovl,rows;
1529
1530 crtc_addr = read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1531 outb(crtc_addr, 0x09);
1532 crtc_r9 = inb(crtc_addr+1);
1533 crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1);
1534 outb(crtc_addr+1, crtc_r9);
1535 if(lines==8)
1536 {
1537 biosfn_set_cursor_shape(0x06,0x07);
1538 }
1539 else
1540 {
1541 biosfn_set_cursor_shape(lines-4,lines-3);
1542 }
1543 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, lines);
1544 outb(crtc_addr, 0x12);
1545 vde = inb(crtc_addr+1);
1546 outb(crtc_addr, 0x07);
1547 ovl = inb(crtc_addr+1);
1548 vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
1549 rows = vde / lines;
1550 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, rows-1);
1551 cols = read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1552 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, rows * cols * 2);
1553}
1554
1555static void biosfn_load_text_user_pat(uint8_t AL, uint16_t ES, uint16_t BP, uint16_t CX,
1556 uint16_t DX, uint8_t BL, uint8_t BH)
1557{
1558 uint16_t blockaddr,dest,i,src;
1559
1560 get_font_access();
1561 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
1562 for(i=0;i<CX;i++)
1563 {
1564 src = BP + i * BH;
1565 dest = blockaddr + (DX + i) * 32;
1566 memcpyb(0xA000, dest, ES, src, BH);
1567 }
1568 release_font_access();
1569 if(AL>=0x10)
1570 {
1571 set_scan_lines(BH);
1572 }
1573}
1574
1575static void biosfn_load_text_8_14_pat(uint8_t AL, uint8_t BL)
1576{
1577 uint16_t blockaddr,dest,i,src;
1578
1579 get_font_access();
1580 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
1581 for(i=0;i<0x100;i++)
1582 {
1583 src = i * 14;
1584 dest = blockaddr + i * 32;
1585 memcpyb(0xA000, dest, 0xC000, (uint16_t)vgafont14+src, 14);
1586 }
1587 release_font_access();
1588 if(AL>=0x10)
1589 {
1590 set_scan_lines(14);
1591 }
1592}
1593
1594static void biosfn_load_text_8_8_pat(uint8_t AL, uint8_t BL)
1595{
1596 uint16_t blockaddr,dest,i,src;
1597
1598 get_font_access();
1599 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
1600 for(i=0;i<0x100;i++)
1601 {
1602 src = i * 8;
1603 dest = blockaddr + i * 32;
1604 memcpyb(0xA000, dest, 0xC000, (uint16_t)vgafont8+src, 8);
1605 }
1606 release_font_access();
1607 if(AL>=0x10)
1608 {
1609 set_scan_lines(8);
1610 }
1611}
1612
1613// --------------------------------------------------------------------------------------------
1614static void biosfn_load_text_8_16_pat(uint8_t AL, uint8_t BL)
1615{
1616 uint16_t blockaddr,dest,i,src;
1617
1618 get_font_access();
1619 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
1620 for(i=0;i<0x100;i++)
1621 {
1622 src = i * 16;
1623 dest = blockaddr + i * 32;
1624 memcpyb(0xA000, dest, 0xC000, (uint16_t)vgafont16+src, 16);
1625 }
1626 release_font_access();
1627 if(AL>=0x10)
1628 {
1629 set_scan_lines(16);
1630 }
1631}
1632
1633static void biosfn_load_gfx_8_8_chars(uint16_t ES, uint16_t BP)
1634{
1635#ifdef VGA_DEBUG
1636 unimplemented();
1637#endif
1638}
1639static void biosfn_load_gfx_user_chars(uint16_t ES, uint16_t BP, uint16_t CX,
1640 uint8_t BL, uint8_t DL)
1641{
1642#ifdef VGA_DEBUG
1643 unimplemented();
1644#endif
1645}
1646static void biosfn_load_gfx_8_14_chars(uint8_t BL)
1647{
1648#ifdef VGA_DEBUG
1649 unimplemented();
1650#endif
1651}
1652static void biosfn_load_gfx_8_8_dd_chars(uint8_t BL)
1653{
1654#ifdef VGA_DEBUG
1655 unimplemented();
1656#endif
1657}
1658static void biosfn_load_gfx_8_16_chars(uint8_t BL)
1659{
1660#ifdef VGA_DEBUG
1661 unimplemented();
1662#endif
1663}
1664// --------------------------------------------------------------------------------------------
1665static void biosfn_alternate_prtsc(void)
1666{
1667#ifdef VGA_DEBUG
1668 unimplemented();
1669#endif
1670}
1671
1672// --------------------------------------------------------------------------------------------
1673static void biosfn_switch_video_interface (AL,ES,DX) uint8_t AL;uint16_t ES;uint16_t DX;
1674{
1675#ifdef VGA_DEBUG
1676 unimplemented();
1677#endif
1678}
1679static void biosfn_enable_video_refresh_control(uint8_t AL)
1680{
1681#ifdef VGA_DEBUG
1682 unimplemented();
1683#endif
1684}
1685
1686// --------------------------------------------------------------------------------------------
1687static void biosfn_write_string(uint8_t flag, uint8_t page, uint8_t attr, uint16_t count,
1688 uint8_t row, uint8_t col, uint16_t seg, uint16_t offset)
1689{
1690 uint16_t newcurs,oldcurs,dummy;
1691 uint8_t car;
1692
1693 // Read curs info for the page
1694 vga_get_cursor_pos(page,&dummy,&oldcurs);
1695
1696 // if row=0xff special case : use current cursor position
1697 if(row==0xff)
1698 {col=oldcurs&0x00ff;
1699 row=(oldcurs&0xff00)>>8;
1700 }
1701
1702 newcurs=row; newcurs<<=8; newcurs+=col;
1703 biosfn_set_cursor_pos(page,newcurs);
1704
1705 while(count--!=0)
1706 {
1707 car=read_byte(seg,offset++);
1708 if((flag&0x02)!=0)
1709 attr=read_byte(seg,offset++);
1710
1711 biosfn_write_teletype(car,page,attr,WITH_ATTR);
1712 }
1713
1714 // Set back curs pos
1715 if((flag&0x01)==0)
1716 biosfn_set_cursor_pos(page,oldcurs);
1717}
1718
1719// --------------------------------------------------------------------------------------------
1720static void biosfn_read_state_info(uint16_t BX, uint16_t ES, uint16_t DI)
1721{
1722 // Address of static functionality table
1723 write_dword(ES,DI+0x00, (uint32_t)(void __far *)static_functionality);
1724
1725 // Hard coded copy from BIOS area. Should it be cleaner ?
1726 memcpyb(ES,DI+0x04,BIOSMEM_SEG,0x49,30);
1727 memcpyb(ES,DI+0x22,BIOSMEM_SEG,0x84,3);
1728
1729 write_byte(ES,DI+0x25,read_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX));
1730 write_byte(ES,DI+0x26,0);
1731 write_byte(ES,DI+0x27,16);
1732 write_byte(ES,DI+0x28,0);
1733 write_byte(ES,DI+0x29,8);
1734 write_byte(ES,DI+0x2a,2);
1735 write_byte(ES,DI+0x2b,0);
1736 write_byte(ES,DI+0x2c,0);
1737 write_byte(ES,DI+0x31,3);
1738 write_byte(ES,DI+0x32,0);
1739
1740 memsetb(ES,DI+0x33,0,13);
1741}
1742
1743// --------------------------------------------------------------------------------------------
1744uint16_t biosfn_read_video_state_size2(uint16_t state)
1745{
1746 uint16_t size;
1747
1748 size = 0;
1749 if (state & 1)
1750 size += 0x46;
1751
1752 if (state & 2)
1753 size += (5 + 8 + 5) * 2 + 6;
1754
1755 if (state & 4)
1756 size += 3 + 256 * 3 + 1;
1757
1758 //@todo: Is this supposed to be in 1-byte or 64-byte units?
1759 return size;
1760}
1761
1762static void vga_get_video_state_size(uint16_t state, uint16_t STACK_BASED *size)
1763{
1764 *size = biosfn_read_video_state_size2(state);
1765}
1766
1767uint16_t biosfn_save_video_state(uint16_t CX, uint16_t ES, uint16_t BX)
1768{
1769 uint16_t i, crtc_addr, ar_index;
1770
1771 crtc_addr = read_word(BIOSMEM_SEG, BIOSMEM_CRTC_ADDRESS);
1772 if (CX & 1) {
1773 write_byte(ES, BX, inb(VGAREG_SEQU_ADDRESS)); BX++;
1774 write_byte(ES, BX, inb(crtc_addr)); BX++;
1775 write_byte(ES, BX, inb(VGAREG_GRDC_ADDRESS)); BX++;
1776 inb(VGAREG_ACTL_RESET);
1777 ar_index = inb(VGAREG_ACTL_ADDRESS);
1778 write_byte(ES, BX, ar_index); BX++;
1779 write_byte(ES, BX, inb(VGAREG_READ_FEATURE_CTL)); BX++;
1780
1781 for(i=1;i<=4;i++){
1782 outb(VGAREG_SEQU_ADDRESS, i);
1783 write_byte(ES, BX, inb(VGAREG_SEQU_DATA)); BX++;
1784 }
1785 outb(VGAREG_SEQU_ADDRESS, 0);
1786 write_byte(ES, BX, inb(VGAREG_SEQU_DATA)); BX++;
1787
1788 for(i=0;i<=0x18;i++) {
1789 outb(crtc_addr,i);
1790 write_byte(ES, BX, inb(crtc_addr+1)); BX++;
1791 }
1792
1793 for(i=0;i<=0x13;i++) {
1794 inb(VGAREG_ACTL_RESET);
1795 outb(VGAREG_ACTL_ADDRESS, i | (ar_index & 0x20));
1796 write_byte(ES, BX, inb(VGAREG_ACTL_READ_DATA)); BX++;
1797 }
1798 inb(VGAREG_ACTL_RESET);
1799
1800 for(i=0;i<=8;i++) {
1801 outb(VGAREG_GRDC_ADDRESS,i);
1802 write_byte(ES, BX, inb(VGAREG_GRDC_DATA)); BX++;
1803 }
1804
1805 write_word(ES, BX, crtc_addr); BX+= 2;
1806
1807 /* XXX: read plane latches */
1808 write_byte(ES, BX, 0); BX++;
1809 write_byte(ES, BX, 0); BX++;
1810 write_byte(ES, BX, 0); BX++;
1811 write_byte(ES, BX, 0); BX++;
1812 }
1813 if (CX & 2) {
1814 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE)); BX++;
1815 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)); BX += 2;
1816 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE)); BX += 2;
1817 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)); BX += 2;
1818 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)); BX++;
1819 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT)); BX += 2;
1820 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL)); BX++;
1821 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES)); BX++;
1822 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)); BX++;
1823 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE)); BX += 2;
1824 for(i=0;i<8;i++) {
1825 write_word(ES, BX, read_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*i));
1826 BX += 2;
1827 }
1828 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START)); BX += 2;
1829 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE)); BX++;
1830 /* current font */
1831 write_word(ES, BX, read_word(0, 0x1f * 4)); BX += 2;
1832 write_word(ES, BX, read_word(0, 0x1f * 4 + 2)); BX += 2;
1833 write_word(ES, BX, read_word(0, 0x43 * 4)); BX += 2;
1834 write_word(ES, BX, read_word(0, 0x43 * 4 + 2)); BX += 2;
1835 }
1836 if (CX & 4) {
1837 /* XXX: check this */
1838 write_byte(ES, BX, inb(VGAREG_DAC_STATE)); BX++; /* read/write mode dac */
1839 write_byte(ES, BX, inb(VGAREG_DAC_WRITE_ADDRESS)); BX++; /* pix address */
1840 write_byte(ES, BX, inb(VGAREG_PEL_MASK)); BX++;
1841 // Set the whole dac always, from 0
1842 outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
1843 for(i=0;i<256*3;i++) {
1844 write_byte(ES, BX, inb(VGAREG_DAC_DATA)); BX++;
1845 }
1846 write_byte(ES, BX, 0); BX++; /* color select register */
1847 }
1848 return BX;
1849}
1850
1851uint16_t biosfn_restore_video_state(uint16_t CX, uint16_t ES, uint16_t BX)
1852{
1853 uint16_t i, crtc_addr, v, addr1, ar_index;
1854
1855 if (CX & 1) {
1856 // Reset Attribute Ctl flip-flop
1857 inb(VGAREG_ACTL_RESET);
1858
1859 crtc_addr = read_word(ES, BX + 0x40);
1860 addr1 = BX;
1861 BX += 5;
1862
1863 for(i=1;i<=4;i++){
1864 outb(VGAREG_SEQU_ADDRESS, i);
1865 outb(VGAREG_SEQU_DATA, read_byte(ES, BX)); BX++;
1866 }
1867 outb(VGAREG_SEQU_ADDRESS, 0);
1868 outb(VGAREG_SEQU_DATA, read_byte(ES, BX)); BX++;
1869
1870 // Disable CRTC write protection
1871 outw(crtc_addr,0x0011);
1872 // Set CRTC regs
1873 for(i=0;i<=0x18;i++) {
1874 if (i != 0x11) {
1875 outb(crtc_addr,i);
1876 outb(crtc_addr+1, read_byte(ES, BX));
1877 }
1878 BX++;
1879 }
1880 // select crtc base address
1881 v = inb(VGAREG_READ_MISC_OUTPUT) & ~0x01;
1882 if (crtc_addr == 0x3d4)
1883 v |= 0x01;
1884 outb(VGAREG_WRITE_MISC_OUTPUT, v);
1885
1886 // enable write protection if needed
1887 outb(crtc_addr, 0x11);
1888 outb(crtc_addr+1, read_byte(ES, BX - 0x18 + 0x11));
1889
1890 // Set Attribute Ctl
1891 ar_index = read_byte(ES, addr1 + 0x03);
1892 inb(VGAREG_ACTL_RESET);
1893 for(i=0;i<=0x13;i++) {
1894 outb(VGAREG_ACTL_ADDRESS, i | (ar_index & 0x20));
1895 outb(VGAREG_ACTL_WRITE_DATA, read_byte(ES, BX)); BX++;
1896 }
1897 outb(VGAREG_ACTL_ADDRESS, ar_index);
1898 inb(VGAREG_ACTL_RESET);
1899
1900 for(i=0;i<=8;i++) {
1901 outb(VGAREG_GRDC_ADDRESS,i);
1902 outb(VGAREG_GRDC_DATA, read_byte(ES, BX)); BX++;
1903 }
1904 BX += 2; /* crtc_addr */
1905 BX += 4; /* plane latches */
1906
1907 outb(VGAREG_SEQU_ADDRESS, read_byte(ES, addr1)); addr1++;
1908 outb(crtc_addr, read_byte(ES, addr1)); addr1++;
1909 outb(VGAREG_GRDC_ADDRESS, read_byte(ES, addr1)); addr1++;
1910 addr1++;
1911 outb(crtc_addr - 0x4 + 0xa, read_byte(ES, addr1)); addr1++;
1912 }
1913 if (CX & 2) {
1914 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE, read_byte(ES, BX)); BX++;
1915 write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS, read_word(ES, BX)); BX += 2;
1916 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, read_word(ES, BX)); BX += 2;
1917 write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS, read_word(ES, BX)); BX += 2;
1918 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, read_byte(ES, BX)); BX++;
1919 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, read_word(ES, BX)); BX += 2;
1920 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL, read_byte(ES, BX)); BX++;
1921 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES, read_byte(ES, BX)); BX++;
1922 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL, read_byte(ES, BX)); BX++;
1923 write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE, read_word(ES, BX)); BX += 2;
1924 for(i=0;i<8;i++) {
1925 write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*i, read_word(ES, BX));
1926 BX += 2;
1927 }
1928 write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START, read_word(ES, BX)); BX += 2;
1929 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE, read_byte(ES, BX)); BX++;
1930 /* current font */
1931 write_word(0, 0x1f * 4, read_word(ES, BX)); BX += 2;
1932 write_word(0, 0x1f * 4 + 2, read_word(ES, BX)); BX += 2;
1933 write_word(0, 0x43 * 4, read_word(ES, BX)); BX += 2;
1934 write_word(0, 0x43 * 4 + 2, read_word(ES, BX)); BX += 2;
1935 }
1936 if (CX & 4) {
1937 BX++;
1938 v = read_byte(ES, BX); BX++;
1939 outb(VGAREG_PEL_MASK, read_byte(ES, BX)); BX++;
1940 // Set the whole dac always, from 0
1941 outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
1942 for(i=0;i<256*3;i++) {
1943 outb(VGAREG_DAC_DATA, read_byte(ES, BX)); BX++;
1944 }
1945 BX++;
1946 outb(VGAREG_DAC_WRITE_ADDRESS, v);
1947 }
1948 return BX;
1949}
1950
1951// ============================================================================================
1952//
1953// Video Utils
1954//
1955// ============================================================================================
1956
1957// --------------------------------------------------------------------------------------------
1958static uint8_t find_vga_entry(uint8_t mode)
1959{
1960 uint8_t i,line=0xFF;
1961 for(i=0;i<=MODE_MAX;i++)
1962 if(vga_modes[i].svgamode==mode)
1963 {line=i;
1964 break;
1965 }
1966 return line;
1967}
1968
1969/* =========================================================== */
1970/*
1971 * Misc Utils
1972*/
1973/* =========================================================== */
1974
1975uint8_t read_byte(uint16_t seg, uint16_t offset)
1976{
1977 return( *(seg:>(uint8_t *)offset) );
1978}
1979
1980void write_byte(uint16_t seg, uint16_t offset, uint8_t data)
1981{
1982 *(seg:>(uint8_t *)offset) = data;
1983}
1984
1985uint16_t read_word(uint16_t seg, uint16_t offset)
1986{
1987 return( *(seg:>(uint16_t *)offset) );
1988}
1989
1990void write_word(uint16_t seg, uint16_t offset, uint16_t data)
1991{
1992 *(seg:>(uint16_t *)offset) = data;
1993}
1994
1995uint32_t read_dword(uint16_t seg, uint16_t offset)
1996{
1997 return( *(seg:>(uint32_t *)offset) );
1998}
1999
2000void write_dword(uint16_t seg, uint16_t offset, uint32_t data)
2001{
2002 *(seg:>(uint32_t *)offset) = data;
2003}
2004
2005#ifdef VGA_DEBUG
2006void __cdecl unimplemented()
2007{
2008 printf("--> Unimplemented\n");
2009}
2010
2011void __cdecl unknown()
2012{
2013 printf("--> Unknown int10\n");
2014}
2015
2016#undef VBE_PRINTF_PORT
2017#define VBE_PRINTF_PORT 0x504
2018
2019// --------------------------------------------------------------------------------------------
2020void __cdecl printf(char *s, ...)
2021{
2022 char c;
2023 Boolean in_format;
2024 unsigned format_width, i;
2025 uint16_t arg, digit, nibble;
2026 uint16_t STACK_BASED *arg_ptr;
2027
2028 arg_ptr = (uint16_t STACK_BASED *)&s;
2029
2030 in_format = 0;
2031 format_width = 0;
2032
2033 while (c = *s) {
2034 if (c == '%') {
2035 in_format = 1;
2036 format_width = 0;
2037 } else if (in_format) {
2038 if ((c >= '0') && (c <= '9')) {
2039 format_width = (format_width * 10) + (c - '0');
2040 } else if (c == 'x') {
2041 arg_ptr++; // increment to next arg
2042 arg = *arg_ptr;
2043 if (format_width == 0)
2044 format_width = 4;
2045 i = 0;
2046 digit = format_width - 1;
2047 for (i = 0; i < format_width; i++) {
2048 nibble = (arg >> (4 * digit)) & 0x000f;
2049 if (nibble <= 9)
2050 outb(VBE_PRINTF_PORT, nibble + '0');
2051 else
2052 outb(VBE_PRINTF_PORT, (nibble - 10) + 'A');
2053 digit--;
2054 }
2055 in_format = 0;
2056 }
2057 //else if (c == 'd') {
2058 // in_format = 0;
2059 // }
2060 } else {
2061 outb(VBE_PRINTF_PORT, c);
2062 }
2063 ++s;
2064 }
2065}
2066#endif
2067
2068//@todo: rearrange, call only from VBE module?
2069extern void vbe_biosfn_return_controller_information(uint16_t STACK_BASED *AX, uint16_t ES, uint16_t DI);
2070extern void vbe_biosfn_return_mode_information(uint16_t STACK_BASED *AX, uint16_t CX, uint16_t ES, uint16_t DI);
2071extern void vbe_biosfn_set_mode(uint16_t STACK_BASED *AX, uint16_t BX, uint16_t ES, uint16_t DI);
2072extern void vbe_biosfn_save_restore_state(uint16_t STACK_BASED *AX, uint16_t CX, uint16_t DX, uint16_t ES, uint16_t STACK_BASED *BX);
2073
2074// --------------------------------------------------------------------------------------------
2075/*
2076 * int10 main dispatcher
2077 */
2078void __cdecl int10_func(uint16_t DI, uint16_t SI, uint16_t BP, uint16_t SP, uint16_t BX,
2079 uint16_t DX, uint16_t CX, uint16_t AX, uint16_t DS, uint16_t ES, uint16_t FLAGS)
2080{
2081
2082 // BIOS functions
2083 switch(GET_AH())
2084 {
2085 case 0x00:
2086 biosfn_set_video_mode(GET_AL());
2087 switch(GET_AL()&0x7F)
2088 {case 6:
2089 SET_AL(0x3F);
2090 break;
2091 case 0:
2092 case 1:
2093 case 2:
2094 case 3:
2095 case 4:
2096 case 5:
2097 case 7:
2098 SET_AL(0x30);
2099 break;
2100 default:
2101 SET_AL(0x20);
2102 }
2103 break;
2104 case 0x01:
2105 biosfn_set_cursor_shape(GET_CH(),GET_CL());
2106 break;
2107 case 0x02:
2108 biosfn_set_cursor_pos(GET_BH(),DX);
2109 break;
2110 case 0x03:
2111 vga_get_cursor_pos(GET_BH(), &CX, &DX);
2112 break;
2113 case 0x04:
2114 // Read light pen pos (unimplemented)
2115#ifdef VGA_DEBUG
2116 unimplemented();
2117#endif
2118 AX=0x00;
2119 BX=0x00;
2120 CX=0x00;
2121 DX=0x00;
2122 break;
2123 case 0x05:
2124 biosfn_set_active_page(GET_AL());
2125 break;
2126 case 0x06:
2127 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_UP);
2128 break;
2129 case 0x07:
2130 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_DOWN);
2131 break;
2132 case 0x08:
2133 vga_read_char_attr(GET_BH(), &AX);
2134 break;
2135 case 0x09:
2136 biosfn_write_char_attr(GET_AL(),GET_BH(),GET_BL(),CX);
2137 break;
2138 case 0x0A:
2139 biosfn_write_char_only(GET_AL(),GET_BH(),GET_BL(),CX);
2140 break;
2141 case 0x0C:
2142 biosfn_write_pixel(GET_BH(),GET_AL(),CX,DX);
2143 break;
2144 case 0x0D:
2145 vga_read_pixel(GET_BH(), CX, DX, &AX);
2146 break;
2147 case 0x0E:
2148 // Ralf Brown Interrupt list is WRONG on bh(page)
2149 // We do output only on the current page !
2150#ifdef VGA_DEBUG
2151 printf("write_teletype %02x\n", GET_AL());
2152#endif
2153
2154 biosfn_write_teletype(GET_AL(),0xff,GET_BL(),NO_ATTR);
2155 break;
2156 case 0x10:
2157 // All other functions of group AH=0x10 rewritten in assembler
2158 biosfn_perform_gray_scale_summing(BX,CX);
2159 break;
2160 case 0x11:
2161 switch(GET_AL())
2162 {
2163 case 0x00:
2164 case 0x10:
2165 biosfn_load_text_user_pat(GET_AL(),ES,BP,CX,DX,GET_BL(),GET_BH());
2166 break;
2167 case 0x01:
2168 case 0x11:
2169 biosfn_load_text_8_14_pat(GET_AL(),GET_BL());
2170 break;
2171 case 0x02:
2172 case 0x12:
2173 biosfn_load_text_8_8_pat(GET_AL(),GET_BL());
2174 break;
2175 case 0x04:
2176 case 0x14:
2177 biosfn_load_text_8_16_pat(GET_AL(),GET_BL());
2178 break;
2179 case 0x20:
2180 biosfn_load_gfx_8_8_chars(ES,BP);
2181 break;
2182 case 0x21:
2183 biosfn_load_gfx_user_chars(ES,BP,CX,GET_BL(),GET_DL());
2184 break;
2185 case 0x22:
2186 biosfn_load_gfx_8_14_chars(GET_BL());
2187 break;
2188 case 0x23:
2189 biosfn_load_gfx_8_8_dd_chars(GET_BL());
2190 break;
2191 case 0x24:
2192 biosfn_load_gfx_8_16_chars(GET_BL());
2193 break;
2194 case 0x30:
2195 vga_get_font_info(GET_BH(), &ES, &BP, &CX, &DX);
2196 break;
2197#ifdef VGA_DEBUG
2198 default:
2199 unknown();
2200#endif
2201 }
2202
2203 break;
2204 case 0x12:
2205 switch(GET_BL())
2206 {
2207 case 0x20:
2208 biosfn_alternate_prtsc();
2209 break;
2210 case 0x35:
2211 biosfn_switch_video_interface(GET_AL(),ES,DX);
2212 SET_AL(0x12);
2213 break;
2214 case 0x36:
2215 biosfn_enable_video_refresh_control(GET_AL());
2216 SET_AL(0x12);
2217 break;
2218#ifdef VGA_DEBUG
2219 default:
2220 unknown();
2221#endif
2222 }
2223 break;
2224 case 0x13:
2225 biosfn_write_string(GET_AL(),GET_BH(),GET_BL(),CX,GET_DH(),GET_DL(),ES,BP);
2226 break;
2227 case 0x1B:
2228 biosfn_read_state_info(BX,ES,DI);
2229 SET_AL(0x1B);
2230 break;
2231 case 0x1C:
2232 switch(GET_AL())
2233 {
2234 case 0x00:
2235 vga_get_video_state_size(CX,&BX);
2236 break;
2237 case 0x01:
2238 biosfn_save_video_state(CX,ES,BX);
2239 break;
2240 case 0x02:
2241 biosfn_restore_video_state(CX,ES,BX);
2242 break;
2243#ifdef VGA_DEBUG
2244 default:
2245 unknown();
2246#endif
2247 }
2248 SET_AL(0x1C);
2249 break;
2250
2251#ifdef VBE
2252 case 0x4f:
2253 if (vbe_has_vbe_display()) {
2254 switch(GET_AL())
2255 {
2256 case 0x00:
2257 vbe_biosfn_return_controller_information(&AX,ES,DI);
2258 break;
2259 case 0x01:
2260 vbe_biosfn_return_mode_information(&AX,CX,ES,DI);
2261 break;
2262 case 0x02:
2263 vbe_biosfn_set_mode(&AX,BX,ES,DI);
2264 break;
2265 case 0x04:
2266 vbe_biosfn_save_restore_state(&AX, CX, DX, ES, &BX);
2267 break;
2268 case 0x09:
2269 //FIXME
2270#ifdef VGA_DEBUG
2271 unimplemented();
2272#endif
2273 // function failed
2274 AX=0x100;
2275 break;
2276 case 0x0A:
2277 //FIXME
2278#ifdef VGA_DEBUG
2279 unimplemented();
2280#endif
2281 // function failed
2282 AX=0x100;
2283 break;
2284 default:
2285#ifdef VGA_DEBUG
2286 unknown();
2287#endif
2288 // function failed
2289 AX=0x100;
2290 }
2291 }
2292 else {
2293 // No VBE display
2294 AX=0x0100;
2295 }
2296 break;
2297#endif
2298
2299#ifdef VGA_DEBUG
2300 default:
2301 unknown();
2302#endif
2303 }
2304}
2305
2306#ifdef VBE
2307//#include "vbe.c"
2308#endif
2309
2310#ifdef CIRRUS
2311#include "clext.c"
2312#endif
2313
2314// --------------------------------------------------------------------------------------------
2315
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette