X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fresume.c;h=f887f454e7cc8d351ade16669ca49d407616dfa9;hb=ecae9bfd29e398cf93864a3effb183a717fa749d;hp=76a8c50d6a679d98077a56f2678dc37673ab0efa;hpb=a3a729f043125b635bb57eb3aff1df849d20c4c3;p=seabios.git diff --git a/src/resume.c b/src/resume.c index 76a8c50..f887f45 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,46 +32,31 @@ 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 eoi_pic2(); // NO BREAK case 0x0a: -#define BDA_JUMP_IP (((struct bios_data_area_s *)0)->jump_ip) +#define BDA_JUMP (((struct bios_data_area_s *)0)->jump) // resume execution by jump via 40h:0067h asm volatile( "movw %w1, %%ds\n" "ljmpw *%0\n" - : : "m"(BDA_JUMP_IP), "r"(SEG_BDA) + : : "m"(BDA_JUMP), "r"(SEG_BDA) ); break; @@ -75,7 +66,7 @@ handle_resume(u8 status) "movw %w1, %%ds\n" "lssw %0, %%sp\n" "iretw\n" - : : "m"(BDA_JUMP_IP), "r"(SEG_BDA) + : : "m"(BDA_JUMP), "r"(SEG_BDA) ); break; @@ -85,42 +76,86 @@ handle_resume(u8 status) "movw %w1, %%ds\n" "lssw %0, %%sp\n" "lretw\n" - : : "m"(BDA_JUMP_IP), "r"(SEG_BDA) + : : "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 MODE16==0 -void VISIBLE32 -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; + } + 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 = FLATPTR_TO_OFFSET(s3_resume_vector); - br.cs = FLATPTR_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); } -#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(); +}