provided code
This commit is contained in:
133
src/devices/shutdown.c
Normal file
133
src/devices/shutdown.c
Normal file
@@ -0,0 +1,133 @@
|
||||
#include "devices/shutdown.h"
|
||||
#include <console.h>
|
||||
#include <stdio.h>
|
||||
#include "devices/kbd.h"
|
||||
#include "devices/serial.h"
|
||||
#include "devices/timer.h"
|
||||
#include "threads/io.h"
|
||||
#include "threads/thread.h"
|
||||
#ifdef USERPROG
|
||||
#include "userprog/exception.h"
|
||||
#endif
|
||||
#ifdef FILESYS
|
||||
#include "devices/block.h"
|
||||
#include "filesys/filesys.h"
|
||||
#endif
|
||||
|
||||
/* Keyboard control register port. */
|
||||
#define CONTROL_REG 0x64
|
||||
|
||||
/* How to shut down when shutdown() is called. */
|
||||
static enum shutdown_type how = SHUTDOWN_NONE;
|
||||
|
||||
static void print_stats (void);
|
||||
|
||||
/* Shuts down the machine in the way configured by
|
||||
shutdown_configure(). If the shutdown type is SHUTDOWN_NONE
|
||||
(which is the default), returns without doing anything. */
|
||||
void
|
||||
shutdown (void)
|
||||
{
|
||||
switch (how)
|
||||
{
|
||||
case SHUTDOWN_POWER_OFF:
|
||||
shutdown_power_off ();
|
||||
break;
|
||||
|
||||
case SHUTDOWN_REBOOT:
|
||||
shutdown_reboot ();
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Nothing to do. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Sets TYPE as the way that machine will shut down when PintOS
|
||||
execution is complete. */
|
||||
void
|
||||
shutdown_configure (enum shutdown_type type)
|
||||
{
|
||||
how = type;
|
||||
}
|
||||
|
||||
/* Reboots the machine via the keyboard controller. */
|
||||
void
|
||||
shutdown_reboot (void)
|
||||
{
|
||||
printf ("Rebooting...\n");
|
||||
|
||||
/* See [kbd] for details on how to program the keyboard
|
||||
* controller. */
|
||||
for (;;)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Poll keyboard controller's status byte until
|
||||
* 'input buffer empty' is reported. */
|
||||
for (i = 0; i < 0x10000; i++)
|
||||
{
|
||||
if ((inb (CONTROL_REG) & 0x02) == 0)
|
||||
break;
|
||||
timer_udelay (2);
|
||||
}
|
||||
|
||||
timer_udelay (50);
|
||||
|
||||
/* Pulse bit 0 of the output port P2 of the keyboard controller.
|
||||
* This will reset the CPU. */
|
||||
outb (CONTROL_REG, 0xfe);
|
||||
timer_udelay (50);
|
||||
}
|
||||
}
|
||||
|
||||
/* Powers down the machine we're running on,
|
||||
as long as we're running on Bochs or QEMU. */
|
||||
void
|
||||
shutdown_power_off (void)
|
||||
{
|
||||
const char s[] = "Shutdown";
|
||||
const char *p;
|
||||
|
||||
#ifdef FILESYS
|
||||
filesys_done ();
|
||||
#endif
|
||||
|
||||
print_stats ();
|
||||
|
||||
printf ("Powering off...\n");
|
||||
serial_flush ();
|
||||
|
||||
/* This is a special power-off sequence supported by Bochs and
|
||||
QEMU, but not by physical hardware. */
|
||||
for (p = s; *p != '\0'; p++){
|
||||
outb (0x8900, *p);
|
||||
}
|
||||
outw (0x604, 0x00 | 0x2000);
|
||||
|
||||
/* This will power off a VMware VM if "gui.exitOnCLIHLT = TRUE"
|
||||
is set in its configuration file. (The "pintos" script does
|
||||
that automatically.) */
|
||||
asm volatile ("cli; hlt" : : : "memory");
|
||||
|
||||
/* None of those worked. */
|
||||
printf ("still running...\n");
|
||||
for (;;);
|
||||
}
|
||||
|
||||
/* Print statistics about PintOS execution. */
|
||||
static void
|
||||
print_stats (void)
|
||||
{
|
||||
timer_print_stats ();
|
||||
thread_print_stats ();
|
||||
#ifdef FILESYS
|
||||
block_print_stats ();
|
||||
#endif
|
||||
console_print_stats ();
|
||||
kbd_print_stats ();
|
||||
#ifdef USERPROG
|
||||
exception_print_stats ();
|
||||
#endif
|
||||
}
|
||||
Reference in New Issue
Block a user