+/**
+ * \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;
+ int ret;
+ char **deps;
+ tModule *mod;
+
+ ENTER("pModule", Module);
+
+ deps = Module->Dependencies;
+
+ // Check if the module has been loaded
+ for( mod = gLoadedModules; mod; mod = mod->Next )
+ {
+ if(mod == Module) LEAVE_RET('i', 0);
+ }
+
+ // Add to the "loading" (prevents circular deps)
+ Module->Next = gLoadingModules;
+ gLoadingModules = Module;
+
+ // Scan dependency list
+ for( j = 0; deps && deps[j]; j++ )
+ {
+ // Check if the module is already loaded
+ for( mod = gLoadedModules; mod; mod = mod->Next )
+ {
+ if(strcmp(deps[j], mod->Name) == 0)
+ break;
+ }
+ if( mod ) continue; // Dependency is loaded, check the rest
+
+ // 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 ) {
+ switch(ret)
+ {
+ case MODULE_ERR_MISC:
+ Warning("[MOD ] Unable to load, reason: Miscelanious");
+ break;
+ case MODULE_ERR_NOTNEEDED:
+ Warning("[MOD ] Unable to load, reason: Module not needed (probably hardware not found)");
+ break;
+ case MODULE_ERR_MALLOC:
+ Warning("[MOD ] Unable to load, reason: Error in malloc/realloc/calloc, probably not good");
+ break;
+ default:
+ Warning("[MOD ] Unable to load reason - Unknown code %i", ret);
+ break;
+ }
+ LEAVE_RET('i', ret);
+ return ret;
+ }
+
+ // Remove from loading list
+ gLoadingModules = gLoadingModules->Next;
+
+ // Add to loaded list
+ LOCK( &glModuleSpinlock );
+ Module->Next = gLoadedModules;
+ gLoadedModules = Module;
+ RELEASE( &glModuleSpinlock );
+
+ LEAVE_RET('i', 0);
+}
+
+/**
+ * \brief Initialises builtin modules
+ */