import/switch of: init, getty, reboot, halt, shutdown, wall, last changes: . change reboot() call to netbsd prototype and args . allows pristine <utmp.h> . use clean <sys/reboot.h> instead of <minix/reboot.h> . implement TIOCSCTTY for use by getty so getty can get controlling terminal from init's child(ren) . allow NULL envp for exec Change-Id: I5ca02cb4230857140c08794bbfeba7df982c58a3
		
			
				
	
	
		
			179 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			179 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
 | 
						|
#include "kernel/kernel.h"
 | 
						|
 | 
						|
#include <ctype.h>
 | 
						|
#include <string.h>
 | 
						|
#include <machine/cmos.h>
 | 
						|
#include <machine/bios.h>
 | 
						|
#include <machine/cpu.h>
 | 
						|
#include <minix/portio.h>
 | 
						|
#include <minix/cpufeature.h>
 | 
						|
#include <sys/reboot.h>
 | 
						|
#include <assert.h>
 | 
						|
#include <signal.h>
 | 
						|
#include <machine/vm.h>
 | 
						|
 | 
						|
#include <minix/u64.h>
 | 
						|
 | 
						|
#include "archconst.h"
 | 
						|
#include "arch_proto.h"
 | 
						|
#include "serial.h"
 | 
						|
#include "oxpcie.h"
 | 
						|
#include "direct_utils.h"
 | 
						|
#include <machine/multiboot.h>
 | 
						|
 | 
						|
#ifdef USE_ACPI
 | 
						|
#include "acpi.h"
 | 
						|
#endif
 | 
						|
 | 
						|
#define     KBCMDP          4       /* kbd controller port (O) */
 | 
						|
#define      KBC_PULSE0     0xfe    /* pulse output bit 0 */
 | 
						|
#define      IO_KBD          0x060           /* 8042 Keyboard */
 | 
						|
 | 
						|
int cpu_has_tsc;
 | 
						|
 | 
						|
void
 | 
						|
