summaryrefslogtreecommitdiffstats
path: root/pintos-progos/devices/shutdown.c
diff options
context:
space:
mode:
Diffstat (limited to 'pintos-progos/devices/shutdown.c')
-rw-r--r--pintos-progos/devices/shutdown.c131
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. */
21static enum shutdown_type how = SHUTDOWN_NONE;
22
23static 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. */
28void
29shutdown (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. */
49void
50shutdown_configure (enum shutdown_type type)
51{
52 how = type;
53}
54
55/* Reboots the machine via the keyboard controller. */
56void
57shutdown_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. */
87void
88shutdown_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. */
118static void
119print_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}