!C99Shell v. 1.0 pre-release build #13!

Software: Apache/2.0.54 (Unix) mod_perl/1.99_09 Perl/v5.8.0 mod_ssl/2.0.54 OpenSSL/0.9.7l DAV/2 FrontPage/5.0.2.2635 PHP/4.4.0 mod_gzip/2.0.26.1a 

uname -a: Linux snow.he.net 4.4.276-v2-mono-1 #1 SMP Wed Jul 21 11:21:17 PDT 2021 i686 

uid=99(nobody) gid=98(nobody) groups=98(nobody) 

Safe-mode: OFF (not secure)

/usr/src/linux-2.4.18-xfs-1.1/arch/mips64/sgi-ip22/   drwxr-xr-x
Free 318.32 GB of 458.09 GB (69.49%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Feedback    Self remove    Logout    


Viewing file:     ip22-timer.c (6.91 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/*
 * indy_timer.c: Setting up the clock on the INDY 8254 controller.
 *
 * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
 * Copytight (C) 1997, 1998 Ralf Baechle (ralf@gnu.org)
 */
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/param.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/timex.h>
#include <linux/kernel_stat.h>

#include <asm/bootinfo.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/ptrace.h>
#include <asm/system.h>
#include <asm/sgi/sgi.h>
#include <asm/sgi/sgihpc.h>
#include <asm/sgi/sgint23.h>
#include <asm/sgialib.h>


/* Because of a bug in the i8254 timer we need to use the onchip r4k
 * counter as our system wide timer interrupt running at 100HZ.
 */
static unsigned long r4k_offset; /* Amount to increment compare reg each time */
static unsigned long r4k_cur;    /* What counter should be at next timer irq */

extern rwlock_t xtime_lock;

static inline void ack_r4ktimer(unsigned long newval)
{
    write_32bit_cp0_register(CP0_COMPARE, newval);
}

static int set_rtc_mmss(unsigned long nowtime)
{
    struct indy_clock *clock = (struct indy_clock *)INDY_CLOCK_REGS;
    int retval = 0;
    int real_seconds, real_minutes, clock_minutes;

#define FROB_FROM_CLOCK(x) (((x) & 0xf) | ((((x) & 0xf0) >> 4) * 10));
#define FROB_TO_CLOCK(x)  ((((((x) & 0xff) / 10)<<4) | (((x) & 0xff) % 10)) & 0xff)

    clock->cmd &= ~(0x80);
    clock_minutes = clock->min;
    clock->cmd |= (0x80);

    clock_minutes = FROB_FROM_CLOCK(clock_minutes);
    real_seconds = nowtime % 60;
    real_minutes = nowtime / 60;

    if(((abs(real_minutes - clock_minutes) + 15)/30) & 1)
        real_minutes += 30; /* correct for half hour time zone */

    real_minutes %= 60;
    if(abs(real_minutes - clock_minutes) < 30) {
        /* Force clock oscillator to be on. */
        clock->month &= ~(0x80);

        /* Write real_seconds and real_minutes into the Dallas. */
        clock->cmd &= ~(0x80);
        clock->sec = real_seconds;
        clock->min = real_minutes;
        clock->cmd |= (0x80);
    } else
        return -1;

#undef FROB_FROM_CLOCK
#undef FROB_TO_CLOCK

    return retval;
}

static long last_rtc_update;
unsigned long missed_heart_beats;

void indy_timer_interrupt(struct pt_regs *regs)
{
    unsigned long count;
    int irq = 7;

    write_lock(&xtime_lock);
    /* Ack timer and compute new compare. */
    count = read_32bit_cp0_register(CP0_COUNT);
    /* This has races.  */
    if ((count - r4k_cur) >= r4k_offset) {
        /* If this happens to often we'll need to compensate.  */
        missed_heart_beats++;
        r4k_cur = count + r4k_offset;
    }
        else
            r4k_cur += r4k_offset;
    ack_r4ktimer(r4k_cur);
    kstat.irqs[0][irq]++;
    do_timer(regs);

    /* We update the Dallas time of day approx. every 11 minutes,
     * because of how the numbers work out we need to make
     * absolutely sure we do this update within 500ms before the
     * next second starts, thus the following code.
     */
    if ((time_status & STA_UNSYNC) == 0 &&
        xtime.tv_sec > last_rtc_update + 660 &&
        xtime.tv_usec >= 500000 - (tick >> 1) &&
        xtime.tv_usec <= 500000 + (tick >> 1)) {
        if (set_rtc_mmss(xtime.tv_sec) == 0)
            last_rtc_update = xtime.tv_sec;
        else
            /* do it again in 60s  */
            last_rtc_update = xtime.tv_sec - 600;
    }
    write_unlock(&xtime_lock);
}

static unsigned long dosample(volatile unsigned char *tcwp,
                              volatile unsigned char *tc2p)
{
    unsigned long ct0, ct1;
    unsigned char msb, lsb;

    /* Start the counter. */
    *tcwp = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CALL | SGINT_TCWORD_MRGEN);
    *tc2p = (SGINT_TCSAMP_COUNTER & 0xff);
    *tc2p = (SGINT_TCSAMP_COUNTER >> 8);

    /* Get initial counter invariant */
    ct0 = read_32bit_cp0_register(CP0_COUNT);

    /* Latch and spin until top byte of counter2 is zero */
    do {
        *tcwp = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CLAT);
        lsb = *tc2p;
        msb = *tc2p;
        ct1 = read_32bit_cp0_register(CP0_COUNT);
    } while(msb);

    /* Stop the counter. */
    *tcwp = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CALL | SGINT_TCWORD_MSWST);

    /* Return the difference, this is how far the r4k counter increments
     * for every one HZ.
     */
    return ct1 - ct0;
}

