Ejemplo n.º 1
0
DB_SHOW_COMMAND(rtc, rtc)
{
	printf("%02x/%02x/%02x %02x:%02x:%02x, A = %02x, B = %02x, C = %02x\n",
		rtcin(RTC_YEAR), rtcin(RTC_MONTH), rtcin(RTC_DAY),
		rtcin(RTC_HRS), rtcin(RTC_MIN), rtcin(RTC_SEC),
		rtcin(RTC_STATUSA), rtcin(RTC_STATUSB), rtcin(RTC_INTR));
}
Ejemplo n.º 2
0
void
atrtc_restore(void)
{

	/* Restore all of the RTC's "status" (actually, control) registers. */
	rtcin(RTC_STATUSA);	/* dummy to get rtc_reg set */
	writertc(RTC_STATUSB, RTCSB_24HR);
	writertc(RTC_STATUSA, rtc_statusa);
	writertc(RTC_STATUSB, rtc_statusb);
	rtcin(RTC_INTR);
}
Ejemplo n.º 3
0
static int
atrtc_settime(device_t dev __unused, struct timespec *ts)
{
	struct clocktime ct;

	clock_ts_to_ct(ts, &ct);

	/* Disable RTC updates and interrupts. */
	writertc(RTC_STATUSB, RTCSB_HALT | RTCSB_24HR);

	writertc(RTC_SEC, bin2bcd(ct.sec)); 		/* Write back Seconds */
	writertc(RTC_MIN, bin2bcd(ct.min)); 		/* Write back Minutes */
	writertc(RTC_HRS, bin2bcd(ct.hour));		/* Write back Hours   */

	writertc(RTC_WDAY, ct.dow + 1);			/* Write back Weekday */
	writertc(RTC_DAY, bin2bcd(ct.day));		/* Write back Day */
	writertc(RTC_MONTH, bin2bcd(ct.mon));           /* Write back Month   */
	writertc(RTC_YEAR, bin2bcd(ct.year % 100));	/* Write back Year    */
#ifdef USE_RTC_CENTURY
	writertc(RTC_CENTURY, bin2bcd(ct.year / 100));	/* ... and Century    */
#endif

	/* Reenable RTC updates and interrupts. */
	writertc(RTC_STATUSB, rtc_statusb);
	rtcin(RTC_INTR);
	return (0);
}
Ejemplo n.º 4
0
static void
atrtc_disable_intr(void)
{

	rtc_statusb &= ~RTCSB_PINTR;
	writertc(RTC_STATUSB, rtc_statusb);
	rtcin(RTC_INTR);
}
Ejemplo n.º 5
0
void
atrtc_enable_intr(void)
{

	rtc_statusb |= RTCSB_PINTR;
	writertc(RTC_STATUSB, rtc_statusb);
	rtcin(RTC_INTR);
}
Ejemplo n.º 6
0
static uint64_t
malta_cpu_freq(void)
{
	uint64_t platform_counter_freq = 0;

#if defined(TICK_USE_YAMON_FREQ)
	/*
	 * If we are running on a board which uses YAMON firmware,
	 * then query CPU pipeline clock from the syscon object.
	 * If unsuccessful, use hard-coded default.
	 */
	platform_counter_freq = yamon_getcpufreq();

#elif defined(TICK_USE_MALTA_RTC)
	/*
	 * If we are running on a board with the MC146818 RTC,
	 * use it to determine CPU pipeline clock frequency.
	 */
	u_int64_t counterval[2];

	/* Set RTC to binary mode. */
	writertc(RTC_STATUSB, (rtcin(RTC_STATUSB) | RTCSB_BCD));

	/* Busy-wait for falling edge of RTC update. */
	while (((rtcin(RTC_STATUSA) & RTCSA_TUP) == 0))
		;
	while (((rtcin(RTC_STATUSA)& RTCSA_TUP) != 0))
		;
	counterval[0] = mips_rd_count();

	/* Busy-wait for falling edge of RTC update. */
	while (((rtcin(RTC_STATUSA) & RTCSA_TUP) == 0))
		;
	while (((rtcin(RTC_STATUSA)& RTCSA_TUP) != 0))
		;
	counterval[1] = mips_rd_count();

	platform_counter_freq = counterval[1] - counterval[0];
#endif

	if (platform_counter_freq == 0)
		platform_counter_freq = MIPS_DEFAULT_HZ;

	return (platform_counter_freq);
}
Ejemplo n.º 7
0
static int
atrtc_gettime(device_t dev, struct timespec *ts)
{
	struct clocktime ct;
	int s;

	/* Look if we have a RTC present and the time is valid */
	if (!(rtcin(RTC_STATUSD) & RTCSD_PWR)) {
		device_printf(dev, "WARNING: Battery failure indication\n");
		return (EINVAL);
	}

	/* wait for time update to complete */
	/* If RTCSA_TUP is zero, we have at least 244us before next update */
	s = splhigh();
	while (rtcin(RTC_STATUSA) & RTCSA_TUP) {
		splx(s);
		s = splhigh();
	}
	ct.nsec = 0;
	ct.sec = readrtc(RTC_SEC);
	ct.min = readrtc(RTC_MIN);
	ct.hour = readrtc(RTC_HRS);
	ct.day = readrtc(RTC_DAY);
	ct.dow = readrtc(RTC_WDAY) - 1;
	ct.mon = readrtc(RTC_MONTH);
	ct.year = readrtc(RTC_YEAR);
#ifdef USE_RTC_CENTURY
	ct.year += readrtc(RTC_CENTURY) * 100;
#else
	ct.year += 2000;
#endif
	/* Set dow = -1 because some clocks don't set it correctly. */
	ct.dow = -1;
	return (clock_ct_to_ts(&ct, ts));
}
Ejemplo n.º 8
0
Archivo: rtc.c Proyecto: epicsdeb/rtems
/*-------------------------------------------------------------------------+
|         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)
{
  uint8_t          sa;
  uint32_t         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 */
