X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fresume.c;h=f887f454e7cc8d351ade16669ca49d407616dfa9;hb=ecae9bfd29e398cf93864a3effb183a717fa749d;hp=9db8cad2e0b1e02a028c9b890233bf1ffd6d9d6e;hpb=cc6a3772f17e05fe79305b6aba6b4e3b3c91570b;p=seabios.git diff --git a/src/resume.c b/src/resume.c index 9db8cad..f887f45 100644 --- a/src/resume.c +++ b/src/resume.c @@ -1,8 +1,8 @@ // Code for handling calls to "post" that are resume related. // -// Copyright (C) 2008 Kevin O'Connor +// Copyright (C) 2008,2009 Kevin O'Connor // -// This file may be distributed under the terms of the GNU GPLv3 license. +// This file may be distributed under the terms of the GNU LGPLv3 license. #include "util.h" // dprintf #include "ioport.h" // outb @@ -10,10 +10,16 @@ #include "biosvar.h" // struct bios_data_area_s #include "bregs.h" // struct bregs #include "acpi.h" // find_resume_vector +#include "ps2port.h" // i8042_reboot +#include "pci.h" // pci_reboot +#include "cmos.h" // inb_cmos + +// Indicator if POST phase has been run. +int HaveRunPost VAR16VISIBLE; // Reset DMA controller void -init_dma() +init_dma(void) { // first reset the DMA controllers outb(0, PORT_DMA1_MASTER_CLEAR); @@ -26,101 +32,130 @@ init_dma() // Handler for post calls that look like a resume. void VISIBLE16 -handle_resume(u8 status) +handle_resume(void) { - init_dma(); - debug_serial_setup(); + int status = inb_cmos(CMOS_RESET_CODE); + outb_cmos(0, CMOS_RESET_CODE); dprintf(1, "In resume (status=%d)\n", status); - switch (status) { - case 0xfe: - // S3 resume request. Jump to 32bit mode to handle the resume. - asm volatile( - "movw %%ax, %%ss\n" - "movl %0, %%esp\n" - "pushl $_code32_s3_resume\n" - "jmp transition32\n" - : : "i"(BUILD_S3RESUME_STACK_ADDR), "a"(0) - ); - break; + init_dma(); - case 0x00: - case 0x09: - case 0x0d ... 0xfd: - case 0xff: - // Normal post - now that status has been cleared a reset will - // run regular boot code.. - reset_vector(); - break; + switch (status) { + case 0x01 ... 0x04: + case 0x06 ... 0x09: + panic("Unimplemented shutdown status: %02x\n", status); case 0x05: // flush keyboard (issue EOI) and jump via 40h:0067h eoi_pic2(); // NO BREAK case 0x0a: +#define BDA_JUMP (((struct bios_data_area_s *)0)->jump) // resume execution by jump via 40h:0067h -#define bda ((struct bios_data_area_s *)0) asm volatile( - "movw %%ax, %%ds\n" + "movw %w1, %%ds\n" "ljmpw *%0\n" - : : "m"(bda->jump_ip), "a"(SEG_BDA) + : : "m"(BDA_JUMP), "r"(SEG_BDA) ); break; case 0x0b: // resume execution via IRET via 40h:0067h asm volatile( - "movw %%ax, %%ds\n" - "movw %0, %%sp\n" - "movw %1, %%ss\n" + "movw %w1, %%ds\n" + "lssw %0, %%sp\n" "iretw\n" - : : "m"(bda->jump_ip), "m"(bda->jump_cs), "a"(SEG_BDA) + : : "m"(BDA_JUMP), "r"(SEG_BDA) ); break; case 0x0c: // resume execution via RETF via 40h:0067h asm volatile( - "movw %%ax, %%ds\n" - "movw %0, %%sp\n" - "movw %1, %%ss\n" + "movw %w1, %%ds\n" + "lssw %0, %%sp\n" "lretw\n" - : : "m"(bda->jump_ip), "m"(bda->jump_cs), "a"(SEG_BDA) + : : "m"(BDA_JUMP), "r"(SEG_BDA) ); break; + + default: + break; } - BX_PANIC("Unimplemented shutdown status: %02x\n", status); + // Not a 16bit resume - do remaining checks in 32bit mode + asm volatile( + "movw %w1, %%ss\n" + "movl %0, %%esp\n" + "movl $_cfunc32flat_handle_resume32, %%edx\n" + "jmp transition32\n" + : : "i"(BUILD_S3RESUME_STACK_ADDR), "r"(0), "a"(status) + ); } -void VISIBLE32 -s3_resume() +// Handle an S3 resume event +static void +s3_resume(void) { - dprintf(1, "In 32bit resume\n"); + if (!CONFIG_S3_RESUME) + return; + u32 s3_resume_vector = find_resume_vector(); + if (!s3_resume_vector) { + dprintf(1, "No resume vector set!\n"); + return; + } + + pic_setup(); smm_init(); - make_bios_readonly(); + s3_resume_vga_init(); - u32 s3_resume_vector = find_resume_vector(); + make_bios_readonly(); // Invoke the resume vector. struct bregs br; memset(&br, 0, sizeof(br)); - if (s3_resume_vector) { - dprintf(1, "Jump to resume vector (%x)\n", s3_resume_vector); - br.ip = FARPTR_TO_OFFSET(s3_resume_vector); - br.cs = FARPTR_TO_SEG(s3_resume_vector); - } else { - dprintf(1, "No resume vector set!\n"); - // Jump to the post vector to restart with a normal boot. - br.ip = (u32)reset_vector - BUILD_BIOS_ADDR; - br.cs = SEG_BIOS; - } + dprintf(1, "Jump to resume vector (%x)\n", s3_resume_vector); + br.code = FLATPTR_TO_SEGOFF((void*)s3_resume_vector); call16big(&br); } -// Ughh - some older gcc compilers have a bug which causes VISIBLE32 -// functions to not be exported as global variables. -asm(".global s3_resume"); +// Attempt to invoke a hard-reboot. +static void +tryReboot(void) +{ + dprintf(1, "Attempting a hard reboot\n"); + + // Setup for reset on qemu. + if (! CONFIG_COREBOOT) { + qemu_prep_reset(); + if (HaveRunPost) + apm_shutdown(); + } + + // Try keyboard controller reboot. + i8042_reboot(); + + // Try PCI 0xcf9 reboot + pci_reboot(); + + // Try triple fault + asm volatile("int3"); + + panic("Could not reboot"); +} + +void VISIBLE32FLAT +handle_resume32(int status) +{ + ASSERT32FLAT(); + dprintf(1, "In 32bit resume\n"); + + if (status == 0xfe) + s3_resume(); + + // Must be a soft reboot - invoke a hard reboot. + tryReboot(); +}