Files
Arquivotheca.AIX-4.1.3/bos/kernel/proc/POWER/reboot.c
seta75D d6fe8fe829 Init
2021-10-11 22:19:34 -03:00

239 lines
5.5 KiB
C

static char sccsid[] = "@(#)29 1.8.1.14 src/bos/kernel/proc/POWER/reboot.c, sysproc, bos41J, 9514A_all 4/4/95 16:59:17";
/*
* COMPONENT_NAME: SYSPROC
*
* FUNCTIONS: reboot
* turn_power_off
*
* ORIGINS: 3,27,83
*
* This module contains IBM CONFIDENTIAL code. -- (IBM
* Confidential Restricted when combined with the aggregated
* modules for this product)
* SOURCE MATERIALS
*
* (C) COPYRIGHT International Business Machines Corp. 1989, 1995
* All Rights Reserved
* US Government Users Restricted Rights - Use, duplication or
* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
*/
#include <sys/intr.h>
#include <sys/priv.h>
#include <sys/user.h>
#include <sys/errno.h>
#include <sys/adspace.h>
#include <sys/iocc.h>
#include <sys/reboot.h>
#include <sys/machine.h>
#include <sys/errids.h>
#include <sys/systm.h>
#include <sys/syspest.h>
#include <sys/systemcfg.h>
#include <sys/sys_resource.h>
#if PM_SUPPORT
#include <sys/pm.h>
extern struct _pm_kernel_data pm_kernel_data;
#endif /* PM_SUPPORT */
extern int copyin();
/*
*
* NAME: turn_power_off
*
* FUNCTION: Powers Down the system
*
* Write to power control registers which should turn
* the power off. Then read the power status register to generate
* the interrupt to the power supply.
*
* NOTE: power will only be turned off on RACK models.
*
* CALLED BY: reboot()
*/
void
turn_power_off(int howto)
{
#ifdef _POWER_RS
caddr_t ioccaddr;
caddr_t *ioccptr;
volatile ulong psr;
int i;
caddr_t ioccaddr1;
volatile ulong *ocscmd_ptr;
if (__power_rs()) {
/*
* get access to the IOCC
*/
ioccaddr = (caddr_t)io_att(IOCC_BID, 0);
if (!__power_rsc()) {
/*
* provided this isn't an RSC box, write the
* power control reset register.
*
*/
ioccptr = (caddr_t *)(ioccaddr + PCRR_ADDRESS);
*((short *)ioccptr) = 0xFFFF;
}
/*
* Now loop forever reading the Power Status Register
*/
ioccptr = (caddr_t *)(ioccaddr + PSR_ADDRESS);
ocscmd_ptr = (ulong *)(ioccaddr + IOCC_DELAY);
for (;;) {
for (i=0; i<500000; i++)
iocc_delay(ocscmd_ptr,4);
psr = *((volatile ulong *) ioccptr);
}
}
#endif /* _POWER_RS */
#ifdef _POWER_PC
if (__power_pc()) {
#ifdef _RS6K_SMP_MCA
if (__rs6k_smp_mca()) {
if (howto == RB_HARDIPL) {
/* A write to the Power On Reset Control
Register will generate a reset to all
processors */
*prcr_addr = 0xFFFF;
} else {
/* A write to the Power Off Control Register
will create a software power-off */
*spocr_addr = 0xFFFF;
}
__iospace_sync();
}
#endif /* _RS6K_SMP_MCA */
/* NOTE: The AWS PowerPC System Architecture defines a
* software Power Off Control Register. At this point only
* Pegasus uses it. Here is how to access it:
* sys_resource_ptr->sys_regs.pwr_off_cr = 0xFFFF;
*/
#ifdef PM_SUPPORT
pm_kernel_data.turn_power_off
= pm_kernel_data.turn_power_off_pm_core;
if (pm_kernel_data.turn_power_off != NULL) {
(*(pm_kernel_data.turn_power_off))();
}
#endif /* PM_SUPPORT */
/*
* Now loop forever reading the Power Status Register
*/
#ifdef _RS6K_SMP_MCA
for (;;) psr = *pksr_addr;
#else
for (;;) psr = sys_resource_ptr->sys_regs.pwr_key_status;
#endif /* _RS6K_SMP_MCA */
}
#endif /* _POWER_PC */
}
/*
*
* NAME: reboot
*
* FUNCTION: Reboots the system
*
* INPUT: boot device
*
* OUTPUT: -1=error, otherwise we're gone
*
* WARNING!!!!
* User's of this system call are NOT portable.
*
*/
int
reboot(int howto, void *time)
{
struct timestruc_t ct, bt;
time_t htime;
int ipri;
struct errstruct {
struct err_rec0 hdr;
int uid;
int howto;
int time;
} err = { ERRID_REBOOT_ID, "SYSPROC", 0, 0 };
/* Check priviledge before stopping the machine */
if (privcheck(SYS_CONFIG) == EPERM)
{
u.u_error = EPERM;
return -1;
}
ipri = disable_lock(INTMAX, &tod_lock);
/*
* Update the time of day chip at shutdown. The processor clock is
* read every clock tick and is used to update the global variable
* tm.sec, which is used to update the time of day chip. The
* processor clock is more accurate than the time of day clock.
* Update the clock at second boundaries. Some clocks do not have
* a finer granularity than one second.
*/
curtime(&bt);
do {
curtime(&ct);
} while ( bt.tv_sec == ct.tv_sec );
write_clock();
/* log shutdown event */
err.uid = curproc->p_uid;
err.howto = howto;
err.time = 0;
switch (howto) {
case RB_SOFTIPL :
/* log the shutdown of the system */
errsave(&err, sizeof(err));
/* Call the system reset slih to send us back to ROS
* the parameter of 1 tells sr_slih() that we came
* from reboot()
*/
sr_slih(1);
case RB_HALT :
case RB_HARDIPL :
/* log the shutdown of the system */
errsave(&err, sizeof(err));
turn_power_off(howto);
case RB_POWIPL :
unlock_enable(ipri, &tod_lock);
if (copyin((caddr_t)time,(caddr_t)&htime,sizeof(htime)))
{
u.u_error = EFAULT;
return(-1);
}
ipri = disable_lock(INTMAX, &tod_lock);
/* log the shutdown of the system */
err.time = htime;
errsave(&err, sizeof(err));
/*
* Program time of day clock so that the system will
* power on automatically. Then turn the power off so
* the alarm interrupt will work at the designated
* time. The alarm and power off functions are only
* supported on racks.
*/
set_alarm(htime);
turn_power_off(howto);
default :
u.u_error = EINVAL;
unlock_enable(ipri, &tod_lock);
return(-1);
}
}