diff options
Diffstat (limited to 'pintos-progos/devices/shutdown.c')
| -rw-r--r-- | pintos-progos/devices/shutdown.c | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/pintos-progos/devices/shutdown.c b/pintos-progos/devices/shutdown.c new file mode 100644 index 0000000..7ff9a95 --- /dev/null +++ b/pintos-progos/devices/shutdown.c | |||
| @@ -0,0 +1,131 @@ | |||
| 1 | #include "devices/shutdown.h" | ||
| 2 | #include <console.h> | ||
| 3 | #include <stdio.h> | ||
| 4 | #include "devices/kbd.h" | ||
| 5 | #include "devices/serial.h" | ||
| 6 | #include "devices/timer.h" | ||
| 7 | #include "threads/io.h" | ||
| 8 | #include "threads/thread.h" | ||
| 9 | #ifdef USERPROG | ||
| 10 | #include "userprog/exception.h" | ||
| 11 | #endif | ||
| 12 | #ifdef FILESYS | ||
| 13 | #include "devices/block.h" | ||
| 14 | #include "filesys/filesys.h" | ||
| 15 | #endif | ||
| 16 | |||
| 17 | /* Keyboard control register port. */ | ||
| 18 | #define CONTROL_REG 0x64 | ||
| 19 | |||
| 20 | /* How to shut down when shutdown() is called. */ | ||
| 21 | static enum shutdown_type how = SHUTDOWN_NONE; | ||
| 22 | |||
| 23 | static void print_stats (void); | ||
| 24 | |||
| 25 | /* Shuts down the machine in the way configured by | ||
| 26 | shutdown_configure(). If the shutdown type is SHUTDOWN_NONE | ||
| 27 | (which is the default), returns without doing anything. */ | ||
| 28 | void | ||
| 29 | shutdown (void) | ||
| 30 | { | ||
| 31 | switch (how) | ||
| 32 | { | ||
| 33 | case SHUTDOWN_POWER_OFF: | ||
| 34 | shutdown_power_off (); | ||
| 35 | break; | ||
| 36 | |||
| 37 | case SHUTDOWN_REBOOT: | ||
| 38 | shutdown_reboot (); | ||
| 39 | break; | ||
| 40 | |||
| 41 | default: | ||
| 42 | /* Nothing to do. */ | ||
| 43 | break; | ||
| 44 | } | ||
| 45 | } | ||
| 46 | |||
| 47 | /* Sets TYPE as the way that machine will shut down when Pintos | ||
| 48 | execution is complete. */ | ||
| 49 | void | ||
| 50 | shutdown_configure (enum shutdown_type type) | ||
| 51 | { | ||
| 52 | how = type; | ||
| 53 | } | ||
| 54 | |||
| 55 | /* Reboots the machine via the keyboard controller. */ | ||
| 56 | void | ||
| 57 | shutdown_reboot (void) | ||
| 58 | { | ||
| 59 | printf ("Rebooting...\n"); | ||
| 60 | |||
| 61 | /* See [kbd] for details on how to program the keyboard | ||
| 62 | * controller. */ | ||
| 63 | for (;;) | ||
| 64 | { | ||
| 65 | int i; | ||
| 66 | |||
| 67 | /* Poll keyboard controller's status byte until | ||
| 68 | * 'input buffer empty' is reported. */ | ||
| 69 | for (i = 0; i < 0x10000; i++) | ||
| 70 | { | ||
| 71 | if ((inb (CONTROL_REG) & 0x02) == 0) | ||
| 72 | break; | ||
| 73 | timer_udelay (2); | ||
| 74 | } | ||
| 75 | |||
| 76 | timer_udelay (50); | ||
| 77 | |||
| 78 | /* Pulse bit 0 of the output port P2 of the keyboard controller. | ||
| 79 | * This will reset the CPU. */ | ||
| 80 | outb (CONTROL_REG, 0xfe); | ||
| 81 | timer_udelay (50); | ||
| 82 | } | ||
| 83 | } | ||
| 84 | |||
| 85 | /* Powers down the machine we're running on, | ||
| 86 | as long as we're running on Bochs or QEMU. */ | ||
| 87 | void | ||
| 88 | shutdown_power_off (void) | ||
| 89 | { | ||
| 90 | const char s[] = "Shutdown"; | ||
| 91 | const char *p; | ||
| 92 | |||
| 93 | #ifdef FILESYS | ||
| 94 | filesys_done (); | ||
| 95 | #endif | ||
| 96 | |||
| 97 | print_stats (); | ||
| 98 | |||
| 99 | printf ("Powering off...\n"); | ||
| 100 | serial_flush (); | ||
| 101 | |||
| 102 | /* This is a special power-off sequence supported by Bochs and | ||
| 103 | QEMU, but not by physical hardware. */ | ||
| 104 | for (p = s; *p != '\0'; p++) | ||
| 105 | outb (0x8900, *p); | ||
| 106 | |||
| 107 | /* This will power off a VMware VM if "gui.exitOnCLIHLT = TRUE" | ||
| 108 | is set in its configuration file. (The "pintos" script does | ||
| 109 | that automatically.) */ | ||
| 110 | asm volatile ("cli; hlt" : : : "memory"); | ||
| 111 | |||
| 112 | /* None of those worked. */ | ||
| 113 | printf ("still running...\n"); | ||
| 114 | for (;;); | ||
| 115 | } | ||
| 116 | |||
| 117 | /* Print statistics about Pintos execution. */ | ||
| 118 | static void | ||
| 119 | print_stats (void) | ||
| 120 | { | ||
| 121 | timer_print_stats (); | ||
| 122 | thread_print_stats (); | ||
| 123 | #ifdef FILESYS | ||
| 124 | block_print_stats (); | ||
| 125 | #endif | ||
| 126 | console_print_stats (); | ||
| 127 | kbd_print_stats (); | ||
| 128 | #ifdef USERPROG | ||
| 129 | exception_print_stats (); | ||
| 130 | #endif | ||
| 131 | } | ||
