summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/i386/pc386/clock
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>1997-12-01 22:06:48 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>1997-12-01 22:06:48 +0000
commit7150f00f5be87fa8e37f7d00fbbef35645081138 (patch)
tree1cc7d3e1c4933404ddc1f742c7e37648cc783364 /c/src/lib/libbsp/i386/pc386/clock
parentFixed test for RTEMS_HAS_POSIX_API so the executive POSIX API related (diff)
downloadrtems-7150f00f5be87fa8e37f7d00fbbef35645081138.tar.bz2
Inclusion of PC386 BSP submitted by Pedro Miguel Da Cruz Neto Romano
<pmcnr@camoes.rnl.ist.utl.pt> and Jose Rufino <ruf@asterix.ist.utl.pt> of NavIST (http://pandora.ist.utl.pt/).
Diffstat (limited to 'c/src/lib/libbsp/i386/pc386/clock')
-rw-r--r--c/src/lib/libbsp/i386/pc386/clock/Makefile.in54
-rw-r--r--c/src/lib/libbsp/i386/pc386/clock/ckinit.c285
-rw-r--r--c/src/lib/libbsp/i386/pc386/clock/rtc.c224
3 files changed, 563 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/i386/pc386/clock/Makefile.in b/c/src/lib/libbsp/i386/pc386/clock/Makefile.in
new file mode 100644
index 0000000000..6444b837e1
--- /dev/null
+++ b/c/src/lib/libbsp/i386/pc386/clock/Makefile.in
@@ -0,0 +1,54 @@
+#
+# $Id$
+#
+
+@SET_MAKE@
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH=@srcdir@
+
+PGM=${ARCH}/clock.rel
+
+# C source names, if any, go here -- minus the .c
+C_PIECES=ckinit rtc
+C_FILES=$(C_PIECES:%=%.c)
+C_O_FILES=$(C_PIECES:%=${ARCH}/%.o)
+
+H_FILES=
+
+SRCS=$(C_FILES) $(H_FILES)
+OBJS=$(C_O_FILES)
+
+include $(RTEMS_CUSTOM)
+include $(PROJECT_ROOT)/make/leaf.cfg
+
+
+#
+# (OPTIONAL) Add local stuff here using +=
+#
+
+DEFINES +=
+CPPFLAGS +=
+CFLAGS +=
+
+LD_PATHS +=
+LD_LIBS +=
+LDFLAGS +=
+
+#
+# Add your list of files to delete here. The config files
+# already know how to delete some stuff, so you may want
+# to just run 'make clean' first to see what gets missed.
+# 'make clobber' already includes 'make clean'
+#
+
+CLEAN_ADDITIONS +=
+CLOBBER_ADDITIONS +=
+
+${PGM}: ${SRCS} ${OBJS}
+ $(make-rel)
+
+all: ${ARCH} $(SRCS) $(PGM)
+
+# the .rel file built here will be put into libbsp.a by ../wrapup/Makefile
+install: all
diff --git a/c/src/lib/libbsp/i386/pc386/clock/ckinit.c b/c/src/lib/libbsp/i386/pc386/clock/ckinit.c
new file mode 100644
index 0000000000..e02510c70e
--- /dev/null
+++ b/c/src/lib/libbsp/i386/pc386/clock/ckinit.c
@@ -0,0 +1,285 @@
+/*-------------------------------------------------------------------------+
+| ckinit.c v1.1 - PC386 BSP - 1997/08/07
++--------------------------------------------------------------------------+
+| This file contains the PC386 clock package.
++--------------------------------------------------------------------------+
+| (C) Copyright 1997 -
+| - NavIST Group - Real-Time Distributed Systems and Industrial Automation
+|
+| http://pandora.ist.utl.pt
+|
+| Instituto Superior Tecnico * Lisboa * PORTUGAL
++--------------------------------------------------------------------------+
+| Disclaimer:
+|
+| This file is provided "AS IS" without warranty of any kind, either
+| expressed or implied.
++--------------------------------------------------------------------------+
+| This code is based on:
+| ckinit.c,v 1.4 1995/12/19 20:07:13 joel Exp - go32 BSP
+| With the following copyright notice:
+| **************************************************************************
+| * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. *
+| * On-Line Applications Research Corporation (OAR). *
+| * All rights assigned to U.S. Government, 1994. *
+| * *
+| * This material may be reproduced by or for the U.S. Government pursuant *
+| * to the copyright license under the clause at DFARS 252.227-7013. This *
+| * notice must appear in all copies of this file and its derivatives. *
+| **************************************************************************
++--------------------------------------------------------------------------*/
+
+
+#include <stdlib.h>
+
+#include <bsp.h>
+#include <irq.h>
+#include <rtems/libio.h>
+
+/*-------------------------------------------------------------------------+
+| Constants
++--------------------------------------------------------------------------*/
+#define CLOCK_IRQ 0x00 /* Clock IRQ. */
+
+/*-------------------------------------------------------------------------+
+| Macros
++--------------------------------------------------------------------------*/
+#if 0
+/* This was dropped in the last revision. Its a nice thing to know. */
+#define TICKS_PER_SECOND() \
+ (1000000 / (Clock_isrs_per_tick * microseconds_per_isr))
+#endif /* 0 */
+
+/*-------------------------------------------------------------------------+
+| Global Variables
++--------------------------------------------------------------------------*/
+
+volatile rtems_unsigned32 Clock_driver_ticks; /* Tick (interrupt) counter. */
+ rtems_unsigned32 Clock_isrs_per_tick; /* ISRs per tick. */
+ rtems_unsigned32 Clock_isrs; /* ISRs until next tick. */
+
+/* The following variables are set by the clock driver during its init */
+
+rtems_device_major_number rtems_clock_major = ~0;
+rtems_device_minor_number rtems_clock_minor;
+
+/*-------------------------------------------------------------------------+
+| Function: clockIsr
+| Description: Interrupt Service Routine for clock (08h) interruption.
+| Global Variables: Clock_driver_ticks, Clock_isrs.
+| Arguments: vector - standard RTEMS argument - see documentation.
+| Returns: standard return value - see documentation.
++--------------------------------------------------------------------------*/
+static rtems_isr
+clockIsr(rtems_vector_number vector)
+{
+ /*-------------------------------------------------------------------------+
+ | PLEASE NOTE: The following is directly transcribed from the go32 BSP for
+ | those who wish to use it with PENTIUM based machine. It needs
+ | to be correctly integrated with the rest of the code!!!
+ +--------------------------------------------------------------------------*/
+
+#if 0 && defined(pentium) /* more accurate clock for PENTIUMs (not supported) */
+ {
+ extern long long Last_RDTSC;
+ __asm __volatile(".byte 0x0F, 0x31" : "=A" (Last_RDTSC));
+ }
+#endif /* 0 && pentium */
+
+ Clock_driver_ticks++;
+
+ if ( Clock_isrs == 1 )
+ {
+ rtems_clock_tick();
+ Clock_isrs = Clock_isrs_per_tick;
+ }
+ else
+ Clock_isrs--;
+
+ PC386_ackIrq(vector - PC386_IRQ_VECTOR_BASE);
+} /* clockIsr */
+
+
+/*-------------------------------------------------------------------------+
+| Function: Clock_exit
+| Description: Clock cleanup routine at RTEMS exit. NOTE: This routine is
+| not really necessary, since there will be a reset at exit.
+| Global Variables: None.
+| Arguments: None.
+| Returns: Nothing.
++--------------------------------------------------------------------------*/
+void Clock_exit(void)
+{
+ if (BSP_Configuration.ticks_per_timeslice)
+ {
+ /* reset timer mode to standard (BIOS) value */
+ outport_byte(TIMER_MODE, TIMER_SEL0 | TIMER_16BIT | TIMER_RATEGEN);
+ outport_byte(TIMER_CNTR0, 0);
+ outport_byte(TIMER_CNTR0, 0);
+ }
+} /* Clock_exit */
+
+
+/*-------------------------------------------------------------------------+
+| Function: Install_clock
+| Description: Initialize and install clock interrupt handler.
+| Global Variables: None.
+| Arguments: None.
+| Returns: Nothing.
++--------------------------------------------------------------------------*/
+void
+Install_clock(rtems_isr_entry isr)
+{
+ rtems_unsigned32 microseconds_per_isr;
+
+ rtems_status_code status;
+
+#if 0
+ /* Initialize clock from on-board real time clock. This breaks the */
+ /* test code which assumes which assumes the application will do it. */
+ {
+ rtems_time_of_day now;
+
+ /* External Prototypes */
+ extern void init_rtc(void); /* defined in 'rtc.c' */
+ extern long rtc_read(rtems_time_of_day *); /* defined in 'rtc.c' */
+
+ init_rtc();
+ if (rtc_read(&now) >= 0)
+ clock_set(&now);
+ }
+#endif /* 0 */
+
+ /* Start by assuming hardware counter is large enough, then scale it until
+ it actually fits. */
+
+ Clock_driver_ticks = 0;
+ Clock_isrs_per_tick = 1;
+
+ if (BSP_Configuration.microseconds_per_tick == 0)
+ microseconds_per_isr = 10000; /* default 10 ms */
+ else
+ microseconds_per_isr = BSP_Configuration.microseconds_per_tick;
+ while (US_TO_TICK(microseconds_per_isr) > 65535)
+ {
+ Clock_isrs_per_tick *= 10;
+ microseconds_per_isr /= 10;
+ }
+
+ Clock_isrs = Clock_isrs_per_tick; /* Initialize Clock_isrs */
+
+ if (BSP_Configuration.ticks_per_timeslice)
+ {
+ /* 105/88 approximates TIMER_TICK * 1e-6 */
+ rtems_unsigned32 count = US_TO_TICK(microseconds_per_isr);
+
+ status = PC386_installRtemsIrqHandler(CLOCK_IRQ, isr);
+
+ if (status != RTEMS_SUCCESSFUL)
+ {
+ printk("Error installing clock interrupt handler!\n");
+ rtems_fatal_error_occurred(status);
+ }
+
+ outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
+ outport_byte(TIMER_CNTR0, count >> 0 & 0xff);
+ outport_byte(TIMER_CNTR0, count >> 8 & 0xff);
+ }
+
+ atexit(Clock_exit);
+} /* Install_clock */
+
+
+/*-------------------------------------------------------------------------+
+| Clock device driver INITIALIZE entry point.
++--------------------------------------------------------------------------+
+| Initilizes the clock driver.
++--------------------------------------------------------------------------*/
+rtems_device_driver
+Clock_initialize(rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *pargp)
+{
+ Install_clock(clockIsr); /* Install the interrupt handler */
+
+ /* make major/minor avail to others such as shared memory driver */
+
+ rtems_clock_major = major;
+ rtems_clock_minor = minor;
+
+ return RTEMS_SUCCESSFUL;
+} /* Clock_initialize */
+
+
+/*-------------------------------------------------------------------------+
+| Console device driver CONTROL entry point
++--------------------------------------------------------------------------*/
+rtems_device_driver
+Clock_control(rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *pargp)
+{
+ if (pargp != NULL)
+ {
+ rtems_libio_ioctl_args_t *args = pargp;
+
+ /*-------------------------------------------------------------------------+
+ | This is hokey, but until we get a defined interface to do this, it will
+ | just be this simple...
+ +-------------------------------------------------------------------------*/
+
+ if (args->command == rtems_build_name('I', 'S', 'R', ' '))
+ clockIsr(PC386_IRQ_VECTOR_BASE + CLOCK_IRQ);
+ else if (args->command == rtems_build_name('N', 'E', 'W', ' '))
+ {
+ rtems_status_code status;
+
+ status = PC386_installRtemsIrqHandler(CLOCK_IRQ, clockIsr);
+
+ if (status != RTEMS_SUCCESSFUL)
+ {
+ printk("Error installing clock interrupt handler!\n");
+ rtems_fatal_error_occurred(status);
+ }
+ }
+ }
+
+ return RTEMS_SUCCESSFUL;
+} /* Clock_control */
+
+
+/*-------------------------------------------------------------------------+
+| PLEASE NOTE: The following is directly transcribed from the go32 BSP for
+| those who wish to use it with PENTIUM based machine. It needs
+| to be correctly integrated with the rest of the code!!!
++--------------------------------------------------------------------------*/
+
+
+#if 0 && defined(pentium)
+
+/* This can be used to get extremely accurate timing on a pentium. */
+/* It isn't supported. [bryce] */
+
+#define HZ 90.0
+
+volatile long long Last_RDTSC;
+
+#define RDTSC()\
+ ({ long long _now; __asm __volatile (".byte 0x0F,0x31":"=A"(_now)); _now; })
+
+long long Kernel_Time_ns( void )
+{
+ extern rtems_unsigned32 _TOD_Ticks_per_second;
+
+ unsigned isrs_per_second = Clock_isrs_per_tick * _TOD_Ticks_per_second;
+ long long now;
+ int flags;
+
+ disable_intr(flags);
+ now = 1e9 * Clock_driver_ticks / isrs_per_second +
+ (RDTSC() - Last_RDTSC) * (1000.0/HZ);
+ enable_intr(flags);
+ return now;
+} /* Kernel_Time_ns */
+
+#endif /* 0 && pentium */
diff --git a/c/src/lib/libbsp/i386/pc386/clock/rtc.c b/c/src/lib/libbsp/i386/pc386/clock/rtc.c
new file mode 100644
index 0000000000..076e06c7e5
--- /dev/null
+++ b/c/src/lib/libbsp/i386/pc386/clock/rtc.c
@@ -0,0 +1,224 @@
+/*-------------------------------------------------------------------------+
+| rtc.c v1.1 - PC386 BSP - 1997/08/07
++--------------------------------------------------------------------------+
+| This file contains the real time clock manipulation package for the
+| PC386 board.
++--------------------------------------------------------------------------+
+| (C) Copyright 1997 -
+| - NavIST Group - Real-Time Distributed Systems and Industrial Automation
+|
+| http://pandora.ist.utl.pt
+|
+| Instituto Superior Tecnico * Lisboa * PORTUGAL
++--------------------------------------------------------------------------+
+| Disclaimer:
+|
+| This file is provided "AS IS" without warranty of any kind, either
+| expressed or implied.
++--------------------------------------------------------------------------+
+| This code is based on:
+| rtc.c,v 1.4 1995/12/19 20:07:15 joel Exp - go32 BSP
+| With the following copyright notice:
+| **************************************************************************
+| * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. *
+| * On-Line Applications Research Corporation (OAR). *
+| * All rights assigned to U.S. Government, 1994. *
+| * *
+| * This material may be reproduced by or for the U.S. Government pursuant *
+| * to the copyright license under the clause at DFARS 252.227-7013. This *
+| * notice must appear in all copies of this file and its derivatives. *
+| **************************************************************************
++--------------------------------------------------------------------------*/
+
+
+#include <string.h>
+
+#include <bsp.h>
+
+/*-------------------------------------------------------------------------+
+| Constants
++--------------------------------------------------------------------------*/
+#define IO_RTC 0x70 /* RTC */
+
+#define RTC_SEC 0x00 /* seconds */
+#define RTC_SECALRM 0x01 /* seconds alarm */
+#define RTC_MIN 0x02 /* minutes */
+#define RTC_MINALRM 0x03 /* minutes alarm */
+#define RTC_HRS 0x04 /* hours */
+#define RTC_HRSALRM 0x05 /* hours alarm */
+#define RTC_WDAY 0x06 /* week day */
+#define RTC_DAY 0x07 /* day of month */
+#define RTC_MONTH 0x08 /* month of year */
+#define RTC_YEAR 0x09 /* month of year */
+#define RTC_STATUSA 0x0a /* status register A */
+#define RTCSA_TUP 0x80 /* time update, don't look now */
+
+#define RTC_STATUSB 0x0b /* status register B */
+
+#define RTC_INTR 0x0c /* status register C (R) interrupt source */
+#define RTCIR_UPDATE 0x10 /* update intr */
+#define RTCIR_ALARM 0x20 /* alarm intr */
+#define RTCIR_PERIOD 0x40 /* periodic intr */
+#define RTCIR_INT 0x80 /* interrupt output signal */
+
+#define RTC_STATUSD 0x0d /* status register D (R) Lost Power */
+#define RTCSD_PWR 0x80 /* clock lost power */
+
+#define RTC_DIAG 0x0e /* status register E - bios diagnostic */
+#define RTCDG_BITS "\020\010clock_battery\007ROM_cksum\006config_unit\005memory_size\004fixed_disk\003invalid_time"
+
+#define RTC_CENTURY 0x32 /* current century - increment in Dec99 */
+
+
+/*-------------------------------------------------------------------------+
+| Auxiliary Functions
++--------------------------------------------------------------------------*/
+/*-------------------------------------------------------------------------+
+| Function: bcd
+| Description: Convert 2 digit number to its BCD representation.
+| Global Variables: None.
+| Arguments: i - Number to convert.
+| Returns: BCD representation of number.
++--------------------------------------------------------------------------*/
+static inline rtems_unsigned8
+bcd(rtems_unsigned8 i)
+{
+ return ((i / 16) * 10 + (i % 16));
+} /* bcd */
+
+#define QUICK_READ /* Quick read of the RTC: don't return number of seconds. */
+
+#ifndef QUICK_READ
+
+#define SECS_PER_DAY (24 * 60 * 60)
+#define SECS_PER_REG_YEAR (365 * SECS_PER_DAY)
+
+/*-------------------------------------------------------------------------+
+| Function: ytos
+| Description: Convert years to seconds (since 1970).
+| Global Variables: None.
+| Arguments: y - year to convert (1970 <= y <= 2100).
+| Returns: number of seconds since 1970.
++--------------------------------------------------------------------------*/
+static inline rtems_unsigned32
+ytos(rtems_unsigned16 y)
+{ /* v NUM LEAP YEARS v */
+ return ((y - 1970) * SECS_PER_REG_YEAR + (y - 1970 + 1) / 4 * SECS_PER_DAY);
+} /* ytos */
+
+
+/*-------------------------------------------------------------------------+
+| Function: mtos
+| Description: Convert months to seconds since January.
+| Global Variables: None.
+| Arguments: m - month to convert, leap - is this a month of a leap year.
+| Returns: number of seconds since January.
++--------------------------------------------------------------------------*/
+static inline rtems_unsigned32
+mtos(rtems_unsigned8 m, rtems_boolean leap)
+{
+ static rtems_unsigned16 daysMonth[] = { 0, 0, 31, 59, 90, 120, 151, 181,
+ 212, 243, 273, 304, 334, 365 };
+ /* Days since beginning of year until beginning of month. */
+
+ return ((daysMonth[m] + (leap ? 1 : 0)) * SECS_PER_DAY);
+} /* mtos */
+
+#endif /* QUICK_READ */
+
+/*-------------------------------------------------------------------------+
+| Function: rtcin
+| Description: Perform action on RTC and return its result.
+| Global Variables: None.
+| Arguments: what - what to write to RTC port (what to do).
+| Returns: result received from RTC port after action performed.
++--------------------------------------------------------------------------*/
+static inline rtems_unsigned8
+rtcin(rtems_unsigned8 what)
+{
+ rtems_unsigned8 r;
+
+ outport_byte(IO_RTC, what);
+ inport_byte (IO_RTC+1, r);
+ return r;
+} /* rtcin */
+
+
+/*-------------------------------------------------------------------------+
+| Functions
++--------------------------------------------------------------------------*/
+/*-------------------------------------------------------------------------+
+| Function: init_rtc
+| Description: Initialize real-time clock (RTC).
+| Global Variables: None.
+| Arguments: None.
+| Returns: Nothing.
++--------------------------------------------------------------------------*/
+void
+init_rtc(void)
+{
+ rtems_unsigned8 s;
+
+ /* initialize brain-dead battery powered clock */
+ outport_byte(IO_RTC, RTC_STATUSA);
+ outport_byte(IO_RTC+1, 0x26);
+ outport_byte(IO_RTC, RTC_STATUSB);
+ outport_byte(IO_RTC+1, 2);
+
+ outport_byte(IO_RTC, RTC_DIAG);
+ inport_byte (IO_RTC+1, s);
+ if (s)
+ printk("RTC BIOS diagnostic error %b\n", s);
+
+ /* FIXME: This was last line's original version. How was it supposed to work?
+ printf("RTC BIOS diagnostic error %b\n", s, RTCDG_BITS); */
+} /* init_rtc */
+
+
+/*-------------------------------------------------------------------------+
+| Function: rtc_read
+| Description: Read present time from RTC and return it.
+| Global Variables: None.
+| Arguments: tod - to return present time in 'rtems_time_of_day' format.
+| Returns: number of seconds from 1970/01/01 corresponding to 'tod'.
++--------------------------------------------------------------------------*/
+long int
+rtc_read(rtems_time_of_day *tod)
+{
+ rtems_unsigned8 sa;
+ rtems_unsigned32 sec = 0;
+
+ memset(tod, 0, sizeof *tod); /* zero tod structure */
+
+ /* do we have a realtime clock present? (otherwise we loop below) */
+ sa = rtcin(RTC_STATUSA);
+ if (sa == 0xff || sa == 0)
+ return -1;
+
+ /* ready for a read? */
+ while ((sa&RTCSA_TUP) == RTCSA_TUP)
+ sa = rtcin(RTC_STATUSA);
+
+ tod->year = bcd(rtcin(RTC_YEAR)) + 1900; /* year */
+ if (tod->year < 1970) tod->year += 100;
+ tod->month = bcd(rtcin(RTC_MONTH)); /* month */
+ tod->day = bcd(rtcin(RTC_DAY)); /* day */
+ (void) bcd(rtcin(RTC_WDAY)); /* weekday */
+ tod->hour = bcd(rtcin(RTC_HRS)); /* hour */
+ tod->minute = bcd(rtcin(RTC_MIN)); /* minutes */
+ tod->second = bcd(rtcin(RTC_SEC)); /* seconds */
+ tod->ticks = 0;
+
+#ifndef QUICK_READ /* Quick read of the RTC: don't return number of seconds. */
+ sec = ytos(tod->year);
+ sec += mtos(tod->month, (tod->year % 4) == 0);
+ sec += tod->day * SECS_PER_DAY;
+ sec += tod->hour * 60 * 60; /* hour */
+ sec += tod->minute * 60; /* minutes */
+ sec += tod->second; /* seconds */
+#endif /* QUICK_READ */
+
+ return (long int)sec;
+} /* rtc_read */
+
+