root/usr/src/grub/grub-0.97/stage2/apm.S
/*
 *  GRUB  --  GRand Unified Bootloader
 *  Copyright (C) 2000, 2001 Free Software Foundation, Inc.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

/* This is stolen from arch/i386/boot/setup.S in Linux 2.2.17 */
/*
!       setup.S         Copyright (C) 1991, 1992 Linus Torvalds
*/

ENTRY(get_apm_info)
        pushl   %ebp
        pushl   %ebx
        pushl   %edi
        pushl   %esi

        call    EXT_C(prot_to_real)
        .code16
        
        /* APM BIOS installation check */
        movw    $0x5300, %ax
        xorw    %bx, %bx
        int     $0x15
        /* error -> no APM BIOS */
        jc      done_apm_bios

        /* check for "PM" signature */
        cmpw    $0x504d, %bx
        /* no signature -> no APM BIOS */
        jne     done_apm_bios

        /* Is 32 bit supported? */
        andw    $0x0002, %cx
        /* no ... */
        je      done_apm_bios

        /* Disconnect first just in case */
        movw    $0x5304, %ax
        xorw    %bx, %bx
        /* ignore return code */
        int     $0x15

        /* 32 bit connect */
        movw    $0x5303, %ax
        xorl    %ebx, %ebx
        /* paranoia */
        xorw    %cx, %cx
        xorw    %dx, %dx
        xorl    %esi, %esi
        xorw    %di, %di
        int     $0x15
        /* error */
        jc      no_32_apm_bios

        /* BIOS code segment */
        movw    %ax, ABS(EXT_C(apm_bios_info)) + 2
        /* BIOS entry point offset */
        movl    %ebx, ABS(EXT_C(apm_bios_info)) + 4
        /* BIOS 16 bit code segment */
        movw    %cx, ABS(EXT_C(apm_bios_info)) + 8
        /* BIOS data segment */
        movw    %dx, ABS(EXT_C(apm_bios_info)) + 10
        /* BIOS code segment length */
        movl    %esi, ABS(EXT_C(apm_bios_info)) + 14
        /* BIOS data segment length */
        movw    %di, ABS(EXT_C(apm_bios_info)) + 18

        /*
         * Redo the installation check as the 32 bit connect
         * modifies the flags returned on some BIOSs
         */

        /* APM BIOS installation check */
        movw    $0x5300, %ax
        xorw    %bx, %bx
        /* paranoia */
        xorw    %cx, %cx
        int     $0x15
        /* error -> should not happen, tidy up */
        jc      done_apm_bios

        /* check for "PM" signature */
        cmpw    $0x504d, %bx
        /* no signature -> should not happen, tidy up */
        jne     done_apm_bios

        /* record the APM BIOS version */
        movw    %ax, ABS(EXT_C(apm_bios_info))
        /* and flags */
        movw    %cx, ABS(EXT_C(apm_bios_info)) + 12
        jmp     done_apm_bios

no_32_apm_bios:
        /* remove 32 bit support bit */
        andw     $0xfffd, ABS(EXT_C(apm_bios_info)) + 12

done_apm_bios:
        /* Some paranoia here: Always Disconnect from APM */
        movw    $0x5304, %ax
        xorw    %bx, %bx
        /* ignore return code */
        int     $0x15

        DATA32  call    EXT_C(real_to_prot)
        .code32

        popl    %esi
        popl    %edi
        popl    %ebx
        popl    %ebp
        ret