cpr_driver.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* CPR driver support routines
*/
#include <sys/ddi_impldefs.h>
#define CPR_BUFSIZE 128
extern int devi_detach(dev_info_t *, int);
extern int devi_attach(dev_info_t *, int);
static char *devi_string(dev_info_t *, char *);
static int cpr_is_real_device(dev_info_t *);
/*
* Traverse the dev info tree:
* Call each device driver in the system via a special case
* of the detach() entry point to quiesce itself.
* Suspend children first.
*
*/
int
{
int error;
char buf[CPR_BUFSIZE];
return (ENXIO);
if (!cpr_is_real_device(dip))
continue;
error = DDI_FAILURE;
else
if (error == DDI_SUCCESS)
else {
return (ENXIO);
}
}
return (0);
}
/*
* Traverse the dev info tree:
* Call each device driver in the system via a special case
* of the attach() entry point to restore itself.
* This is a little tricky because it has to reverse the traversal
* order of cpr_suspend_devices().
*/
int
{
int did_suspend;
int error = resume_failed;
char buf[CPR_BUFSIZE];
}
/*
* cpr is the only one that uses this field and the device
* itself hasn't resumed yet, there is no need to use a
* lock, even though kernel threads are active by now.
*/
if (did_suspend)
/*
* There may be background attaches happening on devices
* that were not originally suspended by cpr, so resume
* only devices that were suspended by cpr. Also, stop
* resuming after the first resume failure, but traverse
* the entire tree to clear the suspend flag.
*/
if (did_suspend && !error) {
/*
* If a device suspended by cpr gets detached during
* the resume process (for example, due to hotplugging)
* before cpr gets around to issuing it a DDI_RESUME,
* we'll have problems.
*/
"not ready for resume\n",
"not ready for resume",
DDI_SUCCESS) {
"WARNING: Unable to resume device %s\n",
}
}
}
return (error);
}
/*
* Returns a string which contains device name and address.
*/
static char *
{
char *name;
char *address;
int size;
/*
* Make sure that we don't over-run the buffer.
* There are 2 additional characters in the string.
*/
else
else
return (buf);
}
/*
* This function determines whether the given device is real (and should
* be suspended) or not (pseudo like). If the device has a "reg" property
*/
static int
{
int length;
int rc;
return (0);
/*
* First those devices for which special arrangements have been made
*/
return (1);
return (0);
/*
* now the general case
*/
if (rc != DDI_PROP_SUCCESS) {
return (0);
} else {
return (1);
}
}
/*
* Power down the system.
*/
void
cpr_power_down(void)
{
int is_defined = 0;
char *wordexists = "p\" power-off\" find nip swap l! ";
char *req = "power-off";
/*
* is_defined has value -1 when defined
*/
if (is_defined) {
prom_interpret(req, 0, 0, 0, 0, 0);
}
}