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