/**
* \brief Create a timestamp from a time
*/
-extern Sint64 timestamp(int sec, int mins, int hrs, int day, int month, int year);
+extern tTime timestamp(int sec, int mins, int hrs, int day, int month, int year);
/**
- * \brief Gets the current timestamp (miliseconds since Midnight 1st January 1970)
- */
-extern Sint64 now(void);
-/**
- * \brief Timer callback function
- */
-typedef void (tTimerCallback)(void *);
-/**
- * \brief Creates a one-shot timer
- * \param Delta Period of the timer
- * \param Callback Function to call each time
- * \param Argument Argument to pass to the callback
- */
-extern int Time_CreateTimer(int Delta, tTimerCallback *Callback, void *Argument);
-/**
- * \brief Removed an active timer
+ * \brief Extract the date/time from a timestamp
*/
-extern void Time_RemoveTimer(int ID);
+extern void format_date(tTime TS, int *year, int *month, int *day, int *hrs, int *mins, int *sec, int *ms);
/**
- * \brief Wait for a period of milliseconds
+ * \brief Gets the current timestamp (miliseconds since Midnight 1st January 1970)
*/
-extern void Time_Delay(int Delay);
+extern Sint64 now(void);
/**
* \}
*/
#define THREAD_EVENT_VFS 0x00000001
#define THREAD_EVENT_IPCMSG 0x00000002
#define THREAD_EVENT_SIGNAL 0x00000004
+#define THREAD_EVENT_TIMER 0x00000008
// === FUNCTIONS ===
extern void Threads_PostEvent(tThread *Thread, Uint32 EventMask);
--- /dev/null
+/*
+ * Acess2 Kernel
+ * - By John Hodge (thePowersGang)
+ *
+ * timers.h
+ * - Kernel timers
+ */
+#ifndef _KERNEL_TIMERS_H_
+#define _KERNEL_TIMERS_H_
+/**
+ * \file timers.h
+ * \brief Kernel timers
+ */
+
+typedef struct sTimer tTimer;
+
+/**
+ * \brief Timer callback function
+ */
+typedef void (tTimerCallback)(void *);
+
+/**
+ * \brief Creates a one-shot timer
+ * \param Delta Period of the timer
+ * \param Callback Function to call each time
+ * \param Argument Argument to pass to the callback
+ */
+extern tTimer *Time_CreateTimer(int Delta, tTimerCallback *Callback, void *Argument);
+/**
+ * \brief Removed an active timer
+ */
+extern void Time_RemoveTimer(tTimer *Timer);
+/**
+ * \brief Wait for a period of milliseconds
+ */
+extern void Time_Delay(int Delay);
+
+#endif
+
int WriteUTF8(Uint8 *str, Uint32 Val);
int DivUp(int num, int dem);
Sint64 timestamp(int sec, int mins, int hrs, int day, int month, int year);
-#endif
void format_date(tTime TS, int *year, int *month, int *day, int *hrs, int *mins, int *sec, int *ms);
-#if 0
int rand(void);
int CheckString(char *String);
* Timer Code
*/
#include <acess.h>
+#include <timers.h>
+#include <events.h>
+#include <hal_proc.h> // Proc_GetCurThread
// === CONSTANTS ===
#define NUM_TIMERS 8
// === TYPEDEFS ===
-typedef struct sTimer {
- int FiresAfter;
+struct sTimer {
+ tTimer *Next;
+ Sint64 FiresAfter;
void (*Callback)(void*);
void *Argument;
-} tTimer;
+};
// === PROTOTYPES ===
void Timer_CallTimers(void);
volatile Uint64 giTicks = 0;
volatile Sint64 giTimestamp = 0;
volatile Uint64 giPartMiliseconds = 0;
-tTimer gTimers[NUM_TIMERS]; // TODO: Replace by a ring-list timer
+tTimer *gTimers; // TODO: Replace by a ring-list timer
// === CODE ===
/**
*/
void Timer_CallTimers()
{
- int i;
- void (*callback)(void *);
- void *arg;
-
- for(i = 0; i < NUM_TIMERS; i ++)
+ while( gTimers && gTimers->FiresAfter < now() )
{
- if(gTimers[i].Callback == NULL) continue;
- if(giTimestamp < gTimers[i].FiresAfter) continue;
- callback = gTimers[i].Callback; arg = gTimers[i].Argument;
- gTimers[i].Callback = NULL;
- callback(arg);
+ tTimer *next;
+
+ if( gTimers->Callback )
+ gTimers->Callback(gTimers->Argument);
+ else
+ Threads_PostEvent(gTimers->Argument, THREAD_EVENT_TIMER);
+
+ next = gTimers->Next;
+ free(gTimers);
+ gTimers = next;
}
}
/**
- * \fn int Time_CreateTimer(int Delta, tTimerCallback *Callback, void *Argument)
+ * \brief Schedule an action
*/
-int Time_CreateTimer(int Delta, tTimerCallback *Callback, void *Argument)
+tTimer *Time_CreateTimer(int Delta, tTimerCallback *Callback, void *Argument)
{
- int ret;
+ tTimer *ret;
+ tTimer *t, *p;
- if(Callback == NULL) return -1;
+ if(Callback == NULL)
+ Argument = Proc_GetCurThread();
+
+ // TODO: Use a pool instead?
+ ret = malloc(sizeof(tTimer));
- for(ret = 0;
- ret < NUM_TIMERS;
- ret++)
+ ret->Callback = Callback;
+ ret->FiresAfter = now() + Delta;
+ ret->Argument = Argument;
+
+ // Add into list (sorted)
+ for( p = (tTimer*)&gTimers, t = gTimers; t; p = t, t = t->Next )
{
- if(gTimers[ret].Callback != NULL) continue;
- gTimers[ret].Callback = Callback;
- gTimers[ret].FiresAfter = giTimestamp + Delta;
- gTimers[ret].Argument = Argument;
- //Log("Callback = %p", Callback);
- //Log("Timer %i fires at %lli", ret, gTimers[ret].FiresAfter);
- return ret;
+ if( t->FiresAfter > ret->FiresAfter ) break;
}
- return -1;
+ ret->Next = t;
+ p->Next = ret;
+
+ return ret;
}
/**
- * \fn void Time_RemoveTimer(int ID)
+ * \brief Delete a timer
*/
-void Time_RemoveTimer(int ID)
+void Time_RemoveTimer(tTimer *Timer)
{
- if(ID < 0 || ID >= NUM_TIMERS) return;
- gTimers[ID].Callback = NULL;
+ tTimer *t, *p;
+ for( p = (tTimer*)&gTimers, t = gTimers; t; p = t, t = t->Next )
+ {
+ if( t == Timer )
+ {
+ p->Next = t->Next;
+ free(Timer);
+ return ;
+ }
+ }
}
/**
*/
void Time_Delay(int Delay)
{
- tTime dest = now() + Delay;
- while(dest > now()) Threads_Yield();
+// tTime dest = now() + Delay;
+// while(dest > now()) Threads_Yield();
+ Time_CreateTimer(Delay, NULL, NULL);
+ Threads_WaitEvents(THREAD_EVENT_TIMER);
}
// === EXPORTS ===
// === PROTOTYPES ===
#if 0
int VFS_MkDir(const char *Path);
-#endif
int VFS_MkNod(const char *Path, Uint Flags);
-// int VFS_Symlink(const char *Name, const char *Link);
+ int VFS_Symlink(const char *Name, const char *Link);
+#endif
// === CODE ===
/**
#define _FDC_COMMON_H_
#include <mutex.h>
+#include <timers.h>
// === CONSTANTS ===
#define MAX_DISKS 8 // 4 per controller, 2 controllers
int bValid;
int bInserted;
int MotorState;
- int Timer;
+ tTimer *Timer;
tMutex Mutex;
#include <acess.h>
#include "common.h"
#include <dma.h>
+#include <timers.h>
// === CONSTANTS ===
#define MOTOR_ON_DELAY 500
// Clear the motor off timer
Time_RemoveTimer(gaFDD_Disks[Disk].Timer);
- gaFDD_Disks[Disk].Timer = -1;
+ gaFDD_Disks[Disk].Timer = NULL;
// Check if the motor is already on
if( gaFDD_Disks[Disk].MotorState == MOTOR_ATSPEED )
{
if( gaFDD_Disks[Disk].MotorState != MOTOR_ATSPEED )
return 0;
- if( gaFDD_Disks[Disk].Timer != -1 )
+ if( gaFDD_Disks[Disk].Timer != NULL )
return 0;
gaFDD_Disks[Disk].Timer = Time_CreateTimer(MOTOR_OFF_DELAY, FDD_int_StopMotorCallback, (void*)(tVAddr)Disk);
int _disk;
Uint16 base = FDD_int_GetBase(Disk, &_disk);
- gaFDD_Disks[Disk].Timer = -1;
+ gaFDD_Disks[Disk].Timer = NULL;
gaFDD_Disks[Disk].MotorState = MOTOR_OFF;
outb(base + FDC_DOR, inb(base+FDC_DOR) & ~(1 << (_disk + 4)));
// === GLOBALS ===
MODULE_DEFINE(0, VERSION, USB_Core, USB_Install, NULL, NULL);
+tVFS_NodeType gUSB_RootNodeType = {
+ .ReadDir = USB_ReadDir,
+ .FindDir = USB_FindDir,
+ .IOCtl = USB_IOCtl
+};
tDevFS_Driver gUSB_DrvInfo = {
NULL, "usb", {
.NumACLs = 1,
.ACLs = &gVFS_ACL_EveryoneRX,
.Flags = VFS_FFLAG_DIRECTORY,
- .ReadDir = USB_ReadDir,
- .FindDir = USB_FindDir,
- .IOCtl = USB_IOCtl
+ .Type = &gUSB_RootNodeType
}
};
tUSBHost *gUSB_Hosts = NULL;