Home | History | Annotate | Line # | Download | only in dosboot
start_dos.S revision 1.1
      1  1.1  rin /*	$NetBSD: start_dos.S,v 1.1 2024/06/29 13:45:14 rin Exp $	*/
      2  1.1  rin 
      3  1.1  rin /*
      4  1.1  rin  * startup for DOS .COM programs
      5  1.1  rin  * with input from:
      6  1.1  rin  * netbsd:sys/arch/i386/boot/start.S
      7  1.1  rin  * Tor Egge's patches for NetBSD boot (pr port-i386/1002)
      8  1.1  rin  * freebsd:sys/i386/boot/netboot/start2.S
      9  1.1  rin  * XMS support by Martin Husemann
     10  1.1  rin  */
     11  1.1  rin 
     12  1.1  rin /*
     13  1.1  rin  * Ported to boot 386BSD by Julian Elischer (julian (at) tfs.com) Sept 1992
     14  1.1  rin  *
     15  1.1  rin  * Mach Operating System
     16  1.1  rin  * Copyright (c) 1992, 1991 Carnegie Mellon University
     17  1.1  rin  * All Rights Reserved.
     18  1.1  rin  *
     19  1.1  rin  * Permission to use, copy, modify and distribute this software and its
     20  1.1  rin  * documentation is hereby granted, provided that both the copyright
     21  1.1  rin  * notice and this permission notice appear in all copies of the
     22  1.1  rin  * software, derivative works or modified versions, and any portions
     23  1.1  rin  * thereof, and that both notices appear in supporting documentation.
     24  1.1  rin  *
     25  1.1  rin  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
     26  1.1  rin  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
     27  1.1  rin  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
     28  1.1  rin  *
     29  1.1  rin  * Carnegie Mellon requests users of this software to return to
     30  1.1  rin  *
     31  1.1  rin  *  Software Distribution Coordinator  or  Software.Distribution (at) CS.CMU.EDU
     32  1.1  rin  *  School of Computer Science
     33  1.1  rin  *  Carnegie Mellon University
     34  1.1  rin  *  Pittsburgh PA 15213-3890
     35  1.1  rin  *
     36  1.1  rin  * any improvements or extensions that they make and grant Carnegie Mellon
     37  1.1  rin  * the rights to redistribute these changes.
     38  1.1  rin  */
     39  1.1  rin 
     40  1.1  rin /*
     41  1.1  rin   Copyright 1988, 1989, 1990, 1991, 1992
     42  1.1  rin    by Intel Corporation, Santa Clara, California.
     43  1.1  rin 
     44  1.1  rin                 All Rights Reserved
     45  1.1  rin 
     46  1.1  rin Permission to use, copy, modify, and distribute this software and
     47  1.1  rin its documentation for any purpose and without fee is hereby
     48  1.1  rin granted, provided that the above copyright notice appears in all
     49  1.1  rin copies and that both the copyright notice and this permission notice
     50  1.1  rin appear in supporting documentation, and that the name of Intel
     51  1.1  rin not be used in advertising or publicity pertaining to distribution
     52  1.1  rin of the software without specific, written prior permission.
     53  1.1  rin 
     54  1.1  rin INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
     55  1.1  rin INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
     56  1.1  rin IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
     57  1.1  rin CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
     58  1.1  rin LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
     59  1.1  rin NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
     60  1.1  rin WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     61  1.1  rin */
     62  1.1  rin 
     63  1.1  rin #include <machine/asm.h>
     64  1.1  rin 
     65  1.1  rin 
     66  1.1  rin CR0_PE		=	0x1
     67  1.1  rin 
     68  1.1  rin 	.data
     69  1.1  rin 	.globl _C_LABEL(ourseg)
     70  1.1  rin _C_LABEL(ourseg):
     71  1.1  rin 	.long	0
     72  1.1  rin 
     73  1.1  rin /**************************************************************************
     74  1.1  rin GLOBAL DESCRIPTOR TABLE
     75  1.1  rin **************************************************************************/
     76  1.1  rin #ifdef __ELF__
     77  1.1  rin 	.align	16
     78  1.1  rin #else
     79  1.1  rin 	.align	4
     80  1.1  rin #endif
     81  1.1  rin gdt:
     82  1.1  rin 	.word	0, 0
     83  1.1  rin 	.byte	0, 0x00, 0x00, 0
     84  1.1  rin 
     85  1.1  rin #ifdef SUPPORT_LINUX	/* additional dummy */
     86  1.1  rin 	.word	0, 0
     87  1.1  rin 	.byte	0, 0x00, 0x00, 0
     88  1.1  rin #endif
     89  1.1  rin 
     90  1.1  rin 	/* kernel code segment */
     91  1.1  rin 	.globl flatcodeseg
     92  1.1  rin flatcodeseg = . - gdt
     93  1.1  rin 	.word	0xffff, 0
     94  1.1  rin 	.byte	0, 0x9f, 0xcf, 0
     95  1.1  rin 
     96  1.1  rin 	/* kernel data segment */
     97  1.1  rin 	.globl flatdataseg
     98  1.1  rin flatdataseg = . - gdt
     99  1.1  rin 	.word	0xffff, 0
    100  1.1  rin 	.byte	0, 0x93, 0xcf, 0
    101  1.1  rin 
    102  1.1  rin 	/* boot code segment, base will be patched */
    103  1.1  rin bootcodeseg = . - gdt
    104  1.1  rin 	.word	0xffff, 0
    105  1.1  rin 	.byte	0, 0x9e, 0x40, 0
    106  1.1  rin 
    107  1.1  rin 	/* boot data segment, base will be patched */
    108  1.1  rin bootdataseg = . - gdt
    109  1.1  rin #ifdef HEAP_BELOW_64K
    110  1.1  rin 	.word	0xffff, 0
    111  1.1  rin 	.byte	0, 0x92, 0x00, 0
    112  1.1  rin #else
    113  1.1  rin 	.word	0xffff, 0
    114  1.1  rin 	.byte	0, 0x92, 0x4f, 0
    115  1.1  rin #endif
    116  1.1  rin 
    117  1.1  rin 	/* 16 bit real mode, base will be patched */
    118  1.1  rin bootrealseg = . - gdt
    119  1.1  rin 	.word	0xffff, 0
    120  1.1  rin 	.byte	0, 0x9e, 0x00, 0
    121  1.1  rin 
    122  1.1  rin 	/* limits (etc) for data segment in real mode */
    123  1.1  rin bootrealdata = . - gdt
    124  1.1  rin 	.word	0xffff, 0
    125  1.1  rin 	.byte	0, 0x92, 0x00, 0
    126  1.1  rin gdtlen = . - gdt
    127  1.1  rin 
    128  1.1  rin #ifdef __ELF__
    129  1.1  rin 	.align	16
    130  1.1  rin #else
    131  1.1  rin 	.align	4
    132  1.1  rin #endif
    133  1.1  rin gdtarg:
    134  1.1  rin 	.word	gdtlen-1		/* limit */
    135  1.1  rin 	.long	0			/* addr, will be inserted */
    136  1.1  rin 
    137  1.1  rin 	.text
    138  1.1  rin ENTRY(start)
    139  1.1  rin 	.code16
    140  1.1  rin 
    141  1.1  rin 	# Check we are in real mode
    142  1.1  rin 	movl	%cr0, %eax
    143  1.1  rin 	testl	$CR0_PE, %eax
    144  1.1  rin 	jz	2f
    145  1.1  rin 	mov	$1f, %si
    146  1.1  rin 	call	message
    147  1.1  rin 	ret
    148  1.1  rin 1:	.asciz	"must be in real mode\r\n"
    149  1.1  rin 2:
    150  1.1  rin 
    151  1.1  rin 	xorl	%eax, %eax
    152  1.1  rin 	mov	%cs, %ax
    153  1.1  rin 	mov	%ax, %ds
    154  1.1  rin 	mov	%ax, %es
    155  1.1  rin 	movl	%eax, _C_LABEL(ourseg)
    156  1.1  rin #ifdef STACK_START
    157  1.1  rin 	add	$STACK_START / 16, %ax
    158  1.1  rin 	mov	%ax, %ss
    159  1.1  rin 	mov	$0xfffc, %sp
    160  1.1  rin #endif
    161  1.1  rin 
    162  1.1  rin 	/* fix up GDT entries for bootstrap */
    163  1.1  rin #define FIXUP(gdt_index) \
    164  1.1  rin 	movw	%ax, gdt+gdt_index+2;	\
    165  1.1  rin 	movb	%bl, gdt+gdt_index+4
    166  1.1  rin 
    167  1.1  rin 	mov	%cs, %ax
    168  1.1  rin 	shll	$4, %eax
    169  1.1  rin 	shldl	$16, %eax, %ebx
    170  1.1  rin 	FIXUP(bootcodeseg)
    171  1.1  rin 	FIXUP(bootrealseg)
    172  1.1  rin 	FIXUP(bootdataseg)
    173  1.1  rin 
    174  1.1  rin 	/* fix up GDT pointer */
    175  1.1  rin 	addl	$gdt, %eax
    176  1.1  rin 	movl	%eax, gdtarg+2
    177  1.1  rin 
    178  1.1  rin 	/* change to protected mode */
    179  1.1  rin 	calll	_C_LABEL(real_to_prot)
    180  1.1  rin 	.code32
    181  1.1  rin 
    182  1.1  rin 	/* clear the bss */
    183  1.1  rin 	movl	$_C_LABEL(edata), %edi
    184  1.1  rin 	movl	$_C_LABEL(end), %ecx
    185  1.1  rin 	subl	%edi, %ecx
    186  1.1  rin 	xorb	%al, %al
    187  1.1  rin 	rep
    188  1.1  rin 	stosb
    189  1.1  rin 
    190  1.1  rin 	call	_C_LABEL(doscommain)
    191  1.1  rin ENTRY(_rtt)
    192  1.1  rin 	call	_C_LABEL(prot_to_real)
    193  1.1  rin 	.code16
    194  1.1  rin ENTRY(exit16)
    195  1.1  rin 	sti
    196  1.1  rin 	movb	$0x4c, %ah		/* return */
    197  1.1  rin 	int	$0x21
    198  1.1  rin 
    199  1.1  rin /*
    200  1.1  rin  * real_to_prot()
    201  1.1  rin  * 	transfer from real mode to protected mode.
    202  1.1  rin  */
    203  1.1  rin ENTRY(real_to_prot)
    204  1.1  rin 	.code16
    205  1.1  rin 	pushl	%eax
    206  1.1  rin 	# guarantee that interrupt is disabled when in prot mode
    207  1.1  rin 	cli
    208  1.1  rin 
    209  1.1  rin 	# load the gdtr
    210  1.1  rin 	lgdtl	%cs:gdtarg
    211  1.1  rin 
    212  1.1  rin 	# set the PE bit of CR0
    213  1.1  rin 	movl	%cr0, %eax
    214  1.1  rin 	orl	$CR0_PE, %eax
    215  1.1  rin 	movl	%eax, %cr0
    216  1.1  rin 
    217  1.1  rin 	# make intrasegment jump to flush the processor pipeline and
    218  1.1  rin 	# reload CS register
    219  1.1  rin 	ljmp	$bootcodeseg, $xprot
    220  1.1  rin 
    221  1.1  rin xprot:
    222  1.1  rin 	.code32
    223  1.1  rin 	# we are in USE32 mode now
    224  1.1  rin 	# set up the protected mode segment registers : DS, SS, ES
    225  1.1  rin 	movl	$bootdataseg, %eax
    226  1.1  rin 	mov	%ax, %ds
    227  1.1  rin 	mov	%ax, %es
    228  1.1  rin 	mov	%ax, %ss
    229  1.1  rin #ifdef STACK_START
    230  1.1  rin 	addl	$STACK_START, %esp
    231  1.1  rin #endif
    232  1.1  rin 
    233  1.1  rin 	popl	%eax
    234  1.1  rin 	ret
    235  1.1  rin 
    236  1.1  rin /*
    237  1.1  rin  * prot_to_real()
    238  1.1  rin  * 	transfer from protected mode to real mode
    239  1.1  rin  */
    240  1.1  rin ENTRY(prot_to_real)
    241  1.1  rin 	.code32
    242  1.1  rin 	pushl	%eax
    243  1.1  rin 	# set up a dummy stack frame for the second seg change.
    244  1.1  rin 	# Adjust the intersegment jump instruction following
    245  1.1  rin 	# the clearing of protected mode bit.
    246  1.1  rin 	# This is self-modifying code, but we need a writable
    247  1.1  rin 	# code segment, and an intersegment return does not give us that.
    248  1.1  rin 
    249  1.1  rin 	movl	_C_LABEL(ourseg), %eax
    250  1.1  rin 	movw	%ax, xreal-2
    251  1.1  rin 
    252  1.1  rin 	/*
    253  1.1  rin 	 * Load the segment registers while still in protected mode.
    254  1.1  rin 	 * Otherwise the control bits don't get changed.
    255  1.1  rin 	 * The correct values are loaded later.
    256  1.1  rin 	 */
    257  1.1  rin 	movw	$bootrealdata, %ax
    258  1.1  rin 	movw	%ax, %ds
    259  1.1  rin 	movw	%ax, %es
    260  1.1  rin 	movw	%ax, %ss
    261  1.1  rin 
    262  1.1  rin 	# Change to use16 mode.
    263  1.1  rin 	ljmp	$bootrealseg, $x16
    264  1.1  rin 
    265  1.1  rin x16:
    266  1.1  rin 	.code16
    267  1.1  rin 	# clear the PE bit of CR0
    268  1.1  rin 	movl	%cr0, %eax
    269  1.1  rin 	andl 	$~CR0_PE, %eax
    270  1.1  rin 	movl	%eax, %cr0
    271  1.1  rin 
    272  1.1  rin 	# Here we have an 16 bits intersegment jump.
    273  1.1  rin 	ljmp	$0, $xreal		/* segment patched above */
    274  1.1  rin 
    275  1.1  rin xreal:
    276  1.1  rin 	# we are in real mode now
    277  1.1  rin 	# set up the real mode segment registers : DS, SS, ES
    278  1.1  rin 	mov	%cs, %ax
    279  1.1  rin 	mov	%ax, %ds
    280  1.1  rin 	mov	%ax, %es
    281  1.1  rin #ifdef STACK_START
    282  1.1  rin 	add	$STACK_START / 16, %ax
    283  1.1  rin 	mov	%ax, %ss
    284  1.1  rin 	subl	$STACK_START, %esp
    285  1.1  rin #else
    286  1.1  rin 	mov	%ax, %ss
    287  1.1  rin #endif
    288  1.1  rin 	push	%bp
    289  1.1  rin 	movw	%sp, %bp
    290  1.1  rin 	/* check we are returning to an address below 64k */
    291  1.1  rin 	movw	2/*bp*/ + 4/*eax*/ + 2(%bp), %ax	/* high bits ret addr */
    292  1.1  rin 	test	%ax, %ax
    293  1.1  rin 	jne	1f
    294  1.1  rin 	pop	%bp
    295  1.1  rin 
    296  1.1  rin 	sti
    297  1.1  rin 	popl	%eax
    298  1.1  rin 	retl
    299  1.1  rin 
    300  1.1  rin 1:	movw	$2f, %si
    301  1.1  rin 	call	message
    302  1.1  rin 	movl	2/*bp*/ + 4/*eax*/(%bp), %eax		/*  return address */
    303  1.1  rin 	call	dump_eax
    304  1.1  rin 	jmp	exit16
    305  1.1  rin 2:	.asciz  "prot_to_real can't return to "
    306  1.1  rin 
    307  1.1  rin 
    308  1.1  rin /**************************************************************************
    309  1.1  rin ___MAIN - Dummy to keep GCC happy
    310  1.1  rin **************************************************************************/
    311  1.1  rin ENTRY(__main)
    312  1.1  rin 	ret
    313  1.1  rin 
    314  1.1  rin /*
    315  1.1  rin  * pbzero(dst, cnt)
    316  1.1  rin  *	where dst is a physical address and cnt is the length
    317  1.1  rin  */
    318  1.1  rin ENTRY(pbzero)
    319  1.1  rin 	.code32
    320  1.1  rin 	pushl	%ebp
    321  1.1  rin 	movl	%esp, %ebp
    322  1.1  rin 	pushl	%es
    323  1.1  rin 	pushl	%edi
    324  1.1  rin 
    325  1.1  rin 	cld
    326  1.1  rin 
    327  1.1  rin 	# set %es to point at the flat segment
    328  1.1  rin 	movl	$flatdataseg, %eax
    329  1.1  rin 	mov	%ax, %es
    330  1.1  rin 
    331  1.1  rin 	movl	8(%ebp), %edi		# destination
    332  1.1  rin 	movl	12(%ebp), %ecx		# count
    333  1.1  rin 	xorl	%eax, %eax		# value
    334  1.1  rin 
    335  1.1  rin 	rep
    336  1.1  rin 	stosb
    337  1.1  rin 
    338  1.1  rin 	popl	%edi
    339  1.1  rin 	popl	%es
    340  1.1  rin 	popl	%ebp
    341  1.1  rin 	ret
    342  1.1  rin 
    343  1.1  rin /*
    344  1.1  rin  * vpbcopy(src, dst, cnt)
    345  1.1  rin  *	where src is a virtual address and dst is a physical address
    346  1.1  rin  */
    347  1.1  rin ENTRY(vpbcopy)
    348  1.1  rin 	.code32
    349  1.1  rin 	pushl	%ebp
    350  1.1  rin 	movl	%esp, %ebp
    351  1.1  rin 	pushl	%es
    352  1.1  rin 	pushl	%esi
    353  1.1  rin 	pushl	%edi
    354  1.1  rin 
    355  1.1  rin 	cld
    356  1.1  rin 
    357  1.1  rin 	# set %es to point at the flat segment
    358  1.1  rin 	movl	$flatdataseg, %eax
    359  1.1  rin 	mov	%ax, %es
    360  1.1  rin 
    361  1.1  rin 	movl	8(%ebp), %esi		# source
    362  1.1  rin 	movl	12(%ebp), %edi		# destination
    363  1.1  rin 	movl	16(%ebp), %ecx		# count
    364  1.1  rin 
    365  1.1  rin 	rep
    366  1.1  rin 	movsb
    367  1.1  rin 
    368  1.1  rin 	popl	%edi
    369  1.1  rin 	popl	%esi
    370  1.1  rin 	popl	%es
    371  1.1  rin 	popl	%ebp
    372  1.1  rin 	ret
    373  1.1  rin 
    374  1.1  rin /*
    375  1.1  rin  * pvbcopy(src, dst, cnt)
    376  1.1  rin  *	where src is a physical address and dst is a virtual address
    377  1.1  rin  */
    378  1.1  rin ENTRY(pvbcopy)
    379  1.1  rin 	.code32
    380  1.1  rin 	pushl	%ebp
    381  1.1  rin 	movl	%esp, %ebp
    382  1.1  rin 	pushl	%ds
    383  1.1  rin 	pushl	%esi
    384  1.1  rin 	pushl	%edi
    385  1.1  rin 
    386  1.1  rin 	cld
    387  1.1  rin 
    388  1.1  rin 	# set %ds to point at the flat segment
    389  1.1  rin 	movl	$flatdataseg, %eax
    390  1.1  rin 	mov	%ax, %ds
    391  1.1  rin 
    392  1.1  rin 	movl	8(%ebp), %esi		# source
    393  1.1  rin 	movl	12(%ebp), %edi		# destination
    394  1.1  rin 	movl	16(%ebp), %ecx		# count
    395  1.1  rin 
    396  1.1  rin 	rep
    397  1.1  rin 	movsb
    398  1.1  rin 
    399  1.1  rin 	popl	%edi
    400  1.1  rin 	popl	%esi
    401  1.1  rin 	popl	%ds
    402  1.1  rin 	popl	%ebp
    403  1.1  rin 	ret
    404  1.1  rin 
    405  1.1  rin ENTRY(vtophys)
    406  1.1  rin 	.code32
    407  1.1  rin 	movl	_C_LABEL(ourseg), %eax
    408  1.1  rin 	shll	$4, %eax
    409  1.1  rin 	addl	4(%esp), %eax
    410  1.1  rin 	ret
    411  1.1  rin 
    412  1.1  rin message:
    413  1.1  rin 	.code16
    414  1.1  rin 	pushal
    415  1.1  rin message_1:
    416  1.1  rin 	cld
    417  1.1  rin 1:	lodsb
    418  1.1  rin 	testb	%al, %al
    419  1.1  rin 	jz	2f
    420  1.1  rin 	movb	$0xe, %ah
    421  1.1  rin 	movw	$1, %bx
    422  1.1  rin 	int	$0x10
    423  1.1  rin 	jmp	1b
    424  1.1  rin 
    425  1.1  rin 2:	movb	$0x86, %ah
    426  1.1  rin 	mov	$16, %cx
    427  1.1  rin 	int	$0x15			/* delay about a second */
    428  1.1  rin 	popal
    429  1.1  rin 	ret
    430  1.1  rin 
    431  1.1  rin /* These are useful for debugging
    432  1.1  rin  */
    433  1.1  rin 	.data
    434  1.1  rin eax_buf:
    435  1.1  rin 	.long	0, 0, 0, 0
    436  1.1  rin 	.text
    437  1.1  rin ENTRY(dump_eax)
    438  1.1  rin 	.code16
    439  1.1  rin 	pushal
    440  1.1  rin 	movw	$eax_buf, %si
    441  1.1  rin 	mov	%si, %di
    442  1.1  rin 	movw	$8, %cx
    443  1.1  rin 1:	roll	$4, %eax
    444  1.1  rin 	mov	%ax, %bx
    445  1.1  rin 	andb	$0x0f, %al
    446  1.1  rin 	addb	$0x30, %al			/* 30..3f - clear AF */
    447  1.1  rin #if 1 /* 5 bytes to generate real hex... */
    448  1.1  rin 	daa					/* 30..39, 40..45 */
    449  1.1  rin 	addb	$0xc0, %al			/* f0..f9, 00..05 */
    450  1.1  rin 	adcb	$0x40, %al			/* 30..39, 41..45 */
    451  1.1  rin #endif
    452  1.1  rin 	movb	%al, (%di)			/* %es != %ds, so can't ... */
    453  1.1  rin 	inc	%di				/* ... use stosb */
    454  1.1  rin 	mov	%bx, %ax
    455  1.1  rin 	loop	1b
    456  1.1  rin 	movw	$0x20, %ax			/* space + null */
    457  1.1  rin 	movw	%ax, (%di)
    458  1.1  rin 	jmp	message_1
    459  1.1  rin 
    460  1.1  rin 	.globl	_C_LABEL(trace_word)
    461  1.1  rin _C_LABEL(trace_word):
    462  1.1  rin 	.code32
    463  1.1  rin 	movl	4(%esp), %edx
    464  1.1  rin 
    465  1.1  rin 	call	_C_LABEL(prot_to_real)
    466  1.1  rin 	.code16
    467  1.1  rin 	movl	%edx, %eax
    468  1.1  rin 	call	dump_eax
    469  1.1  rin 	calll	_C_LABEL(real_to_prot)
    470  1.1  rin 	.code32
    471  1.1  rin 	ret
    472  1.1  rin 
    473  1.1  rin 	.globl	_C_LABEL(trace_str)
    474  1.1  rin _C_LABEL(trace_str):
    475  1.1  rin 	.code32
    476  1.1  rin 	pushl	%esi
    477  1.1  rin 
    478  1.1  rin 	call	_C_LABEL(prot_to_real)
    479  1.1  rin 	.code16
    480  1.1  rin 	mov	%sp, %si
    481  1.1  rin 	mov	8(%si), %si
    482  1.1  rin 	call	message
    483  1.1  rin 	calll	_C_LABEL(real_to_prot)
    484  1.1  rin 	.code32
    485  1.1  rin 	popl	%esi
    486  1.1  rin 	ret
    487  1.1  rin 
    488  1.1  rin #ifdef XMS
    489  1.1  rin 
    490  1.1  rin /* pointer to XMS driver, 0 if no XMS used */
    491  1.1  rin 
    492  1.1  rin 	.data
    493  1.1  rin _C_LABEL(xmsdrv):
    494  1.1  rin 	.long	0
    495  1.1  rin 
    496  1.1  rin 	.text
    497  1.1  rin ENTRY(checkxms)
    498  1.1  rin 	.code32
    499  1.1  rin 	pushl	%ebp
    500  1.1  rin 	movl	%esp, %ebp
    501  1.1  rin 	pushl	%ebx
    502  1.1  rin 	pushl	%edx
    503  1.1  rin 	pushl	%es
    504  1.1  rin 	pushl	%esi
    505  1.1  rin 	pushl	%edi
    506  1.1  rin 
    507  1.1  rin 	call	_C_LABEL(prot_to_real)	# enter real mode
    508  1.1  rin 	.code16
    509  1.1  rin 
    510  1.1  rin 	movw	$0x4300, %ax
    511  1.1  rin 	int	$0x2f			/* check if XMS installed */
    512  1.1  rin 	cmpb	$0x80, %al
    513  1.1  rin 	jnz	noxms
    514  1.1  rin 
    515  1.1  rin 	movw	$0x4310, %ax
    516  1.1  rin 	int	$0x2f			/* get driver address */
    517  1.1  rin 
    518  1.1  rin 	movw	%bx, _C_LABEL(xmsdrv)	/* save es:bx to _xmsdrv */
    519  1.1  rin 	movw	%es, _C_LABEL(xmsdrv) + 2
    520  1.1  rin 
    521  1.1  rin 	movb	$0x08, %ah		/* XMS: query free extended memory */
    522  1.1  rin #if 0
    523  1.1  rin 	movb	$0x00, %bl
    524  1.1  rin #endif
    525  1.1  rin 	lcall	*_C_LABEL(xmsdrv)
    526  1.1  rin 	jmp	xdone
    527  1.1  rin 
    528  1.1  rin noxms:		/* no XMS manager found */
    529  1.1  rin 	mov	$0, %dx
    530  1.1  rin 
    531  1.1  rin xdone:
    532  1.1  rin 	calll	_C_LABEL(real_to_prot) # back to protected mode
    533  1.1  rin 	.code32
    534  1.1  rin 
    535  1.1  rin 	xorl	%eax, %eax
    536  1.1  rin 	movw	%dx, %ax
    537  1.1  rin 
    538  1.1  rin 	popl	%edi
    539  1.1  rin 	popl	%esi
    540  1.1  rin 	popl	%es
    541  1.1  rin 	popl	%edx
    542  1.1  rin 	popl	%ebx
    543  1.1  rin 	popl	%ebp
    544  1.1  rin 	ret
    545  1.1  rin 
    546  1.1  rin /*
    547  1.1  rin 	Allocate a block of XMS memory with the requested size
    548  1.1  rin 		void *xmsalloc(long int kBytes);
    549  1.1  rin 
    550  1.1  rin 	Depends on _xmsdrv being set by getextmem() before first call
    551  1.1  rin 	to this function.
    552  1.1  rin 
    553  1.1  rin 	Return value: a physical address.
    554  1.1  rin */
    555  1.1  rin ENTRY(xmsalloc)
    556  1.1  rin 	.code32
    557  1.1  rin 	pushl	%ebp
    558  1.1  rin 	movl	%esp, %ebp
    559  1.1  rin 	pushl	%ebx
    560  1.1  rin 	pushl	%edx
    561  1.1  rin 	pushl	%esi
    562  1.1  rin 	pushl	%edi
    563  1.1  rin 
    564  1.1  rin 	movl	0x8(%ebp), %edx # Kbytes needed
    565  1.1  rin 
    566  1.1  rin 	call	_C_LABEL(prot_to_real)	# enter real mode
    567  1.1  rin 	.code16
    568  1.1  rin 
    569  1.1  rin 	movb	$0x09, %ah		# XMS allocate block
    570  1.1  rin 	lcall	*_C_LABEL(xmsdrv)	# result: handle in %dx
    571  1.1  rin 	movb	$0x0c, %ah		# XMS lock block
    572  1.1  rin 	lcall	*_C_LABEL(xmsdrv)	# result: 32 bit physical addr in DX:BX
    573  1.1  rin 
    574  1.1  rin 	calll	_C_LABEL(real_to_prot) # back to protected mode
    575  1.1  rin 	.code32
    576  1.1  rin 
    577  1.1  rin 	movl	%edx, %eax
    578  1.1  rin 	shl	$16, %eax
    579  1.1  rin 	movw	%bx, %ax	# result in %eax
    580  1.1  rin 
    581  1.1  rin 	popl	%edi
    582  1.1  rin 	popl	%esi
    583  1.1  rin 	popl	%edx
    584  1.1  rin 	popl	%ebx
    585  1.1  rin 	popl	%ebp
    586  1.1  rin 	ret
    587  1.1  rin 
    588  1.1  rin /*
    589  1.1  rin  * ppbcopy(src, dst, cnt)
    590  1.1  rin  *	where src and dst are physical addresses
    591  1.1  rin  */
    592  1.1  rin ENTRY(ppbcopy)
    593  1.1  rin 	.code32
    594  1.1  rin 	pushl	%ebp
    595  1.1  rin 	movl	%esp, %ebp
    596  1.1  rin 	pushl	%es
    597  1.1  rin 	pushl	%esi
    598  1.1  rin 	pushl	%edi
    599  1.1  rin 
    600  1.1  rin 	cld
    601  1.1  rin 
    602  1.1  rin 	# set %es to point at the flat segment
    603  1.1  rin 	movl	$flatdataseg, %eax
    604  1.1  rin 	mov	%ax, %es
    605  1.1  rin 
    606  1.1  rin 	movl	8(%ebp), %esi		# source
    607  1.1  rin 	movl	12(%ebp), %edi		# destination
    608  1.1  rin 	movl	16(%ebp), %ecx		# count
    609  1.1  rin 
    610  1.1  rin 	es
    611  1.1  rin 	rep
    612  1.1  rin 	movsb
    613  1.1  rin 
    614  1.1  rin 	popl	%edi
    615  1.1  rin 	popl	%esi
    616  1.1  rin 	popl	%es
    617  1.1  rin 	popl	%ebp
    618  1.1  rin 	ret
    619  1.1  rin 
    620  1.1  rin #endif
    621