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