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