coreboot-v2/src/northbridge/via/vx800/vgabios.c
<<
>>
Prefs
   1#include <console/console.h>
   2#include <device/pci.h>
   3#include <device/pci_ids.h>
   4#include <device/pci_ops.h>
   5#undef __KERNEL__
   6#include <arch/io.h>
   7#include <string.h>
   8#include "vgachip.h"
   9#include <cbfs.h>
  10
  11/* vgabios.c. Derived from: */
  12
  13/*------------------------------------------------------------ -*- C -*-
  14 *  2 Kernel Monte a.k.a. Linux loading Linux on x86
  15 *
  16 *  Erik Arjan Hendriks <hendriks@lanl.gov>
  17 *
  18 *  This version is a derivative of the original two kernel monte
  19 *  which is (C) 2000 Scyld.
  20 *
  21 *  Copyright (C) 2000 Scyld Computing Corporation
  22 *
  23 *  This program is free software; you can redistribute it and/or modify
  24 *  it under the terms of the GNU General Public License as published by
  25 *  the Free Software Foundation; version 2 of the License.
  26 *
  27 *  This program is distributed in the hope that it will be useful,
  28 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  29 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  30 *  GNU General Public License for more details.
  31 *
  32 *  You should have received a copy of the GNU General Public License
  33 *  along with this program; if not, write to the Free Software
  34 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
  35 *
  36 * Portions related to the alpha architecture are:
  37 *
  38 *  Copyright(C) 2001 University of California.  LA-CC Number 01-67.
  39 *  This software has been authored by an employee or employees of the
  40 *  University of California, operator of the Los Alamos National
  41 *  Laboratory under Contract No.  W-7405-ENG-36 with the U.S.
  42 *  Department of Energy.  The U.S. Government has rights to use,
  43 *  reproduce, and distribute this software. If the software is
  44 *  modified to produce derivative works, such modified software should
  45 *  be clearly marked, so as not to confuse it with the version
  46 *  available from LANL.
  47 *
  48 *  This software may be used and distributed according to the terms
  49 *  of the GNU General Public License, incorporated herein by
  50 *  reference to http://www.gnu.org/licenses/gpl.html.
  51 *
  52 *  This software is provided by the author(s) "as is" and any express
  53 *  or implied warranties, including, but not limited to, the implied
  54 *  warranties of merchantability and fitness for a particular purpose
  55 *  are disclaimed.  In no event shall the author(s) be liable for any
  56 *  direct, indirect, incidental, special, exemplary, or consequential
  57 *  damages (including, but not limited to, procurement of substitute
  58 *  goods or services; loss of use, data, or profits; or business
  59 *  interruption) however caused and on any theory of liability,
  60 *  whether in contract, strict liability, or tort (including
  61 *  negligence or otherwise) arising in any way out of the use of this
  62 *  software, even if advised of the possibility of such damage.
  63 *
  64 *  $Id: vgabios.c,v 1.5 2004/10/06 17:33:52 rminnich Exp $
  65 *--------------------------------------------------------------------*/
  66
  67/* Modified to be a self sufficient plug in so that it can be used 
  68   without reliance on other parts of coreboot's core
  69   (C) 2005 Nick.Barker9@btinternet.com
  70
  71  Used initially for epia-m where there are problems getting the bios
  72  emulator to successfully run this bios.
  73*/
  74/* Declare a temporary global descriptor table - necessary because the
  75   Core part of the bios no longer sets up any 16 bit segments */
  76__asm__(
  77               /* pointer to original gdt */
  78               "gdtarg:                 \n"
  79               "        .word   gdt_limit       \n"
  80               "        .long   gdt             \n"
  81               /* compute the table limit */
  82               "__mygdt_limit = __mygdt_end - __mygdt - 1       \n"
  83               "__mygdtaddr:                    \n"
  84               "        .word   __mygdt_limit   \n"
  85               "        .long   __mygdt         \n"
  86               "__mygdt:                        \n"
  87               /* selgdt 0, unused */
  88               "        .word   0x0000, 0x0000  \n"
  89               "        .byte   0x00, 0x00, 0x00, 0x00  \n"
  90               /* selgdt 8, unused */
  91               "        .word   0x0000, 0x0000          \n"
  92               "        .byte   0x00, 0x00, 0x00, 0x00  \n"
  93               /* selgdt 0x10, flat code segment */
  94               "        .word   0xffff, 0x0000          \n"
  95               "        .byte   0x00, 0x9b, 0xcf, 0x00  \n"
  96               /* selgdt 0x18, flat data segment */
  97               "        .word   0xffff, 0x0000          \n"
  98               "        .byte   0x00, 0x93, 0xcf, 0x00  \n"
  99               /* selgdt 0x20, unused */
 100               "        .word   0x0000, 0x0000          \n"
 101               "        .byte   0x00, 0x00, 0x00, 0x00  \n"
 102               /* selgdt 0x28 16-bit 64k code at 0x00000000 */
 103               "        .word   0xffff, 0x0000          \n"
 104               "        .byte   0, 0x9a, 0, 0           \n"
 105               /* selgdt 0x30 16-bit 64k data at 0x00000000 */
 106               "        .word   0xffff, 0x0000          \n"
 107               "        .byte   0, 0x92, 0, 0           \n"
 108               "__mygdt_end:                            \n");
 109
 110/* Declare a pointer to where our idt is going to be i.e. at mem zero */
 111__asm__("__myidt:               \n"
 112        /* 16-bit limit */
 113        "       .word 1023      \n"
 114        /* 24-bit base */
 115        "       .long 0         \n" "   .word 0         \n");
 116
 117/* The address arguments to this function are PHYSICAL ADDRESSES */
 118extern u8 acpi_sleep_type;
 119
 120static void real_mode_switch_call_vga(unsigned long devfn)
 121{
 122        if ((acpi_sleep_type == 0)/* && (PAYLOAD_IS_SEABIOS == 1)*/)
 123                return;
 124        __asm__ __volatile__(
 125                                    // paranoia -- does ecx get saved? not sure. This is 
 126                                    // the easiest safe thing to do.
 127                                    "   pushal                  \n"
 128                                    /* save the stack */
 129                                    "   mov     %esp, __stack   \n"
 130                                    "   jmp     1f              \n"
 131                                    "__stack: .long 0           \n" "1:\n"
 132                                    /* get devfn into %ecx */
 133                                    "   movl    %esp, %ebp      \n"
 134                                    "   movl    8(%ebp), %ecx   \n"
 135                                    /* load 'our' gdt */
 136                                    "   lgdt    %cs:__mygdtaddr \n"
 137                                    /*  This configures CS properly for real mode. */
 138                                    "   ljmp    $0x28, $__rms_16bit\n"
 139                                    "__rms_16bit:                       \n"
 140                                    "   .code16                 \n"
 141                                    /* 16 bit code from here on... */
 142                                    /* Load the segment registers w/ properly configured segment
 143                                     * descriptors.  They will retain these configurations (limits,
 144                                     * writability, etc.) once protected mode is turned off. */
 145                                    "   mov     $0x30, %ax      \n"
 146                                    "   mov     %ax, %ds        \n"
 147                                    "   mov     %ax, %es        \n"
 148                                    "   mov     %ax, %fs        \n"
 149                                    "   mov     %ax, %gs        \n"
 150                                    "   mov     %ax, %ss        \n"
 151                                    /* Turn off protection (bit 0 in CR0) */
 152                                    "   movl    %cr0, %eax      \n"
 153                                    "   andl    $0xFFFFFFFE, %eax \n"
 154                                    "   movl    %eax, %cr0      \n"
 155                                    /* Now really going into real mode */
 156                                    "   ljmp    $0,  $__rms_real\n"
 157                                    "__rms_real:                        \n"
 158                                    /* put the stack at the end of page zero. 
 159                                     * that way we can easily share it between real and protected, 
 160                                     * since the 16-bit ESP at segment 0 will work for any case. 
 161                                     /* Setup a stack */
 162                                    "   mov     $0x0, %ax       \n"
 163                                    "   mov     %ax, %ss        \n"
 164                                    "   movl    $0x1000, %eax   \n"
 165                                    "   movl    %eax, %esp      \n"
 166                                    /* Load our 16 it idt */
 167                                    "   xor     %ax, %ax        \n"
 168                                    "   mov     %ax, %ds        \n"
 169                                    "   lidt    __myidt         \n"
 170                                    /* Dump zeros in the other segregs */
 171                                    "   mov     %ax, %es        \n"
 172                                    "   mov     %ax, %fs        \n"
 173                                    "   mov     %ax, %gs        \n"
 174                                    "   mov     $0x40, %ax      \n"
 175                                    "   mov     %ax, %ds        \n"
 176                                    "   mov     %cx, %ax        \n"
 177                                    /* run VGA BIOS at 0xc000:0003 */
 178                                    "   lcall   $0xc000, $0x0003\n"
 179                                    /* if we got here, just about done. 
 180                                     * Need to get back to protected mode */
 181                                    "   movl    %cr0, %eax      \n" "   orl     $0x0000001, %eax\n"     /* PE = 1 */
 182                                    "   movl    %eax, %cr0      \n"
 183                                    /* Now that we are in protected mode jump to a 32 bit code segment. */
 184                                    "   data32  ljmp    $0x10, $vgarestart\n"
 185                                    "vgarestart:\n"
 186                                    "   .code32\n"
 187                                    "   movw    $0x18, %ax      \n"
 188                                    "   mov     %ax, %ds        \n"
 189                                    "   mov     %ax, %es        \n"
 190                                    "   mov     %ax, %fs        \n"
 191                                    "   mov     %ax, %gs        \n"
 192                                    "   mov     %ax, %ss        \n"
 193                                    /* restore proper gdt and idt */
 194                                    "   lgdt    %cs:gdtarg      \n"
 195                                    "   lidt    idtarg          \n"
 196                                    ".globl vga_exit            \n"
 197                                    "vga_exit:                  \n"
 198                                    "   mov     __stack, %esp   \n"
 199                                    "   popal                   \n");
 200}
 201
 202__asm__(".text\n" "real_mode_switch_end:\n");
 203extern char real_mode_switch_end[];
 204
 205/* call vga bios int 10 function 0x4f14 to enable main console 
 206   epia-m does not always autosence the main console so forcing it on is good !! */
 207void vga_enable_console()
 208{
 209        if ((acpi_sleep_type == 0)/* && (PAYLOAD_IS_SEABIOS == 1)*/)
 210                return;
 211        __asm__ __volatile__(
 212                                    /* paranoia -- does ecx get saved? not sure. This is 
 213                                     * the easiest safe thing to do. */
 214                                    "   pushal                  \n"
 215                                    /* save the stack */
 216                                    "   mov     %esp, __stack   \n"
 217                                    /* load 'our' gdt */
 218                                    "   lgdt    %cs:__mygdtaddr \n"
 219                                    /*  This configures CS properly for real mode. */
 220                                    "   ljmp    $0x28, $__vga_ec_16bit\n"
 221                                    "__vga_ec_16bit:            \n"
 222                                    "   .code16                 \n"
 223                                    /* 16 bit code from here on... */
 224                                    /* Load the segment registers w/ properly configured segment
 225                                     * descriptors.  They will retain these configurations (limits,
 226                                     * writability, etc.) once protected mode is turned off. */
 227                                    "   mov     $0x30, %ax      \n"
 228                                    "   mov     %ax, %ds        \n"
 229                                    "   mov     %ax, %es        \n"
 230                                    "   mov     %ax, %fs        \n"
 231                                    "   mov     %ax, %gs        \n"
 232                                    "   mov     %ax, %ss        \n"
 233                                    /* Turn off protection (bit 0 in CR0) */
 234                                    "   movl    %cr0, %eax      \n"
 235                                    "   andl    $0xFFFFFFFE, %eax\n"
 236                                    "   movl    %eax, %cr0      \n"
 237                                    /* Now really going into real mode */
 238                                    "   ljmp    $0, $__vga_ec_real \n"
 239                                    "__vga_ec_real:                  \n"
 240                                    /* put the stack at the end of page zero. 
 241                                     * that way we can easily share it between real and protected, 
 242                                     * since the 16-bit ESP at segment 0 will work for any case. 
 243                                     /* Setup a stack */
 244                                    "   mov     $0x0, %ax       \n"
 245                                    "   mov     %ax, %ss        \n"
 246                                    "   movl    $0x1000, %eax   \n"
 247                                    "   movl    %eax, %esp      \n"
 248                                    /* debugging for RGM */
 249                                    "   mov     $0x11, %al      \n"
 250                                    "   outb    %al, $0x80      \n"
 251                                    /* Load our 16 it idt */
 252                                    "   xor     %ax, %ax        \n"
 253                                    "   mov     %ax, %ds        \n"
 254                                    "   lidt    __myidt         \n"
 255                                    /* Dump zeros in the other segregs */
 256                                    "   mov     %ax, %ds        \n"
 257                                    "   mov     %ax, %es        \n"
 258                                    "   mov     %ax, %fs        \n"
 259                                    "   mov     %ax, %gs        \n"
 260                                    /* ask bios to enable main console */
 261                                    /* set up for int 10 call - values found from X server
 262                                     * bios call routines */
 263                                    "   movw    $0x4f14,%ax     \n"
 264                                    "   movw    $0x8003,%bx     \n"
 265                                    "   movw    $1, %cx         \n"
 266                                    "   movw    $0, %dx         \n"
 267                                    "   movw    $0, %di         \n"
 268                                    "   int     $0x10           \n"
 269                                    "   movb    $0x55, %al      \n"
 270                                    "   outb    %al, $0x80      \n"
 271                                    /* if we got here, just about done. 
 272                                     * Need to get back to protected mode */
 273                                    "   movl    %cr0, %eax      \n" "   orl     $0x0000001, %eax\n"     /* PE = 1 */
 274                                    "   movl    %eax, %cr0      \n"
 275                                    /* Now that we are in protected mode jump to a 32 bit code segment. */
 276                                    "   data32  ljmp    $0x10, $vga_ec_restart\n"
 277                                    "vga_ec_restart:\n"
 278                                    "   .code32\n"
 279                                    "   movw    $0x18, %ax      \n"
 280                                    "   mov     %ax, %ds        \n"
 281                                    "   mov     %ax, %es        \n"
 282                                    "   mov     %ax, %fs        \n"
 283                                    "   mov     %ax, %gs        \n"
 284                                    "   mov     %ax, %ss        \n"
 285                                    /* restore proper gdt and idt */
 286                                    "   lgdt    %cs:gdtarg      \n"
 287                                    "   lidt    idtarg          \n"
 288                                    "   .globl  vga__ec_exit    \n"
 289                                    "vga_ec_exit:\n"
 290                                    "   mov     __stack, %esp   \n"
 291                                    "   popal\n");
 292}
 293
 294void do_vgabios(void)
 295{
 296        device_t dev;
 297        unsigned long busdevfn;
 298        unsigned int rom = 0;
 299        unsigned char *buf;
 300        unsigned int size = 64 * 1024;
 301        int i;
 302        u16 tmp;
 303        u8 tmp8;
 304
 305        printk_emerg("file '%s', line %d\n\n", __FILE__, __LINE__);
 306
 307        /* clear vga bios data area */
 308        for (i = 0x400; i < 0x500; i++) {
 309                *(unsigned char *)i = 0;
 310        }
 311
 312        dev = dev_find_class(PCI_CLASS_DISPLAY_VGA << 8, 0);
 313
 314        if (!dev) {
 315                printk_debug("NO VGA FOUND\n");
 316                return;
 317        }
 318        printk_debug("found VGA: vid=%x, did=%x\n", dev->vendor, dev->device);
 319
 320        /* declare rom address here - keep any config data out of the way
 321         * of core LXB stuff */
 322
 323        rom = cbfs_load_optionrom(dev->vendor, dev->device, 0);
 324        pci_write_config32(dev, PCI_ROM_ADDRESS, rom | 1);
 325        printk_debug("rom base: %x\n", rom);
 326        buf = (unsigned char *)rom;
 327        printk_emerg("file '%s', line %d\n\n", __FILE__, __LINE__);
 328
 329        if ((buf[0] == 0x55) && (buf[1] == 0xaa)) {
 330                memcpy((void *)0xc0000, buf, size);
 331
 332                printk_emerg("file '%s', line %d\n\n", __FILE__, __LINE__);
 333
 334                write_protect_vgabios();        // in northbridge
 335
 336                // check signature again
 337                buf = (unsigned char *)0xc0000;
 338                if (buf[0] == 0x55 && buf[1] == 0xAA) {
 339                        busdevfn =
 340                            (dev->bus->secondary << 8) | dev->path.pci.devfn;
 341                        printk_debug("bus/devfn = %#x\n", busdevfn);
 342                        real_mode_switch_call_vga(busdevfn);
 343                } else
 344                        printk_debug("Failed to copy VGA BIOS to 0xc0000\n");
 345        } else
 346                printk_debug("BAD SIGNATURE 0x%x 0x%x\n", buf[0], buf[1]);
 347
 348        printk_emerg("file '%s', line %d\n\n", __FILE__, __LINE__);
 349
 350        pci_write_config32(dev, PCI_ROM_ADDRESS, 0);
 351}
 352
 353// we had hoped to avoid this. 
 354// this is a stub IDT only. It's main purpose is to ignore calls 
 355// to the BIOS. 
 356// no longer. Dammit. We have to respond to these.
 357struct realidt {
 358        unsigned short offset, cs;
 359};
 360
 361// from a handy writeup that andrey found.
 362
 363// handler. 
 364// There are some assumptions we can make here. 
 365// First, the Top Of Stack (TOS) is located on the top of page zero. 
 366// we can share this stack between real and protected mode. 
 367// that simplifies a lot of things ...
 368// we'll just push all the registers on the stack as longwords, 
 369// and pop to protected mode. 
 370// second, since this only ever runs as part of coreboot, 
 371// we know all the segment register values -- so we don't save any.
 372// keep the handler that calls things small. It can do a call to 
 373// more complex code in coreboot itself. This helps a lot as we don't
 374// have to do address fixup in this little stub, and calls are absolute
 375// so the handler is relocatable.
 376void handler(void)
 377{
 378        __asm__ __volatile__("  .code16         \n"
 379                             "idthandle:                \n"
 380                             "  pushal          \n"
 381                             "  movb    $0, %al \n"
 382                             "  ljmp    $0, $callbiosint16\n"
 383                             "end_idthandle:            \n"
 384                             "  .code32         \n");
 385}
 386
 387void debughandler(void)
 388{
 389        __asm__ __volatile__("  .code16         \n"
 390                             "debughandle:              \n"
 391                             "  pushw   %cx     \n"
 392                             "  movw    $250, %cx \n"
 393                             "dbh1:                     \n"
 394                             "  loop    dbh1    \n"
 395                             "  popw    %cx     \n"
 396                             "  iret            \n"
 397                             "end_debughandle:  \n" ".code32            \n");
 398}
 399
 400// Calling conventions. The first C function is called with this stuff
 401// on the stack. They look like value parameters, but note that if you
 402// modify them they will go back to the INTx function modified. 
 403// the C function will call the biosint function with these as
 404// REFERENCE parameters. In this way, we can easily get 
 405// returns back to the INTx caller (i.e. vgabios)
 406void callbiosint(void)
 407{
 408        __asm__ __volatile__("  .code16         \n"
 409                             "callbiosint16:            \n"
 410                             "  push    %ds     \n"
 411                             "  push    %es     \n"
 412                             "  push    %fs     \n" "   push    %gs     \n"
 413                             // clean up the int #. To save space we put it in the lower
 414                             // byte. But the top 24 bits are junk. 
 415                             "  andl    $0xff, %eax\n"
 416                             // this push does two things:
 417                             // - put the INT # on the stack as a parameter
 418                             // - provides us with a temp for the %cr0 mods.
 419                             "  pushl   %eax    \n" "   movl    %cr0, %eax\n" " orl     $0x00000001, %eax\n"    /* PE = 1 */
 420                             "  movl    %eax, %cr0\n"
 421                             /* Now that we are in protected mode jump to a 32 bit code segment. */
 422                             "  data32  ljmp    $0x10, $biosprotect\n"
 423                             "biosprotect:              \n"
 424                             "  .code32         \n"
 425                             "  movw    $0x18, %ax          \n"
 426                             "  mov     %ax, %ds          \n"
 427                             "  mov     %ax, %es          \n"
 428                             "  mov     %ax, %fs          \n"
 429                             "  mov     %ax, %gs          \n"
 430                             "  mov     %ax, %ss          \n"
 431                             "  lidt    idtarg         \n"
 432                             "  call    biosint \n"
 433                             // back to real mode ...
 434                             "  ljmp    $0x28, $__rms_16bit2\n"
 435                             "__rms_16bit2:                     \n"
 436                             "  .code16                 \n"
 437                             /* 16 bit code from here on... */
 438                             /* Load the segment registers w/ properly configured segment
 439                              * descriptors.  They will retain these configurations (limits,
 440                              * writability, etc.) once protected mode is turned off. */
 441                             "  mov     $0x30, %ax      \n"
 442                             "  mov     %ax, %ds        \n"
 443                             "  mov     %ax, %es        \n"
 444                             "  mov     %ax, %fs        \n"
 445                             "  mov     %ax, %gs        \n"
 446                             "  mov     %ax, %ss        \n"
 447                             /* Turn off protection (bit 0 in CR0) */
 448                             "  movl    %cr0, %eax              \n"
 449                             "  andl    $0xFFFFFFFE, %eax       \n"
 450                             "  movl    %eax, %cr0              \n"
 451                             /* Now really going into real mode */
 452                             "  ljmp $0,  $__rms_real2  \n"
 453                             "__rms_real2:                      \n"
 454                             /* Setup a stack
 455                              * FixME: where is esp? */
 456                             "  mov     $0x0, %ax       \n"
 457                             "  mov     %ax, %ss        \n"
 458                             /* ebugging for RGM */
 459                             "  mov     $0x11, %al      \n"
 460                             "  outb    %al, $0x80      \n"
 461                             /* Load our 16 it idt */
 462                             "  xor     %ax, %ax        \n"
 463                             "  mov     %ax, %ds        \n"
 464                             "  lidt    __myidt         \n"
 465                             /* Dump zeros in the other segregs */
 466                             "  mov     %ax, %es        \n"
 467                             "  mov     %ax, %fs        \n"
 468                             "  mov     %ax, %gs        \n"
 469                             "  mov     $0x40, %ax      \n"
 470                             "  mov     %ax, %ds        \n"
 471                             /* pop the INT # that you pushed earlier */
 472                             "  popl    %eax            \n"
 473                             "  pop     %gs             \n"
 474                             "  pop     %fs             \n"
 475                             "  pop     %es             \n"
 476                             "  pop     %ds             \n"
 477                             "  popal                   \n"
 478                             "  iret                    \n"
 479                             "  .code32                 \n");
 480}
 481
 482enum {
 483        PCIBIOS = 0x1a,
 484        MEMSIZE = 0x12
 485};
 486
 487int pcibios(unsigned long *pedi, unsigned long *pesi, unsigned long *pebp,
 488            unsigned long *pesp, unsigned long *pebx, unsigned long *pedx,
 489            unsigned long *pecx, unsigned long *peax, unsigned long *pflags);
 490
 491int handleint21(unsigned long *pedi, unsigned long *pesi,
 492                unsigned long *pebp, unsigned long *pesp,
 493                unsigned long *pebx, unsigned long *pedx,
 494                unsigned long *pecx, unsigned long *peax,
 495                unsigned long *pflags);
 496
 497extern void vga_exit(void);
 498
 499int biosint(unsigned long intnumber,
 500            unsigned long gsfs, unsigned long dses,
 501            unsigned long edi, unsigned long esi,
 502            unsigned long ebp, unsigned long esp,
 503            unsigned long ebx, unsigned long edx,
 504            unsigned long ecx, unsigned long eax,
 505            unsigned long cs_ip, unsigned short stackflags)
 506{
 507        unsigned long ip;
 508        unsigned long cs;
 509        unsigned long flags;
 510        int ret = -1;
 511
 512        ip = cs_ip & 0xffff;
 513        cs = cs_ip >> 16;
 514        flags = stackflags;
 515
 516        printk_debug("biosint: INT# 0x%lx\n", intnumber);
 517        printk_debug("biosint: eax 0x%lx ebx 0x%lx ecx 0x%lx edx 0x%lx\n",
 518                     eax, ebx, ecx, edx);
 519        printk_debug("biosint: ebp 0x%lx esp 0x%lx edi 0x%lx esi 0x%lx\n",
 520                     ebp, esp, edi, esi);
 521        printk_debug("biosint:  ip 0x%x   cs 0x%x  flags 0x%x\n",
 522                     ip, cs, flags);
 523
 524        // cases in a good compiler are just as good as your own tables. 
 525        switch (intnumber) {
 526        case 0: case 1: case 2: case 3: case 4: case 5:
 527        case 6: case 7: case 8: case 9: case 10:
 528        case 11: case 12: case 13: case 14: case 15:
 529                // These are not BIOS service, but the CPU-generated exceptions
 530                printk_info("biosint: Oops, exception %u\n", intnumber);
 531                if (esp < 0x1000) {
 532                        printk_debug("Stack contents: ");
 533                        while (esp < 0x1000) {
 534                                printk_debug("0x%04x ", *(unsigned short *)esp);
 535                                esp += 2;
 536                        }
 537                        printk_debug("\n");
 538                }
 539                printk_debug("biosint: Bailing out\n");
 540                // "longjmp"
 541                if ((acpi_sleep_type == 3)/* || (PAYLOAD_IS_SEABIOS == 0)*/)    // add this to keep same with kevin's seabios patch in 2008-9-8
 542                        vga_exit();
 543                break;
 544
 545        case PCIBIOS:
 546                ret = pcibios(&edi, &esi, &ebp, &esp,
 547                              &ebx, &edx, &ecx, &eax, &flags);
 548                break;
 549        case MEMSIZE:
 550                // who cares. 
 551                eax = 64 * 1024;
 552                ret = 0;
 553                break;
 554        case 0x15:
 555                ret = handleint21(&edi, &esi, &ebp, &esp,
 556                                  &ebx, &edx, &ecx, &eax, &flags);
 557                break;
 558        default:
 559                printk_info("BIOSINT: Unsupport int #0x%x\n", intnumber);
 560                break;
 561        }
 562        if (ret)
 563                flags |= 1;     // carry flags
 564        else
 565                flags &= ~1;
 566        stackflags = flags;
 567        return ret;
 568}
 569
 570void setup_realmode_idt(void)
 571{
 572        extern unsigned char idthandle, end_idthandle;
 573        extern unsigned char debughandle, end_debughandle;
 574
 575        int i;
 576        struct realidt *idts = (struct realidt *)0;
 577        int codesize = &end_idthandle - &idthandle;
 578        unsigned char *intbyte, *codeptr;
 579
 580        // for each int, we create a customized little handler
 581        // that just pushes %ax, puts the int # in %al, 
 582        // then calls the common interrupt handler. 
 583        // this necessitated because intel didn't know much about 
 584        // architecture when they did the 8086 (it shows)
 585        // (hmm do they know anymore even now :-)
 586        // obviously you can see I don't really care about memory 
 587        // efficiency. If I did I would probe back through the stack
 588        // and get it that way. But that's really disgusting.
 589        for (i = 0; i < 256; i++) {
 590                idts[i].cs = 0;
 591                codeptr = (char *)4096 + i * codesize;
 592                idts[i].offset = (unsigned)codeptr;
 593                memcpy(codeptr, &idthandle, codesize);
 594                intbyte = codeptr + 3;
 595                *intbyte = i;
 596        }
 597
 598        // fixed entry points
 599
 600        // VGA BIOSes tend to hardcode f000:f065 as the previous handler of
 601        // int10. 
 602        // calling convention here is the same as INTs, we can reuse
 603        // the int entry code.
 604        codeptr = (char *)0xff065;
 605        memcpy(codeptr, &idthandle, codesize);
 606        intbyte = codeptr + 3;
 607        *intbyte = 0x42;        /* int42 is the relocated int10 */
 608/*
 609 Fixed entry points
 610  VBIOS will call f000:f859 instead of sending int15.
 611 calling convertion here is the same as INTs, we can reuse the int entry code.
 612*/
 613        codeptr = (char *)0xff859;
 614        memcpy(codeptr, &idthandle, codesize);
 615        intbyte = codeptr + 3;
 616        *intbyte = 0x15;
 617
 618        /* debug handler - useful to set a programmable delay between instructions if the
 619           TF bit is set upon call to real mode */
 620        idts[1].cs = 0;
 621        idts[1].offset = 16384;
 622        memcpy(16384, &debughandle, &end_debughandle - &debughandle);
 623
 624}
 625
 626enum {
 627        CHECK = 0xb001,
 628        FINDDEV = 0xb102,
 629        READCONFBYTE = 0xb108,
 630        READCONFWORD = 0xb109,
 631        READCONFDWORD = 0xb10a,
 632        WRITECONFBYTE = 0xb10b,
 633        WRITECONFWORD = 0xb10c,
 634        WRITECONFDWORD = 0xb10d
 635};
 636
 637// errors go in AH. Just set these up so that word assigns
 638// will work. KISS. 
 639enum {
 640        PCIBIOS_NODEV = 0x8600,
 641        PCIBIOS_BADREG = 0x8700
 642};
 643
 644int
 645pcibios(unsigned long *pedi, unsigned long *pesi, unsigned long *pebp,
 646        unsigned long *pesp, unsigned long *pebx, unsigned long *pedx,
 647        unsigned long *pecx, unsigned long *peax, unsigned long *pflags)
 648{
 649        unsigned long edi = *pedi;
 650        unsigned long esi = *pesi;
 651        unsigned long ebp = *pebp;
 652        unsigned long esp = *pesp;
 653        unsigned long ebx = *pebx;
 654        unsigned long edx = *pedx;
 655        unsigned long ecx = *pecx;
 656        unsigned long eax = *peax;
 657        unsigned long flags = *pflags;
 658        unsigned short func = (unsigned short)eax;
 659        int retval = 0;
 660        unsigned short devid, vendorid, devfn;
 661        short devindex;         /* Use short to get rid of garbage in upper half of 32-bit register */
 662        unsigned char bus;
 663        device_t dev;
 664
 665        switch (func) {
 666        case CHECK:
 667                *pedx = 0x4350;
 668                *pecx = 0x2049;
 669                retval = 0;
 670                break;
 671        case FINDDEV:
 672                {
 673                        devid = *pecx;
 674                        vendorid = *pedx;
 675                        devindex = *pesi;
 676                        dev = 0;
 677                        while ((dev = dev_find_device(vendorid, devid, dev))) {
 678                                if (devindex <= 0)
 679                                        break;
 680                                devindex--;
 681                        }
 682                        if (dev) {
 683                                unsigned short busdevfn;
 684                                *peax = 0;
 685                                // busnum is an unsigned char;
 686                                // devfn is an int, so we mask it off. 
 687                                busdevfn = (dev->bus->secondary << 8)
 688                                    | (dev->path.pci.devfn & 0xff);
 689                                printk_debug("0x%x: return 0x%x\n", func,
 690                                             busdevfn);
 691                                *pebx = busdevfn;
 692                                retval = 0;
 693                        } else {
 694                                *peax = PCIBIOS_NODEV;
 695                                retval = -1;
 696                        }
 697                }
 698                break;
 699        case READCONFDWORD:
 700        case READCONFWORD:
 701        case READCONFBYTE:
 702        case WRITECONFDWORD:
 703        case WRITECONFWORD:
 704        case WRITECONFBYTE:
 705                {
 706                        unsigned long dword;
 707                        unsigned short word;
 708                        unsigned char byte;
 709                        unsigned char reg;
 710
 711                        devfn = *pebx & 0xff;
 712                        bus = *pebx >> 8;
 713                        reg = *pedi;
 714                        dev = dev_find_slot(bus, devfn);
 715                        if (!dev) {
 716                                printk_debug
 717                                    ("0x%x: BAD DEVICE bus %d devfn 0x%x\n",
 718                                     func, bus, devfn);
 719                                // idiots. the pcibios guys assumed you'd never pass a bad bus/devfn!
 720                                *peax = PCIBIOS_BADREG;
 721                                retval = -1;
 722                        }
 723                        switch (func) {
 724                        case READCONFBYTE:
 725                                byte = pci_read_config8(dev, reg);
 726                                *pecx = byte;
 727                                break;
 728                        case READCONFWORD:
 729                                word = pci_read_config16(dev, reg);
 730                                *pecx = word;
 731                                break;
 732                        case READCONFDWORD:
 733                                dword = pci_read_config32(dev, reg);
 734                                *pecx = dword;
 735                                break;
 736                        case WRITECONFBYTE:
 737                                byte = *pecx;
 738                                pci_write_config8(dev, reg, byte);
 739                                break;
 740                        case WRITECONFWORD:
 741                                word = *pecx;
 742                                pci_write_config16(dev, reg, word);
 743                                break;
 744                        case WRITECONFDWORD:
 745                                dword = *pecx;
 746                                pci_write_config32(dev, reg, dword);
 747                                break;
 748                        }
 749
 750                        if (retval)
 751                                retval = PCIBIOS_BADREG;
 752                        printk_debug
 753                            ("0x%x: bus %d devfn 0x%x reg 0x%x val 0x%lx\n",
 754                             func, bus, devfn, reg, *pecx);
 755                        *peax = 0;
 756                        retval = 0;
 757                }
 758                break;
 759        default:
 760                printk_err("UNSUPPORTED PCIBIOS FUNCTION 0x%x\n", func);
 761                break;
 762        }
 763
 764        return retval;
 765}
 766
 767/* return value of int0x15(int21)
 768AH  AL                  Completion status 
 769??  5Fh                 Function call supported 
 770??  !=5Fh       Function not supported 
 77100  5Fh                 Function call successful 
 77201  5Fh                 Function call failed 
 773*/
 774int handleint21(unsigned long *edi, unsigned long *esi, unsigned long *ebp,
 775                unsigned long *esp, unsigned long *ebx, unsigned long *edx,
 776                unsigned long *ecx, unsigned long *eax, unsigned long *flags)
 777{
 778        int res = -1;
 779        switch (*eax & 0xffff) {
 780        case 0x5f19:
 781                *eax = 0x5f;
 782                *ecx = 0x3;
 783                res = 0;
 784                break;
 785        case 0x5f18:
 786                {
 787                        /*
 788                           BL  
 789                           Bit[7:4] 
 790                           Memory Data Rate 
 791                           0000: 66MHz 
 792                           0001: 100MHz 
 793                           0010: 133MHz 
 794                           0011: 200MHz ( DDR200 ) 
 795                           0100: 266MHz ( DDR266 ) 
 796                           0101: 333MHz ( DDR333 ) 
 797                           0110: 400MHz ( DDR400 ) 
 798                           0111: 533MHz ( DDR I/II 533 
 799                           1000: 667MHz ( DDR I/II 667)
 800                           Bit[3:0]  
 801                           N:  Frame Buffer Size 2^N  MB 
 802                         */
 803                        u8 i;
 804                        device_t dev;
 805                        dev = dev_find_slot(0, PCI_DEVFN(0, 3));
 806                        i = pci_read_config8(dev, 0xa1);
 807                        i = (i & 0x70);
 808                        i = i >> 4;
 809                        if (i == 0) {
 810                                *eax = 0x00;    //not support 5f18
 811                                break;
 812                        }
 813                        i = i + 2;
 814                        *ebx = (u32) i;
 815                        i = pci_read_config8(dev, 0x90);
 816                        i = (i & 0x07);
 817                        i = i + 3;
 818                        i = i << 4;
 819                        *ebx = (*ebx) + ((u32) i);
 820                        *eax = 0x5f;
 821                        res = 0;
 822                        break;
 823                }
 824        case 0x5f00:
 825                *eax = 0x005f;
 826                res = 0;
 827                break;
 828        case 0x5f01:
 829                *eax = 0x5f;
 830                *ecx = (*ecx & 0xffffff00) | 2; // panel type =  2 = 1024 * 768
 831                res = 0;
 832                break;
 833        case 0x5f02:
 834                *eax = 0x5f;
 835                *ebx = (*ebx & 0xffff0000) | 2;
 836                *ecx = (*ecx & 0xffff0000) | 0x401;     // PAL + crt only 
 837                *edx = (*edx & 0xffff0000) | 0; // TV Layout - default
 838                res = 0;
 839                break;
 840        case 0x5f0f:
 841                *eax = 0x005f;
 842                res = 0;
 843                break;
 844        default:
 845                *eax = 0;
 846                break;
 847        }
 848        return res;
 849}
 850
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.