reset(void)
 | 
						|
{
 | 
						|
        uint8_t b;
 | 
						|
        /*
 | 
						|
         * The keyboard controller has 4 random output pins, one of which is
 | 
						|
         * connected to the RESET pin on the CPU in many PCs.  We tell the
 | 
						|
         * keyboard controller to pulse this line a couple of times.
 | 
						|
         */
 | 
						|
        outb(IO_KBD + KBCMDP, KBC_PULSE0);
 | 
						|
        busy_delay_ms(100);
 | 
						|
        outb(IO_KBD + KBCMDP, KBC_PULSE0);
 | 
						|
        busy_delay_ms(100);
 | 
						|
 | 
						|
        /*
 | 
						|
         * Attempt to force a reset via the Reset Control register at
 | 
						|
         * I/O port 0xcf9.  Bit 2 forces a system reset when it
 | 
						|
         * transitions from 0 to 1.  Bit 1 selects the type of reset
 | 
						|
         * to attempt: 0 selects a "soft" reset, and 1 selects a
 | 
						|
         * "hard" reset.  We try a "hard" reset.  The first write sets
 | 
						|
         * bit 1 to select a "hard" reset and clears bit 2.  The
 | 
						|
         * second write forces a 0 -> 1 transition in bit 2 to trigger
 | 
						|
         * a reset.
 | 
						|
         */
 | 
						|
        outb(0xcf9, 0x2);
 | 
						|
        outb(0xcf9, 0x6);
 | 
						|
        busy_delay_ms(500);  /* wait 0.5 sec to see if that did it */
 | 
						|
 | 
						|
        /*
 | 
						|
         * Attempt to force a reset via the Fast A20 and Init register
 | 
						|
         * at I/O port 0x92.  Bit 1 serves as an alternate A20 gate.
 | 
						|
         * Bit 0 asserts INIT# when set to 1.  We are careful to only
 | 
						|
         * preserve bit 1 while setting bit 0.  We also must clear bit
 | 
						|
         * 0 before setting it if it isn't already clear.
 | 
						|
         */
 | 
						|
        b = inb(0x92);
 | 
						|
        if (b != 0xff) {
 | 
						|
                if ((b & 0x1) != 0)
 | 
						|
                        outb(0x92, b & 0xfe);
 | 
						|
                outb(0x92, b | 0x1);
 | 
						|
                busy_delay_ms(500);  /* wait 0.5 sec to see if that did it */
 | 
						|
        }
 | 
						|
 | 
						|
	/* Triple fault */
 | 
						|
	x86_triplefault();
 | 
						|
 | 
						|
	/* Give up on resetting */
 | 
						|
	while(1) {
 | 
						|
		;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static __dead void
 | 
						|
halt(void)
 | 
						|
{
 | 
						|
	for ( ; ; )
 | 
						|
		halt_cpu();
 | 
						|
}
 | 
						|
 | 
						|
static __dead void
 | 
						|
poweroff(void)
 | 
						|
{
 | 
						|
	const char *shutdown_str;
 | 
						|
 | 
						|
#ifdef USE_ACPI
 | 
						|
	acpi_poweroff();
 | 
						|
#endif
 | 
						|
	/* Bochs/QEMU poweroff */
 | 
						|
	shutdown_str = "Shutdown";
 | 
						|
        while (*shutdown_str) outb(0x8900, *(shutdown_str++));
 | 
						|
 | 
						|
	/* VMware magic power off; likely to halt CPU */
 | 
						|
	poweroff_vmware_clihlt();
 | 
						|
 | 
						|
	/* fallback option: hang */
 | 
						|
	halt();
 | 
						|
}
 | 
						|
 | 
						|
__dead void arch_shutdown(int how)
 | 
						|
{
 | 
						|
	unsigned char unused_ch;
 | 
						|
	/* Mask all interrupts, including the clock. */
 | 
						|
	outb( INT_CTLMASK, ~0);
 | 
						|
 | 
						|
	/* Empty buffer */
 | 
						|
	while(direct_read_char(&unused_ch))
 | 
						|
		;
 | 
						|
 | 
						|
	if(kinfo.minix_panicing) {
 | 
						|
		/* Printing is done synchronously over serial. */
 | 
						|
		if (kinfo.do_serial_debug)
 | 
						|
			reset();
 | 
						|
 | 
						|
		/* Print accumulated diagnostics buffer and reset. */
 | 
						|
		direct_cls();
 | 
						|
		direct_print("Minix panic. System diagnostics buffer:\n\n");
 | 
						|
		direct_print(kmess.kmess_buf);
 | 
						|
		direct_print("\nSystem has panicked, press any key to reboot");
 | 
						|
		while (!direct_read_char(&unused_ch))
 | 
						|
			;
 | 
						|
		reset();
 | 
						|
	}
 | 
						|
		
 | 
						|
	if((how & RB_POWERDOWN) == RB_POWERDOWN) {
 | 
						|
		/* Power off if possible, hang otherwise */
 | 
						|
		poweroff();
 | 
						|
		NOT_REACHABLE;
 | 
						|
	}
 | 
						|
 | 
						|
	if(how & RB_HALT) {
 | 
						|
		/* Hang */
 | 
						|
		for (; ; ) halt_cpu();
 | 
						|
		NOT_REACHABLE;
 | 
						|
	}
 | 
						|
 | 
						|
	/* Reset the system by forcing a processor shutdown. 
 | 
						|
	 * First stop the BIOS memory test by setting a soft
 | 
						|
	 * reset flag.
 | 
						|
	 */
 | 
						|
	reset();
 | 
						|
	NOT_REACHABLE;
 | 
						|
}
 | 
						|
 | 
						|
#ifdef DEBUG_SERIAL
 | 
						|
void ser_putc(char c)
 | 
						|
{
 | 
						|
        int i;
 | 
						|
        int lsr, thr;
 | 
						|
 | 
						|
#if CONFIG_OXPCIE
 | 
						|
        oxpcie_putc(c);
 | 
						|
#else
 | 
						|
        lsr= COM1_LSR;
 | 
						|
        thr= COM1_THR;
 | 
						|
        for (i= 0; i<100000; i++)
 | 
						|
        {
 | 
						|
                if (inb( lsr) & LSR_THRE)
 | 
						|
                        break;
 | 
						|
        }
 | 
						|
        outb( thr, c);
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
#endif
 |