X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fresume.c;h=4390fb59c43941354cfc14d606f0862685b085ca;hb=b93739776593eb470bd18ce8f8b028054cee0e3d;hp=59bb90195427e01be1525aeb4d4a3f1813f61f69;hpb=52a300f1c1ec2d9733d41ecd3ecaf78be48097b8;p=seabios.git diff --git a/src/resume.c b/src/resume.c index 59bb901..4390fb5 100644 --- a/src/resume.c +++ b/src/resume.c @@ -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,34 +32,19 @@ 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); + init_dma(); + switch (status) { - case 0xfe: - if (CONFIG_S3_RESUME) { - // S3 resume request. Jump to 32bit mode to handle the resume. - asm volatile( - "movw %w1, %%ss\n" - "movl %0, %%esp\n" - "pushl $s3_resume\n" - "jmp transition32\n" - : : "i"(BUILD_S3RESUME_STACK_ADDR), "r"(0) - ); - break; - } - // NO BREAK - case 0x00: - case 0x0d ... 0xfd: - case 0xff: - // Normal post - now that status has been cleared a reset will - // run regular boot code.. - reset_vector(); - break; + case 0x01 ... 0x04: + case 0x06 ... 0x09: + panic("Unimplemented shutdown status: %02x\n", status); case 0x05: // flush keyboard (issue EOI) and jump via 40h:0067h @@ -88,19 +79,33 @@ handle_resume(u8 status) : : "m"(BDA_JUMP), "r"(SEG_BDA) ); break; + + default: + break; } - 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) + ); } -#if MODESEGMENT == 0 -void VISIBLE32FLAT -s3_resume() +// Handle an S3 resume event +static void +s3_resume(void) { if (!CONFIG_S3_RESUME) - panic("S3 resume support not compiled in.\n"); + return; - dprintf(1, "In 32bit resume\n"); + u32 s3_resume_vector = find_resume_vector(); + if (!s3_resume_vector) { + dprintf(1, "No resume vector set!\n"); + return; + } smm_init(); @@ -108,19 +113,48 @@ s3_resume() make_bios_readonly(); - u32 s3_resume_vector = find_resume_vector(); - // 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.code = FLATPTR_TO_SEGOFF((void*)s3_resume_vector); - } else { - dprintf(1, "No resume vector set!\n"); - // Jump to the post vector to restart with a normal boot. - br.code = SEGOFF(SEG_BIOS, (u32)reset_vector - BUILD_BIOS_ADDR); - } + dprintf(1, "Jump to resume vector (%x)\n", s3_resume_vector); + br.code = FLATPTR_TO_SEGOFF((void*)s3_resume_vector); call16big(&br); } -#endif + +// 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(); +}