summaryrefslogtreecommitdiffstats
path: root/clockB/directio.c
diff options
context:
space:
mode:
Diffstat (limited to 'clockB/directio.c')
-rw-r--r--clockB/directio.c727
1 files changed, 0 insertions, 727 deletions
diff --git a/clockB/directio.c b/clockB/directio.c
deleted file mode 100644
index d3a77eb19..000000000
--- a/clockB/directio.c
+++ /dev/null
@@ -1,727 +0,0 @@
-/**************************************************************************
-
- This is a component of the hwclock program.
-
- This file contains the code for accessing the hardware clock via
- direct I/O (kernel-style input and output operations) as opposed
- to via a device driver.
-
-
- MAINTENANCE NOTES
-
- Here is some information on how the Hardware Clock works, from
- unknown source and authority. In theory, the specification for this
- stuff is the specification of Motorola's MC146818A clock chip, used
- in the early ISA machines. Subsequent machines should have copied
- its function exactly. In reality, though, the copies are inexact
- and the MC146818A itself may fail to implement its specifications,
- and we have just have to work with whatever is there (actually,
- anything that Windows works with, because that's what determines
- whether broken hardware has to be fixed!).
-
- i386 CMOS starts out with 14 bytes clock data
- alpha has something similar, but with details
- depending on the machine type.
-
- byte 0: seconds (0-59)
- byte 2: minutes (0-59)
- byte 4: hours (0-23 in 24hr mode,
- 1-12 in 12hr mode, with high bit unset/set if am/pm)
- byte 6: weekday (1-7, Sunday=1)
- byte 7: day of the month (1-31)
- byte 8: month (1-12)
- byte 9: year (0-99)
-
-
- Numbers are stored in BCD/binary if bit 2 of byte 11 is unset/set
- The clock is in 12hr/24hr mode if bit 1 of byte 11 is unset/set
- The clock is undefined (being updated) if bit 7 of byte 10 is set.
- The clock is frozen (to be updated) by setting bit 7 of byte 11
- Bit 7 of byte 14 indicates whether the CMOS clock is reliable:
- it is 1 if RTC power has been good since this bit was last read;
- it is 0 when the battery is dead and system power has been off.
-
- The century situation is messy:
-
- Usually byte 50 (0x32) gives the century (in BCD, so 0x19 or 0x20 in
- pure binary), but IBM PS/2 has (part of) a checksum there and uses
- byte 55 (0x37). Sometimes byte 127 (0x7f) or Bank 1, byte 0x48
- gives the century. The original RTC will not access any century
- byte; some modern versions will. If a modern RTC or BIOS increments
- the century byte it may go from 0x19 to 0x20, but in some buggy
- cases 0x1a is produced.
-
- CMOS byte 10 (clock status register A) has 3 bitfields:
- bit 7: 1 if data invalid, update in progress (read-only bit)
- (this is raised 224 us before the actual update starts)
- 6-4 select base frequency
- 010: 32768 Hz time base (default)
- 111: reset
- all other combinations are manufacturer-dependent
- (e.g.: DS1287: 010 = start oscillator, anything else = stop)
- 3-0 rate selection bits for interrupt
- 0000 none
- 0001, 0010 give same frequency as 1000, 1001
- 0011 122 microseconds (minimum, 8192 Hz)
- .... each increase by 1 halves the frequency, doubles the period
- 1111 500 milliseconds (maximum, 2 Hz)
- 0110 976.562 microseconds (default 1024 Hz)
-
- Avoid setting the RTC clock within 2 seconds of the day rollover
- that starts a new month or enters daylight saving time.
-
-****************************************************************************/
-
-#include <stdio.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-
-#if defined(__i386__) || defined(__alpha__)
-#include <asm/io.h> /* for inb, outb */
-#else
-void outb(int a, int b){}
-int inb(int c){ return 0; }
-#endif
-
-#include "hwclock.h"
-
-#define BCD_TO_BIN(val) (((val)&0x0f) + ((val)>>4)*10)
-#define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10)
-
-
-/*----------------------------------------------------------------------------
- ATOMIC_TOP and ATOMIC_BOTTOM are wierd macros that help us to do
- atomic operations when we do ugly low level I/O.
-
- You put ATOMIC_TOP above some code and ATOMIC_BOTTOM below it and
- it makes sure all the enclosed code executes without interruption
- by some other process (and, in some cases, even the kernel).
-
- These work fundamentally differently depending on the machine
- architecture. In the case of a x86, it simply turns interrupts off
- at the top and turns them back on at the bottom.
-
- For Alpha, we can't mess with interrupts (we shouldn't for x86
- either, but at least it tends to work!), so instead we start a loop
- at the top and close it at the bottom. This loop repeats the
- enclosed code until the upper 32 bits of the cycle counter are the
- same before and after. That means there was no context change
- while the enclosed code was executing.
-
- For other architectures, we do nothing, and the atomicity is only
- feigned.
-
------------------------------------------------------------------------------*/
-
-#if defined(__i386__)
-#define ATOMIC_TOP \
- { \
- const bool interrupts_were_enabled = interrupts_enabled; \
- __asm__ volatile ("cli"); \
- interrupts_enabled = FALSE;
-
-#define ATOMIC_BOTTOM \
- if (interrupts_were_enabled) { \
- __asm__ volatile ("sti"); \
- interrupts_enabled = TRUE; \
- } \
- }
-#elif defined(__alpha__)
-#define ATOMIC_TOP \
- { \
- unsigned long ts1, ts2, n; \
- n = 0; \
- do { \
- asm volatile ("rpcc %0" : "r="(ts1));
-
-#define ATOMIC_BOTTOM \
- asm volatile ("rpcc %0" : "r="(ts2)); \
- n++; \
- } while ((ts1 ^ ts2) >> 32 != 0); \
- }
-#else
-#define ATOMIC_BOTTOM
-#define ATOMIC_TOP
-#endif
-
-
-#if defined(__i386__) || defined(__alpha__)
-/* The following are just constants. Oddly, this program will not
- compile if the inb() and outb() functions use something even
- slightly different from these variables. This is probably at least
- partially related to the fact that __builtin_constant_p() doesn't
- work (is never true) in an inline function. See comment to this
- effect in asm/io.h.
-*/
-static unsigned short clock_ctl_addr = 0x70;
-static unsigned short clock_data_addr = 0x71;
-#endif
-
-
-static bool interrupts_enabled;
- /* Interrupts are enabled as normal. We, unfortunately, turn interrupts
- on the machine off in some places where we do the direct ISA accesses
- to the Hardware Clock. It is in extremely poor form for a user space
- program to do this, but that's the price we have to pay to run on an
- ISA machine without the rtc driver in the kernel.
-
- Code which turns interrupts off uses this value to determine if they
- need to be turned back on.
- */
-
-
-void
-assume_interrupts_enabled(void) {
- interrupts_enabled = TRUE;
-}
-
-
-
-static int
-i386_iopl(const int level) {
-/*----------------------------------------------------------------------------
- When compiled for an Intel target, this is just the iopl() kernel call.
- When compiled for any other target, this is a dummy function.
-
- We do it this way in order to keep the conditional compilation stuff
- out of the way so it doesn't mess up readability of the code.
------------------------------------------------------------------------------*/
-#ifdef __i386__
- extern int iopl(int level);
- return iopl(level);
-#else
- return -1;
-#endif
-}
-
-
-
-bool
-uf_bit_needed(const bool user_wants_uf) {
-/*----------------------------------------------------------------------------
- Return true iff the UIP bit doesn't work on this hardware clock, so
- we will need to use the UF bit to synchronize with the clock (if in
- fact we synchronize using direct I/O to the clock).
-
- To wit, we need to use the UF bit on a DEC Alpha PC164/LX164/SX164.
- Or, of course, if the user told us to.
------------------------------------------------------------------------------*/
- bool retval;
-
- if (user_wants_uf) retval = TRUE;
- else {
- if (alpha_machine && (
- is_in_cpuinfo("system variation", "PC164") ||
- is_in_cpuinfo("system variation", "LX164") ||
- is_in_cpuinfo("system variation", "SX164")))
- retval = TRUE;
- else retval = FALSE;
- }
- if (debug && retval)
- printf("We will be using the UF bit instead of the usual "
- "UIP bit to synchronize with the clock, as required on "
- "certain models of DEC Alpha.\n");
-
- return retval;
-}
-
-
-
-int
-zero_year(const bool arc_opt, const bool srm_opt) {
-/*----------------------------------------------------------------------------
- Return the year of the century (e.g. 0) to which a zero value in
- the year register of the hardware clock applies (or at least what
- we are to assume -- nobody can say for sure!)
-
- 'arc_opt' and 'srm_opt' are the true iff the user specified the
- corresponding invocation option to instruct us that the machine is an
- Alpha with ARC or SRM console time.
-
- A note about hardware clocks:
-
- ISA machines are simple: the year register is a year-of-century
- register, so the zero year is zero. On Alphas, we may see 1980 or
- 1952 (Digital Unix?) or 1958 (ALPHA_PRE_V1_2_SRM_CONSOLE)
------------------------------------------------------------------------------*/
- int retval; /* our return value */
-
- if (arc_opt || srm_opt) {
- /* User is telling us what epoch his machine uses. Believe it. */
- if (arc_opt) retval = 0;
- else retval = 0;
- } else {
- unsigned long kernel_epoch;
- char *reason; /* malloc'ed */
-
- get_epoch(&kernel_epoch, &reason);
- if (reason == NULL) retval = kernel_epoch;
- else {
- /* OK, the user doesn't know and the kernel doesn't know;
- figure it out from the machine model
- */
- free(reason); /* Don't care about kernel's excuses */
- /* See whether we are dealing with SRM or MILO, as they have
- different "epoch" ideas. */
- if (is_in_cpuinfo("system serial number", "MILO")) {
- if (debug) printf("booted from MILO\n");
- /* See whether we are dealing with a RUFFIAN aka UX, as they
- have REALLY different TOY (TimeOfYear) format: BCD, and not
- an ARC-style epoch. BCD is detected dynamically, but we
- must NOT adjust like ARC.
- */
- if (is_in_cpuinfo("system type", "Ruffian")) {
- if (debug) printf("Ruffian BCD clock\n");
- retval = 0;
- } else {
- if (debug) printf("Not Ruffian BCD clock\n");
- retval = 80;
- }
- } else {
- if (debug) printf("Not booted from MILO\n");
- retval = 0;
- }
- }
- }
- return retval;
-}
-
-
-
-static inline unsigned char
-hclock_read(const unsigned char reg, const int dev_port) {
-/*---------------------------------------------------------------------------
- Relative byte 'reg' of the Hardware Clock value.
-
- Get this with direct CPU I/O instructions. If 'dev_port' is not -1,
- use the /dev/port device driver (via the 'dev_port' file descriptor)
- to do this I/O. Otherwise, use the kernel's inb()/outb() facility.
-
- On a system without the inb()/outb() facility, if 'dev_port' is -1,
- just return 0.
-
- Results undefined if 'reg' is out of range.
----------------------------------------------------------------------------*/
- unsigned char ret;
-
- ATOMIC_TOP
- if (dev_port >= 0) {
- const unsigned char v = reg | 0x80;
- lseek(dev_port, 0x170, 0);
- write(dev_port, &v, 1);
- lseek(dev_port, 0x171, 0);
- read(dev_port, &ret, 1);
- } else {
-#if defined(__i386__) || defined(__alpha__)
- /* & 0x7f ensures that we are not disabling NMI while we read.
- Setting on Bit 7 here would disable NMI
-
- Various docs suggest that one should disable NMI while
- reading/writing CMOS data, and enable it again afterwards.
- This would yield the sequence
- outb (reg | 0x80, 0x70);
- val = inb(0x71);
- outb (0x0d, 0x70); // 0x0d: random read-only location
- Other docs state that "any write to 0x70 should be followed
- by an action to 0x71 or the RTC wil be left in an unknown state".
- Most docs say that it doesn't matter at all what one does.
- */
- outb(reg & 0x7f, clock_ctl_addr);
- ret = inb(clock_data_addr);
-#else
- ret = 0;
-#endif
- }
- ATOMIC_BOTTOM
- return ret;
-}
-
-
-
-static inline void
-hclock_write(unsigned char reg, unsigned char val, const int dev_port) {
-/*----------------------------------------------------------------------------
- Set relative byte 'reg' of the Hardware Clock value to 'val'.
- Do this with the kernel's outb() function if 'dev_port' is -1, but
- if not, use the /dev/port device (via the 'dev_port' file descriptor),
- which is almost the same thing.
-
- On a non-ISA, non-Alpha machine, if 'dev_port' is -1, do nothing.
-----------------------------------------------------------------------------*/
- if (dev_port >= 0) {
- unsigned char v;
- v = reg | 0x80;
- lseek(dev_port, 0x170, 0);
- write(dev_port, &v, 1);
- v = (val & 0xff);
- lseek(dev_port, 0x171, 0);
- write(dev_port, &v, 1);
- } else {
-#if defined(__i386__) || defined(__alpha__)
- /* & 0x7f ensures that we are not disabling NMI while we read.
- Setting on Bit 7 here would disable NMI
- */
- outb(reg & 0x7f, clock_ctl_addr);
- outb(val, clock_data_addr);
-#endif
- }
-}
-
-
-
-static inline int
-hardware_clock_busy(const int dev_port, const bool use_uf_bit) {
-/*----------------------------------------------------------------------------
- Return whether the hardware clock is in the middle of an update
- (which happens once each second).
-
- Use the clock's UIP bit (bit 7 of Control Register A) to tell
- unless 'use_uf_bit' is true, in which case use the UF bit (bit 4 of
- Control Register C).
------------------------------------------------------------------------------*/
- return
- use_uf_bit ? (hclock_read(12, dev_port) & 0x10) :
- (hclock_read(10, dev_port) & 0x80);
-}
-
-
-
-void
-synchronize_to_clock_tick_ISA(int *retcode_p, const int dev_port,
- const bool use_uf_bit) {
-/*----------------------------------------------------------------------------
- Same as synchronize_to_clock_tick(), but just for ISA.
------------------------------------------------------------------------------*/
- int i; /* local loop index */
-
- /* Wait for rise. Should be within a second, but in case something
- weird happens, we have a limit on this loop to reduce the impact
- of this failure.
- */
- for (i = 0;
- !hardware_clock_busy(dev_port, use_uf_bit) && (i < 10000000);
- i++);
- if (i >= 10000000) *retcode_p = 1;
- else {
- /* Wait for fall. Should be within 2.228 ms. */
- for (i = 0;
- hardware_clock_busy(dev_port, use_uf_bit) && (i < 1000000);
- i++);
- if (i >= 10000000) *retcode_p = 1;
- else *retcode_p = 0;
- }
-}
-
-
-
-void
-read_hardware_clock_isa(struct tm *tm, const int dev_port,
- int hc_zero_year) {
-/*----------------------------------------------------------------------------
- Read the hardware clock and return the current time via <tm> argument.
- Assume we have an ISA machine and read the clock directly with CPU I/O
- instructions. If 'dev_port' isn't -1, use the /dev/port facility to
- do this I/O. Otherwise, use the kernel's inb()/outb() service.
-
- This function is not totally reliable. It takes a finite and
- unpredictable amount of time to execute the code below. During that
- time, the clock may change and we may even read an invalid value in
- the middle of an update. We do a few checks to minimize this
- possibility, but only the kernel can actually read the clock
- properly, since it can execute code in a short and predictable
- amount of time (by turning off interrupts).
-
- In practice, the chance of this function returning the wrong time is
- extremely remote.
-
------------------------------------------------------------------------------*/
- bool got_time;
- /* We've successfully read a time from the Hardware Clock */
- int attempts;
- /* Number of times we've tried to read the clock. This only
- matters because we will give up (and proceed with garbage in
- variables) rather than hang if something is broken and we are
- never able to read the clock
- */
- int hclock_sec = 0, hclock_min = 0, hclock_hour = 0, hclock_wday = 0,
- hclock_mon = 0, hclock_mday = 0, hclock_year = 0;
- /* The values we got from the Hardware Clock's registers, assuming
- they are in pure binary.
- */
-
- int status = 0; /* Hardware Clock status register, as if pure binary */
- int adjusted_year;
- int ampmhour;
- int pmbit;
-
- got_time = FALSE;
- attempts = 0; /* initial value */
- while (!got_time && attempts++ < 1000000) {
- /* Bit 7 of Byte 10 of the Hardware Clock value is the Update In Progress
- (UIP) bit, which is on while and 244 uS before the Hardware Clock
- updates itself. It updates the counters individually, so reading
- them during an update would produce garbage. The update takes 2mS,
- so we could be spinning here that long waiting for this bit to turn
- off.
-
- Furthermore, it is pathologically possible for us to be in this
- code so long that even if the UIP bit is not on at first, the
- clock has changed while we were running. We check for that too,
- and if it happens, we start over.
- */
-
- if ((hclock_read(10, dev_port) & 0x80) == 0) {
- /* No clock update in progress, go ahead and read */
-
- status = hclock_read(11, dev_port);
-
- hclock_sec = hclock_read(0, dev_port);
- hclock_min = hclock_read(2, dev_port);
- hclock_hour = hclock_read(4, dev_port);
- hclock_wday = hclock_read(6, dev_port);
- hclock_mday = hclock_read(7, dev_port);
- hclock_mon = hclock_read(8, dev_port);
- hclock_year = hclock_read(9, dev_port);
- /* Unless the clock changed while we were reading, consider this
- a good clock read .
- */
- if (hclock_sec == hclock_read(0, dev_port)) got_time = TRUE;
- /* Yes, in theory we could have been running for 60 seconds and
- the above test wouldn't work!
- */
- }
- }
-
- if (!(status & 0x04)) {
- /* The hardware clock is in BCD mode. This is normal. */
- tm->tm_sec = BCD_TO_BIN(hclock_sec);
- tm->tm_min = BCD_TO_BIN(hclock_min);
- ampmhour = BCD_TO_BIN(hclock_hour & 0x7f);
- pmbit = hclock_hour & 0x80;
- tm->tm_wday = BCD_TO_BIN(hclock_wday) - 1; /* Used to be 3. Why?? */
- tm->tm_mday = BCD_TO_BIN(hclock_mday);
- tm->tm_mon = BCD_TO_BIN(hclock_mon) - 1;
- adjusted_year = BCD_TO_BIN(hclock_year);
- } else {
- /* The hardware clock registers are in pure binary format. */
- tm->tm_sec = hclock_sec;
- tm->tm_min = hclock_min;
- ampmhour = hclock_hour & 0x7f;
- pmbit = hclock_hour & 0x80;
- tm->tm_wday = hclock_wday - 1; /* Used to be 3. Why?? */
- tm->tm_mday = hclock_mday;
- tm->tm_mon = hclock_mon - 1;
- adjusted_year = hclock_year;
- }
-
- if (!(status & 0x02)) {
- /* Clock is in 12 hour (am/pm) mode. This is unusual. */
- if (pmbit == 0x80) {
- if (ampmhour == 12) tm->tm_hour = 12;
- else tm->tm_hour = 12 + ampmhour;
- } else {
- if (ampmhour ==12) tm->tm_hour = 0;
- else tm->tm_hour = ampmhour;
- }
- } else {
- /* Clock is in 24 hour mode. This is normal. */
- tm->tm_hour = ampmhour;
- }
- /* We don't use the century byte (Byte 50) of the Hardware Clock.
- Here's why: It didn't exist in the original ISA specification,
- so old machines don't have it, and even some new ones don't.
- Some machines, including the IBM Valuepoint 6387-X93, use that
- byte for something else. Some machines have the century in
- Byte 55.
-
- Furthermore, the Linux standard time data structure doesn't
- allow for times beyond about 2037 and no Linux systems were
- running before 1937. Therefore, all the century byte could tell
- us is that the clock is wrong or this whole program is obsolete!
-
- So we just say if the year of century is less than 37, it's the
- 2000's, otherwise it's the 1900's.
-
- Alpha machines (some, anyway) don't have this ambiguity
- because they do not have a year-of-century register. We
- pretend they do anyway, for simplicity and to avoid
- recognizing times that can't be represented in Linux standard
- time. So even though we already have enough information to
- know that the clock says 2050, we will render it as 1950.
- */
- {
- const int year_of_century = (adjusted_year + hc_zero_year) % 100;
- if (year_of_century >= 37) tm->tm_year = year_of_century;
- else tm->tm_year = year_of_century + 100;
- }
- tm->tm_isdst = -1; /* don't know whether it's daylight */
-}
-
-
-
-void
-set_hardware_clock_isa(const struct tm new_tm,
- const int hc_zero_year,
- const int dev_port,
- const bool testing) {
-/*----------------------------------------------------------------------------
- Set the Hardware Clock to the time (in broken down format)
- new_tm. Use direct I/O instructions to what we assume is
- an ISA Hardware Clock.
-
- Iff 'dev_port' is -1, use the kernel inb()/outb() service, otherwise
- use the /dev/port device (via file descriptor 'dev_port')
- to do those I/O instructions.
-----------------------------------------------------------------------------*/
- unsigned char save_control, save_freq_select;
-
- if (testing)
- printf("Not setting Hardware Clock because running in test mode.\n");
- else {
- int ampmhour;
- /* The hour number that goes into the hardware clock, taking into
- consideration whether the clock is in 12 or 24 hour mode
- */
- int pmbit;
- /* Value to OR into the hour register as the am/pm bit */
- const int adjusted_year =
- (new_tm.tm_year - hc_zero_year)%100;
- /* The number that goes in the hardware clock's year register */
-
- int hclock_sec, hclock_min, hclock_hour, hclock_wday, hclock_mon,
- hclock_mday, hclock_year;
- /* The values we will put, in pure binary, in the Hardware Clock's
- registers.
- */
-
- ATOMIC_TOP
-
- save_control = hclock_read(11, dev_port);
- /* tell the clock it's being set */
- hclock_write(11, (save_control | 0x80), dev_port);
- save_freq_select = hclock_read(10, dev_port);
- /* stop and reset prescaler */
- hclock_write (10, (save_freq_select | 0x70), dev_port);
-
-
- if (!(save_control & 0x02)) {
- /* Clock is in 12 hour (am/pm) mode. This is unusual. */
- if (new_tm.tm_hour == 0) {
- ampmhour = 12;
- pmbit = 0x00;
- } else if (new_tm.tm_hour < 12) {
- ampmhour = new_tm.tm_hour;
- pmbit = 0x00;
- } else if (new_tm.tm_hour == 12) {
- ampmhour = 12;
- pmbit = 0x80;
- } else {
- ampmhour = new_tm.tm_hour - 12;
- pmbit = 0x80;
- }
- } else {
- /* Clock is in 24 hour mode. This is normal. */
- ampmhour = new_tm.tm_hour;
- pmbit = 0x00;
- }
-
-
- if (!(save_control & 0x04)) {
- /* Clock's registers are in BCD. This is normal. */
- hclock_sec = BIN_TO_BCD(new_tm.tm_sec);
- hclock_min = BIN_TO_BCD(new_tm.tm_min);
- hclock_hour = pmbit | BIN_TO_BCD(ampmhour);
- hclock_wday = BIN_TO_BCD(new_tm.tm_wday + 1); /* Used to be 3. Why??*/
- hclock_mday = BIN_TO_BCD(new_tm.tm_mday);
- hclock_mon = BIN_TO_BCD(new_tm.tm_mon + 1);
- hclock_year = BIN_TO_BCD(adjusted_year);
- } else {
- /* Clock's registers are in pure binary. This is unusual. */
- hclock_sec = new_tm.tm_sec;
- hclock_min = new_tm.tm_min;
- hclock_hour = pmbit | ampmhour;
- hclock_wday = new_tm.tm_wday + 1; /* Used to be 3. Why?? */
- hclock_mday = new_tm.tm_mday;
- hclock_mon = new_tm.tm_mon + 1;
- hclock_year = adjusted_year;
- }
-
- hclock_write(0, hclock_sec, dev_port);
- hclock_write(2, hclock_min, dev_port);
- hclock_write(4, hclock_hour, dev_port);
- hclock_write(6, hclock_wday, dev_port);
- hclock_write(7, hclock_mday, dev_port);
- hclock_write(8, hclock_mon, dev_port);
- hclock_write(9, hclock_year, dev_port);
-
- /* We don't set the century byte (usually Byte 50) because it isn't
- always there. (see further comments in read_hardware_clock_isa).
- In previous releases, we did.
- */
-
- /* The kernel sources, linux/arch/i386/kernel/time.c, have the
- following comment:
-
- The following flags have to be released exactly in this order,
- otherwise the DS12887 (popular MC146818A clone with integrated
- battery and quartz) will not reset the oscillator and will not
- update precisely 500 ms later. You won't find this mentioned
- in the Dallas Semiconductor data sheets, but who believes data
- sheets anyway ... -- Markus Kuhn
-
- Hence, they will also be done in this order here.
- faith@cs.unc.edu, Thu Nov 9 08:26:37 1995
- */
-
- hclock_write (11, save_control, dev_port);
- hclock_write (10, save_freq_select, dev_port);
-
- ATOMIC_BOTTOM
- }
-}
-
-
-
-void
-get_inb_outb_privilege(const enum clock_access_method clock_access,
- bool * const no_auth_p) {
-
- if (clock_access == ISA) {
- const int rc = i386_iopl(3);
- if (rc != 0) {
- fprintf(stderr, MYNAME " is unable to get I/O port access. "
- "I.e. iopl(3) returned nonzero return code %d.\n"
- "This is often because the program isn't running "
- "with superuser privilege, which it needs.\n",
- rc);
- *no_auth_p = TRUE;
- } else *no_auth_p = FALSE;
- } else *no_auth_p = FALSE;
-}
-
-
-
-void
-get_dev_port_access(const enum clock_access_method clock_access,
- int * dev_port_p) {
-
- if (clock_access == DEV_PORT) {
- /* Get the /dev/port file open */
- *dev_port_p = open("/dev/port", O_RDWR);
- if (*dev_port_p < 0) {
- fprintf(stderr, MYNAME "is unable to open the /dev/port file. "
- "I.e. open() of the file failed with errno = %s (%d).\n"
- "Run with the --debug option and check documentation "
- "to find out why we are trying "
- "to use /dev/port instead of some other means to access "
- "the Hardware Clock.",
- strerror(errno), errno);
- }
- } else *dev_port_p = 0;
-}
-
-
-