Subversion Repositories shark

Rev

Rev 619 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/* Project:     OSLib
 * Description: The OS Construction Kit
 * Date:                1.6.2000
 * Idea by:             Luca Abeni & Gerardo Lamastra
 *
 * OSLib is an SO project aimed at developing a common, easy-to-use
 * low-level infrastructure for developing OS kernels and Embedded
 * Applications; it partially derives from the HARTIK project but it
 * currently is independently developed.
 *
 * OSLib is distributed under GPL License, and some of its code has
 * been derived from the Linux kernel source; also some important
 * ideas come from studying the DJGPP go32 extender.
 *
 * We acknowledge the Linux Community, Free Software Foundation,
 * D.J. Delorie and all the other developers who believe in the
 * freedom of software and ideas.
 *
 * For legalese, check out the included GPL license.
 */


/*      Time management code: ll_getttime()     */

/* Added Advanced Timer Code
 *
 * Date:   8.4.2003
 * Author: Giacomo Guidi <giacomo@gandalf.sssup.it>
 *
 */


#include <ll/i386/pit.h>
#include <ll/i386/stdlib.h>
#include <ll/i386/error.h>
#include <ll/i386/mem.h>
#include <ll/i386/advtimer.h>
#include <ll/sys/ll/ll-data.h>
#include <ll/sys/ll/ll-func.h>
#include <ll/sys/ll/time.h>

/* These are for the EXECT and TICK modes */
extern DWORD ticksize;          /* From init.c  */
extern struct timespec actTime; /* From event.c */
extern WORD  pit_time_const;    /* From init.c  */
extern DWORD  timermode;        /* From init.c  */

/* These two are for the NEW algorithm */
extern WORD lastTime;                /* From event.c */
extern struct pitspec globalCounter; /* From event.c */
extern BYTE frc;
extern int activeEvent;
extern unsigned char use_tsc;

FILE(Time);

TIME ll_gettime(int mode, struct timespec *tsres)
{
 
        if (!use_tsc) {

                DWORD res, tc;
                BYTE isr;
                struct timespec tmp;

#if 1
                if (activeEvent) {
                        if (tsres != NULL) {
                                PITSPEC2TIMESPEC(&globalCounter, tsres);
                        } else {
                                struct timespec tmp;

                                PITSPEC2TIMESPEC(&globalCounter, &tmp);
                                return TIMESPEC2USEC(&tmp);
                        }
                        return TIMESPEC2USEC(tsres);
                }
#endif
       
                if (mode == TIME_PTICK) {
                        if (timermode != LL_PERIODIC) {
                                return 0;
                        }
                        res = TIMESPEC2USEC(&actTime);
                        if (tsres != NULL) {
                                memcpy(tsres, &actTime, sizeof(struct timespec));
                        }
                        return res;
                }

                if (mode == TIME_NEW) {
                        WORD tmp;
         
                        tmp = pit_read(frc);
                        ADDPITSPEC((WORD)(lastTime - tmp), &globalCounter);
                        lastTime = tmp;
                        if (tsres != NULL) {
                                PITSPEC2TIMESPEC(&globalCounter, tsres);
                        }
                        return (PITSPEC2USEC(&globalCounter));
                }

                if (mode == TIME_EXACT) {
                        if (timermode == LL_PERIODIC) {
                                memcpy(&tmp, &actTime, sizeof(struct timespec));
                                /* How much time has elapsed
                                 * from the last Tick Boundary?
                                 */

                                tc = pit_read(0);
                                if (tc > pit_time_const) {
                                        error("LL Time Panic!!!\n");
                                        ll_abort(1);
                                }
                                res = pit_time_const - tc;
                                res *= ticksize;
                                res /= pit_time_const;

                                /* Detect tick boundary and adjust the time... */
                                outp(0x20, 0x0A);
                                isr = inp(0x20);
                                if ((isr & 1) && res < ((8*ticksize)/10)){
                                        /*
                                        res += ticksize;
                                        ADDNANO2TIMESPEC(ticksize * 1000, &tmp);
                                        */

                                        res = ticksize;
                                }

                                /* Sum the Tick time... */
                                ADDNANO2TIMESPEC(res * 1000, &tmp);
                                res += TIMESPEC2USEC(&actTime);

                                if (tsres != NULL) {
                                        memcpy(tsres, &tmp, sizeof(struct timespec));
                                }
                                return res;
                        } else {
                                return 0;
                        }
                }
                return 0;
        } else {
                if (tsres != NULL) {
                        ll_read_timespec(tsres);
                        return TIMESPEC2USEC(tsres);
                } else {
                        struct timespec tmp;
       
                        ll_read_timespec(&tmp);
                        return TIMESPEC2USEC(&tmp);
                }
        }
}