X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fresume.c;h=f887f454e7cc8d351ade16669ca49d407616dfa9;hb=ecae9bfd29e398cf93864a3effb183a717fa749d;hp=2a743c9475ad9a396bbd2e4a098f09286641176b;hpb=4057f9847e94147aaa9799b92ba4561506333a57;p=seabios.git diff --git a/src/resume.c b/src/resume.c index 2a743c9..f887f45 100644 --- a/src/resume.c +++ b/src/resume.c @@ -10,6 +10,12 @@ #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 @@ -26,34 +32,19 @@ init_dma(void) // 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" - "movl $s3_resume, %%edx\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,38 +79,83 @@ 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) + ); } -void VISIBLE32FLAT +// Handle an S3 resume event +static void s3_resume(void) { - ASSERT32FLAT(); 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; + } + pic_setup(); smm_init(); s3_resume_vga_init(); 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); } + +// 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(); +}