180028Stakawata/*-
280028Stakawata * Copyright (c) 2001 Takanori Watanabe <takawata@jp.freebsd.org>
3235622Siwasaki * Copyright (c) 2001-2012 Mitsuru IWASAKI <iwasaki@jp.freebsd.org>
4235622Siwasaki * Copyright (c) 2003 Peter Wemm
5235622Siwasaki * 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>
33235622Siwasaki#include <machine/ppireg.h>
3480028Stakawata#include <machine/specialreg.h>
35235622Siwasaki#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 */
46235622Siwasaki
47235622Siwasaki	.data				/* So we can modify it */
48235622Siwasaki
49235622Siwasaki	ALIGN_TEXT
5080028Stakawata	.code16
51235622Siwasakiwakeup_start:
52121830Snjl	/*
53159478Snjl	 * Set up segment registers for real mode, a small stack for
54159478Snjl	 * any calls we make, and clear any flags.
55121830Snjl	 */
56235622Siwasaki	cli				/* make sure no interrupts */
57235622Siwasaki	mov	%cs, %ax		/* copy %cs to %ds.  Remember these */
58235622Siwasaki	mov	%ax, %ds		/* are offsets rather than selectors */
59235622Siwasaki	mov	%ax, %ss
60235622Siwasaki	movw	$PAGE_SIZE, %sp
61235622Siwasaki	xorw	%ax, %ax
62235622Siwasaki	pushw	%ax
63235622Siwasaki	popfw
64121830Snjl
65159409Snjl	/* To debug resume hangs, beep the speaker if the user requested. */
66235622Siwasaki	testb	$~0, resume_beep - wakeup_start
67235622Siwasaki	jz	1f
68235622Siwasaki	movb	$0, resume_beep - wakeup_start
69159409Snjl
70235622Siwasaki	/* Set PIC timer2 to beep. */
71235622Siwasaki	movb	$(TIMER_SEL2 | TIMER_SQWAVE | TIMER_16BIT), %al
72235622Siwasaki	outb	%al, $TIMER_MODE
73121830Snjl
74235622Siwasaki	/* Turn on speaker. */
75235622Siwasaki	inb	$IO_PPI, %al
76235622Siwasaki	orb	$PIT_SPKR, %al
77235622Siwasaki	outb	%al, $IO_PPI
7880028Stakawata
79235622Siwasaki	/* Set frequency. */
80235622Siwasaki	movw	$0x4c0, %ax
81235622Siwasaki	outb	%al, $TIMER_CNTR2
82235622Siwasaki	shrw	$8, %ax
83235622Siwasaki	outb	%al, $TIMER_CNTR2
84235622Siwasaki1:
8580028Stakawata
86235622Siwasaki	/* Re-initialize video BIOS if the reset_video tunable is set. */
87235622Siwasaki	testb	$~0, reset_video - wakeup_start
88235622Siwasaki	jz	1f
89235622Siwasaki	movb	$0, reset_video - wakeup_start
90235622Siwasaki	lcall	$0xc000, $3
9180028Stakawata
92235622Siwasaki	/* When we reach here, int 0x10 should be ready.  Hide cursor. */
93235622Siwasaki	movb	$0x01, %ah
94235622Siwasaki	movb	$0x20, %ch
95235622Siwasaki	int	$0x10
9680028Stakawata
97235622Siwasaki	/* Re-start in case the previous BIOS call clobbers them. */
98235622Siwasaki	jmp	wakeup_start
99235622Siwasaki1:
10080028Stakawata
101235622Siwasaki	/*
102235622Siwasaki	 * Find relocation base and patch the gdt descript and ljmp targets
103235622Siwasaki	 */
104235622Siwasaki	xorl	%ebx, %ebx
105235622Siwasaki	mov	%cs, %bx
106235622Siwasaki	sall	$4, %ebx		/* %ebx is now our relocation base */
10780028Stakawata
108235622Siwasaki	/*
109235622Siwasaki	 * Load the descriptor table pointer.  We'll need it when running
110235622Siwasaki	 * in 16-bit protected mode.
111235622Siwasaki	 */
112235622Siwasaki	lgdtl	bootgdtdesc - wakeup_start
113235622Siwasaki
11480028Stakawata	/* Enable protected mode */
115235622Siwasaki	movl	$CR0_PE, %eax
116235622Siwasaki	mov	%eax, %cr0
11780028Stakawata
118235622Siwasaki	/*
119235622Siwasaki	 * Now execute a far jump to turn on protected mode.  This
120235622Siwasaki	 * causes the segment registers to turn into selectors and causes
121235622Siwasaki	 * %cs to be loaded from the gdt.
122235622Siwasaki	 *
123235622Siwasaki	 * The following instruction is:
124235622Siwasaki	 * ljmpl $bootcode32 - bootgdt, $wakeup_32 - wakeup_start
125235622Siwasaki	 * but gas cannot assemble that.  And besides, we patch the targets
126235622Siwasaki	 * in early startup and its a little clearer what we are patching.
127235622Siwasaki	 */
12880028Stakawatawakeup_sw32:
129235622Siwasaki	.byte	0x66			/* size override to 32 bits */
130235622Siwasaki	.byte	0xea			/* opcode for far jump */
131235622Siwasaki	.long	wakeup_32 - wakeup_start /* offset in segment */
132235622Siwasaki	.word	bootcode32 - bootgdt	/* index in gdt for 32 bit code */
13380028Stakawata
134159478Snjl	/*
135235622Siwasaki	 * At this point, we are running in 32 bit legacy protected mode.
136159478Snjl	 */
137235622Siwasaki	ALIGN_TEXT
13880028Stakawata	.code32
13980028Stakawatawakeup_32:
14080028Stakawata
141235622Siwasaki	mov	$bootdata32 - bootgdt, %eax
142235622Siwasaki	mov	%ax, %ds
14380028Stakawata
144235622Siwasaki	/* Get PCB and return address. */
145237027Sjkim	movl	wakeup_pcb - wakeup_start(%ebx), %ecx
146237027Sjkim	movl	wakeup_ret - wakeup_start(%ebx), %edx
14780028Stakawata
148235622Siwasaki	/* Restore CR4 and CR3. */
149235622Siwasaki	movl	wakeup_cr4 - wakeup_start(%ebx), %eax
150235622Siwasaki	mov	%eax, %cr4
151235622Siwasaki	movl	wakeup_cr3 - wakeup_start(%ebx), %eax
152235622Siwasaki	mov	%eax, %cr3
15380028Stakawata
154235622Siwasaki	/*
155235622Siwasaki	 * Finally, switch to long bit mode by enabling paging.  We have
156235622Siwasaki	 * to be very careful here because all the segmentation disappears
157235622Siwasaki	 * out from underneath us.  The spec says we can depend on the
158235622Siwasaki	 * subsequent pipelined branch to execute, but *only if* everthing
159235622Siwasaki	 * is still identity mapped.  If any mappings change, the pipeline
160235622Siwasaki	 * will flush.
161235622Siwasaki	 */
162235622Siwasaki	mov	%cr0, %eax
163235622Siwasaki	orl	$CR0_PG, %eax
164235622Siwasaki	mov	%eax, %cr0
16580028Stakawata
16680028Stakawata	jmp	1f
16780028Stakawata1:
168235622Siwasaki	/* Jump to return address. */
169237027Sjkim	jmp	*%edx
170159478Snjl
171235622Siwasaki	.data
17280028Stakawata
173235622Siwasakiresume_beep:
174235622Siwasaki	.byte	0
175235622Siwasakireset_video:
176235622Siwasaki	.byte	0
17780028Stakawata
178235622Siwasaki	ALIGN_DATA
179235622Siwasakibootgdt:
180235622Siwasaki	.long	0x00000000
181235622Siwasaki	.long	0x00000000
18280028Stakawata
183235622Siwasakibootcode32:
184235622Siwasaki	.long	0x0000ffff
185235622Siwasaki	.long	0x00cf9b00
18680028Stakawata
187235622Siwasakibootdata32:
188235622Siwasaki	.long	0x0000ffff
189235622Siwasaki	.long	0x00cf9300
190235622Siwasakibootgdtend:
19180028Stakawata
192235622Siwasakibootgdtdesc:
193235622Siwasaki	.word	bootgdtend - bootgdt	/* Length */
194235622Siwasaki	.long	bootgdt - wakeup_start	/* Offset plus %ds << 4 */
195235622Siwasaki
196235622Siwasaki	ALIGN_DATA
197235622Siwasakiwakeup_cr4:
198235622Siwasaki	.long	0
199235622Siwasakiwakeup_cr3:
200235622Siwasaki	.long	0
201235622Siwasakiwakeup_pcb:
202235622Siwasaki	.long	0
203235622Siwasakiwakeup_ret:
204235622Siwasaki	.long	0
205236772Siwasakiwakeup_gdt:		/* not used */
206236772Siwasaki	.word	0
207236772Siwasaki	.long	0
208235622Siwasakidummy:
209