180028Stakawata/*-
280028Stakawata * Copyright (c) 2001 Takanori Watanabe <takawata@jp.freebsd.org>
3235796Siwasaki * Copyright (c) 2001-2012 Mitsuru IWASAKI <iwasaki@jp.freebsd.org>
4235796Siwasaki * Copyright (c) 2003 Peter Wemm
5235796Siwasaki * Copyright (c) 2008-2012 Jung-uk Kim <jkim@FreeBSD.org>
680028Stakawata * All rights reserved.
780028Stakawata *
880028Stakawata * Redistribution and use in source and binary forms, with or without
980028Stakawata * modification, are permitted provided that the following conditions
1080028Stakawata * are met:
1180028Stakawata * 1. Redistributions of source code must retain the above copyright
1280028Stakawata *    notice, this list of conditions and the following disclaimer.
1380028Stakawata * 2. Redistributions in binary form must reproduce the above copyright
1480028Stakawata *    notice, this list of conditions and the following disclaimer in the
1580028Stakawata *    documentation and/or other materials provided with the distribution.
1680028Stakawata *
1780028Stakawata * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1880028Stakawata * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1980028Stakawata * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2080028Stakawata * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2180028Stakawata * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2280028Stakawata * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2380028Stakawata * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2480028Stakawata * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2580028Stakawata * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2680028Stakawata * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2780028Stakawata * SUCH DAMAGE.
28124051Snjl *
29124051Snjl * $FreeBSD$
3080028Stakawata */
3180028Stakawata
32124051Snjl#include <machine/asmacros.h>
33235796Siwasaki#include <machine/ppireg.h>
3480028Stakawata#include <machine/specialreg.h>
35235796Siwasaki#include <machine/timerreg.h>
3680028Stakawata
37145397Siedowse#include "assym.s"
38145397Siedowse
39159478Snjl/*
40159478Snjl * Resume entry point.  The BIOS enters here in real mode after POST with
41159478Snjl * CS set to the page where we stored this code.  It should configure the
42159478Snjl * segment registers with a flat 4 GB address space and EFLAGS.IF = 0.
43159478Snjl * Depending on the previous sleep state, we may need to initialize more
44159478Snjl * of the system (i.e., S3 suspend-to-RAM vs. S4 suspend-to-disk).
45159478Snjl */
46235796Siwasaki
47235796Siwasaki	.data				/* So we can modify it */
48235796Siwasaki
49235796Siwasaki	ALIGN_TEXT
5080028Stakawata	.code16
51235796Siwasakiwakeup_start:
52121830Snjl	/*
53159478Snjl	 * Set up segment registers for real mode, a small stack for
54159478Snjl	 * any calls we make, and clear any flags.
55121830Snjl	 */
56235796Siwasaki	cli				/* make sure no interrupts */
57235796Siwasaki	mov	%cs, %ax		/* copy %cs to %ds.  Remember these */
58235796Siwasaki	mov	%ax, %ds		/* are offsets rather than selectors */
59235796Siwasaki	mov	%ax, %ss
60235796Siwasaki	movw	$PAGE_SIZE, %sp
61235796Siwasaki	xorw	%ax, %ax
62235796Siwasaki	pushw	%ax
63235796Siwasaki	popfw
64121830Snjl
65159409Snjl	/* To debug resume hangs, beep the speaker if the user requested. */
66235796Siwasaki	testb	$~0, resume_beep - wakeup_start
67235796Siwasaki	jz	1f
68235796Siwasaki	movb	$0, resume_beep - wakeup_start
69159409Snjl
70235796Siwasaki	/* Set PIC timer2 to beep. */
71235796Siwasaki	movb	$(TIMER_SEL2 | TIMER_SQWAVE | TIMER_16BIT), %al
72235796Siwasaki	outb	%al, $TIMER_MODE
73121830Snjl
74235796Siwasaki	/* Turn on speaker. */
75235796Siwasaki	inb	$IO_PPI, %al
76235796Siwasaki	orb	$PIT_SPKR, %al
77235796Siwasaki	outb	%al, $IO_PPI
7880028Stakawata
79235796Siwasaki	/* Set frequency. */
80235796Siwasaki	movw	$0x4c0, %ax
81235796Siwasaki	outb	%al, $TIMER_CNTR2
82235796Siwasaki	shrw	$8, %ax
83235796Siwasaki	outb	%al, $TIMER_CNTR2
84235796Siwasaki1:
8580028Stakawata
86235796Siwasaki	/* Re-initialize video BIOS if the reset_video tunable is set. */
87235796Siwasaki	testb	$~0, reset_video - wakeup_start
88235796Siwasaki	jz	1f
89235796Siwasaki	movb	$0, reset_video - wakeup_start
90235796Siwasaki	lcall	$0xc000, $3
9180028Stakawata
92235796Siwasaki	/* When we reach here, int 0x10 should be ready.  Hide cursor. */
93235796Siwasaki	movb	$0x01, %ah
94235796Siwasaki	movb	$0x20, %ch
95235796Siwasaki	int	$0x10
9680028Stakawata
97235796Siwasaki	/* Re-start in case the previous BIOS call clobbers them. */
98235796Siwasaki	jmp	wakeup_start
99235796Siwasaki1:
10080028Stakawata
101235796Siwasaki	/*
102235796Siwasaki	 * Find relocation base and patch the gdt descript and ljmp targets
103235796Siwasaki	 */
104235796Siwasaki	xorl	%ebx, %ebx
105235796Siwasaki	mov	%cs, %bx
106235796Siwasaki	sall	$4, %ebx		/* %ebx is now our relocation base */
10780028Stakawata
108235796Siwasaki	/*
109235796Siwasaki	 * Load the descriptor table pointer.  We'll need it when running
110235796Siwasaki	 * in 16-bit protected mode.
111235796Siwasaki	 */
112235796Siwasaki	lgdtl	bootgdtdesc - wakeup_start
113235796Siwasaki
11480028Stakawata	/* Enable protected mode */
115235796Siwasaki	movl	$CR0_PE, %eax
116235796Siwasaki	mov	%eax, %cr0
11780028Stakawata
118235796Siwasaki	/*
119235796Siwasaki	 * Now execute a far jump to turn on protected mode.  This
120235796Siwasaki	 * causes the segment registers to turn into selectors and causes
121235796Siwasaki	 * %cs to be loaded from the gdt.
122235796Siwasaki	 *
123235796Siwasaki	 * The following instruction is:
124235796Siwasaki	 * ljmpl $bootcode32 - bootgdt, $wakeup_32 - wakeup_start
125235796Siwasaki	 * but gas cannot assemble that.  And besides, we patch the targets
126235796Siwasaki	 * in early startup and its a little clearer what we are patching.
127235796Siwasaki	 */
12880028Stakawatawakeup_sw32:
129235796Siwasaki	.byte	0x66			/* size override to 32 bits */
130235796Siwasaki	.byte	0xea			/* opcode for far jump */
131235796Siwasaki	.long	wakeup_32 - wakeup_start /* offset in segment */
132235796Siwasaki	.word	bootcode32 - bootgdt	/* index in gdt for 32 bit code */
13380028Stakawata
134159478Snjl	/*
135235796Siwasaki	 * At this point, we are running in 32 bit legacy protected mode.
136159478Snjl	 */
137235796Siwasaki	ALIGN_TEXT
13880028Stakawata	.code32
13980028Stakawatawakeup_32:
14080028Stakawata
141235796Siwasaki	mov	$bootdata32 - bootgdt, %eax
142235796Siwasaki	mov	%ax, %ds
14380028Stakawata
144235796Siwasaki	/* Get PCB and return address. */
145235796Siwasaki	movl	wakeup_pcb - wakeup_start(%ebx), %esi
146235796Siwasaki	movl	wakeup_ret - wakeup_start(%ebx), %edi
14780028Stakawata
148235796Siwasaki	/* Restore CR4 and CR3. */
149235796Siwasaki	movl	wakeup_cr4 - wakeup_start(%ebx), %eax
150235796Siwasaki	mov	%eax, %cr4
151235796Siwasaki	movl	wakeup_cr3 - wakeup_start(%ebx), %eax
152235796Siwasaki	mov	%eax, %cr3
15380028Stakawata
154235796Siwasaki	/*
155235796Siwasaki	 * Finally, switch to long bit mode by enabling paging.  We have
156235796Siwasaki	 * to be very careful here because all the segmentation disappears
157235796Siwasaki	 * out from underneath us.  The spec says we can depend on the
158235796Siwasaki	 * subsequent pipelined branch to execute, but *only if* everthing
159235796Siwasaki	 * is still identity mapped.  If any mappings change, the pipeline
160235796Siwasaki	 * will flush.
161235796Siwasaki	 */
162235796Siwasaki	mov	%cr0, %eax
163235796Siwasaki	orl	$CR0_PG, %eax
164235796Siwasaki	mov	%eax, %cr0
16580028Stakawata
16680028Stakawata	jmp	1f
16780028Stakawata1:
168235796Siwasaki	/* Jump to return address. */
169235796Siwasaki	jmp	*%edi
170159478Snjl
171235796Siwasaki	.data
17280028Stakawata
173235796Siwasakiresume_beep:
174235796Siwasaki	.byte	0
175235796Siwasakireset_video:
176235796Siwasaki	.byte	0
17780028Stakawata
178235796Siwasaki	ALIGN_DATA
179235796Siwasakibootgdt:
180235796Siwasaki	.long	0x00000000
181235796Siwasaki	.long	0x00000000
18280028Stakawata
183235796Siwasakibootcode32:
184235796Siwasaki	.long	0x0000ffff
185235796Siwasaki	.long	0x00cf9b00
18680028Stakawata
187235796Siwasakibootdata32:
188235796Siwasaki	.long	0x0000ffff
189235796Siwasaki	.long	0x00cf9300
190235796Siwasakibootgdtend:
19180028Stakawata
192235796Siwasakibootgdtdesc:
193235796Siwasaki	.word	bootgdtend - bootgdt	/* Length */
194235796Siwasaki	.long	bootgdt - wakeup_start	/* Offset plus %ds << 4 */
195235796Siwasaki
196235796Siwasaki	ALIGN_DATA
197235796Siwasakiwakeup_cr4:
198235796Siwasaki	.long	0
199235796Siwasakiwakeup_cr3:
200235796Siwasaki	.long	0
201235796Siwasakiwakeup_pcb:
202235796Siwasaki	.long	0
203235796Siwasakiwakeup_ret:
204235796Siwasaki	.long	0
205235796Siwasakidummy:
206