Kernel/timers - Cleaning up timer code... might have made more mess
authorJohn Hodge <[email protected]>
Mon, 13 Feb 2012 10:18:26 +0000 (18:18 +0800)
committerJohn Hodge <[email protected]>
Mon, 13 Feb 2012 10:18:26 +0000 (18:18 +0800)
- Moved callbacks into a worker thread
- BUG: Possibly some race conditions causing lockups
- Re-enabled preemption :)
- Fixed workqueue not setting ->Next to NULL

15 files changed:
KernelLand/Kernel/arch/x86/errors.c
KernelLand/Kernel/arch/x86/kpanic.c
KernelLand/Kernel/arch/x86/mm_virt.c
KernelLand/Kernel/arch/x86/proc.c
KernelLand/Kernel/debug.c
KernelLand/Kernel/include/acess.h
KernelLand/Kernel/include/timers.h
KernelLand/Kernel/system.c
KernelLand/Kernel/threads.c
KernelLand/Kernel/time.c
KernelLand/Kernel/workqueue.c
KernelLand/Modules/Display/VESA/main.c
KernelLand/Modules/Storage/FDDv2/fdc.c
KernelLand/Modules/USB/Core/hub.c
KernelLand/Modules/USB/UHCI/uhci.c

index d2d2cef..f0f6e2b 100644 (file)
@@ -80,7 +80,6 @@ void ErrorHandler(tRegs *Regs)
        // Page Fault
        if(Regs->int_num == 14)
        {
-               __asm__ __volatile__ ("sti");   // Should be OK, TODO: Test
                __asm__ __volatile__ ("mov %%cr2, %0":"=r"(cr));
                MM_PageFault( cr, Regs->err_code, Regs );
                return ;
index 9300c69..3e2ccac 100644 (file)
@@ -78,6 +78,8 @@ const struct {
 void KernelPanic_SetMode(void)
 {
         int    i;
+
+       __asm__ __volatile__ ("cli");   // Stop the processor!
        
        // This function is called by Panic(), but MM_PageFault and the
        // CPU exception handers also call it, so let's not clear the screen
index bd7b1df..c17b57b 100644 (file)
@@ -171,6 +171,7 @@ void MM_PageFault(tVAddr Addr, Uint ErrorCode, tRegs *Regs)
         && gaPageTable[Addr>>12] & PF_COW )
        {
                tPAddr  paddr;
+               __asm__ __volatile__ ("sti");
                if(MM_GetRefCount( gaPageTable[Addr>>12] & ~0xFFF ) == 1)
                {
                        gaPageTable[Addr>>12] &= ~PF_COW;
@@ -197,6 +198,7 @@ void MM_PageFault(tVAddr Addr, Uint ErrorCode, tRegs *Regs)
 
        // If it was a user, tell the thread handler
        if(ErrorCode & 4) {
+               __asm__ __volatile__ ("sti");
                Log_Warning("MMVirt", "User %s %s memory%s",
                        (ErrorCode&2?"write to":"read from"),
                        (ErrorCode&1?"bad/locked":"non-present"),
index 82a3f40..8d85608 100644 (file)
@@ -35,6 +35,7 @@ typedef struct sCPU
        Uint8   State;  // 0: Unavaliable, 1: Idle, 2: Active
        Uint16  Resvd;
        tThread *Current;
+       tThread *LastTimerThread;       // Used to do preeemption
 }      tCPU;
 
 // === IMPORTS ===
@@ -939,6 +940,7 @@ void Proc_Reschedule(void)
 
        // Update CPU state
        gaCPUs[cpu].Current = nextthread;
+       gaCPUs[cpu].LastTimerThread = NULL;
        gTSSs[cpu].ESP0 = nextthread->KernelStack-4;
        __asm__ __volatile__("mov %0, %%db0\n\t" : : "r"(nextthread) );
 
@@ -976,49 +978,14 @@ void Proc_Reschedule(void)
  */
 void Proc_Scheduler(int CPU)
 {
-#if 0
-       tThread *thread;
-       
-       // If the spinlock is set, let it complete
-       if(IS_LOCKED(&glThreadListLock))        return;
-       
-       // Get current thread
-       thread = gaCPUs[CPU].Current;
-       
-       if( thread )
+       // If two ticks happen within the same task, and it's not an idle task, swap
+       if( gaCPUs[CPU].Current->TID > giNumCPUs && gaCPUs[CPU].Current == gaCPUs[CPU].LastTimerThread )
        {
-               tRegs   *regs;
-               Uint    ebp;
-               // Reduce remaining quantum and continue timeslice if non-zero
-               if( thread->Remaining-- )
-                       return;
-               // Reset quantum for next call
-               thread->Remaining = thread->Quantum;
-               
-               // TODO: Make this more stable somehow
-               __asm__ __volatile__("mov %%ebp, %0" : "=r" (ebp));
-               regs = (tRegs*)(ebp+(2+2)*4);   // EBP,Ret + CPU,CurThread
-               thread->SavedState.UserCS = regs->cs;
-               thread->SavedState.UserEIP = regs->eip;
-               
-               if(thread->bInstrTrace) {
-                       regs->eflags |= 0x100;  // Set TF
-                       Log("%p De-scheduled", thread);
-               }
-               else
-                       regs->eflags &= ~0x100; // Clear TF
+               Proc_Reschedule();
        }
-
-       // TODO: Ack timer?
-       #if USE_MP
-       if( GetCPUNum() )
-               gpMP_LocalAPIC->EOI.Val = 0;
-       else
-       #endif
-               outb(0x20, 0x20);
-       __asm__ __volatile__ ("sti");
-       Proc_Reschedule();
-#endif
+       gaCPUs[CPU].LastTimerThread = gaCPUs[CPU].Current;
+       // Call the timer update code
+       Timer_CallTimers();
 }
 
 // === EXPORTS ===
index 355624d..25ffda1 100644 (file)
@@ -9,7 +9,7 @@
 
 #define        DEBUG_MAX_LINE_LEN      256
 
-#define        LOCK_DEBUG_OUTPUT       1
+#define        LOCK_DEBUG_OUTPUT       0
 
 #define TRACE_TO_KTERM 0
 
index 2cd2cff..0121eb2 100644 (file)
@@ -15,6 +15,8 @@
 #define PACKED __attribute__((packed))
 //! Mark a function as not returning
 #define NORETURN       __attribute__((noreturn))
+//! Mark a function (or variable) as deprecated
+#define DEPRECATED     __attribute__((deprecated))
 //! Mark a parameter as unused
 #define UNUSED(x)      UNUSED_##x __attribute__((unused))
 //! Get the offset of a member in a structure
@@ -182,7 +184,7 @@ extern void Debug_HexDump(const char *Header, const void *Data, Uint Length);
 # define LEAVE_RET0()  return
 #endif
 #if SANITY
-# define ASSERT(expr) do{if(!(expr))Panic("%s: Assertion '"#expr"' failed",(char*)__func__);}while(0)
+# define ASSERT(expr) do{if(!(expr))Panic("%s:%i - %s: Assertion '"#expr"' failed",__FILE__,__LINE__,(char*)__func__);}while(0)
 #else
 # define ASSERT(expr)
 #endif
index 22dd5c6..c43c401 100644 (file)
@@ -25,11 +25,34 @@ typedef void (tTimerCallback)(void *);
  * \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);
+extern tTimer  *Time_CreateTimer(int Delta, tTimerCallback *Callback, void *Argument) DEPRECATED;
+
+/**
+ * \brief Allocate (but don't schedule) a timer object
+ * \param Callback     Function to call (if NULL, EVENT_TIMER is delivered to the current thread)
+ * \param Argument     Argument passed to \a Callback (ignored if \a Callback is NULL)
+ * \return New timer pointer
+ */
+extern tTimer  *Time_AllocateTimer(tTimerCallback *Callback, void *Argument);
+
+/**
+ * \brief Free an allocated timer object
+ * \param Timer        Object pointer returned by Time_AllocateTimer
+ */
+extern void    Time_FreeTimer(tTimer *Timer);
+
+/**
+ * \brief Schedules a timer to fire in \a Delta ms
+ * \param Timer        Timer object returned by Time_AllocateTimer
+ * \param Delta        Time until timer fires (in milliseconds)
+ */
+extern void    Time_ScheduleTimer(tTimer *Timer, int Delta);
+
 /**
  * \brief Removed an active timer
  */
 extern void    Time_RemoveTimer(tTimer *Timer);
+
 /**
  * \brief Wait for a period of milliseconds
  */
index 8fc2a1c..d8eba83 100644 (file)
@@ -12,6 +12,7 @@ extern void   Arch_LoadBootModules(void);
 extern int     Modules_LoadBuiltins(void);
 extern void    Modules_SetBuiltinParams(char *Name, char *ArgString);
 extern void    Debug_SetKTerminal(const char *File);
+extern void    Timer_CallbackThread(void *);
 
 // === PROTOTYPES ===
 void   System_Init(char *Commandline);
@@ -29,6 +30,8 @@ char  *argv[32];
 // === CODE ===
 void System_Init(char *CommandLine)
 {
+       Proc_SpawnWorker(Timer_CallbackThread, NULL);
+
        // Parse Kernel's Command Line
        System_ParseCommandLine(CommandLine);
        
index 956eede..5e60c46 100644 (file)
@@ -926,7 +926,6 @@ tThread *Threads_RemActive(void)
        ret->Next = NULL;
        ret->Remaining = 0;
        
-       giNumActiveThreads --;
        // no need to decrement tickets, scheduler did it for us
        
        #if SCHEDULER_TYPE == SCHED_LOTTERY && DEBUG_TRACE_TICKETS
@@ -936,6 +935,7 @@ tThread *Threads_RemActive(void)
        
        return ret;
        #else
+       giNumActiveThreads --;
        return Proc_GetCurThread();
        #endif
 }
index 2c83fa3..cf3370a 100644 (file)
@@ -4,13 +4,13 @@
  *
  * Timer Code
  */
+#define SANITY 1       // Enable ASSERTs
+#define DEBUG  0
 #include <acess.h>
 #include <timers.h>
 #include <events.h>
 #include <hal_proc.h>  // Proc_GetCurThread
-
-// === CONSTANTS ===
-#define        NUM_TIMERS      8
+#include <workqueue.h>
 
 // === TYPEDEFS ===
 struct sTimer {
@@ -18,82 +18,219 @@ struct sTimer {
        Sint64  FiresAfter;
        void    (*Callback)(void*);
        void    *Argument;
+//     tMutex  Lock;
+       BOOL    bActive;
 };
 
 // === PROTOTYPES ===
+void   Timer_CallbackThread(void *Unused);
 void   Timer_CallTimers(void);
+#if 0
+tTimer *Time_CreateTimer(int Delta, tTimerCallback *Callback, void *Argument);
+void   Time_ScheduleTimer(tTimer *Timer, int Delta);
+void   Time_RemoveTimer(tTimer *Timer);
+tTimer *Time_AllocateTimer(tTimerCallback *Callback, void *Argument);
+#endif
+void   Time_InitTimer(tTimer *Timer, tTimerCallback *Callback, void *Argument);
+#if 0
+void   Time_FreeTimer(tTimer *Timer);
+void   Time_Delay(int Time);
+#endif
 
 // === GLOBALS ===
 volatile Uint64        giTicks = 0;
 volatile Sint64        giTimestamp = 0;
 volatile Uint64        giPartMiliseconds = 0;
-tTimer *gTimers;       // TODO: Replace by a ring-list timer
+tTimer *gTimers;
+tWorkqueue     gTimers_CallbackQueue;
+tShortSpinlock gTimers_ListLock;
 
 // === CODE ===
+void Timer_CallbackThread(void *Unused)
+{
+       Threads_SetName("Timer Callback Thread");
+
+       for(;;)
+       {
+               tTimer *timer = Workqueue_GetWork(&gTimers_CallbackQueue);
+       
+               if( !timer->Callback ) {
+                       LOG("Timer %p doesn't have a callback", timer);
+                       ASSERT( timer->Callback );
+               }
+
+               // Save callback and argument (because once the mutex is released
+               // the timer may no longer be valid)
+               tTimerCallback  *cb = timer->Callback;
+               void    *arg = timer->Argument;
+               
+               LOG("Callback fire %p", timer);
+       
+               // Allow Time_RemoveTimer to be called safely
+               timer->bActive = 0;
+               
+               // Fire callback
+               cb(arg);
+
+               // Mark timer as no longer needed
+       }
+}
+
 /**
  * \fn void Timer_CallTimers()
  */
 void Timer_CallTimers()
 {
+       SHORTLOCK(&gTimers_ListLock);
        while( gTimers && gTimers->FiresAfter < now() )
        {
-               tTimer  *next;
+               // Get timer from list
+               tTimer  *timer = gTimers;
        
-               if( gTimers->Callback )
-                       gTimers->Callback(gTimers->Argument);
-               else
-                       Threads_PostEvent(gTimers->Argument, THREAD_EVENT_TIMER);
-               
-               next = gTimers->Next;
-               free(gTimers);
-               gTimers = next;
+               ASSERT( gTimers != gTimers->Next );     
+               gTimers = gTimers->Next;
+       
+               // Perform event
+               if( timer->Callback ) {
+                       LOG("Callback schedule %p", timer);
+                       // PROBLEM! Possibly causes rescheudle during interrupt
+//                     Mutex_Acquire( &timer->Lock );  // Released once the callback fires
+                       Workqueue_AddWork(&gTimers_CallbackQueue, timer);
+               }
+               else {
+                       LOG("Event fire %p", timer);
+                       ASSERT( timer->Argument );
+                       Threads_PostEvent(timer->Argument, THREAD_EVENT_TIMER);
+                       timer->bActive = 0;
+               }
        }
+       SHORTREL(&gTimers_ListLock);
 }
 
 /**
- * \brief Schedule an action
+ * \brief Schedule an action (Legacy)
  */
 tTimer *Time_CreateTimer(int Delta, tTimerCallback *Callback, void *Argument)
 {
-       tTimer  *ret;
+       tTimer  *ret = malloc(sizeof(tTimer));
+       if( !ret )      return NULL;
+       Time_InitTimer(ret, Callback, Argument);
+       Time_ScheduleTimer(ret, Delta);
+       return ret;
+}
+
+/**
+ * \brief Schedule a timer to fire
+ */
+void Time_ScheduleTimer(tTimer *Timer, int Delta)
+{
        tTimer  *t, *p;
-       
-       if(Callback == NULL)
-               Argument = Proc_GetCurThread();
 
-       // TODO: Use a pool instead?
-       ret = malloc(sizeof(tTimer));
+       // Sanity checks
+       if( !Timer )    return ;
+
+       if( Timer->bActive )    return;
+       
+       // Set time
+       Timer->FiresAfter = now() + Delta;
        
-       ret->Callback = Callback;
-       ret->FiresAfter = now() + Delta;
-       ret->Argument = Argument;
+       // Debug
+       LOG("%p added timer %p - %i ms (ts=%lli)",
+               __builtin_return_address(0), Timer, Delta, Timer->FiresAfter);
 
        // Add into list (sorted)
+       SHORTLOCK(&gTimers_ListLock);
+//     Mutex_Release( &Timer->Lock );  // Prevent deadlocks
        for( p = (tTimer*)&gTimers, t = gTimers; t; p = t, t = t->Next )
        {
-               if( t->FiresAfter > ret->FiresAfter )   break;
+               ASSERT( p != t ); ASSERT( CheckMem(t, sizeof(tTimer)) );
+               if( t == Timer )
+               {
+                       LOG("Double schedule - increasing delta");
+                       SHORTREL(&gTimers_ListLock);
+                       return ;
+               }
+               LOG(" t = %p ts:%lli", t, t->FiresAfter);
+               if( t->FiresAfter > Timer->FiresAfter ) break;
        }
-       ret->Next = t;
-       p->Next = ret;
-
-       return ret;
+       Timer->Next = t;
+       p->Next = Timer;
+       Timer->bActive = 1;
+       LOG(" %p %p %p", p, Timer, t);
+       SHORTREL(&gTimers_ListLock);
 }
 
 /**
- * \brief Delete a timer
+ * \brief Delete a timer from the running list
  */
 void Time_RemoveTimer(tTimer *Timer)
 {
        tTimer  *t, *p;
+
+       if( !Timer )    return ;
+       
+       SHORTLOCK(&gTimers_ListLock);
        for( p = (tTimer*)&gTimers, t = gTimers; t; p = t, t = t->Next )
        {
+               ASSERT( p != t ); ASSERT( CheckMem(t, sizeof(tTimer)) );
                if( t == Timer )
                {
                        p->Next = t->Next;
-                       free(Timer);
-                       return ;
+                       break ;
                }
        }
+       SHORTREL(&gTimers_ListLock);
+
+       if( t ) {
+               Timer->bActive = 0;
+               LOG("%p removed %p", __builtin_return_address(0), Timer);
+       }
+       else
+               LOG("%p tried to remove %p (already complete)", __builtin_return_address(0), Timer);
+}
+
+/**
+ * \brief Allocate a timer object, but don't schedule it
+ */
+tTimer *Time_AllocateTimer(tTimerCallback *Callback, void *Argument)
+{
+       tTimer  *ret = malloc(sizeof(tTimer));
+       if( !ret )      return NULL;
+       Time_InitTimer(ret, Callback, Argument);
+       return ret;
+}
+
+/**
+ * \brief Initialise a timer
+ * \note Mostly an internal function
+ */
+void Time_InitTimer(tTimer *Timer, tTimerCallback *Callback, void *Argument)
+{
+       if(Callback == NULL)
+               Argument = Proc_GetCurThread();
+       Timer->FiresAfter = 0;
+       Timer->Callback = Callback;
+       Timer->Argument = Argument;
+//     memset( &Timer->Lock, 0, sizeof(Timer->Lock) );
+       Timer->bActive = 0;
+}
+
+/**
+ * \brief Free an allocated timer
+ */
+void Time_FreeTimer(tTimer *Timer)
+{
+       if( !Timer )    return ;
+       Time_RemoveTimer( Timer );      // Just in case
+
+       // Ensures that we don't free until the timer callback has started
+       while( Timer->bActive ) Threads_Yield();
+       // Release won't be needed, as nothing should be waiting on it
+//     Mutex_Acquire( &Timer->Lock );
+       
+       // Free timer
+       free(Timer);
+       LOG("%p deallocated %p", __builtin_return_address(0), Timer);
 }
 
 /**
@@ -102,13 +239,18 @@ void Time_RemoveTimer(tTimer *Timer)
  */
 void Time_Delay(int Delay)
 {
-//     tTime   dest = now() + Delay;
-//     while(dest > now())     Threads_Yield();
-       Time_CreateTimer(Delay, NULL, NULL);
+       tTimer  *t;
+       t = Time_AllocateTimer(NULL, NULL);
+       Time_ScheduleTimer(t, Delay);
        Threads_WaitEvents(THREAD_EVENT_TIMER);
+       Time_FreeTimer(t);
 }
 
 // === EXPORTS ===
-EXPORT(Time_CreateTimer);
+//EXPORT(Time_CreateTimer);
+EXPORT(Time_ScheduleTimer);
 EXPORT(Time_RemoveTimer);
+EXPORT(Time_AllocateTimer);
+//EXPORT(Time_InitTimer);
+EXPORT(Time_FreeTimer);
 EXPORT(Time_Delay);
index b1a6385..9e2c6f6 100644 (file)
@@ -9,6 +9,8 @@
 #include <workqueue.h>
 #include <threads_int.h>
 
+#define QUEUENEXT(ptr) (*( (void**)(ptr) + Queue->NextOffset/sizeof(void*) ))
+
 // === CODE ===
 void Workqueue_Init(tWorkqueue *Queue, const char *Name, size_t NextOfset)
 {
@@ -27,7 +29,7 @@ void *Workqueue_GetWork(tWorkqueue *Queue)
                if(Queue->Head)
                {
                        void *ret = Queue->Head;
-                       Queue->Head = *( (void**)ret + Queue->NextOffset/sizeof(void*) );
+                       Queue->Head = QUEUENEXT( ret );
                        if(Queue->Tail == ret)
                                Queue->Tail = NULL;
                        SHORTREL(&Queue->Protector);    
@@ -58,11 +60,12 @@ void Workqueue_AddWork(tWorkqueue *Queue, void *Ptr)
        SHORTLOCK(&Queue->Protector);
 
        if( Queue->Tail )
-               *( (void**)Queue->Tail + Queue->NextOffset/sizeof(void*) ) = Ptr;
+               QUEUENEXT(Queue->Tail) = Ptr;
        else
                Queue->Head = Ptr;
        Queue->Tail = Ptr;
-       
+       QUEUENEXT(Ptr) = NULL;
+
        if( Queue->Sleeper )
        {       
                if( Queue->Sleeper->Status != THREAD_STAT_ACTIVE )
index a85d313..c57d57d 100644 (file)
@@ -12,6 +12,7 @@
 #include <modules.h>\r
 #include <vm8086.h>\r
 #include "common.h"\r
+#include <timers.h>\r
 \r
 // === CONSTANTS ===\r
 #define        FLAG_LFB        0x1\r
@@ -59,7 +60,9 @@ char  *gpVesa_Framebuffer = (void*)VESA_DEFAULT_FRAMEBUFFER;
 // --- Cursor Control ---\r
  int   giVesaCursorX = -1;\r
  int   giVesaCursorY = -1;\r
- int   giVesaCursorTimer = -1; // Invalid timer\r
+#if BLINKING_CURSOR\r
+tTimer *gpVesaCursorTimer;\r
+#endif\r
  int   gbVesa_CursorVisible = 0;\r
 // --- 2D Video Stream Handlers ---\r
 tDrvUtil_Video_BufInfo gVesa_BufInfo;\r
@@ -112,10 +115,15 @@ int Vesa_Install(char **Arguments)
 \r
 //     VM8086_Deallocate( info );\r
        \r
+       #if BLINKING_CURSOR\r
+       // Create blink timer\r
+       gpVesaCursorTimer = Time_AllocateTimer( Vesa_FlipCursor, NULL );\r
+       #endif\r
+\r
        // Install Device\r
        giVesaDriverId = DevFS_AddDevice( &gVesa_DriverStruct );\r
        if(giVesaDriverId == -1)        return MODULE_ERR_MISC;\r
-       \r
+\r
        return MODULE_ERR_OK;\r
 }\r
 \r
@@ -246,8 +254,7 @@ int Vesa_Int_SetMode(int mode)
        \r
        Vesa_int_FillModeList();\r
 \r
-       Time_RemoveTimer(giVesaCursorTimer);\r
-       giVesaCursorTimer = -1;\r
+       Time_RemoveTimer(gpVesaCursorTimer);\r
        \r
        Mutex_Acquire( &glVesa_Lock );\r
        \r
@@ -365,9 +372,8 @@ void Vesa_int_HideCursor(void)
 {\r
        DrvUtil_Video_RemoveCursor( &gVesa_BufInfo );\r
        #if BLINKING_CURSOR\r
-       if(giVesaCursorTimer != -1) {\r
-               Time_RemoveTimer(giVesaCursorTimer);\r
-               giVesaCursorTimer = -1;\r
+       if(gpVesaCursorTimer) {\r
+               Time_RemoveTimer(gpVesaCursorTimer);\r
        }\r
        #endif\r
 }\r
@@ -383,7 +389,7 @@ void Vesa_int_ShowCursor(void)
                        giVesaCursorY*giVT_CharHeight\r
                        );\r
                #if BLINKING_CURSOR\r
-               giVesaCursorTimer = Time_CreateTimer(VESA_CURSOR_PERIOD, Vesa_FlipCursor, NULL);\r
+               Time_ScheduleTimer( gpVesaCursorTimer, VESA_CURSOR_PERIOD );\r
                #endif\r
        }\r
        else\r
@@ -412,7 +418,7 @@ void Vesa_FlipCursor(void *Arg)
        gbVesa_CursorVisible = !gbVesa_CursorVisible;\r
                \r
        #if BLINKING_CURSOR\r
-       giVesaCursorTimer = Time_CreateTimer(VESA_CURSOR_PERIOD, Vesa_FlipCursor, Arg);\r
+       Time_ScheduleTimer( gpVesaCursorTimer, VESA_CURSOR_PERIOD );\r
        #endif\r
 }\r
 \r
index e86b31c..7b9042b 100644 (file)
@@ -84,10 +84,17 @@ int FDD_SetupIO(void)
        // Install IRQ6 Handler
        IRQ_AddHandler(6, FDD_int_IRQHandler, NULL);
        
+       for( int i = 0; i < 2; i ++ )
+       {
+               if( !gaFDD_Disks[i].bValid )    continue ;
+               
+               gaFDD_Disks[i].Timer = Time_AllocateTimer(FDD_int_StopMotorCallback, (void*)(tVAddr)i);
+       }
+       
        // Reset controller
        FDD_int_Reset(0);
        // TODO: All controllers
-       
+
        return 0;
 }
 
@@ -401,7 +408,6 @@ int FDD_int_StartMotor(int Disk)
        
        // Clear the motor off timer    
        Time_RemoveTimer(gaFDD_Disks[Disk].Timer);
-       gaFDD_Disks[Disk].Timer = NULL;
 
        // Check if the motor is already on
        if( gaFDD_Disks[Disk].MotorState == MOTOR_ATSPEED )
@@ -425,10 +431,8 @@ int FDD_int_StopMotor(int Disk)
 {
        if( gaFDD_Disks[Disk].MotorState != MOTOR_ATSPEED )
                return 0;
-       if( gaFDD_Disks[Disk].Timer != NULL )
-               return 0;
 
-       gaFDD_Disks[Disk].Timer = Time_CreateTimer(MOTOR_OFF_DELAY, FDD_int_StopMotorCallback, (void*)(tVAddr)Disk);
+       Time_ScheduleTimer(gaFDD_Disks[Disk].Timer, MOTOR_OFF_DELAY);
 
        return 0;
 }
@@ -443,7 +447,6 @@ void FDD_int_StopMotorCallback(void *Ptr)
         int    _disk;
        Uint16  base = FDD_int_GetBase(Disk, &_disk);
 
-       gaFDD_Disks[Disk].Timer = NULL;
        gaFDD_Disks[Disk].MotorState = MOTOR_OFF;
        
        outb(base + FDC_DOR, inb(base+FDC_DOR) & ~(1 << (_disk + 4)));
index 849e8a3..eccaa3f 100644 (file)
@@ -7,6 +7,7 @@
  */
 #define DEBUG  1
 #include <usb_hub.h>
+#include <timers.h>
 
 #define MAX_PORTS      32      // Not actually a max, but used for DeviceRemovable
 
index 3b2c659..8477c8f 100644 (file)
@@ -12,6 +12,7 @@
 #include <modules.h>
 #include <usb_host.h>
 #include "uhci.h"
+#include <timers.h>
 
 // === CONSTANTS ===
 #define        MAX_CONTROLLERS 4

UCC git Repository :: git.ucc.asn.au