xref: /illumos-gate/usr/src/grub/grub-0.97/stage2/asm.S (revision af28f636)
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
111*af28f636SEnrico Perla - Sun Microsystems	. = EXT_C(main) + 0x60
112*af28f636SEnrico Perla - Sun MicrosystemsVARIABLE(fake_mboot)
113*af28f636SEnrico Perla - Sun Microsystems	.long	0x1BADB002
114*af28f636SEnrico Perla - Sun Microsystems	.long   0x00010003
115*af28f636SEnrico Perla - Sun Microsystems	.long	-0x1BAEB005
1167ce76caaSEnrico Perla - Sun Microsystems	/*
117*af28f636SEnrico Perla - Sun Microsystems	 * installgrub will place the rest of the fake
118*af28f636SEnrico Perla - Sun Microsystems	 * multiboot header here.
1197ce76caaSEnrico Perla - Sun Microsystems	 */
120*af28f636SEnrico 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
17927c478bd9Sstevel@tonic-gate	ret
17937c478bd9Sstevel@tonic-gate
17946ee4b8d7Ssetje3:	/*
17956ee4b8d7Ssetje	 * try to switch gateA20 using PORT92, the "Fast A20 and Init"
17966ee4b8d7Ssetje	 * register
17976ee4b8d7Ssetje	 */
17986ee4b8d7Ssetje	mov	$0x92, %dx
17996ee4b8d7Ssetje	inb	%dx, %al
18006ee4b8d7Ssetje	/* skip the port92 code if it's unimplemented (read returns 0xff) */
18016ee4b8d7Ssetje	cmpb	$0xff, %al
18026ee4b8d7Ssetje	jz	6f
18036ee4b8d7Ssetje
18046ee4b8d7Ssetje	/* set or clear bit1, the ALT_A20_GATE bit */
18056ee4b8d7Ssetje	movb	4(%esp), %ah
18066ee4b8d7Ssetje	testb	%ah, %ah
18076ee4b8d7Ssetje	jz	4f
18086ee4b8d7Ssetje	orb	$2, %al
18096ee4b8d7Ssetje	jmp	5f
18106ee4b8d7Ssetje4:	and	$0xfd, %al
18116ee4b8d7Ssetje
18126ee4b8d7Ssetje	/* clear the INIT_NOW bit; don't accidently reset the machine */
18136ee4b8d7Ssetje5:	and	$0xfe, %al
18146ee4b8d7Ssetje	outb	%al, %dx
18156ee4b8d7Ssetje
18166ee4b8d7Ssetje6:	/* use keyboard controller */
18177c478bd9Sstevel@tonic-gate	pushl	%eax
18187c478bd9Sstevel@tonic-gate
18197c478bd9Sstevel@tonic-gate	call    gloop1
18207c478bd9Sstevel@tonic-gate
18217c478bd9Sstevel@tonic-gate	movb	$KC_CMD_WOUT, %al
18227c478bd9Sstevel@tonic-gate	outb	$K_CMD
18237c478bd9Sstevel@tonic-gate
18247c478bd9Sstevel@tonic-gategloopint1:
18257c478bd9Sstevel@tonic-gate	inb	$K_STATUS
18266ee4b8d7Ssetje	cmpb    $0xff, %al
18276ee4b8d7Ssetje	jz      gloopint1_done
18287c478bd9Sstevel@tonic-gate	andb	$K_IBUF_FUL, %al
18297c478bd9Sstevel@tonic-gate	jnz	gloopint1
18307c478bd9Sstevel@tonic-gate
18316ee4b8d7Ssetjegloopint1_done:
18327c478bd9Sstevel@tonic-gate	movb	$KB_OUTPUT_MASK, %al
18337c478bd9Sstevel@tonic-gate	cmpb	$0, 0x8(%esp)
18347c478bd9Sstevel@tonic-gate	jz	gdoit
18357c478bd9Sstevel@tonic-gate
18367c478bd9Sstevel@tonic-gate	orb	$KB_A20_ENABLE, %al
18377c478bd9Sstevel@tonic-gategdoit:
18387c478bd9Sstevel@tonic-gate	outb	$K_RDWR
18397c478bd9Sstevel@tonic-gate
18407c478bd9Sstevel@tonic-gate	call	gloop1
18417c478bd9Sstevel@tonic-gate
18427c478bd9Sstevel@tonic-gate	/* output a dummy command (USB keyboard hack) */
18437c478bd9Sstevel@tonic-gate	movb	$0xff, %al
18447c478bd9Sstevel@tonic-gate	outb	$K_CMD
18457c478bd9Sstevel@tonic-gate	call	gloop1
18467c478bd9Sstevel@tonic-gate
18477c478bd9Sstevel@tonic-gate	popl	%eax
18487c478bd9Sstevel@tonic-gate	ret
18497c478bd9Sstevel@tonic-gate
18507c478bd9Sstevel@tonic-gategloop1:
18517c478bd9Sstevel@tonic-gate	inb	$K_STATUS
18526ee4b8d7Ssetje	cmpb	$0xff, %al
18536ee4b8d7Ssetje	jz	gloop2ret
18547c478bd9Sstevel@tonic-gate	andb	$K_IBUF_FUL, %al
18557c478bd9Sstevel@tonic-gate	jnz	gloop1
18567c478bd9Sstevel@tonic-gate
18577c478bd9Sstevel@tonic-gategloop2:
18587c478bd9Sstevel@tonic-gate	inb	$K_STATUS
18597c478bd9Sstevel@tonic-gate	andb	$K_OBUF_FUL, %al
18607c478bd9Sstevel@tonic-gate	jz	gloop2ret
18617c478bd9Sstevel@tonic-gate	inb	$K_RDWR
18627c478bd9Sstevel@tonic-gate	jmp	gloop2
18637c478bd9Sstevel@tonic-gate
18647c478bd9Sstevel@tonic-gategloop2ret:
18657c478bd9Sstevel@tonic-gate	ret
18667c478bd9Sstevel@tonic-gate
18677c478bd9Sstevel@tonic-gate
18687c478bd9Sstevel@tonic-gateENTRY(patch_code)	/* labels start with "pc_" */
18697c478bd9Sstevel@tonic-gate	.code16
18707c478bd9Sstevel@tonic-gate
18717c478bd9Sstevel@tonic-gate	mov	%cs, %ax
18727c478bd9Sstevel@tonic-gate	mov	%ax, %ds
18737c478bd9Sstevel@tonic-gate	mov	%ax, %es
18747c478bd9Sstevel@tonic-gate	mov	%ax, %fs
18757c478bd9Sstevel@tonic-gate	mov	%ax, %gs
18767c478bd9Sstevel@tonic-gate	ADDR32	movl	$0, 0
18777c478bd9Sstevel@tonic-gatepc_stop:
18787c478bd9Sstevel@tonic-gate	hlt
18797c478bd9Sstevel@tonic-gate	DATA32	jmp	pc_stop
18807c478bd9Sstevel@tonic-gateENTRY(patch_code_end)
18817c478bd9Sstevel@tonic-gate
18827c478bd9Sstevel@tonic-gate	.code32
18837c478bd9Sstevel@tonic-gate
18847c478bd9Sstevel@tonic-gate
18857c478bd9Sstevel@tonic-gate/*
18867c478bd9Sstevel@tonic-gate * linux_boot()
18877c478bd9Sstevel@tonic-gate *
18887c478bd9Sstevel@tonic-gate * Does some funky things (including on the stack!), then jumps to the
18897c478bd9Sstevel@tonic-gate * entry point of the Linux setup code.
18907c478bd9Sstevel@tonic-gate */
18917c478bd9Sstevel@tonic-gate
18927c478bd9Sstevel@tonic-gateVARIABLE(linux_text_len)
18937c478bd9Sstevel@tonic-gate	.long	0
18947c478bd9Sstevel@tonic-gate
18957c478bd9Sstevel@tonic-gateVARIABLE(linux_data_tmp_addr)
18967c478bd9Sstevel@tonic-gate	.long	0
18977c478bd9Sstevel@tonic-gate
18987c478bd9Sstevel@tonic-gateVARIABLE(linux_data_real_addr)
18997c478bd9Sstevel@tonic-gate	.long	0
19007c478bd9Sstevel@tonic-gate
19017c478bd9Sstevel@tonic-gateENTRY(linux_boot)
19027c478bd9Sstevel@tonic-gate	/* don't worry about saving anything, we're committed at this point */
19037c478bd9Sstevel@tonic-gate	cld	/* forward copying */
19047c478bd9Sstevel@tonic-gate
19057c478bd9Sstevel@tonic-gate	/* copy kernel */
19067c478bd9Sstevel@tonic-gate	movl	EXT_C(linux_text_len), %ecx
19077c478bd9Sstevel@tonic-gate	addl	$3, %ecx
19087c478bd9Sstevel@tonic-gate	shrl	$2, %ecx
19097c478bd9Sstevel@tonic-gate	movl	$LINUX_BZIMAGE_ADDR, %esi
19107c478bd9Sstevel@tonic-gate	movl	$LINUX_ZIMAGE_ADDR, %edi
19117c478bd9Sstevel@tonic-gate
19127c478bd9Sstevel@tonic-gate	rep
19137c478bd9Sstevel@tonic-gate	movsl
19147c478bd9Sstevel@tonic-gate
19157c478bd9Sstevel@tonic-gateENTRY(big_linux_boot)
19167c478bd9Sstevel@tonic-gate	movl	EXT_C(linux_data_real_addr), %ebx
19177c478bd9Sstevel@tonic-gate
19187c478bd9Sstevel@tonic-gate	/* copy the real mode part */
19197c478bd9Sstevel@tonic-gate	movl	EXT_C(linux_data_tmp_addr), %esi
19207c478bd9Sstevel@tonic-gate	movl	%ebx, %edi
19217c478bd9Sstevel@tonic-gate	movl	$LINUX_SETUP_MOVE_SIZE, %ecx
19227c478bd9Sstevel@tonic-gate	cld
19237c478bd9Sstevel@tonic-gate	rep
19247c478bd9Sstevel@tonic-gate	movsb
19257c478bd9Sstevel@tonic-gate
19267c478bd9Sstevel@tonic-gate	/* change %ebx to the segment address */
19277c478bd9Sstevel@tonic-gate	shrl	$4, %ebx
19287c478bd9Sstevel@tonic-gate	movl	%ebx, %eax
19297c478bd9Sstevel@tonic-gate	addl	$0x20, %eax
19307c478bd9Sstevel@tonic-gate	movl	%eax, linux_setup_seg
19317c478bd9Sstevel@tonic-gate
19327c478bd9Sstevel@tonic-gate	/* XXX new stack pointer in safe area for calling functions */
19337c478bd9Sstevel@tonic-gate	movl	$0x4000, %esp
19347c478bd9Sstevel@tonic-gate	call	EXT_C(stop_floppy)
19357c478bd9Sstevel@tonic-gate
19367c478bd9Sstevel@tonic-gate	/* final setup for linux boot */
19377c478bd9Sstevel@tonic-gate
19387c478bd9Sstevel@tonic-gate	call	EXT_C(prot_to_real)
19397c478bd9Sstevel@tonic-gate	.code16
19407c478bd9Sstevel@tonic-gate
19417c478bd9Sstevel@tonic-gate	/* final setup for linux boot */
19427c478bd9Sstevel@tonic-gate	cli
19437c478bd9Sstevel@tonic-gate	movw	%bx, %ss
19447c478bd9Sstevel@tonic-gate	movw	$LINUX_SETUP_STACK, %sp
19457c478bd9Sstevel@tonic-gate
19467c478bd9Sstevel@tonic-gate	movw	%bx, %ds
19477c478bd9Sstevel@tonic-gate	movw	%bx, %es
19487c478bd9Sstevel@tonic-gate	movw	%bx, %fs
19497c478bd9Sstevel@tonic-gate	movw	%bx, %gs
19507c478bd9Sstevel@tonic-gate
19517c478bd9Sstevel@tonic-gate	/* jump to start */
19527c478bd9Sstevel@tonic-gate	/* ljmp */
19537c478bd9Sstevel@tonic-gate	.byte	0xea
19547c478bd9Sstevel@tonic-gate	.word	0
19557c478bd9Sstevel@tonic-gatelinux_setup_seg:
19567c478bd9Sstevel@tonic-gate	.word	0
19577c478bd9Sstevel@tonic-gate	.code32
19587c478bd9Sstevel@tonic-gate
19597c478bd9Sstevel@tonic-gate
19607c478bd9Sstevel@tonic-gate/*
19617c478bd9Sstevel@tonic-gate * multi_boot(int start, int mb_info)
19627c478bd9Sstevel@tonic-gate *
19637c478bd9Sstevel@tonic-gate *  This starts a kernel in the manner expected of the multiboot standard.
19647c478bd9Sstevel@tonic-gate */
19657c478bd9Sstevel@tonic-gate
19667c478bd9Sstevel@tonic-gateENTRY(multi_boot)
19677c478bd9Sstevel@tonic-gate	/* no need to save anything */
19687c478bd9Sstevel@tonic-gate	call	EXT_C(stop_floppy)
19697c478bd9Sstevel@tonic-gate
19707c478bd9Sstevel@tonic-gate	movl	$0x2BADB002, %eax
19717c478bd9Sstevel@tonic-gate	movl	0x8(%esp), %ebx
19727c478bd9Sstevel@tonic-gate
19737c478bd9Sstevel@tonic-gate	/* boot kernel here (absolute address call) */
19747c478bd9Sstevel@tonic-gate	call	*0x4(%esp)
19757c478bd9Sstevel@tonic-gate
19767c478bd9Sstevel@tonic-gate	/* error */
19777c478bd9Sstevel@tonic-gate	call	EXT_C(stop)
19787c478bd9Sstevel@tonic-gate
19797c478bd9Sstevel@tonic-gate#endif /* ! STAGE1_5 */
19807c478bd9Sstevel@tonic-gate
19817c478bd9Sstevel@tonic-gate/*
19827c478bd9Sstevel@tonic-gate * void console_putchar (int c)
19837c478bd9Sstevel@tonic-gate *
19847c478bd9Sstevel@tonic-gate * Put the character C on the console. Because GRUB wants to write a
19857c478bd9Sstevel@tonic-gate * character with an attribute, this implementation is a bit tricky.
19867c478bd9Sstevel@tonic-gate * If C is a control character (CR, LF, BEL, BS), use INT 10, AH = 0Eh
19877c478bd9Sstevel@tonic-gate * (TELETYPE OUTPUT). Otherwise, save the original position, put a space,
19887c478bd9Sstevel@tonic-gate * save the current position, restore the original position, write the
19897c478bd9Sstevel@tonic-gate * character and the attribute, and restore the current position.
19907c478bd9Sstevel@tonic-gate *
19917c478bd9Sstevel@tonic-gate * The reason why this is so complicated is that there is no easy way to
19927c478bd9Sstevel@tonic-gate * get the height of the screen, and the TELETYPE OUPUT BIOS call doesn't
19937c478bd9Sstevel@tonic-gate * support setting a background attribute.
19947c478bd9Sstevel@tonic-gate */
19957c478bd9Sstevel@tonic-gateENTRY(console_putchar)
19967c478bd9Sstevel@tonic-gate	movl	0x4(%esp), %edx
19977c478bd9Sstevel@tonic-gate	pusha
19987c478bd9Sstevel@tonic-gate#ifdef STAGE1_5
19997c478bd9Sstevel@tonic-gate	movb	$0x07, %bl
20007c478bd9Sstevel@tonic-gate#else
20017c478bd9Sstevel@tonic-gate	movl	EXT_C(console_current_color), %ebx
20027c478bd9Sstevel@tonic-gate#endif
20037c478bd9Sstevel@tonic-gate
20047c478bd9Sstevel@tonic-gate	call	EXT_C(prot_to_real)
20057c478bd9Sstevel@tonic-gate	.code16
20067c478bd9Sstevel@tonic-gate	movb	%dl, %al
20077c478bd9Sstevel@tonic-gate	xorb	%bh, %bh
20087c478bd9Sstevel@tonic-gate
20097c478bd9Sstevel@tonic-gate#ifndef STAGE1_5
20107c478bd9Sstevel@tonic-gate	/* use teletype output if control character */
20117c478bd9Sstevel@tonic-gate	cmpb	$0x7, %al
20127c478bd9Sstevel@tonic-gate	je	1f
20137c478bd9Sstevel@tonic-gate	cmpb	$0x8, %al
20147c478bd9Sstevel@tonic-gate	je	1f
20157c478bd9Sstevel@tonic-gate	cmpb	$0xa, %al
20167c478bd9Sstevel@tonic-gate	je	1f
20177c478bd9Sstevel@tonic-gate	cmpb	$0xd, %al
20187c478bd9Sstevel@tonic-gate	je	1f
20197c478bd9Sstevel@tonic-gate
20207c478bd9Sstevel@tonic-gate	/* save the character and the attribute on the stack */
20217c478bd9Sstevel@tonic-gate	pushw	%ax
20227c478bd9Sstevel@tonic-gate	pushw	%bx
20237c478bd9Sstevel@tonic-gate
20247c478bd9Sstevel@tonic-gate	/* get the current position */
20257c478bd9Sstevel@tonic-gate	movb	$0x3, %ah
20267c478bd9Sstevel@tonic-gate	int	$0x10
20277c478bd9Sstevel@tonic-gate
20287c478bd9Sstevel@tonic-gate	/* check the column with the width */
20297c478bd9Sstevel@tonic-gate	cmpb	$79, %dl
20307c478bd9Sstevel@tonic-gate	jl	2f
20317c478bd9Sstevel@tonic-gate
20327c478bd9Sstevel@tonic-gate	/* print CR and LF, if next write will exceed the width */
20337c478bd9Sstevel@tonic-gate	movw	$0x0e0d, %ax
20347c478bd9Sstevel@tonic-gate	int	$0x10
20357c478bd9Sstevel@tonic-gate	movb	$0x0a, %al
20367c478bd9Sstevel@tonic-gate	int	$0x10
20377c478bd9Sstevel@tonic-gate
20387c478bd9Sstevel@tonic-gate	/* get the current position */
20397c478bd9Sstevel@tonic-gate	movb	$0x3, %ah
20407c478bd9Sstevel@tonic-gate	int	$0x10
20417c478bd9Sstevel@tonic-gate
20427c478bd9Sstevel@tonic-gate2:
20437c478bd9Sstevel@tonic-gate	/* restore the character and the attribute */
20447c478bd9Sstevel@tonic-gate	popw	%bx
20457c478bd9Sstevel@tonic-gate	popw	%ax
20467c478bd9Sstevel@tonic-gate
20477c478bd9Sstevel@tonic-gate	/* write the character with the attribute */
20487c478bd9Sstevel@tonic-gate	movb	$0x9, %ah
20497c478bd9Sstevel@tonic-gate	movw	$1, %cx
20507c478bd9Sstevel@tonic-gate	int	$0x10
20517c478bd9Sstevel@tonic-gate
20527c478bd9Sstevel@tonic-gate	/* move the cursor forward */
20537c478bd9Sstevel@tonic-gate	incb	%dl
20547c478bd9Sstevel@tonic-gate	movb	$0x2, %ah
20557c478bd9Sstevel@tonic-gate	int	$0x10
20567c478bd9Sstevel@tonic-gate
20577c478bd9Sstevel@tonic-gate	jmp	3f
20587c478bd9Sstevel@tonic-gate#endif /* ! STAGE1_5 */
20597c478bd9Sstevel@tonic-gate
20607c478bd9Sstevel@tonic-gate1:	movb	$0xe, %ah
20617c478bd9Sstevel@tonic-gate	int	$0x10
20627c478bd9Sstevel@tonic-gate
20637c478bd9Sstevel@tonic-gate3:	DATA32	call	EXT_C(real_to_prot)
20647c478bd9Sstevel@tonic-gate	.code32
20657c478bd9Sstevel@tonic-gate
20667c478bd9Sstevel@tonic-gate	popa
20677c478bd9Sstevel@tonic-gate	ret
20687c478bd9Sstevel@tonic-gate
20697c478bd9Sstevel@tonic-gate
20707c478bd9Sstevel@tonic-gate#ifndef STAGE1_5
20717c478bd9Sstevel@tonic-gate
20727c478bd9Sstevel@tonic-gate/* this table is used in translate_keycode below */
20737c478bd9Sstevel@tonic-gatetranslation_table:
20747c478bd9Sstevel@tonic-gate	.word	KEY_LEFT, 2
20757c478bd9Sstevel@tonic-gate	.word	KEY_RIGHT, 6
20767c478bd9Sstevel@tonic-gate	.word	KEY_UP, 16
20777c478bd9Sstevel@tonic-gate	.word	KEY_DOWN, 14
20787c478bd9Sstevel@tonic-gate	.word	KEY_HOME, 1
20797c478bd9Sstevel@tonic-gate	.word	KEY_END, 5
20807c478bd9Sstevel@tonic-gate	.word	KEY_DC, 4
20817c478bd9Sstevel@tonic-gate	.word	KEY_BACKSPACE, 8
20827c478bd9Sstevel@tonic-gate	.word	KEY_PPAGE, 7
20837c478bd9Sstevel@tonic-gate	.word	KEY_NPAGE, 3
20847c478bd9Sstevel@tonic-gate	.word	0
20857c478bd9Sstevel@tonic-gate
20867c478bd9Sstevel@tonic-gate/*
20877c478bd9Sstevel@tonic-gate * translate_keycode translates the key code %dx to an ascii code.
20887c478bd9Sstevel@tonic-gate */
20897c478bd9Sstevel@tonic-gate	.code16
20907c478bd9Sstevel@tonic-gate
20917c478bd9Sstevel@tonic-gatetranslate_keycode:
20927c478bd9Sstevel@tonic-gate	pushw	%bx
20937c478bd9Sstevel@tonic-gate	pushw	%si
20947c478bd9Sstevel@tonic-gate
20957c478bd9Sstevel@tonic-gate	movw	$ABS(translation_table), %si
20967c478bd9Sstevel@tonic-gate
20977c478bd9Sstevel@tonic-gate1:	lodsw
20987c478bd9Sstevel@tonic-gate	/* check if this is the end */
20997c478bd9Sstevel@tonic-gate	testw	%ax, %ax
21007c478bd9Sstevel@tonic-gate	jz	2f
21017c478bd9Sstevel@tonic-gate	/* load the ascii code into %ax */
21027c478bd9Sstevel@tonic-gate	movw	%ax, %bx
21037c478bd9Sstevel@tonic-gate	lodsw
21047c478bd9Sstevel@tonic-gate	/* check if this matches the key code */
21057c478bd9Sstevel@tonic-gate	cmpw	%bx, %dx
21067c478bd9Sstevel@tonic-gate	jne	1b
21077c478bd9Sstevel@tonic-gate	/* translate %dx, if successful */
21087c478bd9Sstevel@tonic-gate	movw	%ax, %dx
21097c478bd9Sstevel@tonic-gate
21107c478bd9Sstevel@tonic-gate2:	popw	%si
21117c478bd9Sstevel@tonic-gate	popw	%bx
21127c478bd9Sstevel@tonic-gate	ret
21137c478bd9Sstevel@tonic-gate
21147c478bd9Sstevel@tonic-gate	.code32
21157c478bd9Sstevel@tonic-gate
21167c478bd9Sstevel@tonic-gate
21177c478bd9Sstevel@tonic-gate/*
21187c478bd9Sstevel@tonic-gate * remap_ascii_char remaps the ascii code %dl to another if the code is
21197c478bd9Sstevel@tonic-gate * contained in ASCII_KEY_MAP.
21207c478bd9Sstevel@tonic-gate */
21217c478bd9Sstevel@tonic-gate	.code16
21227c478bd9Sstevel@tonic-gate
21237c478bd9Sstevel@tonic-gateremap_ascii_char:
21247c478bd9Sstevel@tonic-gate	pushw	%si
21257c478bd9Sstevel@tonic-gate
21267c478bd9Sstevel@tonic-gate	movw	$ABS(EXT_C(ascii_key_map)), %si
21277c478bd9Sstevel@tonic-gate1:
21287c478bd9Sstevel@tonic-gate	lodsw
21297c478bd9Sstevel@tonic-gate	/* check if this is the end */
21307c478bd9Sstevel@tonic-gate	testw	%ax, %ax
21317c478bd9Sstevel@tonic-gate	jz	2f
21327c478bd9Sstevel@tonic-gate	/* check if this matches the ascii code */
21337c478bd9Sstevel@tonic-gate	cmpb	%al, %dl
21347c478bd9Sstevel@tonic-gate	jne	1b
21357c478bd9Sstevel@tonic-gate	/* if so, perform the mapping */
21367c478bd9Sstevel@tonic-gate	movb	%ah, %dl
21377c478bd9Sstevel@tonic-gate2:
21387c478bd9Sstevel@tonic-gate	/* restore %si */
21397c478bd9Sstevel@tonic-gate	popw	%si
21407c478bd9Sstevel@tonic-gate
21417c478bd9Sstevel@tonic-gate	ret
21427c478bd9Sstevel@tonic-gate
21437c478bd9Sstevel@tonic-gate	.code32
21447c478bd9Sstevel@tonic-gate
21457c478bd9Sstevel@tonic-gate	.align	4
21467c478bd9Sstevel@tonic-gateENTRY(ascii_key_map)
21477c478bd9Sstevel@tonic-gate	.space	(KEY_MAP_SIZE + 1) * 2
21487c478bd9Sstevel@tonic-gate
21497c478bd9Sstevel@tonic-gate
21507c478bd9Sstevel@tonic-gate/*
21517c478bd9Sstevel@tonic-gate * int console_getkey (void)
21527c478bd9Sstevel@tonic-gate * BIOS call "INT 16H Function 00H" to read character from keyboard
21537c478bd9Sstevel@tonic-gate *	Call with	%ah = 0x0
21547c478bd9Sstevel@tonic-gate *	Return:		%ah = keyboard scan code
21557c478bd9Sstevel@tonic-gate *			%al = ASCII character
21567c478bd9Sstevel@tonic-gate */
21577c478bd9Sstevel@tonic-gate
21587c478bd9Sstevel@tonic-gateENTRY(console_getkey)
21597c478bd9Sstevel@tonic-gate	push	%ebp
21607c478bd9Sstevel@tonic-gate
21616ee4b8d7Ssetjewait_for_key:
21626ee4b8d7Ssetje	call	EXT_C(console_checkkey)
2163c99350c4Ssetje	incl	%eax
2164c99350c4Ssetje	jz	wait_for_key
21656ee4b8d7Ssetje
21667c478bd9Sstevel@tonic-gate	call	EXT_C(prot_to_real)
21677c478bd9Sstevel@tonic-gate	.code16
21687c478bd9Sstevel@tonic-gate
21697c478bd9Sstevel@tonic-gate	int	$0x16
21707c478bd9Sstevel@tonic-gate
21717c478bd9Sstevel@tonic-gate	movw	%ax, %dx		/* real_to_prot uses %eax */
21727c478bd9Sstevel@tonic-gate	call	translate_keycode
21737c478bd9Sstevel@tonic-gate	call	remap_ascii_char
21747c478bd9Sstevel@tonic-gate
21757c478bd9Sstevel@tonic-gate	DATA32	call	EXT_C(real_to_prot)
21767c478bd9Sstevel@tonic-gate	.code32
21777c478bd9Sstevel@tonic-gate
21787c478bd9Sstevel@tonic-gate	movw	%dx, %ax
21797c478bd9Sstevel@tonic-gate
21807c478bd9Sstevel@tonic-gate	pop	%ebp
21817c478bd9Sstevel@tonic-gate	ret
21827c478bd9Sstevel@tonic-gate
21837c478bd9Sstevel@tonic-gate
21847c478bd9Sstevel@tonic-gate/*
21857c478bd9Sstevel@tonic-gate * int console_checkkey (void)
21867c478bd9Sstevel@tonic-gate *	if there is a character pending, return it; otherwise return -1
21877c478bd9Sstevel@tonic-gate * BIOS call "INT 16H Function 01H" to check whether a character is pending
21887c478bd9Sstevel@tonic-gate *	Call with	%ah = 0x1
21897c478bd9Sstevel@tonic-gate *	Return:
21907c478bd9Sstevel@tonic-gate *		If key waiting to be input:
21917c478bd9Sstevel@tonic-gate *			%ah = keyboard scan code
21927c478bd9Sstevel@tonic-gate *			%al = ASCII character
21937c478bd9Sstevel@tonic-gate *			Zero flag = clear
21947c478bd9Sstevel@tonic-gate *		else
21957c478bd9Sstevel@tonic-gate *			Zero flag = set
21967c478bd9Sstevel@tonic-gate */
21977c478bd9Sstevel@tonic-gateENTRY(console_checkkey)
21987c478bd9Sstevel@tonic-gate	push	%ebp
21997c478bd9Sstevel@tonic-gate	xorl	%edx, %edx
22007c478bd9Sstevel@tonic-gate
22017c478bd9Sstevel@tonic-gate	call	EXT_C(prot_to_real)	/* enter real mode */
22027c478bd9Sstevel@tonic-gate	.code16
22037c478bd9Sstevel@tonic-gate
22047c478bd9Sstevel@tonic-gate	movb	$0x1, %ah
22057c478bd9Sstevel@tonic-gate	int	$0x16
22067c478bd9Sstevel@tonic-gate
22077c478bd9Sstevel@tonic-gate	DATA32	jz	notpending
22087c478bd9Sstevel@tonic-gate
22097c478bd9Sstevel@tonic-gate	movw	%ax, %dx
22107c478bd9Sstevel@tonic-gate	call	translate_keycode
22117c478bd9Sstevel@tonic-gate	call	remap_ascii_char
22127c478bd9Sstevel@tonic-gate	DATA32	jmp	pending
22137c478bd9Sstevel@tonic-gate
22147c478bd9Sstevel@tonic-gatenotpending:
22157c478bd9Sstevel@tonic-gate	movl	$0xFFFFFFFF, %edx
22167c478bd9Sstevel@tonic-gate
22177c478bd9Sstevel@tonic-gatepending:
22187c478bd9Sstevel@tonic-gate	DATA32	call	EXT_C(real_to_prot)
22197c478bd9Sstevel@tonic-gate	.code32
22207c478bd9Sstevel@tonic-gate
22217c478bd9Sstevel@tonic-gate	mov	%edx, %eax
22227c478bd9Sstevel@tonic-gate
22237c478bd9Sstevel@tonic-gate	pop	%ebp
22247c478bd9Sstevel@tonic-gate	ret
22257c478bd9Sstevel@tonic-gate
22267c478bd9Sstevel@tonic-gate
22277c478bd9Sstevel@tonic-gate/*
22287c478bd9Sstevel@tonic-gate * int console_getxy (void)
22297c478bd9Sstevel@tonic-gate * BIOS call "INT 10H Function 03h" to get cursor position
22307c478bd9Sstevel@tonic-gate *	Call with	%ah = 0x03
22317c478bd9Sstevel@tonic-gate *			%bh = page
22327c478bd9Sstevel@tonic-gate *      Returns         %ch = starting scan line
22337c478bd9Sstevel@tonic-gate *                      %cl = ending scan line
22347c478bd9Sstevel@tonic-gate *                      %dh = row (0 is top)
22357c478bd9Sstevel@tonic-gate *                      %dl = column (0 is left)
22367c478bd9Sstevel@tonic-gate */
22377c478bd9Sstevel@tonic-gate
22387c478bd9Sstevel@tonic-gate
22397c478bd9Sstevel@tonic-gateENTRY(console_getxy)
22407c478bd9Sstevel@tonic-gate	push	%ebp
22417c478bd9Sstevel@tonic-gate	push	%ebx                    /* save EBX */
22427c478bd9Sstevel@tonic-gate
22437c478bd9Sstevel@tonic-gate	call	EXT_C(prot_to_real)
22447c478bd9Sstevel@tonic-gate	.code16
22457c478bd9Sstevel@tonic-gate
22467c478bd9Sstevel@tonic-gate        xorb	%bh, %bh                /* set page to 0 */
22477c478bd9Sstevel@tonic-gate	movb	$0x3, %ah
22487c478bd9Sstevel@tonic-gate	int	$0x10			/* get cursor position */
22497c478bd9Sstevel@tonic-gate
22507c478bd9Sstevel@tonic-gate	DATA32	call	EXT_C(real_to_prot)
22517c478bd9Sstevel@tonic-gate	.code32
22527c478bd9Sstevel@tonic-gate
22537c478bd9Sstevel@tonic-gate	movb	%dl, %ah
22547c478bd9Sstevel@tonic-gate	movb	%dh, %al
22557c478bd9Sstevel@tonic-gate
22567c478bd9Sstevel@tonic-gate	pop	%ebx
22577c478bd9Sstevel@tonic-gate	pop	%ebp
22587c478bd9Sstevel@tonic-gate	ret
22597c478bd9Sstevel@tonic-gate
22607c478bd9Sstevel@tonic-gate
22617c478bd9Sstevel@tonic-gate/*
22627c478bd9Sstevel@tonic-gate * void console_gotoxy(int x, int y)
22637c478bd9Sstevel@tonic-gate * BIOS call "INT 10H Function 02h" to set cursor position
22647c478bd9Sstevel@tonic-gate *	Call with	%ah = 0x02
22657c478bd9Sstevel@tonic-gate *			%bh = page
22667c478bd9Sstevel@tonic-gate *                      %dh = row (0 is top)
22677c478bd9Sstevel@tonic-gate *                      %dl = column (0 is left)
22687c478bd9Sstevel@tonic-gate */
22697c478bd9Sstevel@tonic-gate
22707c478bd9Sstevel@tonic-gate
22717c478bd9Sstevel@tonic-gateENTRY(console_gotoxy)
22727c478bd9Sstevel@tonic-gate	push	%ebp
22737c478bd9Sstevel@tonic-gate	push	%ebx                    /* save EBX */
22747c478bd9Sstevel@tonic-gate
22757c478bd9Sstevel@tonic-gate	movb	0xc(%esp), %dl           /* %dl = x */
22767c478bd9Sstevel@tonic-gate	movb	0x10(%esp), %dh          /* %dh = y */
22777c478bd9Sstevel@tonic-gate
22787c478bd9Sstevel@tonic-gate	call	EXT_C(prot_to_real)
22797c478bd9Sstevel@tonic-gate	.code16
22807c478bd9Sstevel@tonic-gate
22817c478bd9Sstevel@tonic-gate        xorb	%bh, %bh                /* set page to 0 */
22827c478bd9Sstevel@tonic-gate	movb	$0x2, %ah
22837c478bd9Sstevel@tonic-gate	int	$0x10			/* set cursor position */
22847c478bd9Sstevel@tonic-gate
22857c478bd9Sstevel@tonic-gate	DATA32	call	EXT_C(real_to_prot)
22867c478bd9Sstevel@tonic-gate	.code32
22877c478bd9Sstevel@tonic-gate
22887c478bd9Sstevel@tonic-gate	pop	%ebx
22897c478bd9Sstevel@tonic-gate	pop	%ebp
22907c478bd9Sstevel@tonic-gate	ret
22917c478bd9Sstevel@tonic-gate
22927c478bd9Sstevel@tonic-gate
22937c478bd9Sstevel@tonic-gate/*
22947c478bd9Sstevel@tonic-gate * void console_cls (void)
22957c478bd9Sstevel@tonic-gate * BIOS call "INT 10H Function 09h" to write character and attribute
22967c478bd9Sstevel@tonic-gate *	Call with	%ah = 0x09
22977c478bd9Sstevel@tonic-gate *                      %al = (character)
22987c478bd9Sstevel@tonic-gate *                      %bh = (page number)
22997c478bd9Sstevel@tonic-gate *                      %bl = (attribute)
23007c478bd9Sstevel@tonic-gate *                      %cx = (number of times)
23017c478bd9Sstevel@tonic-gate */
23027c478bd9Sstevel@tonic-gate
23037c478bd9Sstevel@tonic-gate
23047c478bd9Sstevel@tonic-gateENTRY(console_cls)
23057c478bd9Sstevel@tonic-gate	push	%ebp
23067c478bd9Sstevel@tonic-gate	push	%ebx                    /* save EBX */
23077c478bd9Sstevel@tonic-gate
23087c478bd9Sstevel@tonic-gate	call	EXT_C(prot_to_real)
23097c478bd9Sstevel@tonic-gate	.code16
23107c478bd9Sstevel@tonic-gate
23117c478bd9Sstevel@tonic-gate	/* move the cursor to the beginning */
23127c478bd9Sstevel@tonic-gate	movb	$0x02, %ah
23137c478bd9Sstevel@tonic-gate	xorb	%bh, %bh
23147c478bd9Sstevel@tonic-gate	xorw	%dx, %dx
23157c478bd9Sstevel@tonic-gate	int	$0x10
23167c478bd9Sstevel@tonic-gate
23177c478bd9Sstevel@tonic-gate	/* write spaces to the entire screen */
23187c478bd9Sstevel@tonic-gate	movw	$0x0920, %ax
23197c478bd9Sstevel@tonic-gate	movw	$0x07, %bx
23207c478bd9Sstevel@tonic-gate	movw	$(80 * 25), %cx
23217c478bd9Sstevel@tonic-gate        int	$0x10
23227c478bd9Sstevel@tonic-gate
23237c478bd9Sstevel@tonic-gate	/* move back the cursor */
23247c478bd9Sstevel@tonic-gate	movb	$0x02, %ah
23257c478bd9Sstevel@tonic-gate	int	$0x10
23267c478bd9Sstevel@tonic-gate
23277c478bd9Sstevel@tonic-gate	DATA32	call	EXT_C(real_to_prot)
23287c478bd9Sstevel@tonic-gate	.code32
23297c478bd9Sstevel@tonic-gate
23307c478bd9Sstevel@tonic-gate	pop	%ebx
23317c478bd9Sstevel@tonic-gate	pop	%ebp
23327c478bd9Sstevel@tonic-gate	ret
23337c478bd9Sstevel@tonic-gate
23347c478bd9Sstevel@tonic-gate
23357c478bd9Sstevel@tonic-gate/*
23367c478bd9Sstevel@tonic-gate * int console_setcursor (int on)
23377c478bd9Sstevel@tonic-gate * BIOS call "INT 10H Function 01h" to set cursor type
23387c478bd9Sstevel@tonic-gate *      Call with       %ah = 0x01
23397c478bd9Sstevel@tonic-gate *                      %ch = cursor starting scanline
23407c478bd9Sstevel@tonic-gate *                      %cl = cursor ending scanline
23417c478bd9Sstevel@tonic-gate */
23427c478bd9Sstevel@tonic-gate
23437c478bd9Sstevel@tonic-gateconsole_cursor_state:
23447c478bd9Sstevel@tonic-gate	.byte	1
23457c478bd9Sstevel@tonic-gateconsole_cursor_shape:
23467c478bd9Sstevel@tonic-gate	.word	0
23477c478bd9Sstevel@tonic-gate
23487c478bd9Sstevel@tonic-gateENTRY(console_setcursor)
23497c478bd9Sstevel@tonic-gate	push	%ebp
23507c478bd9Sstevel@tonic-gate	push	%ebx
23517c478bd9Sstevel@tonic-gate
23527c478bd9Sstevel@tonic-gate	/* check if the standard cursor shape has already been saved */
23537c478bd9Sstevel@tonic-gate	movw	console_cursor_shape, %ax
23547c478bd9Sstevel@tonic-gate	testw	%ax, %ax
23557c478bd9Sstevel@tonic-gate	jne	1f
23567c478bd9Sstevel@tonic-gate
23577c478bd9Sstevel@tonic-gate	call	EXT_C(prot_to_real)
23587c478bd9Sstevel@tonic-gate	.code16
23597c478bd9Sstevel@tonic-gate
23607c478bd9Sstevel@tonic-gate	movb	$0x03, %ah
23617c478bd9Sstevel@tonic-gate	xorb	%bh, %bh
23627c478bd9Sstevel@tonic-gate	int	$0x10
23637c478bd9Sstevel@tonic-gate
23647c478bd9Sstevel@tonic-gate	DATA32	call	EXT_C(real_to_prot)
23657c478bd9Sstevel@tonic-gate	.code32
23667c478bd9Sstevel@tonic-gate
23677c478bd9Sstevel@tonic-gate	movw	%cx, console_cursor_shape
23687c478bd9Sstevel@tonic-gate1:
23697c478bd9Sstevel@tonic-gate	/* set %cx to the designated cursor shape */
23707c478bd9Sstevel@tonic-gate	movw	$0x2000, %cx
23717c478bd9Sstevel@tonic-gate	movl	0xc(%esp), %ebx
23727c478bd9Sstevel@tonic-gate	testl	%ebx, %ebx
23737c478bd9Sstevel@tonic-gate	jz	2f
23747c478bd9Sstevel@tonic-gate	movw	console_cursor_shape, %cx
23757c478bd9Sstevel@tonic-gate2:
23767c478bd9Sstevel@tonic-gate	call	EXT_C(prot_to_real)
23777c478bd9Sstevel@tonic-gate	.code16
23787c478bd9Sstevel@tonic-gate
23797c478bd9Sstevel@tonic-gate	movb    $0x1, %ah
23807c478bd9Sstevel@tonic-gate	int     $0x10
23817c478bd9Sstevel@tonic-gate
23827c478bd9Sstevel@tonic-gate	DATA32	call	EXT_C(real_to_prot)
23837c478bd9Sstevel@tonic-gate	.code32
23847c478bd9Sstevel@tonic-gate
23857c478bd9Sstevel@tonic-gate	movzbl	console_cursor_state, %eax
23867c478bd9Sstevel@tonic-gate	movb	%bl, console_cursor_state
23877c478bd9Sstevel@tonic-gate
23887c478bd9Sstevel@tonic-gate	pop	%ebx
23897c478bd9Sstevel@tonic-gate	pop	%ebp
23907c478bd9Sstevel@tonic-gate	ret
23917c478bd9Sstevel@tonic-gate
23927c478bd9Sstevel@tonic-gate/* graphics mode functions */
23937c478bd9Sstevel@tonic-gate#ifdef SUPPORT_GRAPHICS
23947c478bd9Sstevel@tonic-gateVARIABLE(cursorX)
23957c478bd9Sstevel@tonic-gate.word	0
23967c478bd9Sstevel@tonic-gateVARIABLE(cursorY)
23977c478bd9Sstevel@tonic-gate.word	0
23987c478bd9Sstevel@tonic-gateVARIABLE(cursorCount)
23997c478bd9Sstevel@tonic-gate.word 0
24007c478bd9Sstevel@tonic-gateVARIABLE(cursorBuf)
24017c478bd9Sstevel@tonic-gate.byte	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
24027c478bd9Sstevel@tonic-gate
24037c478bd9Sstevel@tonic-gate
24047c478bd9Sstevel@tonic-gate/*
24057c478bd9Sstevel@tonic-gate * int set_videomode(mode)
24067c478bd9Sstevel@tonic-gate * BIOS call "INT 10H Function 0h" to set video mode
24077c478bd9Sstevel@tonic-gate *	Call with	%ah = 0x0
24087c478bd9Sstevel@tonic-gate *			%al = video mode
24097c478bd9Sstevel@tonic-gate *      Returns old videomode.
24107c478bd9Sstevel@tonic-gate */
24117c478bd9Sstevel@tonic-gateENTRY(set_videomode)
24127c478bd9Sstevel@tonic-gate	push	%ebp
24137c478bd9Sstevel@tonic-gate	push	%ebx
24147c478bd9Sstevel@tonic-gate	push	%ecx
24157c478bd9Sstevel@tonic-gate
24167c478bd9Sstevel@tonic-gate	movb	0x10(%esp), %cl
24177c478bd9Sstevel@tonic-gate
24187c478bd9Sstevel@tonic-gate	call	EXT_C(prot_to_real)
24197c478bd9Sstevel@tonic-gate	.code16
24207c478bd9Sstevel@tonic-gate
24217c478bd9Sstevel@tonic-gate	xorw	%bx, %bx
24227c478bd9Sstevel@tonic-gate	movb	$0xf, %ah
24237c478bd9Sstevel@tonic-gate	int	$0x10			/* Get Current Video mode */
24247c478bd9Sstevel@tonic-gate	movb	%al, %ch
24257c478bd9Sstevel@tonic-gate	xorb	%ah, %ah
24267c478bd9Sstevel@tonic-gate	movb	%cl, %al
24277c478bd9Sstevel@tonic-gate        int	$0x10			/* Set Video mode */
24287c478bd9Sstevel@tonic-gate
24297c478bd9Sstevel@tonic-gate	DATA32	call	EXT_C(real_to_prot)
24307c478bd9Sstevel@tonic-gate	.code32
24317c478bd9Sstevel@tonic-gate
24327c478bd9Sstevel@tonic-gate	xorb	%ah, %ah
24337c478bd9Sstevel@tonic-gate	movb	%ch, %al
24347c478bd9Sstevel@tonic-gate
24357c478bd9Sstevel@tonic-gate	pop	%ecx
24367c478bd9Sstevel@tonic-gate	pop	%ebx
24377c478bd9Sstevel@tonic-gate	pop	%ebp
24387c478bd9Sstevel@tonic-gate	ret
24397c478bd9Sstevel@tonic-gate
24407c478bd9Sstevel@tonic-gate
24417c478bd9Sstevel@tonic-gate/*
24427c478bd9Sstevel@tonic-gate * unsigned char * graphics_get_font()
24437c478bd9Sstevel@tonic-gate * BIOS call "INT 10H Function 11h" to set font
24447c478bd9Sstevel@tonic-gate *      Call with       %ah = 0x11
24457c478bd9Sstevel@tonic-gate */
24467c478bd9Sstevel@tonic-gateENTRY(graphics_get_font)
24477c478bd9Sstevel@tonic-gate	push	%ebp
24487c478bd9Sstevel@tonic-gate	push	%ebx
24497c478bd9Sstevel@tonic-gate	push	%ecx
24507c478bd9Sstevel@tonic-gate	push	%edx
24517c478bd9Sstevel@tonic-gate
24527c478bd9Sstevel@tonic-gate	call	EXT_C(prot_to_real)
24537c478bd9Sstevel@tonic-gate	.code16
24547c478bd9Sstevel@tonic-gate
24557c478bd9Sstevel@tonic-gate	movw	$0x1130, %ax
24567c478bd9Sstevel@tonic-gate	movb	$6, %bh		/* font 8x16 */
24577c478bd9Sstevel@tonic-gate	int	$0x10
24587c478bd9Sstevel@tonic-gate	movw	%bp, %dx
24597c478bd9Sstevel@tonic-gate	movw	%es, %cx
24607c478bd9Sstevel@tonic-gate
24617c478bd9Sstevel@tonic-gate	DATA32	call	EXT_C(real_to_prot)
24627c478bd9Sstevel@tonic-gate	.code32
24637c478bd9Sstevel@tonic-gate
24647c478bd9Sstevel@tonic-gate	xorl	%eax, %eax
24657c478bd9Sstevel@tonic-gate	movw	%cx, %ax
24667c478bd9Sstevel@tonic-gate	shll	$4, %eax
24677c478bd9Sstevel@tonic-gate	movw	%dx, %ax
24687c478bd9Sstevel@tonic-gate
24697c478bd9Sstevel@tonic-gate	pop	%edx
24707c478bd9Sstevel@tonic-gate	pop	%ecx
24717c478bd9Sstevel@tonic-gate	pop	%ebx
24727c478bd9Sstevel@tonic-gate	pop	%ebp
24737c478bd9Sstevel@tonic-gate	ret
24747c478bd9Sstevel@tonic-gate
24757c478bd9Sstevel@tonic-gate
24767c478bd9Sstevel@tonic-gate
24777c478bd9Sstevel@tonic-gate/*
24787c478bd9Sstevel@tonic-gate * graphics_set_palette(index, red, green, blue)
24797c478bd9Sstevel@tonic-gate * BIOS call "INT 10H Function 10h" to set individual dac register
24807c478bd9Sstevel@tonic-gate *	Call with	%ah = 0x10
24817c478bd9Sstevel@tonic-gate *			%bx = register number
24827c478bd9Sstevel@tonic-gate *			%ch = new value for green (0-63)
24837c478bd9Sstevel@tonic-gate *			%cl = new value for blue (0-63)
24847c478bd9Sstevel@tonic-gate *			%dh = new value for red (0-63)
24857c478bd9Sstevel@tonic-gate */
24867c478bd9Sstevel@tonic-gate
24877c478bd9Sstevel@tonic-gateENTRY(graphics_set_palette)
24887c478bd9Sstevel@tonic-gate	push	%ebp
24897c478bd9Sstevel@tonic-gate	push	%eax
24907c478bd9Sstevel@tonic-gate	push	%ebx
24917c478bd9Sstevel@tonic-gate	push	%ecx
24927c478bd9Sstevel@tonic-gate	push	%edx
24937c478bd9Sstevel@tonic-gate
24947c478bd9Sstevel@tonic-gate	movw	$0x3c8, %bx		/* address write mode register */
24957c478bd9Sstevel@tonic-gate
24967c478bd9Sstevel@tonic-gate	/* wait vertical retrace */
24977c478bd9Sstevel@tonic-gate
24987c478bd9Sstevel@tonic-gate	movw	$0x3da, %dx
24997c478bd9Sstevel@tonic-gatel1b:	inb	%dx, %al	/* wait vertical active display */
25007c478bd9Sstevel@tonic-gate	test	$8, %al
25017c478bd9Sstevel@tonic-gate	jnz	l1b
25027c478bd9Sstevel@tonic-gate
25037c478bd9Sstevel@tonic-gatel2b:	inb	%dx, %al	/* wait vertical retrace */
25047c478bd9Sstevel@tonic-gate	test	$8, %al
25057c478bd9Sstevel@tonic-gate	jnz	l2b
25067c478bd9Sstevel@tonic-gate
25077c478bd9Sstevel@tonic-gate	mov	%bx, %dx
25087c478bd9Sstevel@tonic-gate	movb	0x18(%esp), %al		/* index */
25097c478bd9Sstevel@tonic-gate	outb	%al, %dx
25107c478bd9Sstevel@tonic-gate	inc	%dx
25117c478bd9Sstevel@tonic-gate
25127c478bd9Sstevel@tonic-gate	movb	0x1c(%esp), %al		/* red */
25137c478bd9Sstevel@tonic-gate	outb	%al, %dx
25147c478bd9Sstevel@tonic-gate
25157c478bd9Sstevel@tonic-gate	movb	0x20(%esp), %al		/* green */
25167c478bd9Sstevel@tonic-gate	outb	%al, %dx
25177c478bd9Sstevel@tonic-gate
25187c478bd9Sstevel@tonic-gate	movb	0x24(%esp), %al		/* blue */
25197c478bd9Sstevel@tonic-gate	outb	%al, %dx
25207c478bd9Sstevel@tonic-gate
25217c478bd9Sstevel@tonic-gate	movw	0x18(%esp), %bx
25227c478bd9Sstevel@tonic-gate
25237c478bd9Sstevel@tonic-gate	call	EXT_C(prot_to_real)
25247c478bd9Sstevel@tonic-gate	.code16
25257c478bd9Sstevel@tonic-gate
25267c478bd9Sstevel@tonic-gate	movb	%bl, %bh
25277c478bd9Sstevel@tonic-gate	movw	$0x1000, %ax
25287c478bd9Sstevel@tonic-gate	int	$0x10
25297c478bd9Sstevel@tonic-gate
25307c478bd9Sstevel@tonic-gate	DATA32	call	EXT_C(real_to_prot)
25317c478bd9Sstevel@tonic-gate	.code32
25327c478bd9Sstevel@tonic-gate
25337c478bd9Sstevel@tonic-gate	pop	%edx
25347c478bd9Sstevel@tonic-gate	pop	%ecx
25357c478bd9Sstevel@tonic-gate	pop	%ebx
25367c478bd9Sstevel@tonic-gate	pop	%eax
25377c478bd9Sstevel@tonic-gate	pop	%ebp
25387c478bd9Sstevel@tonic-gate	ret
25397c478bd9Sstevel@tonic-gate
25407c478bd9Sstevel@tonic-gate#endif /* SUPPORT_GRAPHICS */
25417c478bd9Sstevel@tonic-gate
25427c478bd9Sstevel@tonic-gate/*
25437c478bd9Sstevel@tonic-gate * getrtsecs()
25447c478bd9Sstevel@tonic-gate *	if a seconds value can be read, read it and return it (BCD),
25457c478bd9Sstevel@tonic-gate *      otherwise return 0xFF
25467c478bd9Sstevel@tonic-gate * BIOS call "INT 1AH Function 02H" to check whether a character is pending
25477c478bd9Sstevel@tonic-gate *	Call with	%ah = 0x2
25487c478bd9Sstevel@tonic-gate *	Return:
25497c478bd9Sstevel@tonic-gate *		If RT Clock can give correct values
25507c478bd9Sstevel@tonic-gate *			%ch = hour (BCD)
25517c478bd9Sstevel@tonic-gate *			%cl = minutes (BCD)
25527c478bd9Sstevel@tonic-gate *                      %dh = seconds (BCD)
25537c478bd9Sstevel@tonic-gate *                      %dl = daylight savings time (00h std, 01h daylight)
25547c478bd9Sstevel@tonic-gate *			Carry flag = clear
25557c478bd9Sstevel@tonic-gate *		else
25567c478bd9Sstevel@tonic-gate *			Carry flag = set
25577c478bd9Sstevel@tonic-gate *                         (this indicates that the clock is updating, or
25587c478bd9Sstevel@tonic-gate *                          that it isn't running)
25597c478bd9Sstevel@tonic-gate */
25607c478bd9Sstevel@tonic-gateENTRY(getrtsecs)
25617c478bd9Sstevel@tonic-gate	push	%ebp
25627c478bd9Sstevel@tonic-gate
25637c478bd9Sstevel@tonic-gate	call	EXT_C(prot_to_real)	/* enter real mode */
25647c478bd9Sstevel@tonic-gate	.code16
25657c478bd9Sstevel@tonic-gate
25667c478bd9Sstevel@tonic-gate	movb	$0x2, %ah
25677c478bd9Sstevel@tonic-gate	int	$0x1a
25687c478bd9Sstevel@tonic-gate
25697c478bd9Sstevel@tonic-gate	DATA32	jnc	gottime
25707c478bd9Sstevel@tonic-gate	movb	$0xff, %dh
25717c478bd9Sstevel@tonic-gate
25727c478bd9Sstevel@tonic-gategottime:
25737c478bd9Sstevel@tonic-gate	DATA32	call	EXT_C(real_to_prot)
25747c478bd9Sstevel@tonic-gate	.code32
25757c478bd9Sstevel@tonic-gate
25767c478bd9Sstevel@tonic-gate	movb	%dh, %al
25777c478bd9Sstevel@tonic-gate
25787c478bd9Sstevel@tonic-gate	pop	%ebp
25797c478bd9Sstevel@tonic-gate	ret
25807c478bd9Sstevel@tonic-gate
25817c478bd9Sstevel@tonic-gate
25827c478bd9Sstevel@tonic-gate/*
25837c478bd9Sstevel@tonic-gate * currticks()
25847c478bd9Sstevel@tonic-gate *	return the real time in ticks, of which there are about
25857c478bd9Sstevel@tonic-gate *	18-20 per second
25867c478bd9Sstevel@tonic-gate */
25877c478bd9Sstevel@tonic-gateENTRY(currticks)
25887c478bd9Sstevel@tonic-gate	pushl	%ebp
25897c478bd9Sstevel@tonic-gate
25907c478bd9Sstevel@tonic-gate	call	EXT_C(prot_to_real)	/* enter real mode */
25917c478bd9Sstevel@tonic-gate	.code16
25927c478bd9Sstevel@tonic-gate
25937c478bd9Sstevel@tonic-gate	/* %ax is already zero */
25947c478bd9Sstevel@tonic-gate        int	$0x1a
25957c478bd9Sstevel@tonic-gate
25967c478bd9Sstevel@tonic-gate	DATA32	call	EXT_C(real_to_prot)
25977c478bd9Sstevel@tonic-gate	.code32
25987c478bd9Sstevel@tonic-gate
25997c478bd9Sstevel@tonic-gate	movl	%ecx, %eax
26007c478bd9Sstevel@tonic-gate	shll	$16, %eax
26017c478bd9Sstevel@tonic-gate	movw	%dx, %ax
26027c478bd9Sstevel@tonic-gate
26037c478bd9Sstevel@tonic-gate	popl	%ebp
26047c478bd9Sstevel@tonic-gate	ret
26057c478bd9Sstevel@tonic-gate
2606ae115bc7SmrjENTRY(amd64_rdmsr)
2607ae115bc7Smrj	movl	4(%esp), %ecx
2608ae115bc7Smrj	rdmsr
2609ae115bc7Smrj	movl	8(%esp), %ecx
2610ae115bc7Smrj	movl	%eax, (%ecx)
2611ae115bc7Smrj	movl	%edx, 4(%ecx)
2612ae115bc7Smrj	ret
2613ae115bc7Smrj
2614ae115bc7SmrjENTRY(amd64_wrmsr)
2615ae115bc7Smrj	movl	8(%esp), %ecx
2616ae115bc7Smrj	movl	(%ecx), %eax
2617ae115bc7Smrj	movl	4(%ecx), %edx
2618ae115bc7Smrj	movl	4(%esp), %ecx
2619ae115bc7Smrj	wrmsr
2620ae115bc7Smrj	ret
2621ae115bc7Smrj
2622ae115bc7SmrjENTRY(amd64_cpuid_insn)
2623ae115bc7Smrj	pushl	%ebp
2624ae115bc7Smrj	movl	%esp, %ebp
2625ae115bc7Smrj	pushl	%ebx
2626ae115bc7Smrj	pushl	%esi
2627ae115bc7Smrj	movl	0x8(%ebp), %eax
2628ae115bc7Smrj	movl	0xc(%ebp), %esi
2629ae115bc7Smrj	cpuid
2630ae115bc7Smrj	movl	%eax, 0x0(%esi)
2631ae115bc7Smrj	movl	%ebx, 0x4(%esi)
2632ae115bc7Smrj	movl	%ecx, 0x8(%esi)
2633ae115bc7Smrj	movl	%edx, 0xc(%esi)
2634ae115bc7Smrj	popl	%esi
2635ae115bc7Smrj	popl	%ebx
2636ae115bc7Smrj	popl	%ebp
2637ae115bc7Smrj	ret
2638ae115bc7Smrj
2639ae115bc7Smrj	/*
2640ae115bc7Smrj	 * Based on code from AMD64 Volume 3
2641ae115bc7Smrj	 */
2642ae115bc7SmrjENTRY(amd64_cpuid_supported)
2643ae115bc7Smrj	pushf
2644ae115bc7Smrj	popl	%eax
2645ae115bc7Smrj	mov	%eax, %edx		/* save %eax for later */
2646ae115bc7Smrj	xorl	%eax, 0x200000		/* toggle bit 21 */
2647ae115bc7Smrj	pushl	%eax
2648ae115bc7Smrj	popf				/* save new %eax to EFLAGS */
2649ae115bc7Smrj	pushf				/* save new EFLAGS */
2650ae115bc7Smrj	popl	%ecx			/* copy EFLAGS to %eax */
2651ae115bc7Smrj	xorl	%eax, %eax
2652ae115bc7Smrj	cmpl	%ecx, %edx		/* see if bit 21 has changes */
2653ae115bc7Smrj	jne	1f
2654ae115bc7Smrj	incl	%eax
2655ae115bc7Smrj1:
2656ae115bc7Smrj	ret
2657ae115bc7Smrj
2658ae115bc7SmrjENTRY(get_target_operating_mode)
2659ae115bc7Smrj	pusha
2660ae115bc7Smrj
2661ae115bc7Smrj	call	EXT_C(prot_to_real)
2662ae115bc7Smrj	.code16
2663ae115bc7Smrj
2664ae115bc7Smrj	movw	$0xec00, %ax
2665ae115bc7Smrj	movw	$0x03, %bx
2666ae115bc7Smrj	int	$0x15
2667ae115bc7Smrj/* XXX still need to pass back return */
2668ae115bc7Smrj
2669ae115bc7Smrj	movw	%ax, %cx
2670ae115bc7Smrj
2671ae115bc7Smrj	DATA32	call	EXT_C(real_to_prot)
2672ae115bc7Smrj	.code32
2673ae115bc7Smrj
2674ae115bc7Smrj	xorl	%eax, %eax
2675ae115bc7Smrj	movw	%cx, %ax
2676ae115bc7Smrj
2677ae115bc7Smrj	popa
2678ae115bc7Smrj	ret
2679ae115bc7Smrj
2680ae115bc7Smrj#endif /* ! STAGE1_5 */
26817c478bd9Sstevel@tonic-gate
26827c478bd9Sstevel@tonic-gate/*
26837c478bd9Sstevel@tonic-gate *  This is the area for all of the special variables.
26847c478bd9Sstevel@tonic-gate */
26857c478bd9Sstevel@tonic-gate
26867c478bd9Sstevel@tonic-gate	.p2align	2	/* force 4-byte alignment */
26877c478bd9Sstevel@tonic-gate
26887c478bd9Sstevel@tonic-gateprotstack:
26897c478bd9Sstevel@tonic-gate	.long	PROTSTACKINIT
26907c478bd9Sstevel@tonic-gate
26917c478bd9Sstevel@tonic-gateVARIABLE(boot_drive)
26927c478bd9Sstevel@tonic-gate#ifdef SUPPORT_DISKLESS
26937c478bd9Sstevel@tonic-gate	.long	NETWORK_DRIVE
26947c478bd9Sstevel@tonic-gate#else
26957c478bd9Sstevel@tonic-gate	.long	0
26967c478bd9Sstevel@tonic-gate#endif
26977c478bd9Sstevel@tonic-gate
26987c478bd9Sstevel@tonic-gateVARIABLE(install_second_sector)
26997c478bd9Sstevel@tonic-gate	.long	0
27007c478bd9Sstevel@tonic-gate
27017c478bd9Sstevel@tonic-gate	/* an address can only be long-jumped to if it is in memory, this
27027c478bd9Sstevel@tonic-gate	   is used by multiple routines */
27037c478bd9Sstevel@tonic-gateoffset:
27047c478bd9Sstevel@tonic-gate	.long	0x8000
27057c478bd9Sstevel@tonic-gatesegment:
27067c478bd9Sstevel@tonic-gate	.word	0
27077c478bd9Sstevel@tonic-gate
27087c478bd9Sstevel@tonic-gateVARIABLE(apm_bios_info)
27097c478bd9Sstevel@tonic-gate	.word	0	/* version */
27107c478bd9Sstevel@tonic-gate	.word	0	/* cseg */
27117c478bd9Sstevel@tonic-gate	.long	0	/* offset */
27127c478bd9Sstevel@tonic-gate	.word	0	/* cseg_16 */
27137c478bd9Sstevel@tonic-gate	.word	0	/* dseg_16 */
27147c478bd9Sstevel@tonic-gate	.word	0	/* cseg_len */
27157c478bd9Sstevel@tonic-gate	.word	0	/* cseg_16_len */
27167c478bd9Sstevel@tonic-gate	.word	0	/* dseg_16_len */
27177c478bd9Sstevel@tonic-gate
27187c478bd9Sstevel@tonic-gate/*
27197c478bd9Sstevel@tonic-gate * This is the Global Descriptor Table
27207c478bd9Sstevel@tonic-gate *
27217c478bd9Sstevel@tonic-gate *  An entry, a "Segment Descriptor", looks like this:
27227c478bd9Sstevel@tonic-gate *
27237c478bd9Sstevel@tonic-gate * 31          24         19   16                 7           0
27247c478bd9Sstevel@tonic-gate * ------------------------------------------------------------
27257c478bd9Sstevel@tonic-gate * |             | |B| |A|       | |   |1|0|E|W|A|            |
27267c478bd9Sstevel@tonic-gate * | BASE 31..24 |G|/|0|V| LIMIT |P|DPL|  TYPE   | BASE 23:16 |
27277c478bd9Sstevel@tonic-gate * |             | |D| |L| 19..16| |   |1|1|C|R|A|            |
27287c478bd9Sstevel@tonic-gate * ------------------------------------------------------------
27297c478bd9Sstevel@tonic-gate * |                             |                            |
27307c478bd9Sstevel@tonic-gate * |        BASE 15..0           |       LIMIT 15..0          |
27317c478bd9Sstevel@tonic-gate * |                             |                            |
27327c478bd9Sstevel@tonic-gate * ------------------------------------------------------------
27337c478bd9Sstevel@tonic-gate *
27347c478bd9Sstevel@tonic-gate *  Note the ordering of the data items is reversed from the above
27357c478bd9Sstevel@tonic-gate *  description.
27367c478bd9Sstevel@tonic-gate */
27377c478bd9Sstevel@tonic-gate
27387c478bd9Sstevel@tonic-gate	.p2align	2	/* force 4-byte alignment */
27397c478bd9Sstevel@tonic-gategdt:
27407c478bd9Sstevel@tonic-gate	.word	0, 0
27417c478bd9Sstevel@tonic-gate	.byte	0, 0, 0, 0
27427c478bd9Sstevel@tonic-gate
27437c478bd9Sstevel@tonic-gate	/* code segment */
27447c478bd9Sstevel@tonic-gate	.word	0xFFFF, 0
27457c478bd9Sstevel@tonic-gate	.byte	0, 0x9A, 0xCF, 0
27467c478bd9Sstevel@tonic-gate
27477c478bd9Sstevel@tonic-gate	/* data segment */
27487c478bd9Sstevel@tonic-gate	.word	0xFFFF, 0
27497c478bd9Sstevel@tonic-gate	.byte	0, 0x92, 0xCF, 0
27507c478bd9Sstevel@tonic-gate
27517c478bd9Sstevel@tonic-gate	/* 16 bit real mode CS */
27527c478bd9Sstevel@tonic-gate	.word	0xFFFF, 0
27537c478bd9Sstevel@tonic-gate	.byte	0, 0x9E, 0, 0
27547c478bd9Sstevel@tonic-gate
27557c478bd9Sstevel@tonic-gate	/* 16 bit real mode DS */
27567c478bd9Sstevel@tonic-gate	.word	0xFFFF, 0
27577c478bd9Sstevel@tonic-gate	.byte	0, 0x92, 0, 0
27587c478bd9Sstevel@tonic-gate
27597c478bd9Sstevel@tonic-gate
27607c478bd9Sstevel@tonic-gate/* this is the GDT descriptor */
27617c478bd9Sstevel@tonic-gategdtdesc:
27627c478bd9Sstevel@tonic-gate	.word	0x27			/* limit */
27637c478bd9Sstevel@tonic-gate	.long	gdt			/* addr */
2764