xref: /illumos-gate/usr/src/grub/grub-0.97/stage2/asm.S (revision a5602e1b)
17c478bd9Sstevel@tonic-gate/*
27c478bd9Sstevel@tonic-gate *  GRUB  --  GRand Unified Bootloader
37c478bd9Sstevel@tonic-gate *  Copyright (C) 1999,2000,2001,2002,2004 Free Software Foundation, Inc.
47c478bd9Sstevel@tonic-gate *
57c478bd9Sstevel@tonic-gate *  This program is free software; you can redistribute it and/or modify
67c478bd9Sstevel@tonic-gate *  it under the terms of the GNU General Public License as published by
77c478bd9Sstevel@tonic-gate *  the Free Software Foundation; either version 2 of the License, or
87c478bd9Sstevel@tonic-gate *  (at your option) any later version.
97c478bd9Sstevel@tonic-gate *
107c478bd9Sstevel@tonic-gate *  This program is distributed in the hope that it will be useful,
117c478bd9Sstevel@tonic-gate *  but WITHOUT ANY WARRANTY; without even the implied warranty of
127c478bd9Sstevel@tonic-gate *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
137c478bd9Sstevel@tonic-gate *  GNU General Public License for more details.
147c478bd9Sstevel@tonic-gate *
157c478bd9Sstevel@tonic-gate *  You should have received a copy of the GNU General Public License
167c478bd9Sstevel@tonic-gate *  along with this program; if not, write to the Free Software
177c478bd9Sstevel@tonic-gate *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
187c478bd9Sstevel@tonic-gate */
197c478bd9Sstevel@tonic-gate
207c478bd9Sstevel@tonic-gate
217c478bd9Sstevel@tonic-gate/*
227c478bd9Sstevel@tonic-gate * Note: These functions defined in this file may be called from C.
237c478bd9Sstevel@tonic-gate *       Be careful of that you must not modify some registers. Quote
247c478bd9Sstevel@tonic-gate *       from gcc-2.95.2/gcc/config/i386/i386.h:
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate   1 for registers not available across function calls.
277c478bd9Sstevel@tonic-gate   These must include the FIXED_REGISTERS and also any
287c478bd9Sstevel@tonic-gate   registers that can be used without being saved.
297c478bd9Sstevel@tonic-gate   The latter must include the registers where values are returned
307c478bd9Sstevel@tonic-gate   and the register where structure-value addresses are passed.
317c478bd9Sstevel@tonic-gate   Aside from that, you can include as many other registers as you like.
327c478bd9Sstevel@tonic-gate
337c478bd9Sstevel@tonic-gate  ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg
347c478bd9Sstevel@tonic-gate{  1, 1, 1, 0, 0, 0, 0, 1, 1,  1,  1,  1,  1,  1,  1,  1,  1 }
357c478bd9Sstevel@tonic-gate */
367c478bd9Sstevel@tonic-gate
377c478bd9Sstevel@tonic-gate#define ASM_FILE
387c478bd9Sstevel@tonic-gate
397c478bd9Sstevel@tonic-gate#include "shared.h"
407c478bd9Sstevel@tonic-gate
417c478bd9Sstevel@tonic-gate#ifdef STAGE1_5
427c478bd9Sstevel@tonic-gate# define	ABS(x)	((x) - EXT_C(main) + 0x2200)
437c478bd9Sstevel@tonic-gate#else
447c478bd9Sstevel@tonic-gate# define	ABS(x)	((x) - EXT_C(main) + 0x8200)
457c478bd9Sstevel@tonic-gate#endif
467c478bd9Sstevel@tonic-gate
477c478bd9Sstevel@tonic-gate	.file	"asm.S"
487c478bd9Sstevel@tonic-gate
497c478bd9Sstevel@tonic-gate	.text
507c478bd9Sstevel@tonic-gate
517c478bd9Sstevel@tonic-gate	/* Tell GAS to generate 16-bit instructions so that this code works
527c478bd9Sstevel@tonic-gate	   in real mode. */
537c478bd9Sstevel@tonic-gate	.code16
547c478bd9Sstevel@tonic-gate
557c478bd9Sstevel@tonic-gate#ifndef STAGE1_5
567c478bd9Sstevel@tonic-gate	/*
577c478bd9Sstevel@tonic-gate	 * In stage2, do not link start.S with the rest of the source
587c478bd9Sstevel@tonic-gate	 * files directly, so define the start symbols here just to
597c478bd9Sstevel@tonic-gate	 * force ld quiet. These are not referred anyway.
607c478bd9Sstevel@tonic-gate	 */
617c478bd9Sstevel@tonic-gate	.globl	start, _start
627c478bd9Sstevel@tonic-gatestart:
637c478bd9Sstevel@tonic-gate_start:
647c478bd9Sstevel@tonic-gate#endif /* ! STAGE1_5 */
657c478bd9Sstevel@tonic-gate
667c478bd9Sstevel@tonic-gateENTRY(main)
677c478bd9Sstevel@tonic-gate	/*
687c478bd9Sstevel@tonic-gate	 *  Guarantee that "main" is loaded at 0x0:0x8200 in stage2 and
697c478bd9Sstevel@tonic-gate	 *  at 0x0:0x2200 in stage1.5.
707c478bd9Sstevel@tonic-gate	 */
717c478bd9Sstevel@tonic-gate	ljmp $0, $ABS(codestart)
727c478bd9Sstevel@tonic-gate
737c478bd9Sstevel@tonic-gate	/*
747c478bd9Sstevel@tonic-gate	 *  Compatibility version number
757c478bd9Sstevel@tonic-gate	 *
767c478bd9Sstevel@tonic-gate	 *  These MUST be at byte offset 6 and 7 of the executable
777c478bd9Sstevel@tonic-gate	 *  DO NOT MOVE !!!
787c478bd9Sstevel@tonic-gate	 */
797c478bd9Sstevel@tonic-gate	. = EXT_C(main) + 0x6
807c478bd9Sstevel@tonic-gate	.byte	COMPAT_VERSION_MAJOR, COMPAT_VERSION_MINOR
817c478bd9Sstevel@tonic-gate
827c478bd9Sstevel@tonic-gate	/*
837c478bd9Sstevel@tonic-gate	 *  This is a special data area 8 bytes from the beginning.
847c478bd9Sstevel@tonic-gate	 */
857c478bd9Sstevel@tonic-gate
867c478bd9Sstevel@tonic-gate	. = EXT_C(main) + 0x8
877c478bd9Sstevel@tonic-gate
887c478bd9Sstevel@tonic-gateVARIABLE(install_partition)
897c478bd9Sstevel@tonic-gate	.long	0xFFFFFF
907c478bd9Sstevel@tonic-gate/* This variable is here only because of a historical reason.  */
917c478bd9Sstevel@tonic-gateVARIABLE(saved_entryno)
927c478bd9Sstevel@tonic-gate	.long	0
937c478bd9Sstevel@tonic-gateVARIABLE(stage2_id)
947c478bd9Sstevel@tonic-gate	.byte	STAGE2_ID
957c478bd9Sstevel@tonic-gateVARIABLE(force_lba)
967c478bd9Sstevel@tonic-gate	.byte	0
977c478bd9Sstevel@tonic-gateVARIABLE(version_string)
987c478bd9Sstevel@tonic-gate	.string VERSION
997c478bd9Sstevel@tonic-gateVARIABLE(config_file)
1007c478bd9Sstevel@tonic-gate#ifndef STAGE1_5
1017c478bd9Sstevel@tonic-gate	.string "/boot/grub/menu.lst"
1027c478bd9Sstevel@tonic-gate#else   /* STAGE1_5 */
1037c478bd9Sstevel@tonic-gate	.long	0xffffffff
1047c478bd9Sstevel@tonic-gate	.string "/boot/grub/stage2"
1057c478bd9Sstevel@tonic-gate#endif  /* STAGE1_5 */
1067c478bd9Sstevel@tonic-gate
1077c478bd9Sstevel@tonic-gate	/*
1087c478bd9Sstevel@tonic-gate	 *  Leave some breathing room for the config file name.
1097c478bd9Sstevel@tonic-gate	 */
1107c478bd9Sstevel@tonic-gate
111af28f636SEnrico Perla - Sun Microsystems	. = EXT_C(main) + 0x60
112af28f636SEnrico Perla - Sun MicrosystemsVARIABLE(fake_mboot)
113af28f636SEnrico Perla - Sun Microsystems	.long	0x1BADB002
114af28f636SEnrico Perla - Sun Microsystems	.long   0x00010003
115af28f636SEnrico Perla - Sun Microsystems	.long	-0x1BAEB005
1167ce76caaSEnrico Perla - Sun Microsystems	/*
117af28f636SEnrico Perla - Sun Microsystems	 * installgrub will place the rest of the fake
118af28f636SEnrico Perla - Sun Microsystems	 * multiboot header here.
1197ce76caaSEnrico Perla - Sun Microsystems	 */
120af28f636SEnrico Perla - Sun Microsystems	.= EXT_C(main) + 0x140
1217c478bd9Sstevel@tonic-gate/* the real mode code continues... */
1227c478bd9Sstevel@tonic-gatecodestart:
1237c478bd9Sstevel@tonic-gate	cli		/* we're not safe here! */
1247c478bd9Sstevel@tonic-gate
1257c478bd9Sstevel@tonic-gate	/* set up %ds, %ss, and %es */
1267c478bd9Sstevel@tonic-gate	xorw	%ax, %ax
1277c478bd9Sstevel@tonic-gate	movw	%ax, %ds
1287c478bd9Sstevel@tonic-gate	movw	%ax, %ss
1297c478bd9Sstevel@tonic-gate	movw	%ax, %es
1307c478bd9Sstevel@tonic-gate
1317c478bd9Sstevel@tonic-gate#ifndef SUPPORT_DISKLESS
1327c478bd9Sstevel@tonic-gate	/*
1337c478bd9Sstevel@tonic-gate	 * Save the sector number of the second sector (i.e. this sector)
1347c478bd9Sstevel@tonic-gate	 * in INSTALL_SECOND_SECTOR. See also "stage2/start.S".
1357c478bd9Sstevel@tonic-gate	 */
1367c478bd9Sstevel@tonic-gate	ADDR32	movl	%ebp, EXT_C(install_second_sector)
1377c478bd9Sstevel@tonic-gate#endif
1387c478bd9Sstevel@tonic-gate
1397c478bd9Sstevel@tonic-gate	/* set up the real mode/BIOS stack */
1407c478bd9Sstevel@tonic-gate	movl	$STACKOFF, %ebp
1417c478bd9Sstevel@tonic-gate	movl	%ebp, %esp
1427c478bd9Sstevel@tonic-gate
1437c478bd9Sstevel@tonic-gate	sti		/* we're safe again */
1447c478bd9Sstevel@tonic-gate
1457c478bd9Sstevel@tonic-gate#ifndef SUPPORT_DISKLESS
1467c478bd9Sstevel@tonic-gate	/* save boot drive reference */
1477c478bd9Sstevel@tonic-gate	ADDR32	movb	%dl, EXT_C(boot_drive)
1487c478bd9Sstevel@tonic-gate
1497c478bd9Sstevel@tonic-gate	/* reset disk system (%ah = 0) */
1507c478bd9Sstevel@tonic-gate	int	$0x13
1517c478bd9Sstevel@tonic-gate#endif
1527c478bd9Sstevel@tonic-gate
1537c478bd9Sstevel@tonic-gate	/* transition to protected mode */
1547c478bd9Sstevel@tonic-gate	DATA32	call EXT_C(real_to_prot)
1557c478bd9Sstevel@tonic-gate
1567c478bd9Sstevel@tonic-gate	/* The ".code32" directive takes GAS out of 16-bit mode. */
1577c478bd9Sstevel@tonic-gate	.code32
1587c478bd9Sstevel@tonic-gate
1597c478bd9Sstevel@tonic-gate	/* clean out the bss */
1607c478bd9Sstevel@tonic-gate
1617c478bd9Sstevel@tonic-gate	/* set %edi to the bss starting address */
1627c478bd9Sstevel@tonic-gate#if defined(HAVE_USCORE_USCORE_BSS_START_SYMBOL)
1637c478bd9Sstevel@tonic-gate	movl	$__bss_start, %edi
1647c478bd9Sstevel@tonic-gate#elif defined(HAVE_USCORE_EDATA_SYMBOL)
1657c478bd9Sstevel@tonic-gate	movl	$_edata, %edi
1667c478bd9Sstevel@tonic-gate#elif defined(HAVE_EDATA_SYMBOL)
1677c478bd9Sstevel@tonic-gate	movl	$edata, %edi
1687c478bd9Sstevel@tonic-gate#endif
1697c478bd9Sstevel@tonic-gate
1707c478bd9Sstevel@tonic-gate	/* set %ecx to the bss end */
1717c478bd9Sstevel@tonic-gate#if defined(HAVE_END_SYMBOL)
1727c478bd9Sstevel@tonic-gate	movl	$end, %ecx
1737c478bd9Sstevel@tonic-gate#elif defined(HAVE_USCORE_END_SYMBOL)
1747c478bd9Sstevel@tonic-gate	movl	$_end, %ecx
1757c478bd9Sstevel@tonic-gate#endif
1767c478bd9Sstevel@tonic-gate
1777c478bd9Sstevel@tonic-gate	/* compute the bss length */
1787c478bd9Sstevel@tonic-gate	subl	%edi, %ecx
1797c478bd9Sstevel@tonic-gate
1807c478bd9Sstevel@tonic-gate	/* zero %al */
1817c478bd9Sstevel@tonic-gate	xorb	%al, %al
1827c478bd9Sstevel@tonic-gate
1837c478bd9Sstevel@tonic-gate	/* set the direction */
1847c478bd9Sstevel@tonic-gate	cld
1857c478bd9Sstevel@tonic-gate
1867c478bd9Sstevel@tonic-gate	/* clean out */
1877c478bd9Sstevel@tonic-gate	rep
1887c478bd9Sstevel@tonic-gate	stosb
1897c478bd9Sstevel@tonic-gate
1907c478bd9Sstevel@tonic-gate	/*
1917c478bd9Sstevel@tonic-gate	 *  Call the start of main body of C code, which does some
1927c478bd9Sstevel@tonic-gate	 *  of it's own initialization before transferring to "cmain".
1937c478bd9Sstevel@tonic-gate	 */
1947c478bd9Sstevel@tonic-gate	call EXT_C(init_bios_info)
1957c478bd9Sstevel@tonic-gate
1967c478bd9Sstevel@tonic-gate
1977c478bd9Sstevel@tonic-gate/*
1987c478bd9Sstevel@tonic-gate *  This call is special...  it never returns...  in fact it should simply
1997c478bd9Sstevel@tonic-gate *  hang at this point!
2007c478bd9Sstevel@tonic-gate */
2017c478bd9Sstevel@tonic-gate
2027c478bd9Sstevel@tonic-gateENTRY(stop)
2037c478bd9Sstevel@tonic-gate	call	EXT_C(prot_to_real)
2047c478bd9Sstevel@tonic-gate
2057c478bd9Sstevel@tonic-gate	/*
2067c478bd9Sstevel@tonic-gate	 * This next part is sort of evil.  It takes advantage of the
2077c478bd9Sstevel@tonic-gate	 * byte ordering on the x86 to work in either 16-bit or 32-bit
2087c478bd9Sstevel@tonic-gate	 * mode, so think about it before changing it.
2097c478bd9Sstevel@tonic-gate	 */
2107c478bd9Sstevel@tonic-gate
2117c478bd9Sstevel@tonic-gateENTRY(hard_stop)
2127c478bd9Sstevel@tonic-gate	hlt
2137c478bd9Sstevel@tonic-gate	jmp EXT_C(hard_stop)
2147c478bd9Sstevel@tonic-gate
2157c478bd9Sstevel@tonic-gate#ifndef STAGE1_5
2167c478bd9Sstevel@tonic-gate
2177c478bd9Sstevel@tonic-gate/**************************************************************************
2187c478bd9Sstevel@tonic-gateUNDI_CALL - wrapper around real-mode UNDI API calls
2197c478bd9Sstevel@tonic-gate**************************************************************************/
2207c478bd9Sstevel@tonic-gateENTRY(__undi_call)
2217c478bd9Sstevel@tonic-gate       pushl   %ebp
2227c478bd9Sstevel@tonic-gate       movl    %esp,%ebp
2237c478bd9Sstevel@tonic-gate       pushl   %esi
2247c478bd9Sstevel@tonic-gate       pushl   %edi
2257c478bd9Sstevel@tonic-gate       pushl   %ebx
2267c478bd9Sstevel@tonic-gate
2277c478bd9Sstevel@tonic-gate       movw    8(%ebp),%cx     /* Seg:off addr of undi_call_info_t struct */
2287c478bd9Sstevel@tonic-gate       movw    12(%ebp),%dx    /* Pass to 16-bit code in %cx:%dx */
2297c478bd9Sstevel@tonic-gate
2307c478bd9Sstevel@tonic-gate       call EXT_C(prot_to_real)
2317c478bd9Sstevel@tonic-gate       .code16
2327c478bd9Sstevel@tonic-gate
2337c478bd9Sstevel@tonic-gate       movw    %cx,%es         /* Seg:off addr of undi_call_info_t struct */
2347c478bd9Sstevel@tonic-gate       movw    %dx,%bx         /* into %es:%bx */
2357c478bd9Sstevel@tonic-gate
2367c478bd9Sstevel@tonic-gate       movw    %es:8(%bx),%ax  /* Transfer contents of undi_call_info_t */
2377c478bd9Sstevel@tonic-gate       pushw   %ax             /* structure to the real-mode stack */
2387c478bd9Sstevel@tonic-gate       movw    %es:6(%bx),%ax
2397c478bd9Sstevel@tonic-gate       pushw   %ax
2407c478bd9Sstevel@tonic-gate       movw    %es:4(%bx),%ax
2417c478bd9Sstevel@tonic-gate       pushw   %ax
2427c478bd9Sstevel@tonic-gate
2437c478bd9Sstevel@tonic-gate       lcall   *%es:0(%bx)     /* Do the UNDI call */
2447c478bd9Sstevel@tonic-gate       cld                     /* Don't know whether or not we need this */
2457c478bd9Sstevel@tonic-gate                               /* but pxelinux includes it for some reason, */
2467c478bd9Sstevel@tonic-gate                               /* so we put it in just in case. */
2477c478bd9Sstevel@tonic-gate
2487c478bd9Sstevel@tonic-gate       popw    %cx             /* Tidy up the stack */
2497c478bd9Sstevel@tonic-gate       popw    %cx
2507c478bd9Sstevel@tonic-gate       popw    %cx
2517c478bd9Sstevel@tonic-gate       movw    %ax,%cx         /* Return %ax via %cx */
2527c478bd9Sstevel@tonic-gate
2537c478bd9Sstevel@tonic-gate       DATA32 call EXT_C(real_to_prot)
2547c478bd9Sstevel@tonic-gate       .code32
2557c478bd9Sstevel@tonic-gate
2567c478bd9Sstevel@tonic-gate       xorl    %eax,%eax       /* %ax is returned via %cx */
2577c478bd9Sstevel@tonic-gate       movw    %cx,%ax
2587c478bd9Sstevel@tonic-gate
2597c478bd9Sstevel@tonic-gate       popl    %ebx
2607c478bd9Sstevel@tonic-gate       popl    %edi
2617c478bd9Sstevel@tonic-gate       popl	%esi
2627c478bd9Sstevel@tonic-gate       popl	%ebp
2637c478bd9Sstevel@tonic-gate       ret
2647c478bd9Sstevel@tonic-gate
2657c478bd9Sstevel@tonic-gate/**************************************************************************
2667c478bd9Sstevel@tonic-gateUNDI_IRQ_HANDLER - UNDI IRQ handler: calls PXENV_UNDI_ISR and send EOI
2677c478bd9Sstevel@tonic-gateNOTE: For some reason, this handler needs to be aligned. Else, the
2687c478bd9Sstevel@tonic-gate	undi driver won't get the trigger count on some platforms.
2697c478bd9Sstevel@tonic-gate**************************************************************************/
2707c478bd9Sstevel@tonic-gate	.align 4
2717c478bd9Sstevel@tonic-gateENTRY(_undi_irq_handler)
2727c478bd9Sstevel@tonic-gate	.code16
2737c478bd9Sstevel@tonic-gate	pushw	%ax
2747c478bd9Sstevel@tonic-gate	pushw	%bx
2757c478bd9Sstevel@tonic-gate	pushw	%cx
2767c478bd9Sstevel@tonic-gate	call	1f		/* Position-independent access to */
2777c478bd9Sstevel@tonic-gate1:	popw	%bx		/* various locations.		  */
2787c478bd9Sstevel@tonic-gate	pushw	%bx		/* save for after UNDI call */
2797c478bd9Sstevel@tonic-gate
2807c478bd9Sstevel@tonic-gate	/* set funcflag to PXENV_UNDI_ISR_IN_START */
2817c478bd9Sstevel@tonic-gate	movw	$1,%cs:(pxenv_undi_isr-1b+2)(%bx)
2827c478bd9Sstevel@tonic-gate
2837c478bd9Sstevel@tonic-gate	/* push pxenv_undi_isr struct on stack */
2847c478bd9Sstevel@tonic-gate	movl	$(ABS(pxenv_undi_isr)),%eax
2857c478bd9Sstevel@tonic-gate	movw	%ax,%cx
2867c478bd9Sstevel@tonic-gate	shrl	$4,%eax		/* get segment */
2877c478bd9Sstevel@tonic-gate	pushw	%ax
2887c478bd9Sstevel@tonic-gate	andw	$0xf,%cx	/* get offset */
2897c478bd9Sstevel@tonic-gate	pushw	%cx
2907c478bd9Sstevel@tonic-gate	movw    $0x14,%ax	/* opcode PXENV_UNDI_ISR */
2917c478bd9Sstevel@tonic-gate	pushw   %ax
2927c478bd9Sstevel@tonic-gate
2937c478bd9Sstevel@tonic-gate	lcall   *%cs:(pxenv_entrypointsp-1b)(%bx)	/* Do the UNDI call */
2947c478bd9Sstevel@tonic-gate	cld                     /* Don't know whether or not we need this */
2957c478bd9Sstevel@tonic-gate				/* but pxelinux includes it for some reason, */
2967c478bd9Sstevel@tonic-gate				/* so we put it in just in case. */
2977c478bd9Sstevel@tonic-gate	popw    %cx             /* Tidy up the stack */
2987c478bd9Sstevel@tonic-gate	popw    %cx
2997c478bd9Sstevel@tonic-gate	popw    %cx
3007c478bd9Sstevel@tonic-gate
3017c478bd9Sstevel@tonic-gate	popw	%bx		/* restore old position reg */
3027c478bd9Sstevel@tonic-gate
3037c478bd9Sstevel@tonic-gate	cmpw	$0,%ax		/* did the UNDI call succeed? */
3047c478bd9Sstevel@tonic-gate	jne	3f
3057c478bd9Sstevel@tonic-gate	movw	%cs:(pxenv_undi_isr-1b+2)(%bx),%ax
3067c478bd9Sstevel@tonic-gate	cmpw	$0,%ax		/* is this our interrupt? */
3077c478bd9Sstevel@tonic-gate	jne	3f
3087c478bd9Sstevel@tonic-gate
3097c478bd9Sstevel@tonic-gate	/* send EOI -- non specific for now */
3107c478bd9Sstevel@tonic-gate	movw	$0x20,%ax		/* ICR_EOI_NON_SPECIFIC */
3117c478bd9Sstevel@tonic-gate	movb	%cs:(pxenv_undi_irq-1b),%cl
3127c478bd9Sstevel@tonic-gate	cmpb	$8,%cl
3137c478bd9Sstevel@tonic-gate	jg	2f
3147c478bd9Sstevel@tonic-gate	outb	$0xa0			/* PIC2_ICR */
3157c478bd9Sstevel@tonic-gate2:	outb	$0x20			/* PIC1_ICR */
3167c478bd9Sstevel@tonic-gate
3177c478bd9Sstevel@tonic-gate	/* increment trigger count */
3187c478bd9Sstevel@tonic-gate	incw	%cs:(EXT_C(_undi_irq_trigger_count)-1b)(%bx)
3197c478bd9Sstevel@tonic-gate
3207c478bd9Sstevel@tonic-gate	/* restore other registers */
3217c478bd9Sstevel@tonic-gate3:	popw	%cx
3227c478bd9Sstevel@tonic-gate	popw	%bx
3237c478bd9Sstevel@tonic-gate	popw	%ax
3247c478bd9Sstevel@tonic-gate	iret
3257c478bd9Sstevel@tonic-gateENTRY(_undi_irq_trigger_count)
3267c478bd9Sstevel@tonic-gateundi_irq_trigger_count:
3277c478bd9Sstevel@tonic-gate	.word	0
3287c478bd9Sstevel@tonic-gateENTRY(_undi_irq_chain_to)
3297c478bd9Sstevel@tonic-gate	.long	0
3307c478bd9Sstevel@tonic-gateENTRY(_undi_irq_chain)
3317c478bd9Sstevel@tonic-gate	.byte	0
3327c478bd9Sstevel@tonic-gateENTRY(_pxenv_undi_irq)
3337c478bd9Sstevel@tonic-gatepxenv_undi_irq:
3347c478bd9Sstevel@tonic-gate	.byte	0
3357c478bd9Sstevel@tonic-gateENTRY(_pxenv_undi_entrypointsp)
3367c478bd9Sstevel@tonic-gatepxenv_entrypointsp:
3377c478bd9Sstevel@tonic-gate	.word	0	/* offset */
3387c478bd9Sstevel@tonic-gate	.word	0	/* segment */
3397c478bd9Sstevel@tonic-gatepxenv_undi_isr:
3407c478bd9Sstevel@tonic-gate	.word	0	/* status */
3417c478bd9Sstevel@tonic-gate	.word	0	/* funcflag */
3427c478bd9Sstevel@tonic-gate	.long	0	/* struct padding not used by ISR */
3437c478bd9Sstevel@tonic-gate	.long	0
3447c478bd9Sstevel@tonic-gate	.long	0
3457c478bd9Sstevel@tonic-gate
3467c478bd9Sstevel@tonic-gate	.code32
3477c478bd9Sstevel@tonic-gate
3487c478bd9Sstevel@tonic-gate/*
3497c478bd9Sstevel@tonic-gate * stop_floppy()
3507c478bd9Sstevel@tonic-gate *
3517c478bd9Sstevel@tonic-gate * Stops the floppy drive from spinning, so that other software is
3527c478bd9Sstevel@tonic-gate * jumped to with a known state.
3537c478bd9Sstevel@tonic-gate */
3547c478bd9Sstevel@tonic-gateENTRY(stop_floppy)
3557c478bd9Sstevel@tonic-gate	pusha
3567c478bd9Sstevel@tonic-gate	call	EXT_C(prot_to_real)
3577c478bd9Sstevel@tonic-gate	.code16
3587c478bd9Sstevel@tonic-gate	xorb	%dl, %dl
3597c478bd9Sstevel@tonic-gate	int	$0x13
3607c478bd9Sstevel@tonic-gate	DATA32  call EXT_C(real_to_prot)
3617c478bd9Sstevel@tonic-gate	.code32
3627c478bd9Sstevel@tonic-gate	popa
3637c478bd9Sstevel@tonic-gate	ret
3647c478bd9Sstevel@tonic-gate
3657c478bd9Sstevel@tonic-gate/*
3667c478bd9Sstevel@tonic-gate * grub_reboot()
3677c478bd9Sstevel@tonic-gate *
3687c478bd9Sstevel@tonic-gate * Reboot the system. At the moment, rely on BIOS.
3697c478bd9Sstevel@tonic-gate */
3707c478bd9Sstevel@tonic-gateENTRY(grub_reboot)
3717c478bd9Sstevel@tonic-gate	call	EXT_C(prot_to_real)
3727c478bd9Sstevel@tonic-gate	.code16
3737c478bd9Sstevel@tonic-gate	/* cold boot */
3747c478bd9Sstevel@tonic-gate	movw	$0x0472, %di
3757c478bd9Sstevel@tonic-gate	movw	%ax, (%di)
3767c478bd9Sstevel@tonic-gate	ljmp	$0xFFFF, $0x0000
3777c478bd9Sstevel@tonic-gate	.code32
3787c478bd9Sstevel@tonic-gate
3797c478bd9Sstevel@tonic-gate/*
3807c478bd9Sstevel@tonic-gate * grub_halt(int no_apm)
3817c478bd9Sstevel@tonic-gate *
3827c478bd9Sstevel@tonic-gate * Halt the system, using APM if possible. If NO_APM is true, don't use
3837c478bd9Sstevel@tonic-gate * APM even if it is available.
3847c478bd9Sstevel@tonic-gate */
3857c478bd9Sstevel@tonic-gateENTRY(grub_halt)
3867c478bd9Sstevel@tonic-gate	/* get the argument */
3877c478bd9Sstevel@tonic-gate	movl	4(%esp), %eax
3887c478bd9Sstevel@tonic-gate
3897c478bd9Sstevel@tonic-gate	/* see if zero */
3907c478bd9Sstevel@tonic-gate	testl	%eax, %eax
3917c478bd9Sstevel@tonic-gate	jnz	EXT_C(stop)
3927c478bd9Sstevel@tonic-gate
3937c478bd9Sstevel@tonic-gate	call	EXT_C(prot_to_real)
3947c478bd9Sstevel@tonic-gate	.code16
3957c478bd9Sstevel@tonic-gate
3967c478bd9Sstevel@tonic-gate	/* detect APM */
3977c478bd9Sstevel@tonic-gate	movw	$0x5300, %ax
3987c478bd9Sstevel@tonic-gate	xorw	%bx, %bx
3997c478bd9Sstevel@tonic-gate	int	$0x15
4007c478bd9Sstevel@tonic-gate	jc	EXT_C(hard_stop)
4017c478bd9Sstevel@tonic-gate	/* don't check %bx for buggy BIOSes... */
4027c478bd9Sstevel@tonic-gate
4037c478bd9Sstevel@tonic-gate	/* disconnect APM first */
4047c478bd9Sstevel@tonic-gate	movw	$0x5304, %ax
4057c478bd9Sstevel@tonic-gate	xorw	%bx, %bx
4067c478bd9Sstevel@tonic-gate	int	$0x15
4077c478bd9Sstevel@tonic-gate
4087c478bd9Sstevel@tonic-gate	/* connect APM */
4097c478bd9Sstevel@tonic-gate	movw	$0x5301, %ax
4107c478bd9Sstevel@tonic-gate	xorw	%bx, %bx
4117c478bd9Sstevel@tonic-gate	int	$0x15
4127c478bd9Sstevel@tonic-gate	jc	EXT_C(hard_stop)
4137c478bd9Sstevel@tonic-gate
4147c478bd9Sstevel@tonic-gate	/* set APM protocol level - 1.1 or bust. (this covers APM 1.2 also) */
4157c478bd9Sstevel@tonic-gate	movw	$0x530E, %ax
4167c478bd9Sstevel@tonic-gate	xorw	%bx, %bx
4177c478bd9Sstevel@tonic-gate	movw	$0x0101, %cx
4187c478bd9Sstevel@tonic-gate	int	$0x15
4197c478bd9Sstevel@tonic-gate	jc	EXT_C(hard_stop)
4207c478bd9Sstevel@tonic-gate
4217c478bd9Sstevel@tonic-gate	/* set the power state to off */
4227c478bd9Sstevel@tonic-gate	movw	$0x5307, %ax
4237c478bd9Sstevel@tonic-gate	movw	$1, %bx
4247c478bd9Sstevel@tonic-gate	movw	$3, %cx
4257c478bd9Sstevel@tonic-gate	int	$0x15
4267c478bd9Sstevel@tonic-gate
4277c478bd9Sstevel@tonic-gate	/* shouldn't reach here */
4287c478bd9Sstevel@tonic-gate	jmp	EXT_C(hard_stop)
4297c478bd9Sstevel@tonic-gate	.code32
4307c478bd9Sstevel@tonic-gate
4317c478bd9Sstevel@tonic-gate/*
4327c478bd9Sstevel@tonic-gate * track_int13(int drive)
4337c478bd9Sstevel@tonic-gate *
4347c478bd9Sstevel@tonic-gate * Track the int13 handler to probe I/O address space.
4357c478bd9Sstevel@tonic-gate */
4367c478bd9Sstevel@tonic-gateENTRY(track_int13)
4377c478bd9Sstevel@tonic-gate	pushl	%ebp
4387c478bd9Sstevel@tonic-gate	movl	%esp, %ebp
4397c478bd9Sstevel@tonic-gate
4407c478bd9Sstevel@tonic-gate	pushl	%ebx
4417c478bd9Sstevel@tonic-gate	pushl	%edi
4427c478bd9Sstevel@tonic-gate
4437c478bd9Sstevel@tonic-gate	/* copy the original int13 handler segment:offset */
4447c478bd9Sstevel@tonic-gate	movl	$0x4c, %edi
4457c478bd9Sstevel@tonic-gate	movl	(%edi), %eax
4467c478bd9Sstevel@tonic-gate	movl	%eax, track_int13_addr
4477c478bd9Sstevel@tonic-gate
4487c478bd9Sstevel@tonic-gate	/* replace the int1 handler */
4497c478bd9Sstevel@tonic-gate	movl	$0x4, %edi
4507c478bd9Sstevel@tonic-gate	pushl	(%edi)
4517c478bd9Sstevel@tonic-gate	movl	$ABS(int1_handler), %eax
4527c478bd9Sstevel@tonic-gate	movl	%eax, (%edi)
4537c478bd9Sstevel@tonic-gate
4547c478bd9Sstevel@tonic-gate	/* read the MBR to call int13 successfully */
4557c478bd9Sstevel@tonic-gate	movb	8(%ebp), %dl
4567c478bd9Sstevel@tonic-gate
4577c478bd9Sstevel@tonic-gate	call	EXT_C(prot_to_real)
4587c478bd9Sstevel@tonic-gate	.code16
4597c478bd9Sstevel@tonic-gate
4607c478bd9Sstevel@tonic-gate	movw	$SCRATCHSEG, %ax
4617c478bd9Sstevel@tonic-gate	movw	%ax, %es
4627c478bd9Sstevel@tonic-gate	xorw	%bx, %bx
4637c478bd9Sstevel@tonic-gate	movw	$1, %cx
4647c478bd9Sstevel@tonic-gate	xorb	%dh, %dh
4657c478bd9Sstevel@tonic-gate
4667c478bd9Sstevel@tonic-gate	/* save FLAGS on the stack to emulate int13 */
4677c478bd9Sstevel@tonic-gate	pushfw
4687c478bd9Sstevel@tonic-gate
4697c478bd9Sstevel@tonic-gate	/* set the TF flag */
4707c478bd9Sstevel@tonic-gate	/* FIXME: this can be simplified not to use AX */
4717c478bd9Sstevel@tonic-gate	pushfw
4727c478bd9Sstevel@tonic-gate	popw	%ax
4737c478bd9Sstevel@tonic-gate	orw	$0x100, %ax
4747c478bd9Sstevel@tonic-gate	pushw	%ax
4757c478bd9Sstevel@tonic-gate	popfw
4767c478bd9Sstevel@tonic-gate
4777c478bd9Sstevel@tonic-gate	movw	$0x0201, %ax
4787c478bd9Sstevel@tonic-gate
4797c478bd9Sstevel@tonic-gate	.byte	0x9a		/* lcall */
4807c478bd9Sstevel@tonic-gatetrack_int13_addr:
4817c478bd9Sstevel@tonic-gate	.word	0		/* offset */
4827c478bd9Sstevel@tonic-gate	.word	0		/* segment */
4837c478bd9Sstevel@tonic-gate
4847c478bd9Sstevel@tonic-gate	/* TF is cleared here automatically */
4857c478bd9Sstevel@tonic-gate
4867c478bd9Sstevel@tonic-gate	DATA32	call	EXT_C(real_to_prot)
4877c478bd9Sstevel@tonic-gate	.code32
4887c478bd9Sstevel@tonic-gate
4897c478bd9Sstevel@tonic-gate	/* restore the int1 handler */
4907c478bd9Sstevel@tonic-gate	movl	$0x4, %edi
4917c478bd9Sstevel@tonic-gate	popl	(%edi)
4927c478bd9Sstevel@tonic-gate
4937c478bd9Sstevel@tonic-gate	popl	%edi
4947c478bd9Sstevel@tonic-gate	popl	%ebx
4957c478bd9Sstevel@tonic-gate	popl	%ebp
4967c478bd9Sstevel@tonic-gate
4977c478bd9Sstevel@tonic-gate	ret
4987c478bd9Sstevel@tonic-gate
4997c478bd9Sstevel@tonic-gate
5007c478bd9Sstevel@tonic-gate/*
5017c478bd9Sstevel@tonic-gate * Check if the next instruction is I/O, and if this is true, add the
5027c478bd9Sstevel@tonic-gate * port into the io map.
5037c478bd9Sstevel@tonic-gate *
5047c478bd9Sstevel@tonic-gate * Note: Probably this will make the execution of int13 very slow.
5057c478bd9Sstevel@tonic-gate *
5067c478bd9Sstevel@tonic-gate * Note2: In this implementation, all we can know is I/O-mapped I/O. It
5077c478bd9Sstevel@tonic-gate * is impossible to detect memory-mapped I/O.
5087c478bd9Sstevel@tonic-gate */
5097c478bd9Sstevel@tonic-gateint1_handler:
5107c478bd9Sstevel@tonic-gate	.code16
5117c478bd9Sstevel@tonic-gate
5127c478bd9Sstevel@tonic-gate	pushw	%bp
5137c478bd9Sstevel@tonic-gate	movw	%sp, %bp
5147c478bd9Sstevel@tonic-gate	pushw	%ds
5157c478bd9Sstevel@tonic-gate	pushw	%ax
5167c478bd9Sstevel@tonic-gate	pushw	%si
5177c478bd9Sstevel@tonic-gate	pushw	%dx
5187c478bd9Sstevel@tonic-gate
5197c478bd9Sstevel@tonic-gate	/* IP */
5207c478bd9Sstevel@tonic-gate	movw	2(%bp), %si
5217c478bd9Sstevel@tonic-gate	/* CS */
5227c478bd9Sstevel@tonic-gate	movw	4(%bp), %ax
5237c478bd9Sstevel@tonic-gate	movw	%ax, %ds
5247c478bd9Sstevel@tonic-gate
5257c478bd9Sstevel@tonic-gate	/* examine the next instruction */
5267c478bd9Sstevel@tonic-gate1:	lodsb	(%si), %al
5277c478bd9Sstevel@tonic-gate	/* skip this code if it is a prefix */
5287c478bd9Sstevel@tonic-gate	cmpb	$0x2E, %al
5297c478bd9Sstevel@tonic-gate	je	1b
5307c478bd9Sstevel@tonic-gate	cmpb	$0x36, %al
5317c478bd9Sstevel@tonic-gate	je	1b
5327c478bd9Sstevel@tonic-gate	cmpb	$0x3E, %al
5337c478bd9Sstevel@tonic-gate	je	1b
5347c478bd9Sstevel@tonic-gate	cmpb	$0x26, %al
5357c478bd9Sstevel@tonic-gate	je	1b
5367c478bd9Sstevel@tonic-gate	cmpb	$0x64, %al
5377c478bd9Sstevel@tonic-gate	jl	2f
5387c478bd9Sstevel@tonic-gate	cmpb	$0x67, %al
5397c478bd9Sstevel@tonic-gate	jle	1b
5407c478bd9Sstevel@tonic-gate2:	cmpb	$0xF0, %al
5417c478bd9Sstevel@tonic-gate	jl	3f
5427c478bd9Sstevel@tonic-gate	cmpb	$0xF3, %al
5437c478bd9Sstevel@tonic-gate	jle	1b
5447c478bd9Sstevel@tonic-gate
5457c478bd9Sstevel@tonic-gate3:	/* check if this code is out* or in* */
5467c478bd9Sstevel@tonic-gate
5477c478bd9Sstevel@tonic-gate	/* ins? or outs? */
5487c478bd9Sstevel@tonic-gate	cmpb	$0x6C, %al
5497c478bd9Sstevel@tonic-gate	jl	4f
5507c478bd9Sstevel@tonic-gate	cmpb	$0x6F, %al
5517c478bd9Sstevel@tonic-gate	jle	5f
5527c478bd9Sstevel@tonic-gate
5537c478bd9Sstevel@tonic-gate4:	/* in? or out? (register operand version) */
5547c478bd9Sstevel@tonic-gate	cmpb	$0xEC, %al
5557c478bd9Sstevel@tonic-gate	jl	6f
5567c478bd9Sstevel@tonic-gate	cmpb	$0xEF, %al
5577c478bd9Sstevel@tonic-gate	jle	5f
5587c478bd9Sstevel@tonic-gate
5597c478bd9Sstevel@tonic-gate6:	/* in? or out? (immediate operand version) */
5607c478bd9Sstevel@tonic-gate	cmpb	$0xE4, %al
5617c478bd9Sstevel@tonic-gate	jl	8f
5627c478bd9Sstevel@tonic-gate	cmpb	$0xE7, %al
5637c478bd9Sstevel@tonic-gate	jg	8f
5647c478bd9Sstevel@tonic-gate
5657c478bd9Sstevel@tonic-gate7:	/* immediate has a port */
5667c478bd9Sstevel@tonic-gate	lodsb	(%si), %al
5677c478bd9Sstevel@tonic-gate	movzbw	%al, %dx
5687c478bd9Sstevel@tonic-gate
5697c478bd9Sstevel@tonic-gate5:	/* %dx has a port */
5707c478bd9Sstevel@tonic-gate
5717c478bd9Sstevel@tonic-gate	/* set %ds to zero */
5727c478bd9Sstevel@tonic-gate	xorw	%ax, %ax
5737c478bd9Sstevel@tonic-gate	movw	%ax, %ds
5747c478bd9Sstevel@tonic-gate
5757c478bd9Sstevel@tonic-gate	/* set %si to the io map */
5767c478bd9Sstevel@tonic-gate	movw	$ABS(EXT_C(io_map)), %si
5777c478bd9Sstevel@tonic-gate
5787c478bd9Sstevel@tonic-gate
5797c478bd9Sstevel@tonic-gate9:	/* check if the io map already has the port */
5807c478bd9Sstevel@tonic-gate	lodsw	(%si), %ax
5817c478bd9Sstevel@tonic-gate	/* check if this is the end */
5827c478bd9Sstevel@tonic-gate	testw	%ax, %ax
5837c478bd9Sstevel@tonic-gate	jz	1f
5847c478bd9Sstevel@tonic-gate	/* check if this matches the port */
5857c478bd9Sstevel@tonic-gate	cmpw	%ax, %dx
5867c478bd9Sstevel@tonic-gate	jne	9b
5877c478bd9Sstevel@tonic-gate	/* if so, leave from this handler */
5887c478bd9Sstevel@tonic-gate	jmp	8f
5897c478bd9Sstevel@tonic-gate
5907c478bd9Sstevel@tonic-gate1:	/* check for the buffer overrun */
5917c478bd9Sstevel@tonic-gate	cmpw	$(ABS(EXT_C(io_map)) + (IO_MAP_SIZE + 1) * 2), %si
5927c478bd9Sstevel@tonic-gate	je	8f
5937c478bd9Sstevel@tonic-gate	/* add the port into the io map */
5947c478bd9Sstevel@tonic-gate	movw	%dx, -2(%si)
5957c478bd9Sstevel@tonic-gate
5967c478bd9Sstevel@tonic-gate8:	/* restore registers */
5977c478bd9Sstevel@tonic-gate	popw	%dx
5987c478bd9Sstevel@tonic-gate	popw	%si
5997c478bd9Sstevel@tonic-gate	popw	%ax
6007c478bd9Sstevel@tonic-gate	popw	%ds
6017c478bd9Sstevel@tonic-gate	popw	%bp
6027c478bd9Sstevel@tonic-gate
6037c478bd9Sstevel@tonic-gate	iret
6047c478bd9Sstevel@tonic-gate
6057c478bd9Sstevel@tonic-gate	.code32
6067c478bd9Sstevel@tonic-gate
6077c478bd9Sstevel@tonic-gateENTRY(io_map)
6087c478bd9Sstevel@tonic-gate	.space	(IO_MAP_SIZE + 1) * 2
6097c478bd9Sstevel@tonic-gate
6107c478bd9Sstevel@tonic-gate
6117c478bd9Sstevel@tonic-gate/*
6127c478bd9Sstevel@tonic-gate * set_int15_handler(void)
6137c478bd9Sstevel@tonic-gate *
6147c478bd9Sstevel@tonic-gate * Set up int15_handler.
6157c478bd9Sstevel@tonic-gate */
6167c478bd9Sstevel@tonic-gateENTRY(set_int15_handler)
6177c478bd9Sstevel@tonic-gate	pushl	%edi
6187c478bd9Sstevel@tonic-gate
6197c478bd9Sstevel@tonic-gate	/* save the original int15 handler */
6207c478bd9Sstevel@tonic-gate	movl	$0x54, %edi
6217c478bd9Sstevel@tonic-gate	movw	(%edi), %ax
6227c478bd9Sstevel@tonic-gate	movw	%ax, ABS(int15_offset)
6237c478bd9Sstevel@tonic-gate	movw	2(%edi), %ax
6247c478bd9Sstevel@tonic-gate	movw	%ax, ABS(int15_segment)
6257c478bd9Sstevel@tonic-gate
6267c478bd9Sstevel@tonic-gate	/* save the new int15 handler */
6277c478bd9Sstevel@tonic-gate	movw	$ABS(int15_handler), %ax
6287c478bd9Sstevel@tonic-gate	movw	%ax, (%edi)
6297c478bd9Sstevel@tonic-gate	xorw	%ax, %ax
6307c478bd9Sstevel@tonic-gate	movw	%ax, 2(%edi)
6317c478bd9Sstevel@tonic-gate
6327c478bd9Sstevel@tonic-gate	popl	%edi
6337c478bd9Sstevel@tonic-gate	ret
6347c478bd9Sstevel@tonic-gate
6357c478bd9Sstevel@tonic-gate
6367c478bd9Sstevel@tonic-gate/*
6377c478bd9Sstevel@tonic-gate * unset_int15_handler(void)
6387c478bd9Sstevel@tonic-gate *
6397c478bd9Sstevel@tonic-gate * Restore the original int15 handler
6407c478bd9Sstevel@tonic-gate */
6417c478bd9Sstevel@tonic-gateENTRY(unset_int15_handler)
6427c478bd9Sstevel@tonic-gate	pushl	%edi
6437c478bd9Sstevel@tonic-gate
6447c478bd9Sstevel@tonic-gate	/* check if int15_handler is set */
6457c478bd9Sstevel@tonic-gate	movl	$0x54, %edi
6467c478bd9Sstevel@tonic-gate	movw	$ABS(int15_handler), %ax
6477c478bd9Sstevel@tonic-gate	cmpw	%ax, (%edi)
6487c478bd9Sstevel@tonic-gate	jne	1f
6497c478bd9Sstevel@tonic-gate	xorw	%ax, %ax
6507c478bd9Sstevel@tonic-gate	cmpw	%ax, 2(%edi)
6517c478bd9Sstevel@tonic-gate	jne	1f
6527c478bd9Sstevel@tonic-gate
6537c478bd9Sstevel@tonic-gate	/* restore the original */
6547c478bd9Sstevel@tonic-gate	movw	ABS(int15_offset), %ax
6557c478bd9Sstevel@tonic-gate	movw	%ax, (%edi)
6567c478bd9Sstevel@tonic-gate	movw	ABS(int15_segment), %ax
6577c478bd9Sstevel@tonic-gate	movw	%ax, 2(%edi)
6587c478bd9Sstevel@tonic-gate
6597c478bd9Sstevel@tonic-gate1:
6607c478bd9Sstevel@tonic-gate	popl	%edi
6617c478bd9Sstevel@tonic-gate	ret
6627c478bd9Sstevel@tonic-gate
6637c478bd9Sstevel@tonic-gate
6647c478bd9Sstevel@tonic-gate/*
6657c478bd9Sstevel@tonic-gate * Translate a key code to another.
6667c478bd9Sstevel@tonic-gate *
6677c478bd9Sstevel@tonic-gate * Note: This implementation cannot handle more than one length
6687c478bd9Sstevel@tonic-gate * scancodes (such as Right Ctrl).
6697c478bd9Sstevel@tonic-gate */
6707c478bd9Sstevel@tonic-gate	.code16
6717c478bd9Sstevel@tonic-gateint15_handler:
6727c478bd9Sstevel@tonic-gate	/* if non-carrier, ignore it */
6737c478bd9Sstevel@tonic-gate	jnc	1f
6747c478bd9Sstevel@tonic-gate	/* check if AH=4F */
6757c478bd9Sstevel@tonic-gate	cmpb	$0x4F, %ah
6767c478bd9Sstevel@tonic-gate	jne	1f
6777c478bd9Sstevel@tonic-gate
6787c478bd9Sstevel@tonic-gate	/* E0 and E1 are special */
6797c478bd9Sstevel@tonic-gate	cmpb	$0xE1, %al
6807c478bd9Sstevel@tonic-gate	je	4f
6817c478bd9Sstevel@tonic-gate	cmpb	$0xE0, %al
6827c478bd9Sstevel@tonic-gate	/* this flag is actually the machine code (je or jmp) */
6837c478bd9Sstevel@tonic-gateint15_skip_flag:
6847c478bd9Sstevel@tonic-gate	je	4f
6857c478bd9Sstevel@tonic-gate
6867c478bd9Sstevel@tonic-gate	pushw	%bp
6877c478bd9Sstevel@tonic-gate	movw	%sp, %bp
6887c478bd9Sstevel@tonic-gate
6897c478bd9Sstevel@tonic-gate	pushw	%bx
6907c478bd9Sstevel@tonic-gate	pushw	%dx
6917c478bd9Sstevel@tonic-gate	pushw	%ds
6927c478bd9Sstevel@tonic-gate	pushw	%si
6937c478bd9Sstevel@tonic-gate
6947c478bd9Sstevel@tonic-gate	/* save bits 0-6 of %al in %dl */
6957c478bd9Sstevel@tonic-gate	movw	%ax, %dx
6967c478bd9Sstevel@tonic-gate	andb	$0x7f, %dl
6977c478bd9Sstevel@tonic-gate	/* save the highest bit in %bl */
6987c478bd9Sstevel@tonic-gate	movb	%al, %bl
6997c478bd9Sstevel@tonic-gate	xorb	%dl, %bl
7007c478bd9Sstevel@tonic-gate	/* set %ds to 0 */
7017c478bd9Sstevel@tonic-gate	xorw	%ax, %ax
7027c478bd9Sstevel@tonic-gate	movw	%ax, %ds
7037c478bd9Sstevel@tonic-gate	/* set %si to the key map */
7047c478bd9Sstevel@tonic-gate	movw	$ABS(EXT_C(bios_key_map)), %si
7057c478bd9Sstevel@tonic-gate
7067c478bd9Sstevel@tonic-gate	/* find the key code from the key map */
7077c478bd9Sstevel@tonic-gate2:
7087c478bd9Sstevel@tonic-gate	lodsw
7097c478bd9Sstevel@tonic-gate	/* check if this is the end */
7107c478bd9Sstevel@tonic-gate	testw	%ax, %ax
7117c478bd9Sstevel@tonic-gate	jz	3f
7127c478bd9Sstevel@tonic-gate	/* check if this matches the key code */
7137c478bd9Sstevel@tonic-gate	cmpb	%al, %dl
7147c478bd9Sstevel@tonic-gate	jne	2b
7157c478bd9Sstevel@tonic-gate	/* if so, perform the mapping */
7167c478bd9Sstevel@tonic-gate	movb	%ah, %dl
7177c478bd9Sstevel@tonic-gate3:
7187c478bd9Sstevel@tonic-gate	/* restore %ax */
7197c478bd9Sstevel@tonic-gate	movw	%dx, %ax
7207c478bd9Sstevel@tonic-gate	orb	%bl, %al
7217c478bd9Sstevel@tonic-gate	/* make sure that CF is set */
7227c478bd9Sstevel@tonic-gate	orw	$1, 6(%bp)
7237c478bd9Sstevel@tonic-gate	/* restore other registers */
7247c478bd9Sstevel@tonic-gate	popw	%si
7257c478bd9Sstevel@tonic-gate	popw	%ds
7267c478bd9Sstevel@tonic-gate	popw	%dx
7277c478bd9Sstevel@tonic-gate	popw	%bx
7287c478bd9Sstevel@tonic-gate	popw	%bp
7297c478bd9Sstevel@tonic-gate	iret
7307c478bd9Sstevel@tonic-gate
7317c478bd9Sstevel@tonic-gate4:
7327c478bd9Sstevel@tonic-gate	/* tricky: jmp (0x74) <-> je (0xeb) */
7337c478bd9Sstevel@tonic-gate	xorb	$(0x74 ^ 0xeb), ABS(int15_skip_flag)
7347c478bd9Sstevel@tonic-gate1:
7357c478bd9Sstevel@tonic-gate	/* just cascade to the original */
7367c478bd9Sstevel@tonic-gate	/* ljmp */
7377c478bd9Sstevel@tonic-gate	.byte	0xea
7387c478bd9Sstevel@tonic-gateint15_offset:	.word	0
7397c478bd9Sstevel@tonic-gateint15_segment:	.word	0
7407c478bd9Sstevel@tonic-gate
7417c478bd9Sstevel@tonic-gate	.code32
7427c478bd9Sstevel@tonic-gate
7437c478bd9Sstevel@tonic-gate	.align	4
7447c478bd9Sstevel@tonic-gateENTRY(bios_key_map)
7457c478bd9Sstevel@tonic-gate	.space	(KEY_MAP_SIZE + 1) * 2
7467c478bd9Sstevel@tonic-gate
7477c478bd9Sstevel@tonic-gate
7487c478bd9Sstevel@tonic-gate/*
7497c478bd9Sstevel@tonic-gate * set_int13_handler(map)
7507c478bd9Sstevel@tonic-gate *
7517c478bd9Sstevel@tonic-gate * Copy MAP to the drive map and set up int13_handler.
7527c478bd9Sstevel@tonic-gate */
7537c478bd9Sstevel@tonic-gateENTRY(set_int13_handler)
7547c478bd9Sstevel@tonic-gate	pushl	%ebp
7557c478bd9Sstevel@tonic-gate	movl	%esp, %ebp
7567c478bd9Sstevel@tonic-gate
7577c478bd9Sstevel@tonic-gate	pushl	%edi
7587c478bd9Sstevel@tonic-gate	pushl	%esi
7597c478bd9Sstevel@tonic-gate
7607c478bd9Sstevel@tonic-gate	/* copy MAP to the drive map */
7617c478bd9Sstevel@tonic-gate	movl	$(DRIVE_MAP_SIZE * 2), %ecx
7627c478bd9Sstevel@tonic-gate	movl	$ABS(drive_map), %edi
7637c478bd9Sstevel@tonic-gate	movl	8(%ebp), %esi
7647c478bd9Sstevel@tonic-gate	cld
7657c478bd9Sstevel@tonic-gate	rep
7667c478bd9Sstevel@tonic-gate	movsb
7677c478bd9Sstevel@tonic-gate
7687c478bd9Sstevel@tonic-gate	/* save the original int13 handler */
7697c478bd9Sstevel@tonic-gate	movl	$0x4c, %edi
7707c478bd9Sstevel@tonic-gate	movw	(%edi), %ax
7717c478bd9Sstevel@tonic-gate	movw	%ax, ABS(int13_offset)
7727c478bd9Sstevel@tonic-gate	movw	2(%edi), %ax
7737c478bd9Sstevel@tonic-gate	movw	%ax, ABS(int13_segment)
7747c478bd9Sstevel@tonic-gate
7757c478bd9Sstevel@tonic-gate	/* decrease the lower memory size and set it to the BIOS memory */
7767c478bd9Sstevel@tonic-gate	movl	$0x413, %edi
7777c478bd9Sstevel@tonic-gate	decw	(%edi)
7787c478bd9Sstevel@tonic-gate	xorl	%eax, %eax
7797c478bd9Sstevel@tonic-gate	movw	(%edi), %ax
7807c478bd9Sstevel@tonic-gate
7817c478bd9Sstevel@tonic-gate	/* compute the segment */
7827c478bd9Sstevel@tonic-gate	shll	$6, %eax
7837c478bd9Sstevel@tonic-gate
7847c478bd9Sstevel@tonic-gate	/* save the new int13 handler */
7857c478bd9Sstevel@tonic-gate	movl	$0x4c, %edi
7867c478bd9Sstevel@tonic-gate	movw	%ax, 2(%edi)
7877c478bd9Sstevel@tonic-gate	xorw	%cx, %cx
7887c478bd9Sstevel@tonic-gate	movw	%cx, (%edi)
7897c478bd9Sstevel@tonic-gate
7907c478bd9Sstevel@tonic-gate	/* copy int13_handler to the reserved area */
7917c478bd9Sstevel@tonic-gate	shll	$4, %eax
7927c478bd9Sstevel@tonic-gate	movl	%eax, %edi
7937c478bd9Sstevel@tonic-gate	movl	$ABS(int13_handler), %esi
7947c478bd9Sstevel@tonic-gate	movl	$(int13_handler_end - int13_handler), %ecx
7957c478bd9Sstevel@tonic-gate	rep
7967c478bd9Sstevel@tonic-gate	movsb
7977c478bd9Sstevel@tonic-gate
7987c478bd9Sstevel@tonic-gate	popl	%esi
7997c478bd9Sstevel@tonic-gate	popl	%edi
8007c478bd9Sstevel@tonic-gate	popl	%ebp
8017c478bd9Sstevel@tonic-gate	ret
8027c478bd9Sstevel@tonic-gate
8037c478bd9Sstevel@tonic-gate
8047c478bd9Sstevel@tonic-gate/*
8057c478bd9Sstevel@tonic-gate * Map a drive to another drive.
8067c478bd9Sstevel@tonic-gate */
8077c478bd9Sstevel@tonic-gate
8087c478bd9Sstevel@tonic-gate	.code16
8097c478bd9Sstevel@tonic-gate
8107c478bd9Sstevel@tonic-gateint13_handler:
8117c478bd9Sstevel@tonic-gate	pushw	%ax
8127c478bd9Sstevel@tonic-gate	pushw	%bp
8137c478bd9Sstevel@tonic-gate	movw	%sp, %bp
8147c478bd9Sstevel@tonic-gate
8157c478bd9Sstevel@tonic-gate	pushw	%si
8167c478bd9Sstevel@tonic-gate
8177c478bd9Sstevel@tonic-gate	/* set %si to the drive map */
8187c478bd9Sstevel@tonic-gate	movw	$(drive_map - int13_handler), %si
8197c478bd9Sstevel@tonic-gate	/* find the drive number from the drive map */
8207c478bd9Sstevel@tonic-gate	cld
8217c478bd9Sstevel@tonic-gate1:
8227c478bd9Sstevel@tonic-gate	lodsw	%cs:(%si), %ax
8237c478bd9Sstevel@tonic-gate	/* check if this is the end */
8247c478bd9Sstevel@tonic-gate	testw	%ax, %ax
8257c478bd9Sstevel@tonic-gate	jz	2f
8267c478bd9Sstevel@tonic-gate	/* check if this matches the drive number */
8277c478bd9Sstevel@tonic-gate	cmpb	%al, %dl
8287c478bd9Sstevel@tonic-gate	jne	1b
8297c478bd9Sstevel@tonic-gate	/* if so, perform the mapping */
8307c478bd9Sstevel@tonic-gate	movb	%ah, %dl
8317c478bd9Sstevel@tonic-gate2:
8327c478bd9Sstevel@tonic-gate	/* restore %si */
8337c478bd9Sstevel@tonic-gate	popw	%si
8347c478bd9Sstevel@tonic-gate	/* save %ax in the stack */
8357c478bd9Sstevel@tonic-gate	pushw	%ax
8367c478bd9Sstevel@tonic-gate	/* simulate the interrupt call */
8377c478bd9Sstevel@tonic-gate	pushw	8(%bp)
8387c478bd9Sstevel@tonic-gate	/* set %ax and %bp to the original values */
8397c478bd9Sstevel@tonic-gate	movw	2(%bp), %ax
8407c478bd9Sstevel@tonic-gate	movw	(%bp), %bp
8417c478bd9Sstevel@tonic-gate	/* lcall */
8427c478bd9Sstevel@tonic-gate	.byte	0x9a
8437c478bd9Sstevel@tonic-gateint13_offset:	.word	0
8447c478bd9Sstevel@tonic-gateint13_segment:	.word	0
8457c478bd9Sstevel@tonic-gate	/* save flags */
8467c478bd9Sstevel@tonic-gate	pushf
8477c478bd9Sstevel@tonic-gate	/* restore %bp */
8487c478bd9Sstevel@tonic-gate	movw	%sp, %bp
8497c478bd9Sstevel@tonic-gate	/* save %ax */
8507c478bd9Sstevel@tonic-gate	pushw	%ax
8517c478bd9Sstevel@tonic-gate	/* set the flags in the stack to the value returned by int13 */
8527c478bd9Sstevel@tonic-gate	movw	(%bp), %ax
8537c478bd9Sstevel@tonic-gate	movw	%ax, 0xc(%bp)
8547c478bd9Sstevel@tonic-gate	/* check if should map the drive number */
8557c478bd9Sstevel@tonic-gate	movw	6(%bp), %ax
8567c478bd9Sstevel@tonic-gate	cmpw	$0x8, %ax
8577c478bd9Sstevel@tonic-gate	jne	3f
8587c478bd9Sstevel@tonic-gate	cmpw	$0x15, %ax
8597c478bd9Sstevel@tonic-gate	jne	3f
8607c478bd9Sstevel@tonic-gate	/* check if the mapping was performed */
8617c478bd9Sstevel@tonic-gate	movw	2(%bp), %ax
8627c478bd9Sstevel@tonic-gate	testw	%ax, %ax
8637c478bd9Sstevel@tonic-gate	jz	3f
8647c478bd9Sstevel@tonic-gate	/* perform the mapping */
8657c478bd9Sstevel@tonic-gate	movb	%al, %dl
8667c478bd9Sstevel@tonic-gate3:
8677c478bd9Sstevel@tonic-gate	popw	%ax
8687c478bd9Sstevel@tonic-gate	movw	4(%bp), %bp
8697c478bd9Sstevel@tonic-gate	addw	$8, %sp
8707c478bd9Sstevel@tonic-gate	iret
8717c478bd9Sstevel@tonic-gate
8727c478bd9Sstevel@tonic-gate	.align	4
8737c478bd9Sstevel@tonic-gatedrive_map:	.space	(DRIVE_MAP_SIZE + 1) * 2
8747c478bd9Sstevel@tonic-gateint13_handler_end:
8757c478bd9Sstevel@tonic-gate
8767c478bd9Sstevel@tonic-gate	.code32
8777c478bd9Sstevel@tonic-gate
8787c478bd9Sstevel@tonic-gate
8797c478bd9Sstevel@tonic-gate/*
8807c478bd9Sstevel@tonic-gate * chain_stage1(segment, offset, part_table_addr)
8817c478bd9Sstevel@tonic-gate *
8827c478bd9Sstevel@tonic-gate *  This starts another stage1 loader, at segment:offset.
8837c478bd9Sstevel@tonic-gate */
8847c478bd9Sstevel@tonic-gate
8857c478bd9Sstevel@tonic-gateENTRY(chain_stage1)
8867c478bd9Sstevel@tonic-gate	/* no need to save anything, just use %esp */
8877c478bd9Sstevel@tonic-gate
8887c478bd9Sstevel@tonic-gate	/* store %ESI, presuming %ES is 0 */
8897c478bd9Sstevel@tonic-gate	movl	0xc(%esp), %esi
8907c478bd9Sstevel@tonic-gate
8917c478bd9Sstevel@tonic-gate	/* store new offset */
8927c478bd9Sstevel@tonic-gate	movl	0x8(%esp), %eax
8937c478bd9Sstevel@tonic-gate	movl	%eax, offset
8947c478bd9Sstevel@tonic-gate
8957c478bd9Sstevel@tonic-gate	/* store new segment */
8967c478bd9Sstevel@tonic-gate	movw	0x4(%esp), %ax
8977c478bd9Sstevel@tonic-gate	movw	%ax, segment
8987c478bd9Sstevel@tonic-gate
8997c478bd9Sstevel@tonic-gate	/* set up to pass boot drive */
9007c478bd9Sstevel@tonic-gate	movb	EXT_C(boot_drive), %dl
9017c478bd9Sstevel@tonic-gate
9027c478bd9Sstevel@tonic-gate	call	EXT_C(prot_to_real)
9037c478bd9Sstevel@tonic-gate	.code16
9047c478bd9Sstevel@tonic-gate
9057c478bd9Sstevel@tonic-gate#ifdef ABSOLUTE_WITHOUT_ASTERISK
9067c478bd9Sstevel@tonic-gate	DATA32	ADDR32	ljmp	(offset)
9077c478bd9Sstevel@tonic-gate#else
9087c478bd9Sstevel@tonic-gate	DATA32	ADDR32	ljmp	*(offset)
9097c478bd9Sstevel@tonic-gate#endif
9107c478bd9Sstevel@tonic-gate	.code32
9117c478bd9Sstevel@tonic-gate#endif /* STAGE1_5 */
9127c478bd9Sstevel@tonic-gate
9137c478bd9Sstevel@tonic-gate
9147c478bd9Sstevel@tonic-gate#ifdef STAGE1_5
9157c478bd9Sstevel@tonic-gate/*
9167c478bd9Sstevel@tonic-gate * chain_stage2(segment, offset, second_sector)
9177c478bd9Sstevel@tonic-gate *
9187c478bd9Sstevel@tonic-gate *  This starts another stage2 loader, at segment:offset.  It presumes
9197c478bd9Sstevel@tonic-gate *  that the other one starts with this same "asm.S" file, and passes
9207c478bd9Sstevel@tonic-gate *  parameters by writing the embedded install variables.
9217c478bd9Sstevel@tonic-gate */
9227c478bd9Sstevel@tonic-gate
9237c478bd9Sstevel@tonic-gateENTRY(chain_stage2)
9247c478bd9Sstevel@tonic-gate	/* no need to save anything, just use %esp */
9257c478bd9Sstevel@tonic-gate
9267c478bd9Sstevel@tonic-gate	/* store new offset */
9277c478bd9Sstevel@tonic-gate	movl	0x8(%esp), %eax
9287c478bd9Sstevel@tonic-gate	movl	%eax, offset
9297c478bd9Sstevel@tonic-gate	movl	%eax, %ebx
9307c478bd9Sstevel@tonic-gate
9317c478bd9Sstevel@tonic-gate	/* store new segment */
9327c478bd9Sstevel@tonic-gate	movw	0x4(%esp), %ax
9337c478bd9Sstevel@tonic-gate	movw	%ax, segment
9347c478bd9Sstevel@tonic-gate	shll	$4, %eax
9357c478bd9Sstevel@tonic-gate
9367c478bd9Sstevel@tonic-gate	/* generate linear address */
9377c478bd9Sstevel@tonic-gate	addl	%eax, %ebx
9387c478bd9Sstevel@tonic-gate
9397c478bd9Sstevel@tonic-gate	/* set up to pass the partition where stage2 is located in */
9407c478bd9Sstevel@tonic-gate	movl	EXT_C(current_partition), %eax
9417c478bd9Sstevel@tonic-gate	movl	%eax, (EXT_C(install_partition)-EXT_C(main))(%ebx)
9427c478bd9Sstevel@tonic-gate
9437c478bd9Sstevel@tonic-gate	/* set up to pass the drive where stage2 is located in */
9447c478bd9Sstevel@tonic-gate	movb	EXT_C(current_drive), %dl
9457c478bd9Sstevel@tonic-gate
9467c478bd9Sstevel@tonic-gate	/* set up to pass the second sector of stage2 */
9477c478bd9Sstevel@tonic-gate	movl	0xc(%esp), %ecx
9487c478bd9Sstevel@tonic-gate
9497c478bd9Sstevel@tonic-gate	call	EXT_C(prot_to_real)
9507c478bd9Sstevel@tonic-gate	.code16
9517c478bd9Sstevel@tonic-gate
9527c478bd9Sstevel@tonic-gate	movl	%ecx, %ebp
9537c478bd9Sstevel@tonic-gate
9547c478bd9Sstevel@tonic-gate#ifdef ABSOLUTE_WITHOUT_ASTERISK
9557c478bd9Sstevel@tonic-gate	DATA32	ADDR32	ljmp	(offset)
9567c478bd9Sstevel@tonic-gate#else
9577c478bd9Sstevel@tonic-gate	DATA32	ADDR32	ljmp	*(offset)
9587c478bd9Sstevel@tonic-gate#endif
9597c478bd9Sstevel@tonic-gate
9607c478bd9Sstevel@tonic-gate	.code32
9617c478bd9Sstevel@tonic-gate#endif /* STAGE1_5 */
9627c478bd9Sstevel@tonic-gate
9637c478bd9Sstevel@tonic-gate/*
9647c478bd9Sstevel@tonic-gate *  These next two routines, "real_to_prot" and "prot_to_real" are structured
9657c478bd9Sstevel@tonic-gate *  in a very specific way.  Be very careful when changing them.
9667c478bd9Sstevel@tonic-gate *
9677c478bd9Sstevel@tonic-gate *  NOTE:  Use of either one messes up %eax and %ebp.
9687c478bd9Sstevel@tonic-gate */
9697c478bd9Sstevel@tonic-gate
9707c478bd9Sstevel@tonic-gateENTRY(real_to_prot)
9717c478bd9Sstevel@tonic-gate	.code16
9727c478bd9Sstevel@tonic-gate	cli
9737c478bd9Sstevel@tonic-gate
9747c478bd9Sstevel@tonic-gate	/* load the GDT register */
9757c478bd9Sstevel@tonic-gate	DATA32	ADDR32	lgdt	gdtdesc
9767c478bd9Sstevel@tonic-gate
9777c478bd9Sstevel@tonic-gate	/* turn on protected mode */
9787c478bd9Sstevel@tonic-gate	movl	%cr0, %eax
9797c478bd9Sstevel@tonic-gate	orl	$CR0_PE_ON, %eax
9807c478bd9Sstevel@tonic-gate	movl	%eax, %cr0
9817c478bd9Sstevel@tonic-gate
9827c478bd9Sstevel@tonic-gate	/* jump to relocation, flush prefetch queue, and reload %cs */
9837c478bd9Sstevel@tonic-gate	DATA32	ljmp	$PROT_MODE_CSEG, $protcseg
9847c478bd9Sstevel@tonic-gate
9857c478bd9Sstevel@tonic-gate	/*
9867c478bd9Sstevel@tonic-gate	 *  The ".code32" directive only works in GAS, the GNU assembler!
9877c478bd9Sstevel@tonic-gate	 *  This gets out of "16-bit" mode.
9887c478bd9Sstevel@tonic-gate	 */
9897c478bd9Sstevel@tonic-gate	.code32
9907c478bd9Sstevel@tonic-gate
9917c478bd9Sstevel@tonic-gateprotcseg:
9927c478bd9Sstevel@tonic-gate	/* reload other segment registers */
9937c478bd9Sstevel@tonic-gate	movw	$PROT_MODE_DSEG, %ax
9947c478bd9Sstevel@tonic-gate	movw	%ax, %ds
9957c478bd9Sstevel@tonic-gate	movw	%ax, %es
9967c478bd9Sstevel@tonic-gate	movw	%ax, %fs
9977c478bd9Sstevel@tonic-gate	movw	%ax, %gs
9987c478bd9Sstevel@tonic-gate	movw	%ax, %ss
9997c478bd9Sstevel@tonic-gate
10007c478bd9Sstevel@tonic-gate	/* put the return address in a known safe location */
10017c478bd9Sstevel@tonic-gate	movl	(%esp), %eax
10027c478bd9Sstevel@tonic-gate	movl	%eax, STACKOFF
10037c478bd9Sstevel@tonic-gate
10047c478bd9Sstevel@tonic-gate	/* get protected mode stack */
10057c478bd9Sstevel@tonic-gate	movl	protstack, %eax
10067c478bd9Sstevel@tonic-gate	movl	%eax, %esp
10077c478bd9Sstevel@tonic-gate	movl	%eax, %ebp
10087c478bd9Sstevel@tonic-gate
10097c478bd9Sstevel@tonic-gate	/* get return address onto the right stack */
10107c478bd9Sstevel@tonic-gate	movl	STACKOFF, %eax
10117c478bd9Sstevel@tonic-gate	movl	%eax, (%esp)
10127c478bd9Sstevel@tonic-gate
10137c478bd9Sstevel@tonic-gate	/* zero %eax */
10147c478bd9Sstevel@tonic-gate	xorl	%eax, %eax
10157c478bd9Sstevel@tonic-gate
10167c478bd9Sstevel@tonic-gate	/* return on the old (or initialized) stack! */
10177c478bd9Sstevel@tonic-gate	ret
10187c478bd9Sstevel@tonic-gate
10197c478bd9Sstevel@tonic-gate
10207c478bd9Sstevel@tonic-gateENTRY(prot_to_real)
10217c478bd9Sstevel@tonic-gate	/* just in case, set GDT */
10227c478bd9Sstevel@tonic-gate	lgdt	gdtdesc
10237c478bd9Sstevel@tonic-gate
10247c478bd9Sstevel@tonic-gate	/* save the protected mode stack */
10257c478bd9Sstevel@tonic-gate	movl	%esp, %eax
10267c478bd9Sstevel@tonic-gate	movl	%eax, protstack
10277c478bd9Sstevel@tonic-gate
10287c478bd9Sstevel@tonic-gate	/* get the return address */
10297c478bd9Sstevel@tonic-gate	movl	(%esp), %eax
10307c478bd9Sstevel@tonic-gate	movl	%eax, STACKOFF
10317c478bd9Sstevel@tonic-gate
10327c478bd9Sstevel@tonic-gate	/* set up new stack */
10337c478bd9Sstevel@tonic-gate	movl	$STACKOFF, %eax
10347c478bd9Sstevel@tonic-gate	movl	%eax, %esp
10357c478bd9Sstevel@tonic-gate	movl	%eax, %ebp
10367c478bd9Sstevel@tonic-gate
10377c478bd9Sstevel@tonic-gate	/* set up segment limits */
10387c478bd9Sstevel@tonic-gate	movw	$PSEUDO_RM_DSEG, %ax
10397c478bd9Sstevel@tonic-gate	movw	%ax, %ds
10407c478bd9Sstevel@tonic-gate	movw	%ax, %es
10417c478bd9Sstevel@tonic-gate	movw	%ax, %fs
10427c478bd9Sstevel@tonic-gate	movw	%ax, %gs
10437c478bd9Sstevel@tonic-gate	movw	%ax, %ss
10447c478bd9Sstevel@tonic-gate
10457c478bd9Sstevel@tonic-gate	/* this might be an extra step */
10467c478bd9Sstevel@tonic-gate	ljmp	$PSEUDO_RM_CSEG, $tmpcseg	/* jump to a 16 bit segment */
10477c478bd9Sstevel@tonic-gate
10487c478bd9Sstevel@tonic-gatetmpcseg:
10497c478bd9Sstevel@tonic-gate	.code16
10507c478bd9Sstevel@tonic-gate
10517c478bd9Sstevel@tonic-gate	/* clear the PE bit of CR0 */
10527c478bd9Sstevel@tonic-gate	movl	%cr0, %eax
10537c478bd9Sstevel@tonic-gate	andl 	$CR0_PE_OFF, %eax
10547c478bd9Sstevel@tonic-gate	movl	%eax, %cr0
10557c478bd9Sstevel@tonic-gate
10567c478bd9Sstevel@tonic-gate	/* flush prefetch queue, reload %cs */
10577c478bd9Sstevel@tonic-gate	DATA32	ljmp	$0, $realcseg
10587c478bd9Sstevel@tonic-gate
10597c478bd9Sstevel@tonic-gaterealcseg:
10607c478bd9Sstevel@tonic-gate	/* we are in real mode now
10617c478bd9Sstevel@tonic-gate	 * set up the real mode segment registers : DS, SS, ES
10627c478bd9Sstevel@tonic-gate	 */
10637c478bd9Sstevel@tonic-gate	/* zero %eax */
10647c478bd9Sstevel@tonic-gate	xorl	%eax, %eax
10657c478bd9Sstevel@tonic-gate
10667c478bd9Sstevel@tonic-gate	movw	%ax, %ds
10677c478bd9Sstevel@tonic-gate	movw	%ax, %es
10687c478bd9Sstevel@tonic-gate	movw	%ax, %fs
10697c478bd9Sstevel@tonic-gate	movw	%ax, %gs
10707c478bd9Sstevel@tonic-gate	movw	%ax, %ss
10717c478bd9Sstevel@tonic-gate
10727c478bd9Sstevel@tonic-gate	/* restore interrupts */
10737c478bd9Sstevel@tonic-gate	sti
10747c478bd9Sstevel@tonic-gate
10757c478bd9Sstevel@tonic-gate	/* return on new stack! */
10767c478bd9Sstevel@tonic-gate	DATA32	ret
10777c478bd9Sstevel@tonic-gate
10787c478bd9Sstevel@tonic-gate	.code32
10797c478bd9Sstevel@tonic-gate
10807c478bd9Sstevel@tonic-gate
10817c478bd9Sstevel@tonic-gate/*
10827c478bd9Sstevel@tonic-gate *   int biosdisk_int13_extensions (int ax, int drive, void *dap)
10837c478bd9Sstevel@tonic-gate *
10847c478bd9Sstevel@tonic-gate *   Call IBM/MS INT13 Extensions (int 13 %ax=AX) for DRIVE. DAP
10857c478bd9Sstevel@tonic-gate *   is passed for disk address packet. If an error occurs, return
10867c478bd9Sstevel@tonic-gate *   non-zero, otherwise zero.
10877c478bd9Sstevel@tonic-gate */
10887c478bd9Sstevel@tonic-gate
10897c478bd9Sstevel@tonic-gateENTRY(biosdisk_int13_extensions)
10907c478bd9Sstevel@tonic-gate	pushl	%ebp
10917c478bd9Sstevel@tonic-gate	movl	%esp, %ebp
10927c478bd9Sstevel@tonic-gate
10937c478bd9Sstevel@tonic-gate	pushl	%esi
10947c478bd9Sstevel@tonic-gate	pushl	%ebx
10957c478bd9Sstevel@tonic-gate
10967c478bd9Sstevel@tonic-gate	/* compute the address of disk_address_packet */
10977c478bd9Sstevel@tonic-gate	movl	0x10(%ebp), %eax
10987c478bd9Sstevel@tonic-gate	movw	%ax, %si
10997c478bd9Sstevel@tonic-gate	xorw	%ax, %ax
11007c478bd9Sstevel@tonic-gate	shrl	$4, %eax
11017c478bd9Sstevel@tonic-gate	movw	%ax, %cx	/* save the segment to cx */
11027c478bd9Sstevel@tonic-gate
11037c478bd9Sstevel@tonic-gate	/* drive */
11047c478bd9Sstevel@tonic-gate	movb	0xc(%ebp), %dl
11057c478bd9Sstevel@tonic-gate	/* ax */
11067c478bd9Sstevel@tonic-gate	movw	0x8(%ebp), %bx
11077c478bd9Sstevel@tonic-gate	/* enter real mode */
11087c478bd9Sstevel@tonic-gate	call	EXT_C(prot_to_real)
11097c478bd9Sstevel@tonic-gate
11107c478bd9Sstevel@tonic-gate	.code16
11117c478bd9Sstevel@tonic-gate	movw	%bx, %ax
11127c478bd9Sstevel@tonic-gate	movw	%cx, %ds
11137c478bd9Sstevel@tonic-gate	int	$0x13		/* do the operation */
11147c478bd9Sstevel@tonic-gate	movb	%ah, %dl	/* save return value */
11157c478bd9Sstevel@tonic-gate	/* clear the data segment */
11167c478bd9Sstevel@tonic-gate	xorw	%ax, %ax
11177c478bd9Sstevel@tonic-gate	movw	%ax, %ds
11187c478bd9Sstevel@tonic-gate	/* back to protected mode */
11197c478bd9Sstevel@tonic-gate	DATA32	call	EXT_C(real_to_prot)
11207c478bd9Sstevel@tonic-gate	.code32
11217c478bd9Sstevel@tonic-gate
11227c478bd9Sstevel@tonic-gate	movb	%dl, %al	/* return value in %eax */
11237c478bd9Sstevel@tonic-gate
11247c478bd9Sstevel@tonic-gate	popl	%ebx
11257c478bd9Sstevel@tonic-gate	popl	%esi
11267c478bd9Sstevel@tonic-gate	popl	%ebp
11277c478bd9Sstevel@tonic-gate
11287c478bd9Sstevel@tonic-gate	ret
11297c478bd9Sstevel@tonic-gate
11307c478bd9Sstevel@tonic-gate/*
11317c478bd9Sstevel@tonic-gate *   int biosdisk_standard (int ah, int drive, int coff, int hoff, int soff,
11327c478bd9Sstevel@tonic-gate *                          int nsec, int segment)
11337c478bd9Sstevel@tonic-gate *
11347c478bd9Sstevel@tonic-gate *   Call standard and old INT13 (int 13 %ah=AH) for DRIVE. Read/write
11357c478bd9Sstevel@tonic-gate *   NSEC sectors from COFF/HOFF/SOFF into SEGMENT. If an error occurs,
11367c478bd9Sstevel@tonic-gate *   return non-zero, otherwise zero.
11377c478bd9Sstevel@tonic-gate */
11387c478bd9Sstevel@tonic-gate
11397c478bd9Sstevel@tonic-gateENTRY(biosdisk_standard)
11407c478bd9Sstevel@tonic-gate	pushl	%ebp
11417c478bd9Sstevel@tonic-gate	movl	%esp, %ebp
11427c478bd9Sstevel@tonic-gate
11437c478bd9Sstevel@tonic-gate	pushl	%ebx
11447c478bd9Sstevel@tonic-gate	pushl	%edi
11457c478bd9Sstevel@tonic-gate	pushl	%esi
11467c478bd9Sstevel@tonic-gate
11477c478bd9Sstevel@tonic-gate	/* set up CHS information */
11487c478bd9Sstevel@tonic-gate	movl	0x10(%ebp), %eax
11497c478bd9Sstevel@tonic-gate	movb	%al, %ch
11507c478bd9Sstevel@tonic-gate	movb	0x18(%ebp), %al
11517c478bd9Sstevel@tonic-gate	shlb	$2, %al
11527c478bd9Sstevel@tonic-gate	shrw	$2, %ax
11537c478bd9Sstevel@tonic-gate	movb	%al, %cl
11547c478bd9Sstevel@tonic-gate	movb	0x14(%ebp), %dh
11557c478bd9Sstevel@tonic-gate	/* drive */
11567c478bd9Sstevel@tonic-gate	movb	0xc(%ebp), %dl
11577c478bd9Sstevel@tonic-gate	/* segment */
11587c478bd9Sstevel@tonic-gate	movw	0x20(%ebp), %bx
11597c478bd9Sstevel@tonic-gate	/* save nsec and ah to %di */
11607c478bd9Sstevel@tonic-gate	movb	0x8(%ebp), %ah
11617c478bd9Sstevel@tonic-gate	movb	0x1c(%ebp), %al
11627c478bd9Sstevel@tonic-gate	movw	%ax, %di
11637c478bd9Sstevel@tonic-gate	/* enter real mode */
11647c478bd9Sstevel@tonic-gate	call	EXT_C(prot_to_real)
11657c478bd9Sstevel@tonic-gate
11667c478bd9Sstevel@tonic-gate	.code16
11677c478bd9Sstevel@tonic-gate	movw	%bx, %es
11687c478bd9Sstevel@tonic-gate	xorw	%bx, %bx
11697c478bd9Sstevel@tonic-gate	movw	$3, %si		/* attempt at least three times */
11707c478bd9Sstevel@tonic-gate
11717c478bd9Sstevel@tonic-gate1:
11727c478bd9Sstevel@tonic-gate	movw	%di, %ax
11737c478bd9Sstevel@tonic-gate	int	$0x13		/* do the operation */
11747c478bd9Sstevel@tonic-gate	jnc	2f		/* check if successful */
11757c478bd9Sstevel@tonic-gate
11767c478bd9Sstevel@tonic-gate	movb	%ah, %bl	/* save return value */
11777c478bd9Sstevel@tonic-gate	/* if fail, reset the disk system */
11787c478bd9Sstevel@tonic-gate	xorw	%ax, %ax
11797c478bd9Sstevel@tonic-gate	int	$0x13
11807c478bd9Sstevel@tonic-gate
11817c478bd9Sstevel@tonic-gate	decw	%si
11827c478bd9Sstevel@tonic-gate	cmpw	$0, %si
11837c478bd9Sstevel@tonic-gate	je	2f
11847c478bd9Sstevel@tonic-gate	xorb	%bl, %bl
11857c478bd9Sstevel@tonic-gate	jmp	1b		/* retry */
11867c478bd9Sstevel@tonic-gate2:
11877c478bd9Sstevel@tonic-gate	/* back to protected mode */
11887c478bd9Sstevel@tonic-gate	DATA32	call	EXT_C(real_to_prot)
11897c478bd9Sstevel@tonic-gate	.code32
11907c478bd9Sstevel@tonic-gate
11917c478bd9Sstevel@tonic-gate	movb	%bl, %al	/* return value in %eax */
11927c478bd9Sstevel@tonic-gate
11937c478bd9Sstevel@tonic-gate	popl	%esi
11947c478bd9Sstevel@tonic-gate	popl	%edi
11957c478bd9Sstevel@tonic-gate	popl	%ebx
11967c478bd9Sstevel@tonic-gate	popl	%ebp
11977c478bd9Sstevel@tonic-gate
11987c478bd9Sstevel@tonic-gate	ret
11997c478bd9Sstevel@tonic-gate
12007c478bd9Sstevel@tonic-gate
12017c478bd9Sstevel@tonic-gate/*
12027c478bd9Sstevel@tonic-gate *   int check_int13_extensions (int drive)
12037c478bd9Sstevel@tonic-gate *
12047c478bd9Sstevel@tonic-gate *   Check if LBA is supported for DRIVE. If it is supported, then return
12057c478bd9Sstevel@tonic-gate *   the major version of extensions, otherwise zero.
12067c478bd9Sstevel@tonic-gate */
12077c478bd9Sstevel@tonic-gate
12087c478bd9Sstevel@tonic-gateENTRY(check_int13_extensions)
12097c478bd9Sstevel@tonic-gate	pushl	%ebp
12107c478bd9Sstevel@tonic-gate	movl	%esp, %ebp
12117c478bd9Sstevel@tonic-gate
12127c478bd9Sstevel@tonic-gate	pushl	%ebx
12137c478bd9Sstevel@tonic-gate
12147c478bd9Sstevel@tonic-gate	/* drive */
12157c478bd9Sstevel@tonic-gate	movb	0x8(%ebp), %dl
12167c478bd9Sstevel@tonic-gate	/* enter real mode */
12177c478bd9Sstevel@tonic-gate	call	EXT_C(prot_to_real)
12187c478bd9Sstevel@tonic-gate
12197c478bd9Sstevel@tonic-gate	.code16
12207c478bd9Sstevel@tonic-gate	movb	$0x41, %ah
12217c478bd9Sstevel@tonic-gate	movw	$0x55aa, %bx
12227c478bd9Sstevel@tonic-gate	int	$0x13		/* do the operation */
12237c478bd9Sstevel@tonic-gate
12247c478bd9Sstevel@tonic-gate	/* check the result */
12257c478bd9Sstevel@tonic-gate	jc	1f
12267c478bd9Sstevel@tonic-gate	cmpw	$0xaa55, %bx
12277c478bd9Sstevel@tonic-gate	jne	1f
12287c478bd9Sstevel@tonic-gate
12297c478bd9Sstevel@tonic-gate	movb	%ah, %bl	/* save the major version into %bl */
12307c478bd9Sstevel@tonic-gate
12317c478bd9Sstevel@tonic-gate	/* check if AH=0x42 is supported if FORCE_LBA is zero */
12327c478bd9Sstevel@tonic-gate	movb	EXT_C(force_lba), %al
12337c478bd9Sstevel@tonic-gate	testb	%al, %al
12347c478bd9Sstevel@tonic-gate	jnz	2f
12357c478bd9Sstevel@tonic-gate	andw	$1, %cx
12367c478bd9Sstevel@tonic-gate	jnz	2f
12377c478bd9Sstevel@tonic-gate
12387c478bd9Sstevel@tonic-gate1:
12397c478bd9Sstevel@tonic-gate	xorb	%bl, %bl
12407c478bd9Sstevel@tonic-gate2:
12417c478bd9Sstevel@tonic-gate	/* back to protected mode */
12427c478bd9Sstevel@tonic-gate	DATA32	call	EXT_C(real_to_prot)
12437c478bd9Sstevel@tonic-gate	.code32
12447c478bd9Sstevel@tonic-gate
12457c478bd9Sstevel@tonic-gate	movb	%bl, %al	/* return value in %eax */
12467c478bd9Sstevel@tonic-gate
12477c478bd9Sstevel@tonic-gate	popl	%ebx
12487c478bd9Sstevel@tonic-gate	popl	%ebp
12497c478bd9Sstevel@tonic-gate
12507c478bd9Sstevel@tonic-gate	ret
12517c478bd9Sstevel@tonic-gate
12527c478bd9Sstevel@tonic-gate
12537c478bd9Sstevel@tonic-gate/*
12547c478bd9Sstevel@tonic-gate *   int get_diskinfo_standard (int drive, unsigned long *cylinders,
12557c478bd9Sstevel@tonic-gate *                              unsigned long *heads, unsigned long *sectors)
12567c478bd9Sstevel@tonic-gate *
12577c478bd9Sstevel@tonic-gate *   Return the geometry of DRIVE in CYLINDERS, HEADS and SECTORS. If an
12587c478bd9Sstevel@tonic-gate *   error occurs, then return non-zero, otherwise zero.
12597c478bd9Sstevel@tonic-gate */
12607c478bd9Sstevel@tonic-gate
12617c478bd9Sstevel@tonic-gateENTRY(get_diskinfo_standard)
12627c478bd9Sstevel@tonic-gate	pushl	%ebp
12637c478bd9Sstevel@tonic-gate	movl	%esp, %ebp
12647c478bd9Sstevel@tonic-gate
12657c478bd9Sstevel@tonic-gate	pushl	%ebx
12667c478bd9Sstevel@tonic-gate	pushl	%edi
12677c478bd9Sstevel@tonic-gate
12687c478bd9Sstevel@tonic-gate	/* drive */
12697c478bd9Sstevel@tonic-gate	movb	0x8(%ebp), %dl
12707c478bd9Sstevel@tonic-gate	/* enter real mode */
12717c478bd9Sstevel@tonic-gate	call	EXT_C(prot_to_real)
12727c478bd9Sstevel@tonic-gate
12737c478bd9Sstevel@tonic-gate	.code16
12747c478bd9Sstevel@tonic-gate	movb	$0x8, %ah
12757c478bd9Sstevel@tonic-gate	int	$0x13		/* do the operation */
12767c478bd9Sstevel@tonic-gate	/* check if successful */
12777c478bd9Sstevel@tonic-gate	testb	%ah, %ah
12787c478bd9Sstevel@tonic-gate	jnz	1f
12797c478bd9Sstevel@tonic-gate	/* bogus BIOSes may not return an error number */
12807c478bd9Sstevel@tonic-gate	testb	$0x3f, %cl	/* 0 sectors means no disk */
12817c478bd9Sstevel@tonic-gate	jnz	1f		/* if non-zero, then succeed */
12827c478bd9Sstevel@tonic-gate	/* XXX 0x60 is one of the unused error numbers */
12837c478bd9Sstevel@tonic-gate	movb	$0x60, %ah
12847c478bd9Sstevel@tonic-gate1:
12857c478bd9Sstevel@tonic-gate	movb	%ah, %bl	/* save return value in %bl */
12867c478bd9Sstevel@tonic-gate	/* back to protected mode */
12877c478bd9Sstevel@tonic-gate	DATA32	call	EXT_C(real_to_prot)
12887c478bd9Sstevel@tonic-gate	.code32
12897c478bd9Sstevel@tonic-gate
12907c478bd9Sstevel@tonic-gate	/* restore %ebp */
12917c478bd9Sstevel@tonic-gate	leal	0x8(%esp), %ebp
12927c478bd9Sstevel@tonic-gate
12937c478bd9Sstevel@tonic-gate	/* heads */
12947c478bd9Sstevel@tonic-gate	movb	%dh, %al
12957c478bd9Sstevel@tonic-gate	incl	%eax		/* the number of heads is counted from zero */
12967c478bd9Sstevel@tonic-gate	movl	0x10(%ebp), %edi
12977c478bd9Sstevel@tonic-gate	movl	%eax, (%edi)
12987c478bd9Sstevel@tonic-gate
12997c478bd9Sstevel@tonic-gate	/* sectors */
13007c478bd9Sstevel@tonic-gate	xorl	%eax, %eax
13017c478bd9Sstevel@tonic-gate	movb	%cl, %al
13027c478bd9Sstevel@tonic-gate	andb	$0x3f, %al
13037c478bd9Sstevel@tonic-gate	movl	0x14(%ebp), %edi
13047c478bd9Sstevel@tonic-gate	movl	%eax, (%edi)
13057c478bd9Sstevel@tonic-gate
13067c478bd9Sstevel@tonic-gate	/* cylinders */
13077c478bd9Sstevel@tonic-gate	shrb	$6, %cl
13087c478bd9Sstevel@tonic-gate	movb	%cl, %ah
13097c478bd9Sstevel@tonic-gate	movb	%ch, %al
13107c478bd9Sstevel@tonic-gate	incl	%eax		/* the number of cylinders is
13117c478bd9Sstevel@tonic-gate				   counted from zero */
13127c478bd9Sstevel@tonic-gate	movl	0xc(%ebp), %edi
13137c478bd9Sstevel@tonic-gate	movl	%eax, (%edi)
13147c478bd9Sstevel@tonic-gate
13157c478bd9Sstevel@tonic-gate	xorl	%eax, %eax
13167c478bd9Sstevel@tonic-gate	movb	%bl, %al	/* return value in %eax */
13177c478bd9Sstevel@tonic-gate
13187c478bd9Sstevel@tonic-gate	popl	%edi
13197c478bd9Sstevel@tonic-gate	popl	%ebx
13207c478bd9Sstevel@tonic-gate	popl	%ebp
13217c478bd9Sstevel@tonic-gate
13227c478bd9Sstevel@tonic-gate	ret
13237c478bd9Sstevel@tonic-gate
13247c478bd9Sstevel@tonic-gate
13257c478bd9Sstevel@tonic-gate#if 0
13267c478bd9Sstevel@tonic-gate/*
13277c478bd9Sstevel@tonic-gate *   int get_diskinfo_floppy (int drive, unsigned long *cylinders,
13287c478bd9Sstevel@tonic-gate *                            unsigned long *heads, unsigned long *sectors)
13297c478bd9Sstevel@tonic-gate *
13307c478bd9Sstevel@tonic-gate *   Return the geometry of DRIVE in CYLINDERS, HEADS and SECTORS. If an
13317c478bd9Sstevel@tonic-gate *   error occurs, then return non-zero, otherwise zero.
13327c478bd9Sstevel@tonic-gate */
13337c478bd9Sstevel@tonic-gate
13347c478bd9Sstevel@tonic-gateENTRY(get_diskinfo_floppy)
13357c478bd9Sstevel@tonic-gate	pushl	%ebp
13367c478bd9Sstevel@tonic-gate	movl	%esp, %ebp
13377c478bd9Sstevel@tonic-gate
13387c478bd9Sstevel@tonic-gate	pushl	%ebx
13397c478bd9Sstevel@tonic-gate	pushl	%esi
13407c478bd9Sstevel@tonic-gate
13417c478bd9Sstevel@tonic-gate	/* drive */
13427c478bd9Sstevel@tonic-gate	movb	0x8(%ebp), %dl
13437c478bd9Sstevel@tonic-gate	/* enter real mode */
13447c478bd9Sstevel@tonic-gate	call	EXT_C(prot_to_real)
13457c478bd9Sstevel@tonic-gate
13467c478bd9Sstevel@tonic-gate	.code16
13477c478bd9Sstevel@tonic-gate	/* init probe value */
13487c478bd9Sstevel@tonic-gate	movl	$probe_values-1, %esi
13497c478bd9Sstevel@tonic-gate1:
13507c478bd9Sstevel@tonic-gate	xorw	%ax, %ax
13517c478bd9Sstevel@tonic-gate	int	$0x13		/* reset floppy controller */
13527c478bd9Sstevel@tonic-gate
13537c478bd9Sstevel@tonic-gate	incw	%si
13547c478bd9Sstevel@tonic-gate	movb	(%si), %cl
13557c478bd9Sstevel@tonic-gate	cmpb	$0, %cl		/* probe failed if zero */
13567c478bd9Sstevel@tonic-gate	je	2f
13577c478bd9Sstevel@tonic-gate
13587c478bd9Sstevel@tonic-gate	/* perform read */
13597c478bd9Sstevel@tonic-gate	movw	$SCRATCHSEG, %ax
13607c478bd9Sstevel@tonic-gate	movw	%ax, %es
13617c478bd9Sstevel@tonic-gate	xorw	%bx, %bx
13627c478bd9Sstevel@tonic-gate	movw	$0x0201, %ax
13637c478bd9Sstevel@tonic-gate	movb	$0, %ch
13647c478bd9Sstevel@tonic-gate	movb	$0, %dh
13657c478bd9Sstevel@tonic-gate	int	$0x13
13667c478bd9Sstevel@tonic-gate
13677c478bd9Sstevel@tonic-gate	/* FIXME: Read from floppy may fail even if the geometry is correct.
13687c478bd9Sstevel@tonic-gate	   So should retry at least three times.  */
13697c478bd9Sstevel@tonic-gate	jc	1b		/* next value */
13707c478bd9Sstevel@tonic-gate
13717c478bd9Sstevel@tonic-gate	/* succeed */
13727c478bd9Sstevel@tonic-gate	jmp	2f
13737c478bd9Sstevel@tonic-gate
13747c478bd9Sstevel@tonic-gateprobe_values:
13757c478bd9Sstevel@tonic-gate	.byte	36, 18, 15, 9, 0
13767c478bd9Sstevel@tonic-gate
13777c478bd9Sstevel@tonic-gate2:
13787c478bd9Sstevel@tonic-gate	/* back to protected mode */
13797c478bd9Sstevel@tonic-gate	DATA32	call	EXT_C(real_to_prot)
13807c478bd9Sstevel@tonic-gate	.code32
13817c478bd9Sstevel@tonic-gate
13827c478bd9Sstevel@tonic-gate	/* restore %ebp */
13837c478bd9Sstevel@tonic-gate	leal	0x8(%esp), %ebp
13847c478bd9Sstevel@tonic-gate
13857c478bd9Sstevel@tonic-gate	/* cylinders */
13867c478bd9Sstevel@tonic-gate	movl	0xc(%ebp), %eax
13877c478bd9Sstevel@tonic-gate	movl	$80, %ebx
13887c478bd9Sstevel@tonic-gate	movl	%ebx, (%eax)
13897c478bd9Sstevel@tonic-gate	/* heads */
13907c478bd9Sstevel@tonic-gate	movl	0x10(%ebp), %eax
13917c478bd9Sstevel@tonic-gate	movl	$2, %ebx
13927c478bd9Sstevel@tonic-gate	movl	%ebx, (%eax)
13937c478bd9Sstevel@tonic-gate	/* sectors */
13947c478bd9Sstevel@tonic-gate	movl	0x14(%ebp), %eax
13957c478bd9Sstevel@tonic-gate	movzbl	%cl, %ebx
13967c478bd9Sstevel@tonic-gate	movl	%ebx, (%eax)
13977c478bd9Sstevel@tonic-gate
13987c478bd9Sstevel@tonic-gate	/* return value in %eax */
13997c478bd9Sstevel@tonic-gate	xorl	%eax, %eax
14007c478bd9Sstevel@tonic-gate	cmpb	$0, %cl
14017c478bd9Sstevel@tonic-gate	jne	3f
14027c478bd9Sstevel@tonic-gate	incl	%eax		/* %eax = 1 (non-zero) */
14037c478bd9Sstevel@tonic-gate3:
14047c478bd9Sstevel@tonic-gate	popl	%esi
14057c478bd9Sstevel@tonic-gate	popl	%ebx
14067c478bd9Sstevel@tonic-gate	popl	%ebp
14077c478bd9Sstevel@tonic-gate
14087c478bd9Sstevel@tonic-gate	ret
14097c478bd9Sstevel@tonic-gate#endif
14107c478bd9Sstevel@tonic-gate
14117c478bd9Sstevel@tonic-gate
14127c478bd9Sstevel@tonic-gate/* Source files are splitted, as they have different copyrights.  */
14137c478bd9Sstevel@tonic-gate#ifndef STAGE1_5
14147c478bd9Sstevel@tonic-gate# include "setjmp.S"
14157c478bd9Sstevel@tonic-gate# include "apm.S"
14167c478bd9Sstevel@tonic-gate#endif /* ! STAGE1_5 */
14177c478bd9Sstevel@tonic-gate
14187c478bd9Sstevel@tonic-gate
14197c478bd9Sstevel@tonic-gate
14207c478bd9Sstevel@tonic-gate#ifndef STAGE1_5
14217c478bd9Sstevel@tonic-gate/* get_code_end() :  return the address of the end of the code
14227c478bd9Sstevel@tonic-gate * This is here so that it can be replaced by asmstub.c.
14237c478bd9Sstevel@tonic-gate */
14247c478bd9Sstevel@tonic-gateENTRY(get_code_end)
14257c478bd9Sstevel@tonic-gate	/* will be the end of the bss */
14267c478bd9Sstevel@tonic-gate# if defined(HAVE_END_SYMBOL)
14277c478bd9Sstevel@tonic-gate	movl	$end, %eax
14287c478bd9Sstevel@tonic-gate# elif defined(HAVE_USCORE_END_SYMBOL)
14297c478bd9Sstevel@tonic-gate	movl	$_end, %eax
14307c478bd9Sstevel@tonic-gate# endif
14317c478bd9Sstevel@tonic-gate	shrl	$2, %eax		/* Round up to the next word. */
14327c478bd9Sstevel@tonic-gate	incl	%eax
14337c478bd9Sstevel@tonic-gate	shll	$2, %eax
14347c478bd9Sstevel@tonic-gate	ret
14357c478bd9Sstevel@tonic-gate#endif /* ! STAGE1_5 */
14367c478bd9Sstevel@tonic-gate
14377c478bd9Sstevel@tonic-gate/*
14387c478bd9Sstevel@tonic-gate *
14397c478bd9Sstevel@tonic-gate * get_memsize(i) :  return the memory size in KB. i == 0 for conventional
14407c478bd9Sstevel@tonic-gate *		memory, i == 1 for extended memory
14417c478bd9Sstevel@tonic-gate *	BIOS call "INT 12H" to get conventional memory size
14427c478bd9Sstevel@tonic-gate *	BIOS call "INT 15H, AH=88H" to get extended memory size
14437c478bd9Sstevel@tonic-gate *		Both have the return value in AX.
14447c478bd9Sstevel@tonic-gate *
14457c478bd9Sstevel@tonic-gate */
14467c478bd9Sstevel@tonic-gate
14477c478bd9Sstevel@tonic-gateENTRY(get_memsize)
14487c478bd9Sstevel@tonic-gate	push	%ebp
14497c478bd9Sstevel@tonic-gate	push	%ebx
14507c478bd9Sstevel@tonic-gate
14517c478bd9Sstevel@tonic-gate	mov	0xc(%esp), %ebx
14527c478bd9Sstevel@tonic-gate
14537c478bd9Sstevel@tonic-gate	call	EXT_C(prot_to_real)	/* enter real mode */
14547c478bd9Sstevel@tonic-gate	.code16
14557c478bd9Sstevel@tonic-gate
14567c478bd9Sstevel@tonic-gate	cmpb	$0x1, %bl
14577c478bd9Sstevel@tonic-gate	DATA32	je	xext
14587c478bd9Sstevel@tonic-gate
14597c478bd9Sstevel@tonic-gate	int	$0x12
14607c478bd9Sstevel@tonic-gate	DATA32	jmp	xdone
14617c478bd9Sstevel@tonic-gate
14627c478bd9Sstevel@tonic-gatexext:
14637c478bd9Sstevel@tonic-gate	movb	$0x88, %ah
14647c478bd9Sstevel@tonic-gate	int	$0x15
14657c478bd9Sstevel@tonic-gate
14667c478bd9Sstevel@tonic-gatexdone:
14677c478bd9Sstevel@tonic-gate	movw	%ax, %bx
14687c478bd9Sstevel@tonic-gate
14697c478bd9Sstevel@tonic-gate	DATA32	call	EXT_C(real_to_prot)
14707c478bd9Sstevel@tonic-gate	.code32
14717c478bd9Sstevel@tonic-gate
14727c478bd9Sstevel@tonic-gate	movw	%bx, %ax
14737c478bd9Sstevel@tonic-gate	pop	%ebx
14747c478bd9Sstevel@tonic-gate	pop	%ebp
14757c478bd9Sstevel@tonic-gate	ret
14767c478bd9Sstevel@tonic-gate
14777c478bd9Sstevel@tonic-gate
14787c478bd9Sstevel@tonic-gate#ifndef STAGE1_5
14797c478bd9Sstevel@tonic-gate
14807c478bd9Sstevel@tonic-gate/*
14817c478bd9Sstevel@tonic-gate *
14827c478bd9Sstevel@tonic-gate * get_eisamemsize() :  return packed EISA memory map, lower 16 bits is
14837c478bd9Sstevel@tonic-gate *		memory between 1M and 16M in 1K parts, upper 16 bits is
14847c478bd9Sstevel@tonic-gate *		memory above 16M in 64K parts.  If error, return -1.
14857c478bd9Sstevel@tonic-gate *	BIOS call "INT 15H, AH=E801H" to get EISA memory map,
14867c478bd9Sstevel@tonic-gate *		AX = memory between 1M and 16M in 1K parts.
14877c478bd9Sstevel@tonic-gate *		BX = memory above 16M in 64K parts.
14887c478bd9Sstevel@tonic-gate *
14897c478bd9Sstevel@tonic-gate */
14907c478bd9Sstevel@tonic-gate
14917c478bd9Sstevel@tonic-gateENTRY(get_eisamemsize)
14927c478bd9Sstevel@tonic-gate	push	%ebp
14937c478bd9Sstevel@tonic-gate	push	%ebx
14947c478bd9Sstevel@tonic-gate
14957c478bd9Sstevel@tonic-gate	call	EXT_C(prot_to_real)	/* enter real mode */
14967c478bd9Sstevel@tonic-gate	.code16
14977c478bd9Sstevel@tonic-gate
14987c478bd9Sstevel@tonic-gate	movw	$0xe801, %ax
14997c478bd9Sstevel@tonic-gate	int	$0x15
15007c478bd9Sstevel@tonic-gate
15017c478bd9Sstevel@tonic-gate	shll	$16, %ebx
15027c478bd9Sstevel@tonic-gate	movw	%ax, %bx
15037c478bd9Sstevel@tonic-gate
15047c478bd9Sstevel@tonic-gate	DATA32	call	EXT_C(real_to_prot)
15057c478bd9Sstevel@tonic-gate	.code32
15067c478bd9Sstevel@tonic-gate
15077c478bd9Sstevel@tonic-gate	movl	$0xFFFFFFFF, %eax
15087c478bd9Sstevel@tonic-gate	cmpb	$0x86, %bh
15097c478bd9Sstevel@tonic-gate	je	xnoteisa
15107c478bd9Sstevel@tonic-gate
15117c478bd9Sstevel@tonic-gate	movl	%ebx, %eax
15127c478bd9Sstevel@tonic-gate
15137c478bd9Sstevel@tonic-gatexnoteisa:
15147c478bd9Sstevel@tonic-gate	pop	%ebx
15157c478bd9Sstevel@tonic-gate	pop	%ebp
15167c478bd9Sstevel@tonic-gate	ret
15177c478bd9Sstevel@tonic-gate
15187c478bd9Sstevel@tonic-gate/*
15197c478bd9Sstevel@tonic-gate *
15207c478bd9Sstevel@tonic-gate * get_mmap_entry(addr, cont) :  address and old continuation value (zero to
15217c478bd9Sstevel@tonic-gate *		start), for the Query System Address Map BIOS call.
15227c478bd9Sstevel@tonic-gate *
15237c478bd9Sstevel@tonic-gate *  Sets the first 4-byte int value of "addr" to the size returned by
15247c478bd9Sstevel@tonic-gate *  the call.  If the call fails, sets it to zero.
15257c478bd9Sstevel@tonic-gate *
15267c478bd9Sstevel@tonic-gate *	Returns:  new (non-zero) continuation value, 0 if done.
15277c478bd9Sstevel@tonic-gate *
15287c478bd9Sstevel@tonic-gate * NOTE: Currently hard-coded for a maximum buffer length of 1024.
15297c478bd9Sstevel@tonic-gate */
15307c478bd9Sstevel@tonic-gate
15317c478bd9Sstevel@tonic-gateENTRY(get_mmap_entry)
15327c478bd9Sstevel@tonic-gate	push	%ebp
15337c478bd9Sstevel@tonic-gate	push	%ebx
15347c478bd9Sstevel@tonic-gate	push	%edi
15357c478bd9Sstevel@tonic-gate	push	%esi
15367c478bd9Sstevel@tonic-gate
15377c478bd9Sstevel@tonic-gate	/* place address (+4) in ES:DI */
15387c478bd9Sstevel@tonic-gate	movl	0x14(%esp), %eax
15397c478bd9Sstevel@tonic-gate	addl	$4, %eax
15407c478bd9Sstevel@tonic-gate	movl	%eax, %edi
15417c478bd9Sstevel@tonic-gate	andl	$0xf, %edi
15427c478bd9Sstevel@tonic-gate	shrl	$4, %eax
15437c478bd9Sstevel@tonic-gate	movl	%eax, %esi
15447c478bd9Sstevel@tonic-gate
15457c478bd9Sstevel@tonic-gate	/* set continuation value */
15467c478bd9Sstevel@tonic-gate	movl	0x18(%esp), %ebx
15477c478bd9Sstevel@tonic-gate
15487c478bd9Sstevel@tonic-gate	/* set default maximum buffer size */
15497c478bd9Sstevel@tonic-gate	movl	$0x14, %ecx
15507c478bd9Sstevel@tonic-gate
15517c478bd9Sstevel@tonic-gate	/* set EDX to 'SMAP' */
15527c478bd9Sstevel@tonic-gate	movl	$0x534d4150, %edx
15537c478bd9Sstevel@tonic-gate
15547c478bd9Sstevel@tonic-gate	call	EXT_C(prot_to_real)	/* enter real mode */
15557c478bd9Sstevel@tonic-gate	.code16
15567c478bd9Sstevel@tonic-gate
15577c478bd9Sstevel@tonic-gate	movw	%si, %es
15587c478bd9Sstevel@tonic-gate	movl	$0xe820, %eax
15597c478bd9Sstevel@tonic-gate	int	$0x15
15607c478bd9Sstevel@tonic-gate
15617c478bd9Sstevel@tonic-gate	DATA32	jc	xnosmap
15627c478bd9Sstevel@tonic-gate
15637c478bd9Sstevel@tonic-gate	cmpl	$0x534d4150, %eax
15647c478bd9Sstevel@tonic-gate	DATA32	jne	xnosmap
15657c478bd9Sstevel@tonic-gate
15667c478bd9Sstevel@tonic-gate	cmpl	$0x14, %ecx
15677c478bd9Sstevel@tonic-gate	DATA32	jl	xnosmap
15687c478bd9Sstevel@tonic-gate
15697c478bd9Sstevel@tonic-gate	cmpl	$0x400, %ecx
15707c478bd9Sstevel@tonic-gate	DATA32	jg	xnosmap
15717c478bd9Sstevel@tonic-gate
15727c478bd9Sstevel@tonic-gate	DATA32	jmp	xsmap
15737c478bd9Sstevel@tonic-gate
15747c478bd9Sstevel@tonic-gatexnosmap:
15757c478bd9Sstevel@tonic-gate	movl	$0, %ecx
15767c478bd9Sstevel@tonic-gate
15777c478bd9Sstevel@tonic-gatexsmap:
15787c478bd9Sstevel@tonic-gate	DATA32	call	EXT_C(real_to_prot)
15797c478bd9Sstevel@tonic-gate	.code32
15807c478bd9Sstevel@tonic-gate
15817c478bd9Sstevel@tonic-gate	/* write length of buffer (zero if error) into "addr" */
15827c478bd9Sstevel@tonic-gate	movl	0x14(%esp), %eax
15837c478bd9Sstevel@tonic-gate	movl	%ecx, (%eax)
15847c478bd9Sstevel@tonic-gate
15857c478bd9Sstevel@tonic-gate	/* set return value to continuation */
15867c478bd9Sstevel@tonic-gate	movl	%ebx, %eax
15877c478bd9Sstevel@tonic-gate
15887c478bd9Sstevel@tonic-gate	pop	%esi
15897c478bd9Sstevel@tonic-gate	pop	%edi
15907c478bd9Sstevel@tonic-gate	pop	%ebx
15917c478bd9Sstevel@tonic-gate	pop	%ebp
15927c478bd9Sstevel@tonic-gate	ret
15937c478bd9Sstevel@tonic-gate
15947c478bd9Sstevel@tonic-gate/*
15957c478bd9Sstevel@tonic-gate * get_rom_config_table()
15967c478bd9Sstevel@tonic-gate *
15977c478bd9Sstevel@tonic-gate * Get the linear address of a ROM configuration table. Return zero,
15987c478bd9Sstevel@tonic-gate * if fails.
15997c478bd9Sstevel@tonic-gate */
16007c478bd9Sstevel@tonic-gate
16017c478bd9Sstevel@tonic-gateENTRY(get_rom_config_table)
16027c478bd9Sstevel@tonic-gate	pushl	%ebp
16037c478bd9Sstevel@tonic-gate	pushl	%ebx
16047c478bd9Sstevel@tonic-gate
16057c478bd9Sstevel@tonic-gate	/* zero %ebx for simplicity */
16067c478bd9Sstevel@tonic-gate	xorl	%ebx, %ebx
16077c478bd9Sstevel@tonic-gate
16087c478bd9Sstevel@tonic-gate	call	EXT_C(prot_to_real)
16097c478bd9Sstevel@tonic-gate	.code16
16107c478bd9Sstevel@tonic-gate
16117c478bd9Sstevel@tonic-gate	movw	$0xc0, %ax
16127c478bd9Sstevel@tonic-gate	int	$0x15
16137c478bd9Sstevel@tonic-gate
16147c478bd9Sstevel@tonic-gate	jc	no_rom_table
16157c478bd9Sstevel@tonic-gate	testb	%ah, %ah
16167c478bd9Sstevel@tonic-gate	jnz	no_rom_table
16177c478bd9Sstevel@tonic-gate
16187c478bd9Sstevel@tonic-gate	movw	%es, %dx
16197c478bd9Sstevel@tonic-gate	jmp	found_rom_table
16207c478bd9Sstevel@tonic-gate
16217c478bd9Sstevel@tonic-gateno_rom_table:
16227c478bd9Sstevel@tonic-gate	xorw	%dx, %dx
16237c478bd9Sstevel@tonic-gate	xorw	%bx, %bx
16247c478bd9Sstevel@tonic-gate
16257c478bd9Sstevel@tonic-gatefound_rom_table:
16267c478bd9Sstevel@tonic-gate	DATA32	call	EXT_C(real_to_prot)
16277c478bd9Sstevel@tonic-gate	.code32
16287c478bd9Sstevel@tonic-gate
16297c478bd9Sstevel@tonic-gate	/* compute the linear address */
16307c478bd9Sstevel@tonic-gate	movw	%dx, %ax
16317c478bd9Sstevel@tonic-gate	shll	$4, %eax
16327c478bd9Sstevel@tonic-gate	addl	%ebx, %eax
16337c478bd9Sstevel@tonic-gate
16347c478bd9Sstevel@tonic-gate	popl	%ebx
16357c478bd9Sstevel@tonic-gate	popl	%ebp
16367c478bd9Sstevel@tonic-gate	ret
16377c478bd9Sstevel@tonic-gate
16387c478bd9Sstevel@tonic-gate
16397c478bd9Sstevel@tonic-gate/*
16407c478bd9Sstevel@tonic-gate * int get_vbe_controller_info (struct vbe_controller *controller_ptr)
16417c478bd9Sstevel@tonic-gate *
16427c478bd9Sstevel@tonic-gate * Get VBE controller information.
16437c478bd9Sstevel@tonic-gate */
16447c478bd9Sstevel@tonic-gate
16457c478bd9Sstevel@tonic-gateENTRY(get_vbe_controller_info)
16467c478bd9Sstevel@tonic-gate	pushl	%ebp
16477c478bd9Sstevel@tonic-gate	movl	%esp, %ebp
16487c478bd9Sstevel@tonic-gate
16497c478bd9Sstevel@tonic-gate	pushl	%edi
16507c478bd9Sstevel@tonic-gate	pushl	%ebx
16517c478bd9Sstevel@tonic-gate
16527c478bd9Sstevel@tonic-gate	/* Convert the linear address to segment:offset */
16537c478bd9Sstevel@tonic-gate	movl	8(%ebp), %eax
16547c478bd9Sstevel@tonic-gate	movl	%eax, %edi
16557c478bd9Sstevel@tonic-gate	andl	$0x0000000f, %edi
16567c478bd9Sstevel@tonic-gate	shrl	$4, %eax
16577c478bd9Sstevel@tonic-gate	movl	%eax, %ebx
16587c478bd9Sstevel@tonic-gate
16597c478bd9Sstevel@tonic-gate	call	EXT_C(prot_to_real)
16607c478bd9Sstevel@tonic-gate	.code16
16617c478bd9Sstevel@tonic-gate
16627c478bd9Sstevel@tonic-gate	movw	%bx, %es
16637c478bd9Sstevel@tonic-gate	movw	$0x4F00, %ax
16647c478bd9Sstevel@tonic-gate	int	$0x10
16657c478bd9Sstevel@tonic-gate
16667c478bd9Sstevel@tonic-gate	movw	%ax, %bx
16677c478bd9Sstevel@tonic-gate	DATA32	call	EXT_C(real_to_prot)
16687c478bd9Sstevel@tonic-gate	.code32
16697c478bd9Sstevel@tonic-gate
16707c478bd9Sstevel@tonic-gate	movzwl	%bx, %eax
16717c478bd9Sstevel@tonic-gate
16727c478bd9Sstevel@tonic-gate	popl	%ebx
16737c478bd9Sstevel@tonic-gate	popl	%edi
16747c478bd9Sstevel@tonic-gate	popl	%ebp
16757c478bd9Sstevel@tonic-gate	ret
16767c478bd9Sstevel@tonic-gate
16777c478bd9Sstevel@tonic-gate
16787c478bd9Sstevel@tonic-gate/*
16797c478bd9Sstevel@tonic-gate * int get_vbe_mode_info (int mode_number, struct vbe_mode *mode_ptr)
16807c478bd9Sstevel@tonic-gate *
16817c478bd9Sstevel@tonic-gate * Get VBE mode information.
16827c478bd9Sstevel@tonic-gate */
16837c478bd9Sstevel@tonic-gate
16847c478bd9Sstevel@tonic-gateENTRY(get_vbe_mode_info)
16857c478bd9Sstevel@tonic-gate	pushl	%ebp
16867c478bd9Sstevel@tonic-gate	movl	%esp, %ebp
16877c478bd9Sstevel@tonic-gate
16887c478bd9Sstevel@tonic-gate	pushl	%edi
16897c478bd9Sstevel@tonic-gate	pushl	%ebx
16907c478bd9Sstevel@tonic-gate
16917c478bd9Sstevel@tonic-gate	/* Convert the linear address to segment:offset */
16927c478bd9Sstevel@tonic-gate	movl	0xc(%ebp), %eax
16937c478bd9Sstevel@tonic-gate	movl	%eax, %edi
16947c478bd9Sstevel@tonic-gate	andl	$0x0000000f, %edi
16957c478bd9Sstevel@tonic-gate	shrl	$4, %eax
16967c478bd9Sstevel@tonic-gate	movl	%eax, %ebx
16977c478bd9Sstevel@tonic-gate
16987c478bd9Sstevel@tonic-gate	/* Save the mode number in %cx */
16997c478bd9Sstevel@tonic-gate	movl	0x8(%ebp), %ecx
17007c478bd9Sstevel@tonic-gate
17017c478bd9Sstevel@tonic-gate	call	EXT_C(prot_to_real)
17027c478bd9Sstevel@tonic-gate	.code16
17037c478bd9Sstevel@tonic-gate
17047c478bd9Sstevel@tonic-gate	movw	%bx, %es
17057c478bd9Sstevel@tonic-gate	movw	$0x4F01, %ax
17067c478bd9Sstevel@tonic-gate	int	$0x10
17077c478bd9Sstevel@tonic-gate
17087c478bd9Sstevel@tonic-gate	movw	%ax, %bx
17097c478bd9Sstevel@tonic-gate	DATA32	call	EXT_C(real_to_prot)
17107c478bd9Sstevel@tonic-gate	.code32
17117c478bd9Sstevel@tonic-gate
17127c478bd9Sstevel@tonic-gate	movzwl	%bx, %eax
17137c478bd9Sstevel@tonic-gate
17147c478bd9Sstevel@tonic-gate	popl	%ebx
17157c478bd9Sstevel@tonic-gate	popl	%edi
17167c478bd9Sstevel@tonic-gate	popl	%ebp
17177c478bd9Sstevel@tonic-gate	ret
17187c478bd9Sstevel@tonic-gate
17197c478bd9Sstevel@tonic-gate
17207c478bd9Sstevel@tonic-gate/*
17217c478bd9Sstevel@tonic-gate * int set_vbe_mode (int mode_number)
17227c478bd9Sstevel@tonic-gate *
17237c478bd9Sstevel@tonic-gate * Set VBE mode. Don't support user-specified CRTC information.
17247c478bd9Sstevel@tonic-gate */
17257c478bd9Sstevel@tonic-gate
17267c478bd9Sstevel@tonic-gateENTRY(set_vbe_mode)
17277c478bd9Sstevel@tonic-gate	pushl	%ebp
17287c478bd9Sstevel@tonic-gate	movl	%esp, %ebp
17297c478bd9Sstevel@tonic-gate
17307c478bd9Sstevel@tonic-gate	pushl	%ebx
17317c478bd9Sstevel@tonic-gate
17327c478bd9Sstevel@tonic-gate	/* Save the mode number in %bx */
17337c478bd9Sstevel@tonic-gate	movl	0x8(%ebp), %ebx
17347c478bd9Sstevel@tonic-gate	/* Clear bit D11 */
17357c478bd9Sstevel@tonic-gate	andl	$0xF7FF, %ebx
17367c478bd9Sstevel@tonic-gate
17377c478bd9Sstevel@tonic-gate	call	EXT_C(prot_to_real)
17387c478bd9Sstevel@tonic-gate	.code16
17397c478bd9Sstevel@tonic-gate
17407c478bd9Sstevel@tonic-gate	movw	$0x4F02, %ax
17417c478bd9Sstevel@tonic-gate	int	$0x10
17427c478bd9Sstevel@tonic-gate
17437c478bd9Sstevel@tonic-gate	movw	%ax, %bx
17447c478bd9Sstevel@tonic-gate	DATA32	call	EXT_C(real_to_prot)
17457c478bd9Sstevel@tonic-gate	.code32
17467c478bd9Sstevel@tonic-gate
17477c478bd9Sstevel@tonic-gate	movzwl	%bx, %eax
17487c478bd9Sstevel@tonic-gate
17497c478bd9Sstevel@tonic-gate	popl	%ebx
17507c478bd9Sstevel@tonic-gate	popl	%ebp
17517c478bd9Sstevel@tonic-gate	ret
17527c478bd9Sstevel@tonic-gate
17537c478bd9Sstevel@tonic-gate
17547c478bd9Sstevel@tonic-gate/*
17557c478bd9Sstevel@tonic-gate * gateA20(int linear)
17567c478bd9Sstevel@tonic-gate *
17577c478bd9Sstevel@tonic-gate * Gate address-line 20 for high memory.
17587c478bd9Sstevel@tonic-gate *
17597c478bd9Sstevel@tonic-gate * This routine is probably overconservative in what it does, but so what?
17607c478bd9Sstevel@tonic-gate *
17617c478bd9Sstevel@tonic-gate * It also eats any keystrokes in the keyboard buffer.  :-(
17627c478bd9Sstevel@tonic-gate */
17637c478bd9Sstevel@tonic-gate
17647c478bd9Sstevel@tonic-gateENTRY(gateA20)
17657c478bd9Sstevel@tonic-gate	/* first, try a BIOS call */
17667c478bd9Sstevel@tonic-gate	pushl	%ebp
17677c478bd9Sstevel@tonic-gate	movl	8(%esp), %edx
17687c478bd9Sstevel@tonic-gate
17697c478bd9Sstevel@tonic-gate	call	EXT_C(prot_to_real)
17707c478bd9Sstevel@tonic-gate
17717c478bd9Sstevel@tonic-gate	.code16
17727c478bd9Sstevel@tonic-gate	movw	$0x2400, %ax
17737c478bd9Sstevel@tonic-gate	testw	%dx, %dx
17747c478bd9Sstevel@tonic-gate	jz	1f
17757c478bd9Sstevel@tonic-gate	incw	%ax
17767c478bd9Sstevel@tonic-gate1:	stc
17777c478bd9Sstevel@tonic-gate	int	$0x15
17787c478bd9Sstevel@tonic-gate	jnc	2f
17797c478bd9Sstevel@tonic-gate
17807c478bd9Sstevel@tonic-gate	/* set non-zero if failed */
17817c478bd9Sstevel@tonic-gate	movb	$1, %ah
17827c478bd9Sstevel@tonic-gate
17837c478bd9Sstevel@tonic-gate	/* save the status */
17847c478bd9Sstevel@tonic-gate2:	movb	%ah, %dl
17857c478bd9Sstevel@tonic-gate
17867c478bd9Sstevel@tonic-gate	DATA32	call	EXT_C(real_to_prot)
17877c478bd9Sstevel@tonic-gate	.code32
17887c478bd9Sstevel@tonic-gate
17897c478bd9Sstevel@tonic-gate	popl	%ebp
17907c478bd9Sstevel@tonic-gate	testb	%dl, %dl
17917c478bd9Sstevel@tonic-gate	jnz	3f