VirtualBox

source: vbox/trunk/src/VBox/Devices/Graphics/BIOS-new/vgabios.c@ 43116

Last change on this file since 43116 was 43116, checked in by vboxsync, 12 years ago

Devices/Graphics/BIOS-new: adjust licence comments to the default style

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

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