Various changes, most of them involving the FAT and Ext2 Drivers, adding write support
[tpg/acess2.git] / Kernel / modules.c
index e4f49b2..5b5a906 100644 (file)
@@ -2,6 +2,7 @@
  * Acess2
  * - Module Loader
  */
+#define DEBUG  0
 #include <acess.h>
 #include <modules.h>
 
@@ -28,94 +29,136 @@ extern void        gKernelModulesEnd;
  int   giModuleSpinlock = 0;
 tModule        *gLoadedModules = NULL;
 tModuleLoader  *gModule_Loaders = NULL;
+tModule        *gLoadingModules = NULL;
 
 // === CODE ===
-int Modules_LoadBuiltins()
+/**
+ * \brief Initialises a module
+ * \param Module       Pointer to the module header
+ * \return Zero on success, eModuleErrors or -1 on error
+ * \retval -1  Returned if a dependency fails, or a circular dependency
+ *              exists.
+ * \retval 0   Returned on success
+ * \retval >0  Error code form the module's initialisation function
+ */
+int Module_int_Initialise(tModule *Module)
 {
-        int    i, j, k;
-        int    numToInit = 0;
-       Uint8   *baIsLoaded;
+        int    i, j;
+        int    ret;
        char    **deps;
+       tModule *mod;
        
-       giNumBuiltinModules = (Uint)&gKernelModulesEnd - (Uint)&gKernelModules;
-       giNumBuiltinModules /= sizeof(tModule);
+       ENTER("pModule", Module);
        
-       baIsLoaded = calloc( giNumBuiltinModules, sizeof(*baIsLoaded) );
+       deps = Module->Dependencies;
        
-       // Pass 1 - Are the dependencies compiled in?
-       for( i = 0; i < giNumBuiltinModules; i++ )
+       // Check if the module has been loaded
+       for( mod = gLoadedModules; mod; mod = mod->Next )
        {
-               deps = gKernelModules[i].Dependencies;
-               if(deps)
-               {
-                       for( j = 0; deps[j]; j++ )
-                       {
-                               for( k = 0; k < giNumBuiltinModules; k++ ) {
-                                       if(strcmp(deps[j], gKernelModules[k].Name) == 0)
-                                               break;
-                               }
-                               if(k == giNumBuiltinModules) {
-                                       Warning("Unable to find dependency '%s' for '%s' in kernel",
-                                               deps[j], gKernelModules[i].Name);
-                                       
-                                       baIsLoaded[i] = -1;     // Don't Load
-                                       break;
-                               }
-                       }
-               }
-               numToInit ++;
+               if(mod == Module)       LEAVE_RET('i', 0);
        }
        
-       // Pass 2 - Intialise
-       while(numToInit)
+       // Add to the "loading" (prevents circular deps)
+       Module->Next = gLoadingModules;
+       gLoadingModules = Module;
+       
+       // Scan dependency list
+       for( j = 0; deps && deps[j]; j++ )
        {
-               for( i = 0; i < giNumBuiltinModules; i++ )
+               // Check if the module is already loaded
+               for( mod = gLoadedModules; mod; mod = mod->Next )
                {
-                       if( baIsLoaded[i] )     continue;       // Ignore already loaded modules
+                       if(strcmp(deps[j], mod->Name) == 0)
+                               break;
+               }
+               if( mod )       continue;       // Dependency is loaded, check the rest
                
-                       deps = gKernelModules[i].Dependencies;
-                       
-                       if( deps )
-                       {
-                               for( j = 0; deps[j]; j++ )
-                               {
-                                       for( k = 0; k < giNumBuiltinModules; k++ ) {
-                                               if(strcmp(deps[j], gKernelModules[k].Name) == 0)
-                                                       break;
-                                       }
-                                       // `k` is assumed to be less than `giNumBuiltinModules`
-                                       
-                                       // If a dependency failed, skip and mark as failed
-                                       if( baIsLoaded[k] == -1 ) {
-                                               baIsLoaded[i] = -1;
-                                               numToInit --;
-                                               break;
-                                       }
-                                       // If a dependency is not intialised, skip
-                                       if( !baIsLoaded[k] )    break;
-                               }
-                               // Check if we broke out
-                               if( deps[j] )   continue;
-                       }
-                       
-                       // All Dependencies OK? Initialise
-                       StartupPrint(gKernelModules[i].Name);
-                       Log("Initialising %p '%s' v%i.%i...",
-                               &gKernelModules[i],
-                               gKernelModules[i].Name,
-                               gKernelModules[i].Version>>8, gKernelModules[i].Version & 0xFF
-                               );
-                       if( gKernelModules[i].Init(NULL) == 0 ) {
-                               Log("Loading Failed, all modules that depend on this will also fail");
-                               baIsLoaded[i] = -1;
-                       }
-                       // Mark as loaded
-                       else
-                               baIsLoaded[i] = 1;
-                       numToInit --;
+               // Ok, check if it's loading
+               for( mod = gLoadingModules->Next; mod; mod = mod->Next )
+               {
+                       if(strcmp(deps[j], mod->Name) == 0)
+                               break;
+               }
+               if( mod ) {
+                       Warning("[MOD  ] Circular dependency detected");
+                       LEAVE_RET('i', -1);
+               }
+               
+               // So, if it's not loaded, we better load it then
+               for( i = 0; i < giNumBuiltinModules; i ++ )
+               {
+                       if( strcmp(deps[j], gKernelModules[i].Name) == 0 )
+                               break;
+               }
+               if( i == giNumBuiltinModules ) {
+                       Warning("[MOD  ] Dependency '%s' for module '%s' failed");
+                       return -1;
+               }
+               
+               // Dependency is not loaded, so load it
+               ret = Module_int_Initialise( &gKernelModules[i] );
+               if( ret )
+               {
+                       // The only "ok" error is NOTNEEDED
+                       if(ret != MODULE_ERR_NOTNEEDED)
+                               LEAVE_RET('i', -1);
                }
        }
        
+       // All Dependencies OK? Initialise
+       StartupPrint(Module->Name);
+       Log("[MOD  ] Initialising %p '%s' v%i.%i...",
+               Module, Module->Name,
+               Module->Version >> 8, Module->Version & 0xFF
+               );
+       
+       ret = Module->Init(NULL);
+       if( ret != MODULE_ERR_OK ) {
+               Log("[MOD  ] Loading Failed, all modules that depend on this will also fail");
+               switch(ret)
+               {
+               case MODULE_ERR_MISC:
+                       Log("[MOD  ] Reason: Miscelanious");
+                       break;
+               case MODULE_ERR_NOTNEEDED:
+                       Log("[MOD  ] Reason: Module not needed (probably hardware not found)");
+                       break;
+               case MODULE_ERR_MALLOC:
+                       Log("[MOD  ] Reason: Error in malloc/realloc/calloc, probably not good");
+                       break;
+               default:
+                       Log("[MOD  ] Reason - Unknown code %i", ret);
+                       break;
+               }
+               LEAVE_RET('i', ret);
+       }
+       
+       // Remove from loading list
+       gLoadingModules = gLoadingModules->Next;
+       
+       // Add to loaded list
+       Module->Next = gLoadedModules;
+       gLoadedModules = Module;
+       
+       LEAVE_RET('i', 0);
+}
+
+/**
+ * \brief Initialises builtin modules
+ */
+int Modules_LoadBuiltins()
+{
+        int    i;
+       
+       // Count modules
+       giNumBuiltinModules = (Uint)&gKernelModulesEnd - (Uint)&gKernelModules;
+       giNumBuiltinModules /= sizeof(tModule);
+       
+       for( i = 0; i < giNumBuiltinModules; i++ )
+       {
+               Module_int_Initialise( &gKernelModules[i] );
+       }
+       
        return 0;
 }
 

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