Ejemplo n.º 9
0
int
atrtc_setup_clock(void)
{
	int diag;

	if (atrtcclock_disable)
		return (0);

	diag = rtcin(RTC_DIAG);
	if (diag != 0) {
		printf("RTC BIOS diagnostic error %b\n",
		    diag, RTCDG_BITS);
		return (0);
	}

	stathz = RTC_NOPROFRATE;
	profhz = RTC_PROFRATE;

	return (1);
}
Ejemplo n.º 10
0
/*
 * This routine receives statistical clock interrupts from the RTC.
 * As explained above, these occur at 128 interrupts per second.
 * When profiling, we receive interrupts at a rate of 1024 Hz.
 *
 * This does not actually add as much overhead as it sounds, because
 * when the statistical clock is active, the hardclock driver no longer
 * needs to keep (inaccurate) statistics on its own.  This decouples
 * statistics gathering from scheduling interrupts.
 *
 * The RTC chip requires that we read status register C (RTC_INTR)
 * to acknowledge an interrupt, before it will generate the next one.
 * Under high interrupt load, rtcintr() can be indefinitely delayed and
 * the clock can tick immediately after the read from RTC_INTR.  In this
 * case, the mc146818A interrupt signal will not drop for long enough
 * to register with the 8259 PIC.  If an interrupt is missed, the stat
 * clock will halt, considerably degrading system performance.  This is
 * why we use 'while' rather than a more straightforward 'if' below.
 * Stat clock ticks can still be lost, causing minor loss of accuracy
 * in the statistics, but the stat clock will no longer stop.
 */
