Tried that too, that is where the code sigsegvs: modified from _intr_v86 to
int386:
Linked with -T1 and run as root, the very first int386 call seems to be
where the problem lies (int15 call).
===========================================
/*A modified apm.c previously posted here, just to power-down
(not just “it is now safe to reboot your computer”)
APM-capable machines.
(Didn’t test on ACPI-only machines)
compile:
make apmoff; usemsg apmoff apmoff.c
Now, how should I fire this after “shutdown” “phshutdown” ?
(daemonize, trap SIGPWR, wait 9 secs then powerdown?)
–
kabe
/
/
- apmoff.c
- APM power shutdown
-
- for QNX RTP(x86)
/
/--------------------------------------------------------------------------
-/
/– Modified for use for QNX 4.25 (well attempt to
modify) -----------------/
/--------------------------------------------------------------------------
-*/
#include <stdio.h
#include <stdlib.h
#include <unistd.h
#include <sys/types.h
#include <string.h
#include <i86.h
#define APM_SYSTEM_BIOS 0x15
#define APM_DEV_APM_BIOS 0x0000
#define APM_INSTALLATION_CHECK 0x5300
#define APM_32BIT_CONNECT 0x5303
#define APM_DISCONNECT 0x5304
#define APM_SET_POWER_STATE 0x5307
#define APM_GET_POWER_STATUS 0x530a
#define APM_DRIVER_VERSION 0x530e
#define APM_GET_CAPABILITIES 0x5310
#define PSL_C 1
#define BH(reg) ((((reg).x.ebx)>>8)&0xff)
#define BL(reg) (((reg).x.ebx)&0xff)
#define CH(reg) ((((reg).x.ecx)>>8)&0xff)
#define CL(reg) (((reg).x.ecx)&0xff)
#define DPRINTF(x) if (option.verbose) { printf x; }
#define DUMPREGS(x)
struct {
u_short apm_flags;
u_short apm_version; /* BCD xx.xx /
u_short apm_driver_version; / BCD xx.xx */
} apm_info;
#ifdef __USAGE
%C - Shutdown the power on APM platform
%C [-v] [-S off|standby|suspend]
-v Verbose
-S Next state (default: off)
#endif
struct {
int verbose;
int dryrun;
enum {Standby=1, Suspend=2, Off=3} setstate;
} option = {0,0,Off};
void dumpregs(const union REGS *reg)
{
DPRINTF((“AX=%04X BX=%04X CX=%04X DX=%04X\n”,
(int)reg->x.eax, (int)reg->x.ebx, (int)reg->x.ecx,
(int)reg->x.edx));
DPRINTF((“FL=%04X ESI=%08lX\n”, (int)reg->w.cflag, reg->x.esi));
}
int main(int argc, char *argv[])
{ union REGS reg;
int s;
int c;
while ((c = getopt(argc, argv, “vS:n”)) != -1)
{ switch (c)
{ case ‘v’:
option.verbose++;
break;
case ‘S’:
if (!strcmpi(optarg, “shutdown”) || !strcmpi(optarg, “off”))
{ option.setstate = Off;
}else if (!strcmpi(optarg, “suspend”))
{ option.setstate = Suspend;
} else if (!strcmpi(optarg, “standby”))
{ option.setstate = Standby;
} else
{ fprintf(stderr, “Unknown option -%c %s\n”, c, optarg);
exit(1);
}
break;
case ‘n’:
option.dryrun++;
break;
case ‘?’:
fprintf(stderr, “Unknown option -%c\n”, c);
exit(1);
}
}
/– Installation check -------------------------------------------/
DPRINTF((“APM: Installation Check\n”));
memset(®, 0, sizeof(reg));
reg.x.eax = APM_INSTALLATION_CHECK;
reg.x.ebx = APM_DEV_APM_BIOS;
s = int386(APM_SYSTEM_BIOS, ®, ®);
DPRINTF((“APM: Never Get here as we SIGSEGV (int386)\n”));
if (s || reg.x.cflag&PSL_C) { fprintf(stderr,“error on int386\n”);
exit(s); }
DUMPREGS(®);/XXX/
/*
- AH.AL: APM version number (BCD)
- BH.BL: “PM”
- CX: 0 has16bit
-
1 has32bit
-
2 Idle slows CPU
-
3 disable
-
4 disengage
*/
DPRINTF((" APM Supported: %s\n", (reg.x.cflag&PSL_C)?“no”:“yes”));
apm_info.apm_version = reg.x.eax;
apm_info.apm_flags = reg.x.ecx;
DPRINTF((" BX signature=<%c%c>%s\n",
BH(reg), BL(reg),
((reg.x.ebx&0xffff)==(‘P’<<8)+‘M’)?" (ok)":" (MISMATCH)"));
DPRINTF((" BIOS APM version %x.%x\n",
(apm_info.apm_version>>8)&255, apm_info.apm_version&255 ));
if(apm_info.apm_flags & 1) { DPRINTF((" 16bit mode interface\n")); }
if(apm_info.apm_flags & 2) { DPRINTF((" 32bit mode interface\n")); }
if(apm_info.apm_flags & 4) { DPRINTF((" Slow CPU on Idle\n")); }
DPRINTF((" BIOS PM %s\n", (apm_info.apm_flags&8)?“disabled”:“enabled”));
DPRINTF((" BIOS PM %s\n",
(apm_info.apm_flags&16)?“disengaged”:“engaged”));
if ((reg.x.ebx&0xffff) != (‘P’<<8)+‘M’) {
fprintf(stderr, “APM is not supported on this machine.\n”);
exit(1);
}
/* disconnect first, in case somebody was connected */
memset(®, 0, sizeof(reg));
reg.x.eax = APM_DISCONNECT;
reg.x.ebx = APM_DEV_APM_BIOS;
s = int386(APM_SYSTEM_BIOS, ®, ®);
if (s) { fprintf(stderr,“error on int386\n”); exit(s); }
/* connect 32 /
DPRINTF((“APM: Connect32\n”));
memset(®, 0, sizeof(reg));
reg.x.eax = APM_32BIT_CONNECT;
reg.x.ebx = APM_DEV_APM_BIOS;
s = int386(APM_SYSTEM_BIOS, ®, ®);
if (s) { fprintf(stderr,“error on int386\n”); exit(s); }
if (reg.x.cflag&PSL_C) {
fprintf(stderr, “APM: Connect32 failed (code 0x%02lX)\n”, reg.x.eax);
return 1;
}
DUMPREGS(®);
/
- AX: code32 realmode CS
- (E)BX: entry point offset
- CX: code16 realmode CS
- ESI: 16 code32 length-1
-
16 code16 length-1
- DX: data realmode DS
- DI: data length
*/
DPRINTF((" 32Bit entry=%04X:%04X (len %04X+1)\n", reg.x.eax, reg.x.ebx,
reg.x.esi&0xffff));
DPRINTF((" 16Bit entry=%04X:%04X (len %04X+1)\n", reg.x.ecx, reg.x.ebx,
(reg.x.esi>>16)&0xffff));
DPRINTF((" Data region=%04X:( 0) (len %04X+1)\n", reg.x.edx, reg.x.edi));
/* set my version (needed to access 1.1- BIOS calls) (APM 1.1) /
apm_info.apm_driver_version = 0x0101; / set to APM 1.1 /
DPRINTF((“APM: set Driver Version to %x.%x\n”,
(apm_info.apm_driver_version>>8)&255,
apm_info.apm_driver_version&255
));
memset(®, 0, sizeof(reg));
reg.x.eax = APM_DRIVER_VERSION;
reg.x.ebx = APM_DEV_APM_BIOS;
reg.x.ecx = apm_info.apm_driver_version;
s = int386(APM_SYSTEM_BIOS, ®, ®);
/
- AH.AL: APM connection version
/
if (s) { fprintf(stderr,“error on int386\n”); exit(s); }
if (reg.x.cflag&PSL_C) {
fprintf(stderr, “APM: set Driver Version failed (code 0x%02X)\n”,
(int)(reg.x.eax>>8));
/exit(1);/
} else {
DPRINTF((" Connected as version %x.%x\n", (reg.x.eax>>8)&255,
reg.x.eax&255 ));
}
/ set power status (to OFF etc) (APM 1.1) */
DPRINTF((“APM: Set Power State (All, %d)\n”, option.setstate));
memset(®, 0, sizeof(reg));
reg.x.eax = APM_SET_POWER_STATE;
reg.x.ebx = APM_DEV_APM_BIOS +0x0001;
reg.x.ecx = option.setstate;
if (!option.dryrun)
s = int386(APM_SYSTEM_BIOS, ®, ®);
if (s) { fprintf(stderr,“error on int386\n”); exit(s); }
if (reg.x.cflag&PSL_C)
fprintf(stderr, “APM: Set Power State failed (code 0x%02X)\n”,
(int)(reg.x.eax>>8));
DPRINTF((“APM: Disconnect\n”));
memset(®, 0, sizeof(reg));
reg.x.eax = APM_DISCONNECT;
reg.x.ebx = APM_DEV_APM_BIOS; /APM BIOS/
s = int386(APM_SYSTEM_BIOS, ®, ®);
if (s) { fprintf(stderr,“error on int386\n”); exit(s); }
return s;
}
===========================================
Thanks,
Len.
“Bill Caroselli” <> qtps@earthlink.net> > wrote in message
news:bhqinf$m90$> 2@inn.qnx.com> …
If this is QNX4 there was an int386() function that will help you make
this kinf of call, I think. Check the docs.
Len Meakin <> len.meakin@cirrustesting.com> _remove> wrote:
LM > Already linked with T1 and running as root, so I guess direct int15
calls
LM > are out of the question. I have found some apm code (Apm-1.3.tar.gz)
on
LM > QUICS, but this seems to only support QNX 4.25 (Proc4.25), but we
have to
LM > run with Proc4.24 because of our int10 usage. I’ll be taking a closer
look
LM > at this code today to determine if it will provide any hints on how
to
LM > accomplish this.
LM > Thank you,
LM > Len.
LM > “David Gibbs” <> dagibbs@qnx.com> > wrote in message
LM > news:bhis3c$5uq$> 2@nntp.qnx.com> …
Len Meakin <> len.meakin@cirrustesting.com> > wrote:
Is there any way to implement power management functionality using
QNX
LM > 4.25
(Proc32=4.24). As we require the following functionality:
Get current battery status (PC104 based system).
Complete power down of system, without user intervention (PC104 based
system).
Is this possible, I have tried int15 calls but the code just seems to
sigsegv when ever it is run. Any help on this will be gratefully
LM > received.
QNX does not provide any power management functionality for QNX 4.
I don’t know if the int15 calls are callable from 32-bit protected
mode,
nor how you went about trying to call them.
At minimum, you will need to link your program with -T1 and run as
root.
-David
QNX Training Services
http://www.qnx.com/support/training/
Please followup in this newsgroup if you have further questions.
\
Bill Caroselli – Q-TPS Consulting
1-(626) 824-7983
qtps@earthlink.net