373 lines
9.7 KiB
C
373 lines
9.7 KiB
C
/*
|
|
* Copyright (c) 1995 FirePower Systems, Inc.
|
|
* DO NOT DISTRIBUTE without permission
|
|
*
|
|
* $RCSfile: fpds1385.c $
|
|
* $Revision: 1.14 $
|
|
* $Date: 1996/05/20 22:35:57 $
|
|
* $Locker: $
|
|
*
|
|
* fpds1385.c: set of routines to init, and maintain the DS1385
|
|
*
|
|
*/
|
|
|
|
#include "fpdebug.h"
|
|
#include "halp.h"
|
|
#include "phsystem.h"
|
|
#include "fpreg.h"
|
|
#include "fpio.h" // pick up the io space register access macros
|
|
#include "fpds1385.h" // defines specific to the dallas 1385
|
|
|
|
#define DS1385_BAILOUT_COUNT 10
|
|
|
|
UCHAR OriginalA; // storage location for rtc data in control reg a
|
|
UCHAR OriginalB; // storage location for rtc data in control reg b
|
|
BOOLEAN RtcBinaryMode = FALSE;
|
|
// Flag to indicate if RTC is programmed in BINHEX or
|
|
// BCD format
|
|
|
|
BOOLEAN RtcFailure = FALSE;
|
|
// Flag to indicate if the RTC was read correctly
|
|
BOOLEAN NvramFailure = FALSE;
|
|
// Flag to indicate if the NVRAM was read correctly
|
|
ULONG TotalDs1385Failures = 0;
|
|
// Keep track of failures to read the DS1385
|
|
/*
|
|
* HalpInitFireRTC:
|
|
*
|
|
* Make sure the dallas 1385 chip is correctly setup. This means that
|
|
* all the configuration bits are in place. If the chip is not correctly
|
|
* setup, save the time off, fix the bits, recalculate the time if needed,
|
|
* and restore the time. Particularly, if the "DataMode" or "24/12 hour"
|
|
* bits are changed the time will need to be recalculated.
|
|
*/
|
|
BOOLEAN
|
|
HalpInitFirePowerRTC( VOID )
|
|
{
|
|
TIME_FIELDS TimeFields;
|
|
UCHAR tval;
|
|
BOOLEAN Status = FALSE;
|
|
UCHAR ds1385Data;
|
|
|
|
HDBG(DBG_INTERNAL, HalpDebugPrint("HalpInitFirePowerRTC: begin \n"););
|
|
if ( !(HalQueryRealTimeClock( &TimeFields )) ) {
|
|
HalDisplayString("Not sure RTC is initted \n");
|
|
}
|
|
|
|
//
|
|
// Make sure the time is valid before worrying about any of the bits.
|
|
//
|
|
ds1385Data = HalpDS1385ReadReg(RTC_CONTROL_REGISTERD);
|
|
if ( ds1385Data & RTC_VRT ) {
|
|
|
|
//
|
|
// Verify that the DataMode is BCD
|
|
// the time style is 24 hour,
|
|
// that Daylight Savings is NOT enabled,
|
|
// that the square wave output is enabled.
|
|
//
|
|
tval = HalpDS1385ReadReg(RTC_CONTROL_REGISTERB);
|
|
OriginalB = tval;
|
|
HDBG(DBG_GENERAL,
|
|
HalpDebugPrint("HalpInitFirePowerRTC: register b is %x \n",
|
|
OriginalB););
|
|
|
|
HalpDS1385WriteReg(RTC_CONTROL_REGISTERB,
|
|
RTC_24_HR |
|
|
//
|
|
// for consistency with firmware, setup the RTC
|
|
// to maintain the time in BCD format rather
|
|
// than binary
|
|
//
|
|
// RTC_BIN_MODE |
|
|
RTC_SQWE|
|
|
RTC_UIE |
|
|
RTC_PIE);
|
|
|
|
RtcBinaryMode = FALSE;
|
|
tval = HalpDS1385ReadReg(RTC_CONTROL_REGISTERA);
|
|
OriginalA = tval;
|
|
HDBG(DBG_GENERAL,
|
|
HalpDebugPrint("HalpInitFirePowerRTC: register a is %x\n",
|
|
OriginalA););
|
|
|
|
//
|
|
// Ensure the Oscillator is running and updating, not either
|
|
// stopped or counting but not updating.
|
|
//
|
|
if ((tval & ( RTC_DV1 | RTC_DV2 | RTC_DV0 )) != RTC_DV1 ) {
|
|
tval = RTC_DV1;
|
|
}
|
|
HalpDS1385WriteReg(RTC_CONTROL_REGISTERA, (UCHAR)(tval | RTC_4096_HZ));
|
|
|
|
//
|
|
// Clear the interrupt flag bits
|
|
//
|
|
tval = HalpDS1385ReadReg(RTC_CONTROL_REGISTERC);
|
|
|
|
//
|
|
// Finally, restore the time: HalSetRealTimeClock will take
|
|
// care of any BCD=BIN conversion necessary.
|
|
//
|
|
if ( HalSetRealTimeClock ( &TimeFields)) {
|
|
Status=TRUE;
|
|
}
|
|
|
|
} else {
|
|
|
|
HalDisplayString("RTC Time is invalid: battery is dead?\n");
|
|
}
|
|
HDBG(DBG_INTERNAL,
|
|
HalpDebugPrint("HalpInitFirePowerRTC: end \n"););
|
|
return(Status);
|
|
}
|
|
|
|
|
|
//
|
|
// write a byte to the specified DS1385 register.
|
|
// First acquire the spin lock to make sure something else is not
|
|
// trying to access the DS1385 (RTC or NVRAM). Then do the write
|
|
// Finally, release the spinlock.
|
|
//
|
|
VOID
|
|
HalpDS1385WriteReg(UCHAR reg, UCHAR value)
|
|
{
|
|
KIRQL OldIrql;
|
|
UCHAR data0, data1, data2;
|
|
ULONG failureCount = 0;
|
|
|
|
KeAcquireSpinLock(&HalpDS1385Lock, &OldIrql);
|
|
|
|
// We have a problem accessing the DS1385 correctly. To get around this,
|
|
// we use the Dave Stewart method; after writing the DS1385 regiser, we
|
|
// read it back 3 times - if
|
|
// one of the three values compares with the value written, we are
|
|
// done. If we do not get a comparison, throw all three values away and
|
|
// try the write
|
|
// again. If, after 10 interations we cannot read a consistent pair,
|
|
// we assert a failure flag; the routine calling us must decide what
|
|
// to do with the flag.
|
|
while (failureCount < DS1385_BAILOUT_COUNT) {
|
|
// Write the register
|
|
rIndexRTC = reg;
|
|
FireSyncRegister();
|
|
rDataRTC = value;
|
|
// make sure access to the chip is complete before releasing
|
|
// the spin lock
|
|
FireSyncRegister();
|
|
|
|
// Read it three times
|
|
rIndexRTC = reg;
|
|
FireSyncRegister();
|
|
data0 = rDataRTC;
|
|
|
|
rIndexRTC = reg;
|
|
FireSyncRegister();
|
|
data1 = rDataRTC;
|
|
|
|
rIndexRTC = reg;
|
|
FireSyncRegister();
|
|
data2 = rDataRTC;
|
|
|
|
if ((data0 == value) || (data1 == value) || (data2 == value)) {
|
|
break;
|
|
}
|
|
failureCount++;
|
|
}
|
|
|
|
if (failureCount == DS1385_BAILOUT_COUNT) {
|
|
RtcFailure = TRUE;
|
|
}
|
|
|
|
TotalDs1385Failures += failureCount;
|
|
KeReleaseSpinLock(&HalpDS1385Lock, OldIrql);
|
|
}
|
|
|
|
//
|
|
// read a byte from the specified DS1385 register.
|
|
// First acquire the spin lock to make sure something else is not
|
|
// trying to access the DS1385 (RTC or NVRAM). Then do the read
|
|
// Finally, release the spinlock.
|
|
//
|
|
UCHAR
|
|
HalpDS1385ReadReg(UCHAR reg)
|
|
{
|
|
KIRQL OldIrql;
|
|
UCHAR result = 0xff;
|
|
UCHAR data0, data1, data2;
|
|
ULONG failureCount = 0;
|
|
|
|
KeAcquireSpinLock(&HalpDS1385Lock, &OldIrql);
|
|
|
|
// We have a problem accessing the DS1385 correctly. To get around this,
|
|
// we use the Dave Stewart method; read the DS1385 register 3 times - if
|
|
// one of the three values compares with either of the other two, return
|
|
// it. If we do not get a comparison, throw all three values away and try
|
|
// again. If, after 10 interations we cannot read a consistent pair,
|
|
// we assert a failure flag; the routine calling us must decide what
|
|
// to do with the flag.
|
|
while (failureCount < DS1385_BAILOUT_COUNT) {
|
|
rIndexRTC = reg;
|
|
FireSyncRegister();
|
|
data0 = rDataRTC;
|
|
|
|
rIndexRTC = reg;
|
|
FireSyncRegister();
|
|
data1 = rDataRTC;
|
|
|
|
rIndexRTC = reg;
|
|
FireSyncRegister();
|
|
data2 = rDataRTC;
|
|
|
|
if ((data0 == data1) || (data0 == data2)) {
|
|
result = data0;
|
|
break;
|
|
}
|
|
if (data1 == data2) {
|
|
result = data1;
|
|
break;
|
|
}
|
|
failureCount++;
|
|
}
|
|
|
|
if (failureCount == DS1385_BAILOUT_COUNT) {
|
|
RtcFailure = TRUE;
|
|
}
|
|
|
|
TotalDs1385Failures += failureCount;
|
|
KeReleaseSpinLock(&HalpDS1385Lock, OldIrql);
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// write a byte to the specified address in the DS1385 NVRAM.
|
|
// First acquire the spin lock to make sure something else is not
|
|
// trying to access the DS1385 (RTC or NVRAM). Then do the write
|
|
// Finally, release the spinlock.
|
|
//
|
|
VOID
|
|
HalpDS1385WriteNVRAM(USHORT addr, UCHAR value)
|
|
{
|
|
KIRQL OldIrql;
|
|
UCHAR data0, data1, data2;
|
|
ULONG failureCount = 0;
|
|
|
|
KeAcquireSpinLock(&HalpDS1385Lock, &OldIrql);
|
|
|
|
// We have a problem accessing the DS1385 correctly. To get around this,
|
|
// we use the Dave Stewart method; after writing the DS1385 regiser, we
|
|
// read it back 3 times - if
|
|
// one of the three values compares with the value written, we are
|
|
// done. If we do not get a comparison, throw all three values away and
|
|
// try the write
|
|
// again. If, after 10 interations we cannot read a consistent pair,
|
|
// we assert a failure flag; the routine calling us must decide what
|
|
// to do with the flag.
|
|
while (failureCount < DS1385_BAILOUT_COUNT) {
|
|
// Write the register
|
|
rNvramAddr0 = addr & 0xff;
|
|
FireSyncRegister();
|
|
rNvramAddr1 = addr >> 8;
|
|
FireSyncRegister();
|
|
rNvramData = value;
|
|
// make sure access to the chip is complete before releasing
|
|
// the spin lock
|
|
FireSyncRegister();
|
|
|
|
// Read the register three times
|
|
rNvramAddr0 = addr & 0xff;
|
|
FireSyncRegister();
|
|
rNvramAddr1 = addr >> 8;
|
|
FireSyncRegister();
|
|
data0 = rNvramData;
|
|
|
|
rNvramAddr0 = addr & 0xff;
|
|
FireSyncRegister();
|
|
rNvramAddr1 = addr >> 8;
|
|
FireSyncRegister();
|
|
data1 = rNvramData;
|
|
|
|
rNvramAddr0 = addr & 0xff;
|
|
FireSyncRegister();
|
|
rNvramAddr1 = addr >> 8;
|
|
FireSyncRegister();
|
|
data2 = rNvramData;
|
|
|
|
if ((data0 == value) || (data1 == value) || (data2 == value)) {
|
|
break;
|
|
}
|
|
failureCount++;
|
|
}
|
|
|
|
if (failureCount == DS1385_BAILOUT_COUNT) {
|
|
NvramFailure = TRUE;
|
|
}
|
|
|
|
TotalDs1385Failures += failureCount;
|
|
KeReleaseSpinLock(&HalpDS1385Lock, OldIrql);
|
|
}
|
|
|
|
|
|
//
|
|
// read a byte from the specified address in the DS1385 NVRAM.
|
|
// First acquire the spin lock to make sure something else is not
|
|
// trying to access the DS1385 (RTC or NVRAM). Then do the read
|
|
// Finally, release the spinlock.
|
|
//
|
|
UCHAR
|
|
HalpDS1385ReadNVRAM(USHORT addr)
|
|
{
|
|
KIRQL OldIrql;
|
|
UCHAR data0, data1, data2;
|
|
UCHAR result = 0xff;
|
|
ULONG failureCount = 0;
|
|
|
|
KeAcquireSpinLock(&HalpDS1385Lock, &OldIrql);
|
|
|
|
// We have a problem accessing the DS1385 correctly. To get around this,
|
|
// we use the Dave Stewart method; read the DS1385 register 3 times - if
|
|
// one of the three values compares with either of the other two, return
|
|
// it. If we do not get a comparison, throw all three values away and try
|
|
// again. If, after 10 interations we cannot read a consistent pair,
|
|
// we assert a failure flag; the routine calling us must decide what
|
|
// to do with the flag.
|
|
while (failureCount < DS1385_BAILOUT_COUNT) {
|
|
rNvramAddr0 = addr & 0xff;
|
|
FireSyncRegister();
|
|
rNvramAddr1 = addr >> 8;
|
|
FireSyncRegister();
|
|
data0 = rNvramData;
|
|
|
|
rNvramAddr0 = addr & 0xff;
|
|
FireSyncRegister();
|
|
rNvramAddr1 = addr >> 8;
|
|
FireSyncRegister();
|
|
data1 = rNvramData;
|
|
|
|
rNvramAddr0 = addr & 0xff;
|
|
FireSyncRegister();
|
|
rNvramAddr1 = addr >> 8;
|
|
FireSyncRegister();
|
|
data2 = rNvramData;
|
|
|
|
if ((data0 == data1) || (data0 == data2)) {
|
|
result = data0;
|
|
break;
|
|
}
|
|
if (data1 == data2) {
|
|
result = data1;
|
|
break;
|
|
}
|
|
failureCount++;
|
|
}
|
|
|
|
if (failureCount == DS1385_BAILOUT_COUNT) {
|
|
NvramFailure = TRUE;
|
|
}
|
|
|
|
TotalDs1385Failures += failureCount;
|
|
KeReleaseSpinLock(&HalpDS1385Lock, OldIrql);
|
|
return result;
|
|
}
|
|
|