[comp.os.msdos.programmer] Problems programming the AT CMOS alarm clock - interrupt 0x1a

minar@reed.bitnet (Nelson Minar,L08,x640,7776519) (08/21/90)

  Help! I am trying to exercise a feature of the IBM AT - the CMOS alarm clock.
This is documented in Ralf Brown's interrupt list under interrupt 0x1a,
services 6 and 7.  Presumably, all one has to do is call int 0x1a with ah = 6,
and various other registers equal to the time to interrupt, and the next time
the CMOS clock hits that time, interrupt 0x4a will be called: cheap alarm
clock.  This doesn't work.

  There are two problems I am having.  First, the setCMOSAlarm function
I have written below always returns an error (the TRYTOSET macro
version). It should set the alarm to 23:10:10 with no difficulty.  This
error condition means (according the the interrupt list, my only
reference) "alarm already set or clock inoperable."
  Assuming that the alarm is already set, I tried using my
resetCMOSAlarm function (the TRYTORESET macro version).  This should
work just fine, it seems to me.  Instead, it crashes the computer and I
have to hit the reset switch (no ctrl-alt-del, and it crashes the Turbo
Debugger, too).
  I think the CMOS clock is working ok: I have other functions that use
related interrupt services (0x1a, services 2-5) with no hitches at all. The
alarm seems to break rather badly.

  Is this alarm clock something clone manufacturers are likely to get
wrong (I have a very cheap clone..)  Are there any programs out there
that use the CMOS alarm feature? How do most alarm clocks work, hitch
int 0x1c? (shudder)  Any insight would be appreciated..

  Below is a recreation of my problem.  I've been compiling with Turbo
C++ 1.0 in C++ mode.

--------------------------------------------------------------------------
#include <dos.h>
#include <stdio.h>

int setCMOSAlarm(void);
void resetCMOSAlarm(void);

/* int 0x1a, service 6 - set the AT real time clock alarm to call int 0x4a
 * will return the value of the carry flag, which is set if either the clock
 * is inoperable, or the alarm is already set.
 */
int setCMOSAlarm (void) {
  union REGS regs;

  regs.h.ah = 6;                                 // set alarm service
  regs.h.ch = 0x23;                              // arbitrary time in BCD
  regs.h.cl = 0x10;                              // 23:10:10
  regs.h.dh = 0x10;
  int86 (0x1a, &regs, &regs);                    // clock interrupt
  return (regs.x.cflag == 0) ? 0 : 1;            // 0 means no error.
}

/* use int 0x1a, service 7 to reset the Alarm.. */
void resetCMOSAlarm (void) {
  union REGS regs;

  regs.h.ah = 7;                                 // reset alarm
  int86(0x1a, &regs, &regs);
}

#ifdef TRYTORESET
void main(void) {
  resetCMOSAlarm();
}
#endif TRYTORESET

#ifdef TRYTOSET
void main(void) {
  printf ("%s\n", setCMOSAlarm() == 0 ? "alarm set" : "set failed");
}
#endif TRYTOSET
---------------------------------------------------------------------------
__
\/ minar@reed.bitnet                         You know in your heart its flat.