static unsigned long __init get_indy_time(void)
{
    struct indy_clock *clock = (struct indy_clock *)INDY_CLOCK_REGS;
    unsigned int year, mon, day, hour, min, sec;

    /* Freeze it. */
    clock->cmd &= ~(0x80);

    /* Read regs. */
    sec = clock->sec;
    min = clock->min;
    hour = (clock->hr & 0x3f);
    day = (clock->date & 0x3f);
    mon = (clock->month & 0x1f);
    year = clock->year;

    /* Unfreeze clock. */
    clock->cmd |= 0x80;

    /* Frob the bits. */
#define FROB1(x)  (((x) & 0xf) + ((((x) & 0xf0) >> 4) * 10));
#define FROB2(x)  (((x) & 0xf) + (((((x) & 0xf0) >> 4) & 0x3) * 10));

    /* XXX Should really check that secs register is the same
     * XXX as when we first read it and if not go back and
     * XXX read the regs above again.
     */
    sec = FROB1(sec); min = FROB1(min); day = FROB1(day);
    mon = FROB1(mon); year = FROB1(year);
    hour = FROB2(hour);

#undef FROB1
#undef FROB2

    /* Wheee... */
    if(year < 45)
        year += 30;
    if ((year += 1940) < 1970)
        year += 100;

    return mktime(year, mon, day, hour, min, sec);
}

#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)

void __init indy_timer_init(void)
{
    struct sgi_ioc_timers *p;
    volatile unsigned char *tcwp, *tc2p;

    /* Figure out the r4k offset, the algorithm is very simple and works
     * in _all_ cases as long as the 8254 counter register itself works ok
     * (as an interrupt driving timer it does not because of bug, this is
     * why we are using the onchip r4k counter/compare register to serve
     * this purpose, but for r4k_offset calculation it will work ok for us).
     * There are other very complicated ways of performing this calculation
     * but this one works just fine so I am not going to futz around. ;-)
     */
    p = ioc_timers;
    tcwp = &p->tcword;
    tc2p = &p->tcnt2;

    printk("calculating r4koff... ");
    dosample(tcwp, tc2p);            /* First sample. */
    dosample(tcwp, tc2p);            /* Eat one.    */
    r4k_offset = dosample(tcwp, tc2p);    /* Second sample. */

    printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset);

    r4k_cur = (read_32bit_cp0_register(CP0_COUNT) + r4k_offset);
    write_32bit_cp0_register(CP0_COMPARE, r4k_cur);
    set_cp0_status(ST0_IM, ALLINTS);
    sti();

    write_lock_irq(&xtime_lock);
    xtime.tv_sec = get_indy_time();        /* Read time from RTC. */
    xtime.tv_usec = 0;
    write_unlock_irq(&xtime_lock);
}

void indy_8254timer_irq(void)
{
    int cpu = smp_processor_id();
    int irq = 4;

    irq_enter(cpu, irq);
    kstat.irqs[0][irq]++;
    panic("indy_8254timer_irq: Whoops, should not have gotten this IRQ\n");
    irq_exit(cpu, irq);
}

void do_gettimeofday(struct timeval *tv)
{
    unsigned long flags;

    read_lock_irqsave(&xtime_lock, flags);
    *tv = xtime;
    read_unlock_irqrestore(&xtime_lock, flags);
}

void do_settimeofday(struct timeval *tv)
{
    write_lock_irq(&xtime_lock);
    xtime = *tv;
    time_adjust = 0;        /* stop active adjtime() */
    time_status |= STA_UNSYNC;
    time_maxerror = NTP_PHASE_LIMIT;
    time_esterror = NTP_PHASE_LIMIT;
    write_unlock_irq(&xtime_lock);
}

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ Read-Only ]

:: Make Dir ::
 
[ Read-Only ]
:: Make File ::
 
[ Read-Only ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 1.0 pre-release build #13 powered by Captain Crunch Security Team | http://ccteam.ru | Generation time: 0.0049 ]--