// ============================================================================================ /* * vgabios.c */ // ============================================================================================ // // Copyright (C) 2001-2008 the LGPL VGABios developers Team // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // ============================================================================================ // // This VGA Bios is specific to the plex86/bochs Emulated VGA card. // You can NOT drive any physical vga card with it. // // ============================================================================================ // // This file contains code ripped from : // - rombios.c of plex86 // // This VGA Bios contains fonts from : // - fntcol16.zip (c) by Joseph Gil avalable at : // ftp://ftp.simtel.net/pub/simtelnet/msdos/screen/fntcol16.zip // These fonts are public domain // // This VGA Bios is based on information taken from : // - Kevin Lawton's vga card emulation for bochs/plex86 // - Ralf Brown's interrupts list available at http://www.cs.cmu.edu/afs/cs/user/ralf/pub/WWW/files.html // - Finn Thogersons' VGADOC4b available at http://home.worldonline.dk/~finth/ // - Michael Abrash's Graphics Programming Black Book // - Francois Gervais' book "programmation des cartes graphiques cga-ega-vga" edited by sybex // - DOSEMU 1.0.1 source code for several tables values and formulas // // Thanks for patches, comments and ideas to : // - techt@pikeonline.net // // ============================================================================================ #include "vgabios.h" #ifdef VBE #include "vbe.h" #endif #define USE_BX_INFO /* Declares */ static Bit8u read_byte(); static Bit16u read_word(); static void write_byte(); static void write_word(); static Bit8u inb(); static Bit16u inw(); static void outb(); static void outw(); static Bit16u get_SS(); // Output static void printf(); static void unimplemented(); static void unknown(); static Bit8u find_vga_entry(); static void memsetb(); static void memsetw(); static void memcpyb(); static void memcpyw(); static void biosfn_set_video_mode(); static void biosfn_set_cursor_shape(); static void biosfn_set_cursor_pos(); static void biosfn_get_cursor_pos(); static void biosfn_set_active_page(); static void biosfn_scroll(); static void biosfn_read_char_attr(); static void biosfn_write_char_attr(); static void biosfn_write_char_only(); static void biosfn_write_pixel(); static void biosfn_read_pixel(); static void biosfn_write_teletype(); static void biosfn_perform_gray_scale_summing(); static void biosfn_load_text_user_pat(); static void biosfn_load_text_8_14_pat(); static void biosfn_load_text_8_8_pat(); static void biosfn_load_text_8_16_pat(); static void biosfn_load_gfx_8_8_chars(); static void biosfn_load_gfx_user_chars(); static void biosfn_load_gfx_8_14_chars(); static void biosfn_load_gfx_8_8_dd_chars(); static void biosfn_load_gfx_8_16_chars(); static void biosfn_get_font_info(); static void biosfn_alternate_prtsc(); static void biosfn_switch_video_interface(); static void biosfn_enable_video_refresh_control(); static void biosfn_write_string(); static void biosfn_read_state_info(); static void biosfn_read_video_state_size(); static Bit16u biosfn_save_video_state(); static Bit16u biosfn_restore_video_state(); extern Bit8u video_save_pointer_table[]; // This is for compiling with gcc2 and gcc3 #define ASM_START #asm #define ASM_END #endasm ASM_START MACRO SET_INT_VECTOR push ds xor ax, ax mov ds, ax mov ax, ?3 mov ?1*4, ax mov ax, ?2 mov ?1*4+2, ax pop ds MEND ASM_END ASM_START .text .rom .org 0 use16 386 vgabios_start: .byte 0x55, 0xaa /* BIOS signature, required for BIOS extensions */ .byte 0x40 /* BIOS extension length in units of 512 bytes */ vgabios_entry_point: jmp vgabios_init_func #ifdef PCIBIOS .org 0x18 .word vgabios_pci_data #endif // Info from Bart Oldeman .org 0x1e .ascii "IBM" .byte 0x00 vgabios_name: .ascii "Plex86/Bochs VGABios" #ifdef PCIBIOS .ascii " (PCI)" #endif .ascii " " .byte 0x00 vgabios_version: #ifndef VGABIOS_VERS .ascii "current-cvs" #else .ascii VGABIOS_VERS #endif .ascii " " vgabios_date: .ascii VGABIOS_DATE .byte 0x0a,0x0d .byte 0x00 vgabios_copyright: .ascii "(C) 2008 the LGPL VGABios developers Team" .byte 0x0a,0x0d .byte 0x00 vgabios_license: .ascii "This VGA/VBE Bios is released under the GNU LGPL" .byte 0x0a,0x0d .byte 0x0a,0x0d .byte 0x00 vgabios_website: .ascii "Please visit :" .byte 0x0a,0x0d ;;.ascii " . http://www.plex86.org" ;;.byte 0x0a,0x0d .ascii " . http://bochs.sourceforge.net" .byte 0x0a,0x0d .ascii " . http://www.nongnu.org/vgabios" .byte 0x0a,0x0d .byte 0x0a,0x0d .byte 0x00 #ifdef PCIBIOS vgabios_pci_data: .ascii "PCIR" #ifdef CIRRUS .word 0x1013 .word 0x00b8 // CLGD5446 #else #ifdef PCI_VID .word PCI_VID .word PCI_DID #else #error "Unknown PCI vendor and device id" #endif #endif .word 0 // reserved .word 0x18 // dlen .byte 0 // revision .byte 0x0 // class,hi: vga display .word 0x300 // class,lo: vga display .word 0x40 // bios size .word 1 // revision .byte 0 // intel x86 data .byte 0x80 // last image .word 0 // reserved #endif ;; ============================================================================================ ;; ;; Init Entry point ;; ;; ============================================================================================ vgabios_init_func: ;; init vga card call init_vga_card ;; init basic bios vars call init_bios_area #ifdef VBE ;; init vbe functions call vbe_init #endif ;; set int10 vect SET_INT_VECTOR(0x10, #0xC000, #vgabios_int10_handler) #ifdef CIRRUS call cirrus_init #endif ;; display splash screen call _display_splash_screen ;; init video mode and clear the screen mov ax,#0x0003 int #0x10 ;; show info call _display_info #ifdef VBE ;; show vbe info call vbe_display_info #endif #ifdef CIRRUS ;; show cirrus info call cirrus_display_info #endif retf ASM_END /* * int10 handled here */ ASM_START vgabios_int10_handler: pushf #ifdef DEBUG push es push ds pusha mov bx, #0xc000 mov ds, bx call _int10_debugmsg popa pop ds pop es #endif cmp ah, #0x0f jne int10_test_1A call biosfn_get_video_mode jmp int10_end int10_test_1A: cmp ah, #0x1a jne int10_test_0B call biosfn_group_1A jmp int10_end int10_test_0B: cmp ah, #0x0b jne int10_test_1103 call biosfn_group_0B jmp int10_end int10_test_1103: cmp ax, #0x1103 jne int10_test_12 call biosfn_set_text_block_specifier jmp int10_end int10_test_12: cmp ah, #0x12 jne int10_test_101B cmp bl, #0x10 jne int10_test_BL30 call biosfn_get_ega_info jmp int10_end int10_test_BL30: cmp bl, #0x30 jne int10_test_BL31 call biosfn_select_vert_res jmp int10_end int10_test_BL31: cmp bl, #0x31 jne int10_test_BL32 call biosfn_enable_default_palette_loading jmp int10_end int10_test_BL32: cmp bl, #0x32 jne int10_test_BL33 call biosfn_enable_video_addressing jmp int10_end int10_test_BL33: cmp bl, #0x33 jne int10_test_BL34 call biosfn_enable_grayscale_summing jmp int10_end int10_test_BL34: cmp bl, #0x34 jne int10_normal call biosfn_enable_cursor_emulation jmp int10_end int10_test_101B: cmp ax, #0x101b je int10_normal cmp ah, #0x10 #ifndef V
# Copyright 2016 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# == Class: tripleo::profile::base::nova::api
#
# Nova API profile for tripleo
#
# [*bootstrap_node*]
#   (Optional) The hostname of the node responsible for bootstrapping tasks
#   Defaults to hiera('bootstrap_nodeid')
#
# [*certificates_specs*]
#   (Optional) The specifications to give to certmonger for the certificate(s)
#   it will create.
#   Example with hiera:
#     apache_certificates_specs:
#       httpd-internal_api:
#         hostname: <overcloud controller fqdn>
#         service_certificate: <service certificate path>
#         service_key: <service key path>
#         principal: "haproxy/<overcloud controller fqdn>"
#   Defaults to hiera('apache_certificate_specs', {}).
#
# [*enable_internal_tls*]
#   (Optional) Whether TLS in the internal network is enabled or not.
#   Defaults to hiera('enable_internal_tls', false)
#
# [*generate_service_certificates*]
#   (Optional) Whether or not certmonger will generate certificates for
#   HAProxy. This could be as many as specified by the $certificates_specs
#   variable.
#   Note that this doesn't configure the certificates in haproxy, it merely
#   creates the certificates.
#   Defaults to hiera('generate_service_certificate', false).
#
# [*nova_api_network*]
#   (Optional) The network name where the nova API endpoint is listening on.
#   This is set by t-h-t.
#   Defaults to hiera('nova_api_network', undef)
#
# [*nova_api_wsgi_enabled*]
#   (Optional) Whether or not deploy Nova API in WSGI with Apache.
#   Nova Team discourages it.
#   Defaults to hiera('nova_wsgi_enabled', false)
#
# [*step*]
#   (Optional) The current step in deployment. See tripleo-heat-templates
#   for more details.
#   Defaults to hiera('step')
#
class tripleo::profile::base::nova::api (
  $bootstrap_node                = hiera('bootstrap_nodeid', undef),
  $certificates_specs            = hiera('apache_certificates_specs', {}),
  $enable_internal_tls           = hiera('enable_internal_tls', false),
  $generate_service_certificates = hiera('generate_service_certificates', false),
  $nova_api_network              = hiera('nova_api_network', undef),
  $nova_api_wsgi_enabled         = hiera('nova_wsgi_enabled', false),
  $step                          = hiera('step'),
) {
  if $::hostname == downcase($bootstrap_node) {
    $sync_db = true
  } else {
    $sync_db = false
  }

  include ::tripleo::profile::base::nova
  include ::tripleo::profile::base::nova::authtoken

  if $step >= 3 and $sync_db {
    include ::nova::cell_v2::simple_setup
  }

  if $step >= 4 or ($step >= 3 and $sync_db) {

    class { '::nova::api':
      sync_db     => $sync_db,
      sync_db_api => $sync_db,
    }
    include ::nova::network::neutron
  }
  # Temporarily disable Nova API deployed in WSGI
  # https://bugs.launchpad.net/nova/+bug/1661360
  if $nova_api_wsgi_enabled {
    if $enable_internal_tls {
      if $generate_service_certificates {
        ensure_resources('tripleo::certmonger::httpd', $certificates_specs)
      }

      if !$nova_api_network {
        fail('nova_api_network is not set in the hieradata.')
      }
      $tls_certfile = $certificates_specs["httpd-${nova_api_network}"]['service_certificate']
      $tls_keyfile = $certificates_specs["httpd-${nova_api_network}"]['service_key']
    } else {
      $tls_certfile = undef
      $tls_keyfile = undef
    }
    if $step >= 4 or ($step >= 3 and $sync_db) {
      class { '::nova::wsgi::apache_api':
        ssl_cert => $tls_certfile,
        ssl_key  => $tls_keyfile,
      }
    }
  }

  if $step >= 5 {
    if hiera('nova_enable_db_purge', true) {
      include ::nova::cron::archive_deleted_rows
    }
    # At step 5, we consider all nova-compute services started and registred to nova-conductor
    # So we want to update Nova Cells database to be aware of these hosts by executing the
    # nova-cell_v2-discover_hosts command again.
    # Doing it on a single nova-api node to avoid race condition.
    if $sync_db {
      Exec<| title == 'nova-cell_v2-discover_hosts' |> { refreshonly => false }
    }
  }
}
memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',cols); else memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i-nblines)*nbcols+cul)*2,cols); if (i>rlr) break; } } } } else { // FIXME gfx mode not complete cheight=video_param_table[line_to_vpti[line]].cheight; switch(vga_modes[line].memmodel) { case PLANAR4: case PLANAR1: if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1) { outw(VGAREG_GRDC_ADDRESS, 0x0205); memsetb(vga_modes[line].sstart,0,attr,nbrows*nbcols*cheight); outw(VGAREG_GRDC_ADDRESS, 0x0005); } else {// if Scroll up if(dir==SCROLL_UP) {for(i=rul;i<=rlr;i++) { if((i+nblines>rlr)||(nblines==0)) vgamem_fill_pl4(cul,i,cols,nbcols,cheight,attr); else vgamem_copy_pl4(cul,i+nblines,i,cols,nbcols,cheight); } } else {for(i=rlr;i>=rul;i--) { if((irlr) break; } } } break; case CGA: bpp=vga_modes[line].pixbits; if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1) { memsetb(vga_modes[line].sstart,0,attr,nbrows*nbcols*cheight*bpp); } else { if(bpp==2) { cul<<=1; cols<<=1; nbcols<<=1; } // if Scroll up if(dir==SCROLL_UP) {for(i=rul;i<=rlr;i++) { if((i+nblines>rlr)||(nblines==0)) vgamem_fill_cga(cul,i,cols,nbcols,cheight,attr); else vgamem_copy_cga(cul,i+nblines,i,cols,nbcols,cheight); } } else {for(i=rlr;i>=rul;i--) { if((irlr) break; } } } break; #ifdef DEBUG default: printf("Scroll in graphics mode "); unimplemented(); #endif } } } // -------------------------------------------------------------------------------------------- static void biosfn_read_char_attr (page,car) Bit8u page;Bit16u *car; {Bit16u ss=get_SS(); Bit8u xcurs,ycurs,mode,line; Bit16u nbcols,nbrows,address; Bit16u cursor,dummy; // Get the mode mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE); line=find_vga_entry(mode); if(line==0xFF)return; // Get the cursor pos for the page biosfn_get_cursor_pos(page,&dummy,&cursor); xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8; // Get the dimensions nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1; nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS); if(vga_modes[line].class==TEXT) { // Compute the address address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2; write_word(ss,car,read_word(vga_modes[line].sstart,address)); } else { // FIXME gfx mode #ifdef DEBUG unimplemented(); #endif } } // -------------------------------------------------------------------------------------------- static void write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight) Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u cheight; { Bit8u i,j,mask; Bit8u *fdata; Bit16u addr,dest,src; switch(cheight) {case 14: fdata = &vgafont14; break; case 16: fdata = &vgafont16; break; default: fdata = &vgafont8; } addr=xcurs+ycurs*cheight*nbcols; src = car * cheight; outw(VGAREG_SEQU_ADDRESS, 0x0f02); outw(VGAREG_GRDC_ADDRESS, 0x0205); if(attr&0x80) { outw(VGAREG_GRDC_ADDRESS, 0x1803); } else { outw(VGAREG_GRDC_ADDRESS, 0x0003); } for(i=0;i>j; outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08); read_byte(0xa000,dest); if(fdata[src+i]&mask) { write_byte(0xa000,dest,attr&0x0f); } else { write_byte(0xa000,dest,0x00); } } } ASM_START mov dx, # VGAREG_GRDC_ADDRESS mov ax, #0xff08 out dx, ax mov ax, #0x0005 out dx, ax mov ax, #0x0003 out dx, ax ASM_END } // -------------------------------------------------------------------------------------------- static void write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp) Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u bpp; { Bit8u i,j,mask,data; Bit8u *fdata; Bit16u addr,dest,src; fdata = &vgafont8; addr=(xcurs*bpp)+ycurs*320; src = car * 8; for(i=0;i<8;i++) { dest=addr+(i>>1)*80; if (i & 1) dest += 0x2000; mask = 0x80; if (bpp == 1) { if (attr & 0x80) { data = read_byte(0xb800,dest); } else { data = 0x00; } for(j=0;j<8;j++) { if (fdata[src+i] & mask) { if (attr & 0x80) { data ^= (attr & 0x01) << (7-j); } else { data |= (attr & 0x01) << (7-j); } } mask >>= 1; } write_byte(0xb800,dest,data); } else { while (mask > 0) { if (attr & 0x80) { data = read_byte(0xb800,dest); } else { data = 0x00; } for(j=0;j<4;j++) { if (fdata[src+i] & mask) { if (attr & 0x80) { data ^= (attr & 0x03) << ((3-j)*2); } else { data |= (attr & 0x03) << ((3-j)*2); } } mask >>= 1; } write_byte(0xb800,dest,data); dest += 1; } } } } // -------------------------------------------------------------------------------------------- static void write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols) Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols; { Bit8u i,j,mask,data; Bit8u *fdata; Bit16u addr,dest,src; fdata = &vgafont8; addr=xcurs*8+ycurs*nbcols*64; src = car * 8; for(i=0;i<8;i++) { dest=addr+i*nbcols*8; mask = 0x80; for(j=0;j<8;j++) { data = 0x00; if (fdata[src+i] & mask) { data = attr; } write_byte(0xa000,dest+j,data); mask >>= 1; } } } // -------------------------------------------------------------------------------------------- static void biosfn_write_char_attr (car,page,attr,count) Bit8u car;Bit8u page;Bit8u attr;Bit16u count; { Bit8u cheight,xcurs,ycurs,mode,line,bpp; Bit16u nbcols,nbrows,address; Bit16u cursor,dummy; // Get the mode mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE); line=find_vga_entry(mode); if(line==0xFF)return; // Get the cursor pos for the page biosfn_get_cursor_pos(page,&dummy,&cursor); xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8; // Get the dimensions nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1; nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS); if(vga_modes[line].class==TEXT) { // Compute the address address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2; dummy=((Bit16u)attr<<8)+car; memsetw(vga_modes[line].sstart,address,dummy,count); } else { // FIXME gfx mode not complete cheight=video_param_table[line_to_vpti[line]].cheight; bpp=vga_modes[line].pixbits; while((count-->0) && (xcurs>8; // Get the dimensions nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1; nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS); if(vga_modes[line].class==TEXT) { // Compute the address address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2; while(count-->0) {write_byte(vga_modes[line].sstart,address,car); address+=2; } } else { // FIXME gfx mode not complete cheight=video_param_table[line_to_vpti[line]].cheight; bpp=vga_modes[line].pixbits; while((count-->0) && (xcurs> (CX & 0x07); outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08); outw(VGAREG_GRDC_ADDRESS, 0x0205); data = read_byte(0xa000,addr); if (AL & 0x80) { outw(VGAREG_GRDC_ADDRESS, 0x1803); } write_byte(0xa000,addr,AL); ASM_START mov dx, # VGAREG_GRDC_ADDRESS mov ax, #0xff08 out dx, ax mov ax, #0x0005 out dx, ax mov ax, #0x0003 out dx, ax ASM_END break; case CGA: if(vga_modes[line].pixbits==2) { addr=(CX>>2)+(DX>>1)*80; } else { addr=(CX>>3)+(DX>>1)*80; } if (DX & 1) addr += 0x2000; data = read_byte(0xb800,addr); if(vga_modes[line].pixbits==2) { attr = (AL & 0x03) << ((3 - (CX & 0x03)) * 2); mask = 0x03 << ((3 - (CX & 0x03)) * 2); } else { attr = (AL & 0x01) << (7 - (CX & 0x07)); mask = 0x01 << (7 - (CX & 0x07)); } if (AL & 0x80) { data ^= attr; } else { data &= ~mask; data |= attr; } write_byte(0xb800,addr,data); break; case LINEAR8: addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8); write_byte(0xa000,addr,AL); break; #ifdef DEBUG default: unimplemented(); #endif } } // -------------------------------------------------------------------------------------------- static void biosfn_read_pixel (BH,CX,DX,AX) Bit8u BH;Bit16u CX;Bit16u DX;Bit16u *AX; { Bit8u mode,line,mask,attr,data,i; Bit16u addr; Bit16u ss=get_SS(); // Get the mode mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE); line=find_vga_entry(mode); if(line==0xFF)return; if(vga_modes[line].class==TEXT)return; switch(vga_modes[line].memmodel) { case PLANAR4: case PLANAR1: addr = CX/8+DX*read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS); mask = 0x80 >> (CX & 0x07); attr = 0x00; for(i=0;i<4;i++) { outw(VGAREG_GRDC_ADDRESS, (i << 8) | 0x04); data = read_byte(0xa000,addr) & mask; if (data > 0) attr |= (0x01 << i); } break; case CGA: addr=(CX>>2)+(DX>>1)*80; if (DX & 1) addr += 0x2000; data = read_byte(0xb800,addr); if(vga_modes[line].pixbits==2) { attr = (data >> ((3 - (CX & 0x03)) * 2)) & 0x03; } else { attr = (data >> (7 - (CX & 0x07))) & 0x01; } break; case LINEAR8: addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8); attr=read_byte(0xa000,addr); break; default: #ifdef DEBUG unimplemented(); #endif attr = 0; } write_word(ss,AX,(read_word(ss,AX) & 0xff00) | attr); } // -------------------------------------------------------------------------------------------- static void biosfn_write_teletype (car, page, attr, flag) Bit8u car;Bit8u page;Bit8u attr;Bit8u flag; {// flag = WITH_ATTR / NO_ATTR Bit8u cheight,xcurs,ycurs,mode,line,bpp; Bit16u nbcols,nbrows,address; Bit16u cursor,dummy; // special case if page is 0xff, use current page if(page==0xff) page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); // Get the mode mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE); line=find_vga_entry(mode); if(line==0xFF)return; // Get the cursor pos for the page biosfn_get_cursor_pos(page,&dummy,&cursor); xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8; // Get the dimensions nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1; nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS); switch(car) { case 7: //FIXME should beep break; case 8: if(xcurs>0)xcurs--; break; case '\r': xcurs=0; break; case '\n': ycurs++; break; case '\t': do { biosfn_write_teletype(' ',page,attr,flag); biosfn_get_cursor_pos(page,&dummy,&cursor); xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8; }while(xcurs%8==0); break; default: if(vga_modes[line].class==TEXT) { // Compute the address address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2; // Write the char write_byte(vga_modes[line].sstart,address,car); if(flag==WITH_ATTR) write_byte(vga_modes[line].sstart,address+1,attr); } else { // FIXME gfx mode not complete cheight=video_param_table[line_to_vpti[line]].cheight; bpp=vga_modes[line].pixbits; switch(vga_modes[line].memmodel) { case PLANAR4: case PLANAR1: write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight); break; case CGA: write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp); break; case LINEAR8: write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols); break; #ifdef DEBUG default: unimplemented(); #endif } } xcurs++; } // Do we need to wrap ? if(xcurs==nbcols) {xcurs=0; ycurs++; } // Do we need to scroll ? if(ycurs==nbrows) { if(vga_modes[line].class==TEXT) { address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+(ycurs-1)*nbcols)*2; attr=read_byte(vga_modes[line].sstart,address+1); biosfn_scroll(0x01,attr,0,0,nbrows-1,nbcols-1,page,SCROLL_UP); } else { biosfn_scroll(0x01,0x00,0,0,nbrows-1,nbcols-1,page,SCROLL_UP); } ycurs-=1; } // Set the cursor for the page cursor=ycurs; cursor<<=8; cursor+=xcurs; biosfn_set_cursor_pos(page,cursor); } // -------------------------------------------------------------------------------------------- ASM_START biosfn_get_video_mode: push ds mov ax, # BIOSMEM_SEG mov ds, ax push bx mov bx, # BIOSMEM_CURRENT_PAGE mov al, [bx] pop bx mov bh, al push bx mov bx, # BIOSMEM_VIDEO_CTL mov ah, [bx] and ah, #0x80 mov bx, # BIOSMEM_CURRENT_MODE mov al, [bx] or al, ah mov bx, # BIOSMEM_NB_COLS mov ah, [bx] pop bx pop ds ret ASM_END // -------------------------------------------------------------------------------------------- ASM_START biosfn_group_10: cmp al, #0x00 jne int10_test_1001 jmp biosfn_set_single_palette_reg int10_test_1001: cmp al, #0x01 jne int10_test_1002 jmp biosfn_set_overscan_border_color int10_test_1002: cmp al, #0x02 jne int10_test_1003 jmp biosfn_set_all_palette_reg int10_test_1003: cmp al, #0x03 jne int10_test_1007 jmp biosfn_toggle_intensity int10_test_1007: cmp al, #0x07 jne int10_test_1008 jmp biosfn_get_single_palette_reg int10_test_1008: cmp al, #0x08 jne int10_test_1009 jmp biosfn_read_overscan_border_color int10_test_1009: cmp al, #0x09 jne int10_test_1010 jmp biosfn_get_all_palette_reg int10_test_1010: cmp al, #0x10 jne int10_test_1012 jmp biosfn_set_single_dac_reg int10_test_1012: cmp al, #0x12 jne int10_test_1013 jmp biosfn_set_all_dac_reg int10_test_1013: cmp al, #0x13 jne int10_test_1015 jmp biosfn_select_video_dac_color_page int10_test_1015: cmp al, #0x15 jne int10_test_1017 jmp biosfn_read_single_dac_reg int10_test_1017: cmp al, #0x17 jne int10_test_1018 jmp biosfn_read_all_dac_reg int10_test_1018: cmp al, #0x18 jne int10_test_1019 jmp biosfn_set_pel_mask int10_test_1019: cmp al, #0x19 jne int10_test_101A jmp biosfn_read_pel_mask int10_test_101A: cmp al, #0x1a jne int10_group_10_unknown jmp biosfn_read_video_dac_state int10_group_10_unknown: #ifdef DEBUG call _unknown #endif ret biosfn_set_single_palette_reg: cmp bl, #0x14 ja no_actl_reg1 push ax push dx mov dx, # VGAREG_ACTL_RESET in al, dx mov dx, # VGAREG_ACTL_ADDRESS mov al, bl out dx, al mov al, bh out dx, al mov al, #0x20 out dx, al pop dx pop ax no_actl_reg1: ret ASM_END // -------------------------------------------------------------------------------------------- ASM_START biosfn_set_overscan_border_color: push bx mov bl, #0x11 call biosfn_set_single_palette_reg pop bx ret ASM_END // -------------------------------------------------------------------------------------------- ASM_START biosfn_set_all_palette_reg: push ax push bx push cx push dx mov bx, dx mov dx, # VGAREG_ACTL_RESET in al, dx mov cl, #0x00 mov dx, # VGAREG_ACTL_ADDRESS set_palette_loop: mov al, cl out dx, al seg es mov al, [bx] out dx, al inc bx inc cl cmp cl, #0x10 jne set_palette_loop mov al, #0x11 out dx, al seg es mov al, [bx] out dx, al mov al, #0x20 out dx, al pop dx pop cx pop bx pop ax ret ASM_END // -------------------------------------------------------------------------------------------- ASM_START biosfn_toggle_intensity: push ax push bx push dx mov dx, # VGAREG_ACTL_RESET in al, dx mov dx, # VGAREG_ACTL_ADDRESS mov al, #0x10 out dx, al mov dx, # VGAREG_ACTL_READ_DATA in al, dx and al, #0xf7 and bl, #0x01 shl bl, 3 or al, bl mov dx, # VGAREG_ACTL_ADDRESS out dx, al mov al, #0x20 out dx, al pop dx pop bx pop ax ret ASM_END // -------------------------------------------------------------------------------------------- ASM_START biosfn_get_single_palette_reg: cmp bl, #0x14 ja no_actl_reg2 push ax push dx mov dx, # VGAREG_ACTL_RESET in al, dx mov dx, # VGAREG_ACTL_ADDRESS mov al, bl out dx, al mov dx, # VGAREG_ACTL_READ_DATA in al, dx mov bh, al mov dx, # VGAREG_ACTL_RESET in al, dx mov dx, # VGAREG_ACTL_ADDRESS mov al, #0x20 out dx, al pop dx pop ax no_actl_reg2: ret ASM_END // -------------------------------------------------------------------------------------------- ASM_START biosfn_read_overscan_border_color: push ax push bx mov bl, #0x11 call biosfn_get_single_palette_reg mov al, bh pop bx mov bh, al pop ax ret ASM_END // -------------------------------------------------------------------------------------------- ASM_START biosfn_get_all_palette_reg: push ax push bx push cx push dx mov bx, dx mov cl, #0x00 get_palette_loop: mov dx, # VGAREG_ACTL_RESET in al, dx mov dx, # VGAREG_ACTL_ADDRESS mov al, cl out dx, al mov dx, # VGAREG_ACTL_READ_DATA in al, dx seg es mov [bx], al inc bx inc cl cmp cl, #0x10 jne get_palette_loop mov dx, # VGAREG_ACTL_RESET in al, dx mov dx, # VGAREG_ACTL_ADDRESS mov al, #0x11 out dx, al mov dx, # VGAREG_ACTL_READ_DATA in al, dx seg es mov [bx], al mov dx, # VGAREG_ACTL_RESET in al, dx mov dx, # VGAREG_ACTL_ADDRESS mov al, #0x20 out dx, al pop dx pop cx pop bx pop ax ret ASM_END // -------------------------------------------------------------------------------------------- ASM_START biosfn_set_single_dac_reg: push ax push dx mov dx, # VGAREG_DAC_WRITE_ADDRESS mov al, bl out dx, al mov dx, # VGAREG_DAC_DATA pop ax push ax mov al, ah out dx, al mov al, ch out dx, al mov al, cl out dx, al pop dx pop ax ret ASM_END // -------------------------------------------------------------------------------------------- ASM_START biosfn_set_all_dac_reg: push ax push bx push cx push dx mov dx, # VGAREG_DAC_WRITE_ADDRESS mov al, bl out dx, al pop dx push dx mov bx, dx mov dx, # VGAREG_DAC_DATA set_dac_loop: seg es mov al, [bx] out dx, al inc bx seg es mov al, [bx] out dx, al inc bx seg es mov al, [bx] out dx, al inc bx dec cx jnz set_dac_loop pop dx pop cx pop bx pop ax ret ASM_END // -------------------------------------------------------------------------------------------- ASM_START biosfn_select_video_dac_color_page: push ax push bx push dx mov dx, # VGAREG_ACTL_RESET in al, dx mov dx, # VGAREG_ACTL_ADDRESS mov al, #0x10 out dx, al mov dx, # VGAREG_ACTL_READ_DATA in al, dx and bl, #0x01 jnz set_dac_page and al, #0x7f shl bh, 7 or al, bh mov dx, # VGAREG_ACTL_ADDRESS out dx, al jmp set_actl_normal set_dac_page: push ax mov dx, # VGAREG_ACTL_RESET in al, dx mov dx, # VGAREG_ACTL_ADDRESS mov al, #0x14 out dx, al pop ax and al, #0x80 jnz set_dac_16_page shl bh, 2 set_dac_16_page: and bh, #0x0f mov al, bh out dx, al set_actl_normal: mov al, #0x20 out dx, al pop dx pop bx pop ax ret ASM_END // -------------------------------------------------------------------------------------------- ASM_START biosfn_read_single_dac_reg: push ax push dx mov dx, # VGAREG_DAC_READ_ADDRESS mov al, bl out dx, al pop ax mov ah, al mov dx, # VGAREG_DAC_DATA in al, dx xchg al, ah push ax in al, dx mov ch, al in al, dx mov cl, al pop dx pop ax ret ASM_END // -------------------------------------------------------------------------------------------- ASM_START biosfn_read_all_dac_reg: push ax push bx push cx push dx mov dx, # VGAREG_DAC_READ_ADDRESS mov al, bl out dx, al pop dx push dx mov bx, dx mov dx, # VGAREG_DAC_DATA read_dac_loop: in al, dx seg es mov [bx], al inc bx in al, dx seg es mov [bx], al inc bx in al, dx seg es mov [bx], al inc bx dec cx jnz read_dac_loop pop dx pop cx pop bx pop ax ret ASM_END // -------------------------------------------------------------------------------------------- ASM_START biosfn_set_pel_mask: push ax push dx mov dx, # VGAREG_PEL_MASK mov al, bl out dx, al pop dx pop ax ret ASM_END // -------------------------------------------------------------------------------------------- ASM_START biosfn_read_pel_mask: push ax push dx mov dx, # VGAREG_PEL_MASK in al, dx mov bl, al pop dx pop ax ret ASM_END // -------------------------------------------------------------------------------------------- ASM_START biosfn_read_video_dac_state: push ax push dx mov dx, # VGAREG_ACTL_RESET in al, dx mov dx, # VGAREG_ACTL_ADDRESS mov al, #0x10 out dx, al mov dx, # VGAREG_ACTL_READ_DATA in al, dx mov bl, al shr bl, 7 mov dx, # VGAREG_ACTL_RESET in al, dx mov dx, # VGAREG_ACTL_ADDRESS mov al, #0x14 out dx, al mov dx, # VGAREG_ACTL_READ_DATA in al, dx mov bh, al and bh, #0x0f test bl, #0x01 jnz get_dac_16_page shr bh, 2 get_dac_16_page: mov dx, # VGAREG_ACTL_RESET in al, dx mov dx, # VGAREG_ACTL_ADDRESS mov al, #0x20 out dx, al pop dx pop ax ret ASM_END // -------------------------------------------------------------------------------------------- static void biosfn_perform_gray_scale_summing (start,count) Bit16u start;Bit16u count; {Bit8u r,g,b; Bit16u i; Bit16u index; inb(VGAREG_ACTL_RESET); outb(VGAREG_ACTL_ADDRESS,0x00); for( index = 0; index < count; index++ ) { // set read address and switch to read mode outb(VGAREG_DAC_READ_ADDRESS,start); // get 6-bit wide RGB data values r=inb( VGAREG_DAC_DATA ); g=inb( VGAREG_DAC_DATA ); b=inb( VGAREG_DAC_DATA ); // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue ) i = ( ( 77*r + 151*g + 28*b ) + 0x80 ) >> 8; if(i>0x3f)i=0x3f; // set write address and switch to write mode outb(VGAREG_DAC_WRITE_ADDRESS,start); // write new intensity value outb( VGAREG_DAC_DATA, i&0xff ); outb( VGAREG_DAC_DATA, i&0xff ); outb( VGAREG_DAC_DATA, i&0xff ); start++; } inb(VGAREG_ACTL_RESET); outb(VGAREG_ACTL_ADDRESS,0x20); } // -------------------------------------------------------------------------------------------- static void get_font_access() { ASM_START mov dx, # VGAREG_SEQU_ADDRESS mov ax, #0x0100 out dx, ax mov ax, #0x0402 out dx, ax mov ax, #0x0704 out dx, ax mov ax, #0x0300 out dx, ax mov dx, # VGAREG_GRDC_ADDRESS mov ax, #0x0204 out dx, ax mov ax, #0x0005 out dx, ax mov ax, #0x0406 out dx, ax ASM_END } static void release_font_access() { ASM_START mov dx, # VGAREG_SEQU_ADDRESS mov ax, #0x0100 out dx, ax mov ax, #0x0302 out dx, ax mov ax, #0x0304 out dx, ax mov ax, #0x0300 out dx, ax mov dx, # VGAREG_READ_MISC_OUTPUT in al, dx and al, #0x01 shl al, 2 or al, #0x0a mov ah, al mov al, #0x06 mov dx, # VGAREG_GRDC_ADDRESS out dx, ax mov ax, #0x0004 out dx, ax mov ax, #0x1005 out dx, ax ASM_END } ASM_START idiv_u: xor dx,dx div bx ret ASM_END static void set_scan_lines(lines) Bit8u lines; { Bit16u crtc_addr,cols,page,vde; Bit8u crtc_r9,ovl,rows; crtc_addr = read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS); outb(crtc_addr, 0x09); crtc_r9 = inb(crtc_addr+1); crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1); outb(crtc_addr+1, crtc_r9); if(lines==8) { biosfn_set_cursor_shape(0x06,0x07); } else { biosfn_set_cursor_shape(lines-4,lines-3); } write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, lines); outb(crtc_addr, 0x12); vde = inb(crtc_addr+1); outb(crtc_addr, 0x07); ovl = inb(crtc_addr+1); vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1); rows = vde / lines; write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, rows-1); cols = read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS); write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, rows * cols * 2); } static void biosfn_load_text_user_pat (AL,ES,BP,CX,DX,BL,BH) Bit8u AL;Bit16u ES;Bit16u BP;Bit16u CX;Bit16u DX;Bit8u BL;Bit8u BH; { Bit16u blockaddr,dest,i,src; get_font_access(); blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11); for(i=0;i=0x10) { set_scan_lines(BH); } } static void biosfn_load_text_8_14_pat (AL,BL) Bit8u AL;Bit8u BL; { Bit16u blockaddr,dest,i,src; get_font_access(); blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11); for(i=0;i<0x100;i++) { src = i * 14; dest = blockaddr + i * 32; memcpyb(0xA000, dest, 0xC000, vgafont14+src, 14); } release_font_access(); if(AL>=0x10) { set_scan_lines(14); } } static void biosfn_load_text_8_8_pat (AL,BL) Bit8u AL;Bit8u BL; { Bit16u blockaddr,dest,i,src; get_font_access(); blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11); for(i=0;i<0x100;i++) { src = i * 8; dest = blockaddr + i * 32; memcpyb(0xA000, dest, 0xC000, vgafont8+src, 8); } release_font_access(); if(AL>=0x10) { set_scan_lines(8); } } // -------------------------------------------------------------------------------------------- ASM_START biosfn_set_text_block_specifier: push ax push dx mov dx, # VGAREG_SEQU_ADDRESS mov ah, bl mov al, #0x03 out dx, ax pop dx pop ax ret ASM_END // -------------------------------------------------------------------------------------------- static void biosfn_load_text_8_16_pat (AL,BL) Bit8u AL;Bit8u BL; { Bit16u blockaddr,dest,i,src; get_font_access(); blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11); for(i=0;i<0x100;i++) { src = i * 16; dest = blockaddr + i * 32; memcpyb(0xA000, dest, 0xC000, vgafont16+src, 16); } release_font_access(); if(AL>=0x10) { set_scan_lines(16); } } static void biosfn_load_gfx_8_8_chars (ES,BP) Bit16u ES;Bit16u BP; { #ifdef DEBUG unimplemented(); #endif } static void biosfn_load_gfx_user_chars (ES,BP,CX,BL,DL) Bit16u ES;Bit16u BP;Bit16u CX;Bit8u BL;Bit8u DL; { #ifdef DEBUG unimplemented(); #endif } static void biosfn_load_gfx_8_14_chars (BL) Bit8u BL; { #ifdef DEBUG unimplemented(); #endif } static void biosfn_load_gfx_8_8_dd_chars (BL) Bit8u BL; { #ifdef DEBUG unimplemented(); #endif } static void biosfn_load_gfx_8_16_chars (BL) Bit8u BL; { #ifdef DEBUG unimplemented(); #endif } // -------------------------------------------------------------------------------------------- static void biosfn_get_font_info (BH,ES,BP,CX,DX) Bit8u BH;Bit16u *ES;Bit16u *BP;Bit16u *CX;Bit16u *DX; {Bit16u ss=get_SS(); switch(BH) {case 0x00: write_word(ss,ES,read_word(0x00,0x1f*4)); write_word(ss,BP,read_word(0x00,(0x1f*4)+2)); break; case 0x01: write_word(ss,ES,read_word(0x00,0x43*4)); write_word(ss,BP,read_word(0x00,(0x43*4)+2)); break; case 0x02: write_word(ss,ES,0xC000); write_word(ss,BP,vgafont14); break; case 0x03: write_word(ss,ES,0xC000); write_word(ss,BP,vgafont8); break; case 0x04: write_word(ss,ES,0xC000); write_word(ss,BP,vgafont8+128*8); break; case 0x05: write_word(ss,ES,0xC000); write_word(ss,BP,vgafont14alt); break; case 0x06: write_word(ss,ES,0xC000); write_word(ss,BP,vgafont16); break; case 0x07: write_word(ss,ES,0xC000); write_word(ss,BP,vgafont16alt); break; default: #ifdef DEBUG printf("Get font info BH(%02x) was discarded\n",BH); #endif return; } // Set byte/char of on screen font write_word(ss,CX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT)); // Set Highest char row write_word(ss,DX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)); } // -------------------------------------------------------------------------------------------- ASM_START biosfn_get_ega_info: push ds push ax mov ax, # BIOSMEM_SEG mov ds, ax xor ch, ch mov bx, # BIOSMEM_SWITCHES mov cl, [bx] and cl, #0x0f mov bx, # BIOSMEM_CRTC_ADDRESS mov ax, [bx] mov bx, #0x0003 cmp ax, # VGAREG_MDA_CRTC_ADDRESS jne mode_ega_color mov bh, #0x01 mode_ega_color: pop ax pop ds ret ASM_END // -------------------------------------------------------------------------------------------- static void biosfn_alternate_prtsc() { #ifdef DEBUG unimplemented(); #endif } // -------------------------------------------------------------------------------------------- ASM_START biosfn_select_vert_res: ; res : 00 200 lines, 01 350 lines, 02 400 lines push ds push bx push dx mov dl, al mov ax, # BIOSMEM_SEG mov ds, ax mov bx, # BIOSMEM_MODESET_CTL mov al, [bx] mov bx, # BIOSMEM_SWITCHES mov ah, [bx] cmp dl, #0x01 je vert_res_350 jb vert_res_200 cmp dl, #0x02 je vert_res_400 #ifdef DEBUG mov al, dl xor ah, ah push ax mov bx, #msg_vert_res push bx call _printf add sp, #4 #endif jmp set_retcode vert_res_400: ; reset modeset ctl bit 7 and set bit 4 ; set switches bit 3-0 to 0x09 and al, #0x7f or al, #0x10 and ah, #0xf0 or ah, #0x09 jnz set_vert_res vert_res_350: ; reset modeset ctl bit 7 and bit 4 ; set switches bit 3-0 to 0x09 and al, #0x6f and ah, #0xf0 or ah, #0x09 jnz set_vert_res vert_res_200: ; set modeset ctl bit 7 and reset bit 4 ; set switches bit 3-0 to 0x08 and al, #0xef or al, #0x80 and ah, #0xf0 or ah, #0x08 set_vert_res: mov bx, # BIOSMEM_MODESET_CTL mov [bx], al mov bx, # BIOSMEM_SWITCHES mov [bx], ah set_retcode: mov ax, #0x1212 pop dx pop bx pop ds ret #ifdef DEBUG msg_vert_res: .ascii "Select vert res (%02x) was discarded" .byte 0x0d,0x0a,0x00 #endif biosfn_enable_default_palette_loading: push ds push bx push dx mov dl, al and dl, #0x01 shl dl, 3 mov ax, # BIOSMEM_SEG mov ds, ax mov bx, # BIOSMEM_MODESET_CTL mov al, [bx] and al, #0xf7 or al, dl mov [bx], al mov ax, #0x1212 pop dx pop bx pop ds ret biosfn_enable_video_addressing: push bx push dx mov bl, al and bl, #0x01 xor bl, #0x01 shl bl, 1 mov dx, # VGAREG_READ_MISC_OUTPUT in al, dx and al, #0xfd or al, bl mov dx, # VGAREG_WRITE_MISC_OUTPUT out dx, al mov ax, #0x1212 pop dx pop bx ret biosfn_enable_grayscale_summing: push ds push bx push dx mov dl, al and dl, #0x01 xor dl, #0x01 shl dl, 1 mov ax, # BIOSMEM_SEG mov ds, ax mov bx, # BIOSMEM_MODESET_CTL mov al, [bx] and al, #0xfd or al, dl mov [bx], al mov ax, #0x1212 pop dx pop bx pop ds ret biosfn_enable_cursor_emulation: push ds push bx push dx mov dl, al and dl, #0x01 xor dl, #0x01 mov ax, # BIOSMEM_SEG mov ds, ax mov bx, # BIOSMEM_MODESET_CTL mov al, [bx] and al, #0xfe or al, dl mov [bx], al mov ax, #0x1212 pop dx pop bx pop ds ret ASM_END // -------------------------------------------------------------------------------------------- static void biosfn_switch_video_interface (AL,ES,DX) Bit8u AL;Bit16u ES;Bit16u DX; { #ifdef DEBUG unimplemented(); #endif } static void biosfn_enable_video_refresh_control (AL) Bit8u AL; { #ifdef DEBUG unimplemented(); #endif } // -------------------------------------------------------------------------------------------- static void biosfn_write_string (flag,page,attr,count,row,col,seg,offset) Bit8u flag;Bit8u page;Bit8u attr;Bit16u count;Bit8u row;Bit8u col;Bit16u seg;Bit16u offset; { Bit16u newcurs,oldcurs,dummy; Bit8u car,carattr; // Read curs info for the page biosfn_get_cursor_pos(page,&dummy,&oldcurs); // if row=0xff special case : use current cursor position if(row==0xff) {col=oldcurs&0x00ff; row=(oldcurs&0xff00)>>8; } newcurs=row; newcurs<<=8; newcurs+=col; biosfn_set_cursor_pos(page,newcurs); while(count--!=0) { car=read_byte(seg,offset++); if((flag&0x02)!=0) attr=read_byte(seg,offset++); biosfn_write_teletype(car,page,attr,WITH_ATTR); } // Set back curs pos if((flag&0x01)==0) biosfn_set_cursor_pos(page,oldcurs); } // -------------------------------------------------------------------------------------------- ASM_START biosfn_group_1A: cmp al, #0x00 je biosfn_read_display_code cmp al, #0x01 je biosfn_set_display_code #ifdef DEBUG call _unknown #endif ret biosfn_read_display_code: push ds push ax mov ax, # BIOSMEM_SEG mov ds, ax mov bx, # BIOSMEM_DCC_INDEX mov al, [bx] mov bl, al xor bh, bh pop ax mov al, ah pop ds ret biosfn_set_display_code: push ds push ax push bx mov ax, # BIOSMEM_SEG mov ds, ax mov ax, bx mov bx, # BIOSMEM_DCC_INDEX mov [bx], al #ifdef DEBUG mov al, ah xor ah, ah push ax mov bx, #msg_alt_dcc push bx call _printf add sp, #4 #endif pop bx pop ax mov al, ah pop ds ret #ifdef DEBUG msg_alt_dcc: .ascii "Alternate Display code (%02x) was discarded" .byte 0x0d,0x0a,0x00 #endif ASM_END // -------------------------------------------------------------------------------------------- static void biosfn_read_state_info (BX,ES,DI) Bit16u BX;Bit16u ES;Bit16u DI; { // Address of static functionality table write_word(ES,DI+0x00,&static_functionality); write_word(ES,DI+0x02,0xC000); // Hard coded copy from BIOS area. Should it be cleaner ? memcpyb(ES,DI+0x04,BIOSMEM_SEG,0x49,30); memcpyb(ES,DI+0x22,BIOSMEM_SEG,0x84,3); write_byte(ES,DI+0x25,read_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX)); write_byte(ES,DI+0x26,0); write_byte(ES,DI+0x27,16); write_byte(ES,DI+0x28,0); write_byte(ES,DI+0x29,8); write_byte(ES,DI+0x2a,2); write_byte(ES,DI+0x2b,0); write_byte(ES,DI+0x2c,0); write_byte(ES,DI+0x31,3); write_byte(ES,DI+0x32,0); memsetb(ES,DI+0x33,0,13); } // -------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------- static Bit16u biosfn_read_video_state_size2 (CX) Bit16u CX; { Bit16u size; size = 0; if (CX & 1) { size += 0x46; } if (CX & 2) { size += (5 + 8 + 5) * 2 + 6; } if (CX & 4) { size += 3 + 256 * 3 + 1; } return size; } static void biosfn_read_video_state_size (CX, BX) Bit16u CX; Bit16u *BX; { Bit16u ss=get_SS(); write_word(ss, BX, biosfn_read_video_state_size2(CX)); } static Bit16u biosfn_save_video_state (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX; { Bit16u i, v, crtc_addr, ar_index; crtc_addr = read_word(BIOSMEM_SEG, BIOSMEM_CRTC_ADDRESS); if (CX & 1) { write_byte(ES, BX, inb(VGAREG_SEQU_ADDRESS)); BX++; write_byte(ES, BX, inb(crtc_addr)); BX++; write_byte(ES, BX, inb(VGAREG_GRDC_ADDRESS)); BX++; inb(VGAREG_ACTL_RESET); ar_index = inb(VGAREG_ACTL_ADDRESS); write_byte(ES, BX, ar_index); BX++; write_byte(ES, BX, inb(VGAREG_READ_FEATURE_CTL)); BX++; for(i=1;i<=4;i++){ outb(VGAREG_SEQU_ADDRESS, i); write_byte(ES, BX, inb(VGAREG_SEQU_DATA)); BX++; } outb(VGAREG_SEQU_ADDRESS, 0); write_byte(ES, BX, inb(VGAREG_SEQU_DATA)); BX++; for(i=0;i<=0x18;i++) { outb(crtc_addr,i); write_byte(ES, BX, inb(crtc_addr+1)); BX++; } for(i=0;i<=0x13;i++) { inb(VGAREG_ACTL_RESET); outb(VGAREG_ACTL_ADDRESS, i | (ar_index & 0x20)); write_byte(ES, BX, inb(VGAREG_ACTL_READ_DATA)); BX++; } inb(VGAREG_ACTL_RESET); for(i=0;i<=8;i++) { outb(VGAREG_GRDC_ADDRESS,i); write_byte(ES, BX, inb(VGAREG_GRDC_DATA)); BX++; } write_word(ES, BX, crtc_addr); BX+= 2; /* XXX: read plane latches */ write_byte(ES, BX, 0); BX++; write_byte(ES, BX, 0); BX++; write_byte(ES, BX, 0); BX++; write_byte(ES, BX, 0); BX++; } if (CX & 2) { write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE)); BX++; write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)); BX += 2; write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE)); BX += 2; write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)); BX += 2; write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)); BX++; write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT)); BX += 2; write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL)); BX++; write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES)); BX++; write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)); BX++; write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE)); BX += 2; for(i=0;i<8;i++) { write_word(ES, BX, read_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*i)); BX += 2; } write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START)); BX += 2; write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE)); BX++; /* current font */ write_word(ES, BX, read_word(0, 0x1f * 4)); BX += 2; write_word(ES, BX, read_word(0, 0x1f * 4 + 2)); BX += 2; write_word(ES, BX, read_word(0, 0x43 * 4)); BX += 2; write_word(ES, BX, read_word(0, 0x43 * 4 + 2)); BX += 2; } if (CX & 4) { /* XXX: check this */ write_byte(ES, BX, inb(VGAREG_DAC_STATE)); BX++; /* read/write mode dac */ write_byte(ES, BX, inb(VGAREG_DAC_WRITE_ADDRESS)); BX++; /* pix address */ write_byte(ES, BX, inb(VGAREG_PEL_MASK)); BX++; // Set the whole dac always, from 0 outb(VGAREG_DAC_WRITE_ADDRESS,0x00); for(i=0;i<256*3;i++) { write_byte(ES, BX, inb(VGAREG_DAC_DATA)); BX++; } write_byte(ES, BX, 0); BX++; /* color select register */ } return BX; } static Bit16u biosfn_restore_video_state (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX; { Bit16u i, crtc_addr, v, addr1, ar_index; if (CX & 1) { // Reset Attribute Ctl flip-flop inb(VGAREG_ACTL_RESET); crtc_addr = read_word(ES, BX + 0x40); addr1 = BX; BX += 5; for(i=1;i<=4;i++){ outb(VGAREG_SEQU_ADDRESS, i); outb(VGAREG_SEQU_DATA, read_byte(ES, BX)); BX++; } outb(VGAREG_SEQU_ADDRESS, 0); outb(VGAREG_SEQU_DATA, read_byte(ES, BX)); BX++; // Disable CRTC write protection outw(crtc_addr,0x0011); // Set CRTC regs for(i=0;i<=0x18;i++) { if (i != 0x11) { outb(crtc_addr,i); outb(crtc_addr+1, read_byte(ES, BX)); } BX++; } // select crtc base address v = inb(VGAREG_READ_MISC_OUTPUT) & ~0x01; if (crtc_addr = 0x3d4) v |= 0x01; outb(VGAREG_WRITE_MISC_OUTPUT, v); // enable write protection if needed outb(crtc_addr, 0x11); outb(crtc_addr+1, read_byte(ES, BX - 0x18 + 0x11)); // Set Attribute Ctl ar_index = read_byte(ES, addr1 + 0x03); inb(VGAREG_ACTL_RESET); for(i=0;i<=0x13;i++) { outb(VGAREG_ACTL_ADDRESS, i | (ar_index & 0x20)); outb(VGAREG_ACTL_WRITE_DATA, read_byte(ES, BX)); BX++; } outb(VGAREG_ACTL_ADDRESS, ar_index); inb(VGAREG_ACTL_RESET); for(i=0;i<=8;i++) { outb(VGAREG_GRDC_ADDRESS,i); outb(VGAREG_GRDC_DATA, read_byte(ES, BX)); BX++; } BX += 2; /* crtc_addr */ BX += 4; /* plane latches */ outb(VGAREG_SEQU_ADDRESS, read_byte(ES, addr1)); addr1++; outb(crtc_addr, read_byte(ES, addr1)); addr1++; outb(VGAREG_GRDC_ADDRESS, read_byte(ES, addr1)); addr1++; addr1++; outb(crtc_addr - 0x4 + 0xa, read_byte(ES, addr1)); addr1++; } if (CX & 2) { write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE, read_byte(ES, BX)); BX++; write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS, read_word(ES, BX)); BX += 2; write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, read_word(ES, BX)); BX += 2; write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS, read_word(ES, BX)); BX += 2; write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, read_byte(ES, BX)); BX++; write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, read_word(ES, BX)); BX += 2; write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL, read_byte(ES, BX)); BX++; write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES, read_byte(ES, BX)); BX++; write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL, read_byte(ES, BX)); BX++; write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE, read_word(ES, BX)); BX += 2; for(i=0;i<8;i++) { write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*i, read_word(ES, BX)); BX += 2; } write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START, read_word(ES, BX)); BX += 2; write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE, read_byte(ES, BX)); BX++; /* current font */ write_word(0, 0x1f * 4, read_word(ES, BX)); BX += 2; write_word(0, 0x1f * 4 + 2, read_word(ES, BX)); BX += 2; write_word(0, 0x43 * 4, read_word(ES, BX)); BX += 2; write_word(0, 0x43 * 4 + 2, read_word(ES, BX)); BX += 2; } if (CX & 4) { BX++; v = read_byte(ES, BX); BX++; outb(VGAREG_PEL_MASK, read_byte(ES, BX)); BX++; // Set the whole dac always, from 0 outb(VGAREG_DAC_WRITE_ADDRESS,0x00); for(i=0;i<256*3;i++) { outb(VGAREG_DAC_DATA, read_byte(ES, BX)); BX++; } BX++; outb(VGAREG_DAC_WRITE_ADDRESS, v); } return BX; } // ============================================================================================ // // Video Utils // // ============================================================================================ // -------------------------------------------------------------------------------------------- static Bit8u find_vga_entry(mode) Bit8u mode; { Bit8u i,line=0xFF; for(i=0;i<=MODE_MAX;i++) if(vga_modes[i].svgamode==mode) {line=i; break; } return line; } /* =========================================================== */ /* * Misc Utils */ /* =========================================================== */ // -------------------------------------------------------------------------------------------- static void memsetb(seg,offset,value,count) Bit16u seg; Bit16u offset; Bit16u value; Bit16u count; { ASM_START push bp mov bp, sp push ax push cx push es push di mov cx, 10[bp] ; count cmp cx, #0x00 je memsetb_end mov ax, 4[bp] ; segment mov es, ax mov ax, 6[bp] ; offset mov di, ax mov al, 8[bp] ; value cld rep stosb memsetb_end: pop di pop es pop cx pop ax pop bp ASM_END } // -------------------------------------------------------------------------------------------- static void memsetw(seg,offset,value,count) Bit16u seg; Bit16u offset; Bit16u value; Bit16u count; { ASM_START push bp mov bp, sp push ax push cx push es push di mov cx, 10[bp] ; count cmp cx, #0x00 je memsetw_end mov ax, 4[bp] ; segment mov es, ax mov ax, 6[bp] ; offset mov di, ax mov ax, 8[bp] ; value cld rep stosw memsetw_end: pop di pop es pop cx pop ax pop bp ASM_END } // -------------------------------------------------------------------------------------------- static void memcpyb(dseg,doffset,sseg,soffset,count) Bit16u dseg; Bit16u doffset; Bit16u sseg; Bit16u soffset; Bit16u count; { ASM_START push bp mov bp, sp push ax push cx push es push di push ds push si mov cx, 12[bp] ; count cmp cx, #0x0000 je memcpyb_end mov ax, 4[bp] ; dsegment mov es, ax mov ax, 6[bp] ; doffset mov di, ax mov ax, 8[bp] ; ssegment mov ds, ax mov ax, 10[bp] ; soffset mov si, ax cld rep movsb memcpyb_end: pop si pop ds pop di pop es pop cx pop ax pop bp ASM_END } // -------------------------------------------------------------------------------------------- static void memcpyw(dseg,doffset,sseg,soffset,count) Bit16u dseg; Bit16u doffset; Bit16u sseg; Bit16u soffset; Bit16u count; { ASM_START push bp mov bp, sp push ax push cx push es push di push ds push si mov cx, 12[bp] ; count cmp cx, #0x0000 je memcpyw_end mov ax, 4[bp] ; dsegment mov es, ax mov ax, 6[bp] ; doffset mov di, ax mov ax, 8[bp] ; ssegment mov ds, ax mov ax, 10[bp] ; soffset mov si, ax cld rep movsw memcpyw_end: pop si pop ds pop di pop es pop cx pop ax pop bp ASM_END } /* =========================================================== */ /* * These functions where ripped from Kevin's rombios.c */ /* =========================================================== */ // -------------------------------------------------------------------------------------------- static Bit8u read_byte(seg, offset) Bit16u seg; Bit16u offset; { ASM_START push bp mov bp, sp push bx push ds mov ax, 4[bp] ; segment mov ds, ax mov bx, 6[bp] ; offset mov al, [bx] ;; al = return value (byte) pop ds pop bx pop bp ASM_END } // -------------------------------------------------------------------------------------------- static Bit16u read_word(seg, offset) Bit16u seg; Bit16u offset; { ASM_START push bp mov bp, sp push bx push ds mov ax, 4[bp] ; segment mov ds, ax mov bx, 6[bp] ; offset mov ax, [bx] ;; ax = return value (word) pop ds pop bx pop bp ASM_END } // -------------------------------------------------------------------------------------------- static void write_byte(seg, offset, data) Bit16u seg; Bit16u offset; Bit8u data; { ASM_START push bp mov bp, sp push ax push bx push ds mov ax, 4[bp] ; segment mov ds, ax mov bx, 6[bp] ; offset mov al, 8[bp] ; data byte mov [bx], al ; write data byte pop ds pop bx pop ax pop bp ASM_END } // -------------------------------------------------------------------------------------------- static void write_word(seg, offset, data) Bit16u seg; Bit16u offset; Bit16u data; { ASM_START push bp mov bp, sp push ax push bx push ds mov ax, 4[bp] ; segment mov ds, ax mov bx, 6[bp] ; offset mov ax, 8[bp] ; data word mov [bx], ax ; write data word pop ds pop bx pop ax pop bp ASM_END } // -------------------------------------------------------------------------------------------- Bit8u inb(port) Bit16u port; { ASM_START push bp mov bp, sp push dx mov dx, 4[bp] in al, dx pop dx pop bp ASM_END } Bit16u inw(port) Bit16u port; { ASM_START push bp mov bp, sp push dx mov dx, 4[bp] in ax, dx pop dx pop bp ASM_END } // -------------------------------------------------------------------------------------------- void outb(port, val) Bit16u port; Bit8u val; { ASM_START push bp mov bp, sp push ax push dx mov dx, 4[bp] mov al, 6[bp] out dx, al pop dx pop ax pop bp ASM_END } // -------------------------------------------------------------------------------------------- void outw(port, val) Bit16u port; Bit16u val; { ASM_START push bp mov bp, sp push ax push dx mov dx, 4[bp] mov ax, 6[bp] out dx, ax pop dx pop ax pop bp ASM_END } Bit16u get_SS() { ASM_START mov ax, ss ASM_END } #ifdef DEBUG void unimplemented() { printf("--> Unimplemented\n"); } void unknown() { printf("--> Unknown int10\n"); } #endif // -------------------------------------------------------------------------------------------- #if defined(USE_BX_INFO) || defined(DEBUG) || defined(CIRRUS_DEBUG) void printf(s) Bit8u *s; { Bit8u c, format_char; Boolean in_format; unsigned format_width, i; Bit16u *arg_ptr; Bit16u arg_seg, arg, digit, nibble, shift_count; arg_ptr = &s; arg_seg = get_SS(); in_format = 0; format_width = 0; while (c = read_byte(0xc000, s)) { if ( c == '%' ) { in_format = 1; format_width = 0; } else if (in_format) { if ( (c>='0') && (c<='9') ) { format_width = (format_width * 10) + (c - '0'); } else if (c == 'x') { arg_ptr++; // increment to next arg arg = read_word(arg_seg, arg_ptr); if (format_width == 0) format_width = 4; i = 0; digit = format_width - 1; for (i=0; i> (4 * digit)) & 0x000f; if (nibble <= 9) outb(0x0500, nibble + '0'); else outb(0x0500, (nibble - 10) + 'A'); digit--; } in_format = 0; } //else if (c == 'd') { // in_format = 0; // } } else { outb(0x0500, c); } s ++; } } #endif ASM_START ; get LFB address from PCI ; in - ax: PCI device vendor ; out - ax: LFB address (high 16 bit) ;; NOTE - may be called in protected mode _pci_get_lfb_addr: push bx push cx push dx push eax mov bx, ax xor cx, cx mov dl, #0x00 call pci_read_reg cmp ax, #0xffff jz pci_get_lfb_addr_fail pci_get_lfb_addr_next_dev: mov dl, #0x00 call pci_read_reg cmp ax, bx ;; check vendor jz pci_get_lfb_addr_found add cx, #0x8 cmp cx, #0x200 ;; search bus #0 and #1 jb pci_get_lfb_addr_next_dev pci_get_lfb_addr_fail: xor dx, dx ;; no LFB jmp pci_get_lfb_addr_return pci_get_lfb_addr_found: mov dl, #0x10 ;; I/O space #0 call pci_read_reg test ax, #0xfff1 jz pci_get_lfb_addr_success mov dl, #0x14 ;; I/O space #1 call pci_read_reg test ax, #0xfff1 jnz pci_get_lfb_addr_fail pci_get_lfb_addr_success: shr eax, #16 mov dx, ax ;; LFB address pci_get_lfb_addr_return: pop eax mov ax, dx pop dx pop cx pop bx ret ; read PCI register ; in - cx: device/function ; in - dl: register ; out - eax: value pci_read_reg: mov eax, #0x00800000 mov ax, cx shl eax, #8 mov al, dl mov dx, #0xcf8 out dx, eax add dl, #4 in eax, dx ret ASM_END #ifdef VBE #include "vbe.c" #endif #ifdef CIRRUS #include "clext.c" #endif // -------------------------------------------------------------------------------------------- ASM_START ;; DATA_SEG_DEFS_HERE ASM_END ASM_START .ascii "vgabios ends here" .byte 0x00 vgabios_end: .byte 0xCB ;; BLOCK_STRINGS_BEGIN ASM_END