Hi Linus,
This patch (against 2.3.99pre4-4) does the following:
Allow user mode programs to reject standby and suspend operations.
Make power off work on SMP again.
Add APM_IOC_ENABLE.
Use set_current_state.
Make CONFIG_APM_CPU_IDLE boot time settable.
Make CONFIG_APM_REAL_MODE_POWER_OFF boot time settable.
Make CONFIG_APM_RTC_IS_GMT boot time settable.
Remove CONFIG_APM_IGNORE_USER_SUSPEND as this can now be done by
rejecting USER_SUSPEND events from user mode i.e. in apmd.
Add APM_IOC_LAST_ERROR.
Could you please apply this as the first three items above are very
important to various people.
This patch is also available on the apm web page at
http://linuxcare.com.au/apm/
Cheers,
Stephen
--
Stephen Rothwell, Open Source Project Engineer, Linuxcare, Inc.
+61-2-62628990 tel, +61-2-62628991 fax
[EMAIL PROTECTED], http://www.linuxcare.com/
Linuxcare. Support for the revolution.
diff -ruN 2.3.99pre4-4/Documentation/Configure.help
2.3.99pre4-4-APM/Documentation/Configure.help
--- 2.3.99pre4-4/Documentation/Configure.help Wed Apr 5 12:49:02 2000
+++ 2.3.99pre4-4-APM/Documentation/Configure.help Wed Apr 5 12:58:05 2000
@@ -12206,12 +12206,6 @@
and read Documentation/modules.txt. The module will be called
apm.o.
-Ignore USER SUSPEND
-CONFIG_APM_IGNORE_USER_SUSPEND
- This option will ignore USER SUSPEND requests. On machines with a
- compliant APM BIOS, you want to say N. However, on the NEC Versa M
- series notebooks, it is necessary to say Y because of a BIOS bug.
-
Enable APM at boot time
CONFIG_APM_DO_ENABLE
Enable APM features at boot time. From page 36 of the APM BIOS
@@ -12238,6 +12232,10 @@
whenever the CPU becomes idle. (On machines with more than one CPU,
this option does nothing.)
+ This just sets the default behaviour and may be modified using the
+ "apm=do_idle" kernel command line option or the do_idle module
+ option.
+
Enable console blanking using APM
CONFIG_APM_DISPLAY_BLANK
Enable console blanking using the APM. Some laptops can use this to
@@ -12278,6 +12276,10 @@
reason not to use GMT in your RTC is if you also run a broken OS
that doesn't understand GMT.
+ This just sets the default behaviour and may be modified using the
+ "apm=rtc_is_gmt" kernel command line option or the rtc_is_gmt module
+ option.
+
Allow interrupts during APM BIOS calls
CONFIG_APM_ALLOW_INTS
Normally we disable external interrupts while we are making calls to
@@ -12292,6 +12294,10 @@
Use real mode APM BIOS calls to switch off the computer. This is
a work-around for a number of buggy BIOSes. Switch this option on if
your computer crashes instead of powering off properly.
+
+ This just sets the default behaviour and may be modified using the
+ "apm=real_mode_power_off" kernel command line option or the
+ real_mode_power_off module option.
Watchdog Timer Support
CONFIG_WATCHDOG
diff -ruN 2.3.99pre4-4/arch/i386/kernel/apm.c 2.3.99pre4-4-APM/arch/i386/kernel/apm.c
--- 2.3.99pre4-4/arch/i386/kernel/apm.c Fri Mar 10 12:15:02 2000
+++ 2.3.99pre4-4-APM/arch/i386/kernel/apm.c Wed Apr 5 12:58:05 2000
@@ -132,6 +132,19 @@
* 1.13: Changes for new pm_ interfaces (Andy Henroid
* <[EMAIL PROTECTED]>).
* Modularize the code.
+ * 1.14: Allow user mode programs to reject standby and suspend
+ * operations (Craig Markwardt <[EMAIL PROTECTED]>).
+ * Make power off work on SMP again (Tony Hoyle
+ * <[EMAIL PROTECTED]> and <[EMAIL PROTECTED]>) modified by sfr.
+ * Use set_current_state (Richard Gooch <[EMAIL PROTECTED]>).
+ * 1.15: Make CONFIG_APM_CPU_IDLE boot time settable.
+ * Make CONFIG_APM_REAL_MODE_POWER_OFF boot time settable.
+ * Make CONFIG_APM_RTC_IS_GMT boot time settable.
+ * Remove CONFIG_APM_IGNORE_USER_SUSPEND as this can now be
+ * done by rejecting USER_SUSPEND events from user mode i.e.
+ * in apmd.
+ * Add APM_IOC_ENABLE (Edward A. Falk <[EMAIL PROTECTED]>).
+ * Add APM_IOC_LAST_ERROR.
*
* APM 1.1 Reference:
*
@@ -197,6 +210,10 @@
* apm=on/off enable/disable APM
* [no-]debug log some debugging messages
* [no-]power[-_]off power off on shutdown
+ * [no-]do[-_]idle do BIOS idle calls
+ * [no-]real[-_]mode[-_]power[-_]off switch to real mode before
+ * powering off
+ * [no-]rtc[-_]is[-_]gmt assume the RTC stores GMT
*/
/* KNOWN PROBLEM MACHINES:
@@ -286,6 +303,8 @@
int standbys_pending;
int suspends_read;
int standbys_read;
+ int rejects_pending;
+ int last_error;
int event_head;
int event_tail;
apm_event_t events[APM_MAX_EVENTS];
@@ -303,37 +322,46 @@
unsigned long offset;
unsigned short segment;
} apm_bios_entry;
+static int clock_slowed;
#ifdef CONFIG_APM_CPU_IDLE
-static int clock_slowed = 0;
+static int do_idle = 1;
+#else
+static int do_idle;
#endif
-static int suspends_pending = 0;
-static int standbys_pending = 0;
+static int rejects_pending;
+static int suspends_pending;
+static int standbys_pending;
#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
-static int waiting_for_resume = 0;
+static int waiting_for_resume;
#endif
#ifdef CONFIG_APM_RTC_IS_GMT
-# define clock_cmos_diff 0
-# define got_clock_diff 1
+static int rtc_is_gmt = 1;
#else
-static long clock_cmos_diff;
-static int got_clock_diff = 0;
+static int rtc_is_gmt;
#endif
-static int debug = 0;
-static int apm_disabled = 0;
+static long clock_cmos_diff;
+static int got_clock_diff;
+static int debug;
+static int apm_disabled;
#ifdef CONFIG_SMP
-static int power_off = 0;
+static int power_off;
#else
static int power_off = 1;
#endif
-static int exit_kapmd = 0;
-static int kapmd_running = 0;
+static int exit_kapmd;
+static int kapmd_running;
+#ifdef CONFIG_APM_REAL_MODE_POWER_OFF
+static int real_mode_power_off = 1;
+#else
+static int real_mode_power_off;
+#endif
static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
static struct apm_user * user_list = NULL;
-static char driver_version[] = "1.13"; /* no spaces */
+static char driver_version[] = "1.15"; /* no spaces */
static char * apm_event_name[] = {
"system standby",
@@ -452,7 +480,11 @@
: "memory", "cc");
APM_DO_RESTORE_SEGS;
__restore_flags(flags);
- return *eax & 0xff;
+ if (*eax & 0xff) {
+ *eax = (*eax >> 8) & 0xff;
+ return 1;
+ }
+ return 0;
}
/*
@@ -490,6 +522,8 @@
}
APM_DO_RESTORE_SEGS;
__restore_flags(flags);
+ if (error)
+ *eax = (*eax >> 8) & 0xff;
return error;
}
@@ -498,7 +532,7 @@
u32 eax;
if (apm_bios_call_simple(APM_FUNC_VERSION, 0, *val, &eax))
- return (eax >> 8) & 0xff;
+ return eax;
*val = eax;
return APM_SUCCESS;
}
@@ -512,7 +546,7 @@
if (apm_bios_call(APM_FUNC_GET_EVENT, 0, 0, &eax, &ebx, &ecx,
&dummy, &dummy))
- return (eax >> 8) & 0xff;
+ return eax;
*event = ebx;
if (apm_bios_info.version < 0x0102)
*info = ~0; /* indicate info not valid */
@@ -526,7 +560,7 @@
u32 eax;
if (apm_bios_call_simple(APM_FUNC_SET_STATE, what, state, &eax))
- return (eax >> 8) & 0xff;
+ return eax;
return APM_SUCCESS;
}
@@ -535,7 +569,6 @@
return set_power_state(APM_DEVICE_ALL, state);
}
-#ifdef CONFIG_APM_CPU_IDLE
static int apm_do_idle(void)
{
u32 dummy;
@@ -610,7 +643,6 @@
}
}
#endif
-#endif
#ifdef CONFIG_SMP
static int apm_magic(void * unused)
@@ -622,7 +654,6 @@
static void apm_power_off(void)
{
-#ifdef CONFIG_APM_REAL_MODE_POWER_OFF
unsigned char po_bios_call[] = {
0xb8, 0x00, 0x10, /* movw $0x1000,ax */
0x8e, 0xd0, /* movw ax,ss */
@@ -632,7 +663,6 @@
0xb9, 0x03, 0x00, /* movw $0x0003,cx */
0xcd, 0x15 /* int $0x15 */
};
-#endif
/*
* This may be called on an SMP machine.
@@ -645,11 +675,10 @@
schedule();
}
#endif
-#ifdef CONFIG_APM_REAL_MODE_POWER_OFF
- machine_real_restart(po_bios_call, sizeof(po_bios_call));
-#else
- (void) apm_set_power_state(APM_STATE_OFF);
-#endif
+ if (real_mode_power_off)
+ machine_real_restart(po_bios_call, sizeof(po_bios_call));
+ else
+ (void) apm_set_power_state(APM_STATE_OFF);
}
static int apm_enable_power_management(int enable)
@@ -660,7 +689,7 @@
return APM_NOT_ENGAGED;
if (apm_bios_call_simple(APM_FUNC_ENABLE_PM, APM_DEVICE_BALL,
enable, &eax))
- return (eax >> 8) & 0xff;
+ return eax;
if (enable)
apm_bios_info.flags &= ~APM_BIOS_DISABLED;
else
@@ -678,7 +707,7 @@
if (apm_bios_call(APM_FUNC_GET_STATUS, APM_DEVICE_ALL, 0,
&eax, &ebx, &ecx, &edx, &dummy))
- return (eax >> 8) & 0xff;
+ return eax;
*status = ebx;
*bat = ecx;
*life = edx;
@@ -705,7 +734,7 @@
if (apm_bios_call(APM_FUNC_GET_STATUS, (0x8000 | (which)), 0, &eax,
&ebx, &ecx, &edx, &esi))
- return (eax >> 8) & 0xff;
+ return eax;
*status = ebx;
*bat = ecx;
*life = edx;
@@ -722,7 +751,7 @@
&& (apm_bios_info.flags & APM_BIOS_DISABLED))
return APM_DISABLED;
if (apm_bios_call_simple(APM_FUNC_ENGAGE_PM, device, enable, &eax))
- return (eax >> 8) & 0xff;
+ return eax;
if (device == APM_DEVICE_ALL) {
if (enable)
apm_bios_info.flags &= ~APM_BIOS_DISENGAGED;
@@ -779,7 +808,8 @@
return as->events[as->event_tail];
}
-static void queue_event(apm_event_t event, struct apm_user *sender)
+static void queue_event(apm_event_t event, struct apm_user *sender,
+ int reject_flag)
{
struct apm_user * as;
@@ -811,9 +841,25 @@
as->standbys_pending++;
standbys_pending++;
break;
+
+ case APM_NORMAL_RESUME:
+ if (reject_flag) {
+ as->suspend_wait = 0;
+ as->suspend_result = -EAGAIN;
+ as->last_error = APM_SUCCESS;
+ }
+ /* Fall through to */
+ case APM_STANDBY_RESUME:
+ if (reject_flag) {
+ as->rejects_pending++;
+ rejects_pending++;
+ }
+ break;
}
}
wake_up_interruptible(&apm_waitqueue);
+ if (reject_flag && (event == APM_NORMAL_RESUME))
+ wake_up_interruptible(&apm_suspend_waitqueue);
}
static void set_time(void)
@@ -830,19 +876,19 @@
static void get_time_diff(void)
{
-#ifndef CONFIG_APM_RTC_IS_GMT
unsigned long flags;
- /*
- * Estimate time zone so that set_time can update the clock
- */
- save_flags(flags);
- clock_cmos_diff = -get_cmos_time();
- cli();
- clock_cmos_diff += CURRENT_TIME;
+ if (rtc_is_gmt) {
+ /*
+ * Estimate time zone so that set_time can update the clock
+ */
+ clock_cmos_diff = -get_cmos_time();
+ save_flags(flags);
+ cli();
+ clock_cmos_diff += CURRENT_TIME;
+ restore_flags(flags);
+ }
got_clock_diff = 1;
- restore_flags(flags);
-#endif
}
static void reinit_timer(void)
@@ -866,32 +912,36 @@
static int suspend(void)
{
int err;
- int ret;
struct apm_user *as;
get_time_diff();
err = apm_set_power_state(APM_STATE_SUSPEND);
reinit_timer();
set_time();
- ret = (err == APM_SUCCESS) || (err == APM_NO_ERROR);
- if (!ret)
+ if (err == APM_NO_ERROR)
+ err = APM_SUCCESS;
+ if (err != APM_SUCCESS)
apm_error("suspend", err);
for (as = user_list; as != NULL; as = as->next) {
as->suspend_wait = 0;
- as->suspend_result = (ret ? 0 : -EIO);
+ as->suspend_result = ((err == APM_SUCCESS) ? 0 : -EIO);
+ as->last_error = err;
}
wake_up_interruptible(&apm_suspend_waitqueue);
- return ret;
+ return err;
}
-static void standby(void)
+static int standby(void)
{
int err;
get_time_diff();
err = apm_set_power_state(APM_STATE_STANDBY);
- if ((err != APM_SUCCESS) && (err != APM_NO_ERROR))
+ if (err == APM_NO_ERROR)
+ err = APM_SUCCESS;
+ if (err != APM_SUCCESS)
apm_error("standby", err);
+ return err;
}
static apm_event_t get_event(void)
@@ -933,10 +983,15 @@
break;
}
- queue_event(event, sender);
+ queue_event(event, sender, 0);
return 1;
}
+static void unsend_event(apm_event_t event)
+{
+ (void) pm_send_all(PM_RESUME, (void *)0);
+}
+
static void check_events(void)
{
apm_event_t event;
@@ -971,16 +1026,11 @@
waiting_for_resume = 1;
#endif
if (standbys_pending <= 0)
- standby();
+ (void) standby();
}
break;
case APM_USER_SUSPEND:
-#ifdef CONFIG_APM_IGNORE_USER_SUSPEND
- if (apm_bios_info.version > 0x100)
- apm_set_power_state(APM_STATE_REJECT);
- break;
-#endif
case APM_SYS_SUSPEND:
#ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE
if (ignore_bounce)
@@ -1060,11 +1110,8 @@
{
DECLARE_WAITQUEUE(wait, current);
- if (smp_num_cpus > 1)
- return;
-
add_wait_queue(&apm_waitqueue, &wait);
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
for (;;) {
/* Nothing to do, just sleep for the timeout */
schedule_timeout(APM_CHECK_TIMEOUT);
@@ -1075,22 +1122,22 @@
* Ok, check all events, check for idle (and mark us sleeping
* so as not to count towards the load average)..
*/
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
apm_event_handler();
-#ifdef CONFIG_APM_CPU_IDLE
+ if (!do_idle)
+ continue;
if (!system_idle())
continue;
if (apm_do_idle()) {
unsigned long start = jiffies;
while (system_idle()) {
apm_do_idle();
- if (jiffies - start > APM_CHECK_TIMEOUT)
+ if ((jiffies - start) > APM_CHECK_TIMEOUT)
break;
}
apm_do_busy();
apm_event_handler();
}
-#endif
}
}
@@ -1125,7 +1172,7 @@
schedule();
goto repeat;
}
- current->state = TASK_RUNNING;
+ set_current_state(TASK_RUNNING);
remove_wait_queue(&apm_waitqueue, &wait);
}
i = count;
@@ -1170,9 +1217,44 @@
return 0;
}
+static void apm_send_reject(struct apm_user *as, apm_event_t state)
+{
+ if (as->rejects_pending > 0) {
+ as->rejects_pending--;
+ rejects_pending--;
+ } else {
+ switch (state) {
+ case APM_SYS_SUSPEND:
+ case APM_USER_SUSPEND:
+ queue_event(APM_NORMAL_RESUME, as, 1);
+ break;
+ case APM_SYS_STANDBY:
+ case APM_USER_STANDBY:
+ queue_event(APM_STANDBY_RESUME, as, 1);
+ break;
+ }
+ }
+ if ((rejects_pending <= 0) &&
+ (suspends_pending <= 0) &&
+ (standbys_pending <= 0)) {
+ switch (state) {
+ case APM_SYS_SUSPEND:
+ case APM_USER_SUSPEND:
+ unsend_event(APM_NORMAL_RESUME);
+ break;
+ case APM_SYS_STANDBY:
+ case APM_USER_STANDBY:
+ unsend_event(APM_STANDBY_RESUME);
+ break;
+ }
+ apm_set_power_state(APM_STATE_REJECT);
+ }
+}
+
static int do_ioctl(struct inode * inode, struct file *filp,
u_int cmd, u_long arg)
{
+ int int_arg;
struct apm_user * as;
DECLARE_WAITQUEUE(wait, current);
@@ -1190,7 +1272,7 @@
} else if (!send_event(APM_USER_STANDBY, as))
return -EAGAIN;
if (standbys_pending <= 0)
- standby();
+ as->last_error = standby();
break;
case APM_IOC_SUSPEND:
if (as->suspends_read > 0) {
@@ -1200,7 +1282,8 @@
} else if (!send_event(APM_USER_SUSPEND, as))
return -EAGAIN;
if (suspends_pending <= 0) {
- if (!suspend())
+ as->last_error = suspend();
+ if (as->last_error != APM_SUCCESS)
return -EIO;
} else {
as->suspend_wait = 1;
@@ -1212,11 +1295,34 @@
break;
schedule();
}
- current->state = TASK_RUNNING;
+ set_current_state(TASK_RUNNING);
remove_wait_queue(&apm_suspend_waitqueue, &wait);
return as->suspend_result;
}
break;
+ case APM_IOC_REJECT:
+ if (as->suspends_read > 0) {
+ as->suspends_read--;
+ as->suspends_pending--;
+ suspends_pending--;
+ apm_send_reject(as, APM_SYS_SUSPEND);
+ } else if (as->standbys_read > 0) {
+ as->standbys_read--;
+ as->standbys_pending--;
+ standbys_pending--;
+ apm_send_reject(as, APM_SYS_STANDBY);
+ } else
+ return -EINVAL;
+ break;
+ case APM_IOC_ENABLE:
+ get_user_ret(int_arg, (int *)arg, -EFAULT);
+ as->last_error = apm_enable_power_management(int_arg);
+ if (as->last_error != APM_SUCCESS)
+ return -EIO;
+ break;
+ case APM_IOC_LAST_ERROR:
+ put_user_ret(as->last_error, (int *)arg, -EFAULT);
+ break;
default:
return -EINVAL;
}
@@ -1233,12 +1339,15 @@
filp->private_data = NULL;
if (as->standbys_pending > 0) {
standbys_pending -= as->standbys_pending;
- if (standbys_pending <= 0)
- standby();
+ rejects_pending -= as->rejects_pending;
+ as->rejects_pending = 0;
+ if ((standbys_pending <= 0) && (rejects_pending <=0))
+ (void) standby();
}
if (as->suspends_pending > 0) {
suspends_pending -= as->suspends_pending;
- if (suspends_pending <= 0)
+ rejects_pending -= as->rejects_pending;
+ if ((suspends_pending <= 0) && (rejects_pending <=0))
(void) suspend();
}
if (user_list == as)
@@ -1277,6 +1386,7 @@
as->event_tail = as->event_head = 0;
as->suspends_pending = as->standbys_pending = 0;
as->suspends_read = as->standbys_read = 0;
+ as->rejects_pending = 0;
/*
* XXX - this is a tiny bit broken, when we consider BSD
* process accounting. If the device is opened by root, we
@@ -1475,27 +1585,15 @@
#ifdef CONFIG_MAGIC_SYSRQ
sysrq_power_off = apm_power_off;
#endif
+ if (smp_num_cpus == 1) {
#if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
- if (smp_num_cpus == 1)
console_blank_hook = apm_console_blank;
#endif
-
- pm_active = 1;
-
- apm_mainloop();
-
- pm_active = 0;
-
+ apm_mainloop();
#if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
- if (smp_num_cpus == 1)
console_blank_hook = NULL;
#endif
-#ifdef CONFIG_MAGIC_SYSRQ
- sysrq_power_off = NULL;
-#endif
- if (power_off)
- pm_power_off = NULL;
-
+ }
kapmd_running = 0;
return 0;
@@ -1518,6 +1616,15 @@
if ((strncmp(str, "power-off", 9) == 0) ||
(strncmp(str, "power_off", 9) == 0))
power_off = !invert;
+ if ((strncmp(str, "do-idle", 7) == 0) ||
+ (strncmp(str, "do_idle", 7) == 0))
+ do_idle = !invert;
+ if ((strncmp(str, "real-mode-power-off", 19) == 0) ||
+ (strncmp(str, "real_mode_power_off", 19) == 0))
+ real_mode_power_off = !invert;
+ if ((strncmp(str, "rtc-is-gmt", 10) == 0) ||
+ (strncmp(str, "rtc_is_gmt", 10) == 0))
+ rtc_is_gmt = !invert;
str = strchr(str, ',');
if (str != NULL)
str += strspn(str, ", \t");
@@ -1606,6 +1713,7 @@
printk(KERN_NOTICE "apm: overridden by ACPI.\n");
APM_INIT_ERROR_RETURN;
}
+ pm_active = 1;
/*
* Set up a segment that references the real mode segment 0x40
@@ -1664,9 +1772,18 @@
{
misc_deregister(&apm_device);
remove_proc_entry("apm", NULL);
+
+#ifdef CONFIG_MAGIC_SYSRQ
+ sysrq_power_off = NULL;
+#endif
+ if (power_off)
+ pm_power_off = NULL;
+
exit_kapmd = 1;
while (kapmd_running)
schedule();
+
+ pm_active = 0;
}
module_init(apm_init);
@@ -1676,5 +1793,13 @@
MODULE_DESCRIPTION("Advanced Power Management");
MODULE_PARM(debug, "i");
MODULE_PARM_DESC(debug, "Enable debug mode");
+MODULE_PARM(power_off, "i");
+MODULE_PARM_DESC(power_off, "Enable power off");
+MODULE_PARM(do_idle, "i");
+MODULE_PARM_DESC(do_idle, "Enable calls to BIOS idle routine");
+MODULE_PARM(real_mode_power_off, "i");
+MODULE_PARM_DESC(real_mode_power_off, "Switch to real mode bfore powering off");
+MODULE_PARM(rtc_is_gmt, "i");
+MODULE_PARM_DESC(rtc_is_gmt, "The real time clock stores GMT");
EXPORT_NO_SYMBOLS;
diff -ruN 2.3.99pre4-4/arch/i386/kernel/i386_ksyms.c
2.3.99pre4-4-APM/arch/i386/kernel/i386_ksyms.c
--- 2.3.99pre4-4/arch/i386/kernel/i386_ksyms.c Thu Mar 16 06:08:04 2000
+++ 2.3.99pre4-4-APM/arch/i386/kernel/i386_ksyms.c Wed Apr 5 12:58:05 2000
@@ -26,6 +26,7 @@
extern void dump_thread(struct pt_regs *, struct user *);
extern int dump_fpu(elf_fpregset_t *);
extern spinlock_t rtc_lock;
+extern void machine_real_restart(unsigned char *, int);
#ifdef CONFIG_SMP
extern void FASTCALL( __write_lock_failed(rwlock_t *rw));
@@ -58,6 +59,7 @@
EXPORT_SYMBOL(pm_power_off);
EXPORT_SYMBOL(get_cmos_time);
EXPORT_SYMBOL(apm_bios_info);
+EXPORT_SYMBOL(machine_real_restart);
EXPORT_SYMBOL(gdt);
EXPORT_SYMBOL_NOVERS(__down_failed);
diff -ruN 2.3.99pre4-4/include/linux/apm_bios.h
2.3.99pre4-4-APM/include/linux/apm_bios.h
--- 2.3.99pre4-4/include/linux/apm_bios.h Mon Feb 21 15:37:09 2000
+++ 2.3.99pre4-4-APM/include/linux/apm_bios.h Wed Apr 5 12:58:05 2000
@@ -204,5 +204,8 @@
#define APM_IOC_STANDBY _IO('A', 1)
#define APM_IOC_SUSPEND _IO('A', 2)
+#define APM_IOC_REJECT _IO('A', 3)
+#define APM_IOC_ENABLE _IOW('A', 4, int)
+#define APM_IOC_LAST_ERROR _IOR('A', 5, int)
#endif /* LINUX_APM_H */