1
0
uboot-1.1.4-kirkwood/drivers/sk98lin/sktimer.c

241 lines
5.3 KiB
C
Raw Permalink Normal View History

2024-01-07 23:57:24 +01:00
/******************************************************************************
*
* Name: sktimer.c
2024-01-09 13:41:15 +01:00
* Project: Gigabit Ethernet Adapters, Event Scheduler Module
* Version: $Revision: 2.2 $
* Date: $Date: 2004/05/28 13:44:39 $
2024-01-07 23:57:24 +01:00
* Purpose: High level timer functions.
*
******************************************************************************/
/******************************************************************************
*
2024-01-09 13:41:15 +01:00
* (C)Copyright 1998-2002 SysKonnect GmbH.
* (C)Copyright 2002-2004 Marvell.
2024-01-07 23:57:24 +01:00
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The information in this file is provided "AS IS" without warranty.
*
******************************************************************************/
#include <config.h>
2024-01-09 13:41:15 +01:00
2024-01-07 23:57:24 +01:00
#ifdef CONFIG_SK98
/*
2024-01-09 13:41:15 +01:00
* Event queue and dispatcher
*/
#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
2024-01-07 23:57:24 +01:00
static const char SysKonnectFileId[] =
2024-01-09 13:41:15 +01:00
"@(#) $Id: sktimer.c,v 2.2 2004/05/28 13:44:39 rschmidt Exp $ (C) Marvell.";
#endif
2024-01-07 23:57:24 +01:00
#include "h/skdrv1st.h" /* Driver Specific Definitions */
#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */
#ifdef __C2MAN__
/*
Event queue management.
General Description:
*/
intro()
{}
#endif
/* Forward declaration */
static void timer_done(SK_AC *pAC,SK_IOC Ioc,int Restart);
/*
* Inits the software timer
*
* needs to be called during Init level 1.
*/
void SkTimerInit(
SK_AC *pAC, /* Adapters context */
SK_IOC Ioc, /* IoContext */
2024-01-09 13:41:15 +01:00
int Level) /* Init Level */
2024-01-07 23:57:24 +01:00
{
switch (Level) {
case SK_INIT_DATA:
2024-01-09 13:41:15 +01:00
pAC->Tim.StQueue = 0;
2024-01-07 23:57:24 +01:00
break;
case SK_INIT_IO:
2024-01-09 13:41:15 +01:00
SkHwtInit(pAC, Ioc);
2024-01-07 23:57:24 +01:00
SkTimerDone(pAC, Ioc);
break;
default:
break;
}
}
/*
* Stops a high level timer
* - If a timer is not in the queue the function returns normally, too.
*/
void SkTimerStop(
SK_AC *pAC, /* Adapters context */
SK_IOC Ioc, /* IoContext */
SK_TIMER *pTimer) /* Timer Pointer to be started */
{
2024-01-09 13:41:15 +01:00
SK_TIMER **ppTimPrev;
SK_TIMER *pTm;
/* remove timer from queue */
pTimer->TmActive = SK_FALSE;
2024-01-07 23:57:24 +01:00
if (pAC->Tim.StQueue == pTimer && !pTimer->TmNext) {
2024-01-09 13:41:15 +01:00
SkHwtStop(pAC, Ioc);
2024-01-07 23:57:24 +01:00
}
2024-01-09 13:41:15 +01:00
for (ppTimPrev = &pAC->Tim.StQueue; (pTm = *ppTimPrev);
2024-01-07 23:57:24 +01:00
ppTimPrev = &pTm->TmNext ) {
2024-01-09 13:41:15 +01:00
2024-01-07 23:57:24 +01:00
if (pTm == pTimer) {
/*
* Timer found in queue
2024-01-09 13:41:15 +01:00
* - dequeue it
2024-01-07 23:57:24 +01:00
* - correct delta of the next timer
*/
2024-01-09 13:41:15 +01:00
*ppTimPrev = pTm->TmNext;
2024-01-07 23:57:24 +01:00
if (pTm->TmNext) {
/* correct delta of next timer in queue */
2024-01-09 13:41:15 +01:00
pTm->TmNext->TmDelta += pTm->TmDelta;
2024-01-07 23:57:24 +01:00
}
2024-01-09 13:41:15 +01:00
return;
2024-01-07 23:57:24 +01:00
}
}
}
/*
* Start a high level software timer
*/
void SkTimerStart(
SK_AC *pAC, /* Adapters context */
SK_IOC Ioc, /* IoContext */
SK_TIMER *pTimer, /* Timer Pointer to be started */
2024-01-09 13:41:15 +01:00
SK_U32 Time, /* Time Value (in microsec.) */
2024-01-07 23:57:24 +01:00
SK_U32 Class, /* Event Class for this timer */
SK_U32 Event, /* Event Value for this timer */
SK_EVPARA Para) /* Event Parameter for this timer */
{
2024-01-09 13:41:15 +01:00
SK_TIMER **ppTimPrev;
SK_TIMER *pTm;
SK_U32 Delta;
2024-01-07 23:57:24 +01:00
2024-01-09 13:41:15 +01:00
SkTimerStop(pAC, Ioc, pTimer);
2024-01-07 23:57:24 +01:00
2024-01-09 13:41:15 +01:00
pTimer->TmClass = Class;
pTimer->TmEvent = Event;
pTimer->TmPara = Para;
pTimer->TmActive = SK_TRUE;
2024-01-07 23:57:24 +01:00
if (!pAC->Tim.StQueue) {
2024-01-09 13:41:15 +01:00
/* first Timer to be started */
pAC->Tim.StQueue = pTimer;
pTimer->TmNext = 0;
pTimer->TmDelta = Time;
SkHwtStart(pAC, Ioc, Time);
return;
2024-01-07 23:57:24 +01:00
}
2024-01-09 13:41:15 +01:00
/* timer correction */
timer_done(pAC, Ioc, 0);
2024-01-07 23:57:24 +01:00
2024-01-09 13:41:15 +01:00
/* find position in queue */
Delta = 0;
for (ppTimPrev = &pAC->Tim.StQueue; (pTm = *ppTimPrev);
2024-01-07 23:57:24 +01:00
ppTimPrev = &pTm->TmNext ) {
2024-01-09 13:41:15 +01:00
2024-01-07 23:57:24 +01:00
if (Delta + pTm->TmDelta > Time) {
2024-01-09 13:41:15 +01:00
/* the timer needs to be inserted here */
break;
2024-01-07 23:57:24 +01:00
}
2024-01-09 13:41:15 +01:00
Delta += pTm->TmDelta;
2024-01-07 23:57:24 +01:00
}
/* insert in queue */
2024-01-09 13:41:15 +01:00
*ppTimPrev = pTimer;
pTimer->TmNext = pTm;
pTimer->TmDelta = Time - Delta;
2024-01-07 23:57:24 +01:00
if (pTm) {
2024-01-09 13:41:15 +01:00
/* there is a next timer: correct its Delta value */
pTm->TmDelta -= pTimer->TmDelta;
2024-01-07 23:57:24 +01:00
}
2024-01-09 13:41:15 +01:00
/* restart with first */
SkHwtStart(pAC, Ioc, pAC->Tim.StQueue->TmDelta);
2024-01-07 23:57:24 +01:00
}
void SkTimerDone(
SK_AC *pAC, /* Adapters context */
SK_IOC Ioc) /* IoContext */
{
2024-01-09 13:41:15 +01:00
timer_done(pAC, Ioc, 1);
2024-01-07 23:57:24 +01:00
}
static void timer_done(
SK_AC *pAC, /* Adapters context */
SK_IOC Ioc, /* IoContext */
2024-01-09 13:41:15 +01:00
int Restart) /* Do we need to restart the Hardware timer ? */
2024-01-07 23:57:24 +01:00
{
2024-01-09 13:41:15 +01:00
SK_U32 Delta;
SK_TIMER *pTm;
SK_TIMER *pTComp; /* Timer completed now now */
SK_TIMER **ppLast; /* Next field of Last timer to be deq */
int Done = 0;
Delta = SkHwtRead(pAC, Ioc);
ppLast = &pAC->Tim.StQueue;
pTm = pAC->Tim.StQueue;
2024-01-07 23:57:24 +01:00
while (pTm && !Done) {
if (Delta >= pTm->TmDelta) {
/* Timer ran out */
2024-01-09 13:41:15 +01:00
pTm->TmActive = SK_FALSE;
Delta -= pTm->TmDelta;
ppLast = &pTm->TmNext;
pTm = pTm->TmNext;
}
else {
2024-01-07 23:57:24 +01:00
/* We found the first timer that did not run out */
2024-01-09 13:41:15 +01:00
pTm->TmDelta -= Delta;
Delta = 0;
Done = 1;
2024-01-07 23:57:24 +01:00
}
}
2024-01-09 13:41:15 +01:00
*ppLast = 0;
2024-01-07 23:57:24 +01:00
/*
* pTm points to the first Timer that did not run out.
* StQueue points to the first Timer that run out.
*/
2024-01-09 13:41:15 +01:00
for (pTComp = pAC->Tim.StQueue; pTComp; pTComp = pTComp->TmNext) {
SkEventQueue(pAC,pTComp->TmClass, pTComp->TmEvent, pTComp->TmPara);
2024-01-07 23:57:24 +01:00
}
/* Set head of timer queue to the first timer that did not run out */
2024-01-09 13:41:15 +01:00
pAC->Tim.StQueue = pTm;
2024-01-07 23:57:24 +01:00
if (Restart && pAC->Tim.StQueue) {
/* Restart HW timer */
2024-01-09 13:41:15 +01:00
SkHwtStart(pAC, Ioc, pAC->Tim.StQueue->TmDelta);
2024-01-07 23:57:24 +01:00
}
}
/* End of file */
2024-01-09 13:41:15 +01:00
#endif