static int
rtcintr(struct trapframe *frame)
{
	int flag = 0;

	while (rtcin(RTC_INTR) & RTCIR_PERIOD) {
		flag = 1;
		if (--pscnt <= 0) {
			pscnt = psdiv;
#ifdef SMP
			if (smp_started)
				ipi_all_but_self(IPI_STATCLOCK);
#endif
			statclockintr(frame);
		} else {
#ifdef SMP
			if (smp_started)
				ipi_all_but_self(IPI_PROFCLOCK);
#endif
			profclockintr(frame);
		}
	}
	return(flag ? FILTER_HANDLED : FILTER_STRAY);
}
Ejemplo n.º 11
0
static __inline int
readrtc(int port)
{
	return(bcd2bin(rtcin(port)));
}
Ejemplo n.º 12
0
// the kernel bootstrap routine
PUBLIC
void 
kernel_thread_t::bootstrap()
{
  // Initializations done -- helping_lock_t can now use helping lock
  helping_lock_t::threading_system_active = true;

  //
  // set up my own thread control block
  //
  state_change (0, Thread_running);

  sched()->set_prio (config::kernel_prio);
  sched()->set_mcp (config::kernel_mcp);
  sched()->set_timeslice (config::default_time_slice);
  sched()->set_ticks_left (config::default_time_slice);

  present_next = present_prev = this;
  ready_next = ready_prev = this;

  //
  // set up class variables
  //
  for (int i = 0; i < 256; i++) prio_next[i] = prio_first[i] = 0;
  prio_next[config::kernel_prio] = prio_first[config::kernel_prio] = this;
  prio_highest = config::kernel_prio;

  timeslice_ticks_left = config::default_time_slice;
  timeslice_owner = this;

  // 
  // install our slow trap handler
  //
  nested_trap_handler = base_trap_handler;
  base_trap_handler = thread_handle_trap;

  // 
  // initialize FPU
  // 
  set_ts();			// FPU ops -> exception

  //
  // initialize interrupts
  //
  irq_t::lookup(2)->alloc(this, false); // reserve cascade irq
  irq_t::lookup(8)->alloc(this, false); // reserve timer irq

  pic_enable_irq(2);		// allow cascaded irqs

  // set up serial console
  if (! strstr(kmem::cmdline(), " -I-") 
      && !strstr(kmem::cmdline(), " -irqcom"))
    {
      int com_port = console::serial_com_port;
      int com_irq = com_port & 1 ? 4 : 3;

      irq_t::lookup(com_irq)->alloc(this, false); // the remote-gdb interrupt
      pic_enable_irq(com_irq);

      // for some reason, we have to re-enable the com irq here
      if (config::serial_esc)
	com_cons_enable_receive_interrupt();
    }

  // initialize the profiling timer
  bool user_irq0 = strstr(kmem::cmdline(), "irq0");

  if (config::profiling)
    {
      if (user_irq0)
	{
	  kdb_ke("options `-profile' and `-irq0' don't mix "
		  "-- disabling `-irq0'");
	}
      irq_t::lookup(0)->alloc(this, false);

      profile::init();

      if (strstr(kmem::cmdline(), " -profstart"))
	profile::start();
    }
  else if (! user_irq0)
    irq_t::lookup(0)->alloc(this, false); // reserve irq0 even though
                                          // we don't use it

  // 
  // set up timer interrupt (~ 1ms)
  //
  while (rtcin(RTC_STATUSA) & RTCSA_TUP) ; // wait till RTC ready
  rtcout(RTC_STATUSA, RTCSA_DIVIDER | RTCSA_1024); // 1024 Hz
  // set up 1024 Hz interrupt
  rtcout(RTC_STATUSB, rtcin(RTC_STATUSB) | RTCSB_PINTR | RTCSB_SQWE); 
  rtcin(RTC_INTR);		// reset

  pic_enable_irq(8);		// allow this interrupt

  //
  // set PCE-Flag in CR4 to enable read of performace measurement counters
  // in usermode. PMC were introduced in Pentium MMX and PPro processors.
  //
  #ifndef CPUF_MMX
  #define CPUF_MMX 0x00800000
  #endif
  if(strncmp(cpu.vendor_id, "GenuineIntel", 12) == 0
     && (cpu.family == CPU_FAMILY_PENTIUM_PRO ||
	 cpu.feature_flags & CPUF_MMX))
    {
      set_cr4(get_cr4() | CR4_PCE);
    }
  
  //
  // allow the boot task to create more tasks
  //
  for (unsigned i = config::boot_taskno + 1; 
       i < space_index_t::max_space_number;
       i++)
    {
      check(space_index_t(i).set_chief(space_index(), 
				       space_index_t(config::boot_taskno)));
    }

  //
  // create sigma0
  //

  // sigma0's chief is the boot task
  space_index_t(config::sigma0_id.id.task).
    set_chief(space_index(), space_index_t(config::sigma0_id.id.chief));

  sigma0 = new space_t(config::sigma0_id.id.task);
  sigma0_thread = 
    new (&config::sigma0_id) thread_t (sigma0, &config::sigma0_id, 
				       config::sigma0_prio, 
				       config::sigma0_mcp);
  
  // push address of kernel info page to sigma0's stack
  vm_offset_t esp = kmem::info()->sigma0_esp;

  * reinterpret_cast<vm_offset_t*>(kmem::phys_to_virt(--esp)) 
    = kmem::virt_to_phys(kmem::info());

  sigma0_thread->initialize(kmem::info()->sigma0_eip, esp,
			    0, 0);

  //
  // create the boot task
  //

  // the boot task's chief is the boot task itself
  space_index_t(config::boot_id.id.task).
    set_chief(space_index(), space_index_t(config::boot_id.id.chief));

  space_t *boot = new space_t(config::boot_id.id.task);
  thread_t *boot_thread
    = new (&config::boot_id) thread_t (boot, &config::boot_id, 
				       config::boot_prio, 
				       config::boot_mcp);

  boot_thread->initialize(0x200000,
			  0x200000,
			  sigma0_thread, 0);

  //
  // the idle loop
  //
  for (;;) 
    {
      // printf("I");

      sti();			// enable irqs, otherwise idling is fatal

      if (config::hlt_works_ok)
	asm("hlt");		// stop the CPU, waiting for an int

      while (ready_next != this) // are there any other threads ready?
	schedule();
    }
}
void
platform_start(__register_t a0, __register_t a1,  __register_t a2, 
    __register_t a3)
{
	vm_offset_t kernend;
	uint64_t platform_counter_freq;
	int argc = a0;
	char **argv = (char **)a1;
	char **envp = (char **)a2;
	unsigned int memsize = a3;
	int i;

	/* clear the BSS and SBSS segments */
	kernend = round_page((vm_offset_t)&end);
	memset(&edata, 0, kernend - (vm_offset_t)(&edata));

	cninit();
	printf("entry: platform_start()\n");

	bootverbose = 1;
	if (bootverbose) {
		printf("cmd line: ");
		for (i = 0; i < argc; i++)
			printf("%s ", argv[i]);
		printf("\n");

		printf("envp:\n");
		for (i = 0; envp[i]; i += 2)
			printf("\t%s = %s\n", envp[i], envp[i+1]);

		printf("memsize = %08x\n", memsize);
	}

	realmem = btoc(memsize);
	mips_init();

	do {
#if defined(TICK_USE_YAMON_FREQ)
		/*
		 * If we are running on a board which uses YAMON firmware,
		 * then query CPU pipeline clock from the syscon object.
		 * If unsuccessful, use hard-coded default.
		 */
		platform_counter_freq = yamon_getcpufreq();
		if (platform_counter_freq == 0)
			platform_counter_freq = MIPS_DEFAULT_HZ;

#elif defined(TICK_USE_MALTA_RTC)
		/*
		 * If we are running on a board with the MC146818 RTC,
		 * use it to determine CPU pipeline clock frequency.
		 */
		u_int64_t counterval[2];

		/* Set RTC to binary mode. */
		writertc(RTC_STATUSB, (rtcin(RTC_STATUSB) | RTCSB_BCD));

		/* Busy-wait for falling edge of RTC update. */
		while (((rtcin(RTC_STATUSA) & RTCSA_TUP) == 0))
			;
		while (((rtcin(RTC_STATUSA)& RTCSA_TUP) != 0))
			;
		counterval[0] = mips_rd_count();

		/* Busy-wait for falling edge of RTC update. */
		while (((rtcin(RTC_STATUSA) & RTCSA_TUP) == 0))
			;
		while (((rtcin(RTC_STATUSA)& RTCSA_TUP) != 0))
			;
		counterval[1] = mips_rd_count();

		platform_counter_freq = counterval[1] - counterval[0];
#endif
	} while(0);

	mips_timer_init_params(platform_counter_freq, 0);
}