/**
 *  File:
 *    OSRModuleLoading.ycp
 *
 *  Module:
 *    OSRModuleLoading
 *
 *  Summary:
 *    Load and unload kernel modules
 *
 *  Author:
 *    Johannes Buchhold <jbuch@suse.de>
 *
 * $Id: OSRModuleLoading.ycp 15132 2004-03-01 20:29:12Z jsuchome $
 */
{
  module "OSRModuleLoading";

  import "ModuleLoading";

  textdomain "repair";

  /**
   * Contains a list with the name of all kernel modules loaded at the first
   * import of the OSRModuleLoading module.
   */
  list<string> startup_loaded_modules	= [];

  /**
   * Contains a list with the name of all kernel modules loaded with
   * the Load define (OSRModuleLoading::Load(..); .
   */
  list<string> loaded_modules		= [];

  /**
   * The constructor init the startup_loaded_modules list.
   */
  global define void OSRModuleLoading()``{
    startup_loaded_modules = (list<string>)
	maplist (string key, any v, (map<string,any>)SCR::Read(.proc.modules), ``(key));

    y2milestone ("module loaded at start: %1", startup_loaded_modules);
  }

  /**
   * Load a module if not already loaded by linuxrc and
   * saves the name of the loaded modules in the list
   * loaded_modules.
   *
   * @param	string modulename
   * @param	string moduleargs
   * @param	string vendorname
   * @param	string devicename
   * @param	boolean ask_before_loading
   * @param	boolean with_modprobe
   *
   * @return symbol:	`dont	user choose *not* to load module
   *			`ok	module loaded ok
   *			`fail	module loading failed
   */
  global define boolean Load( string modulename, string moduleargs,
			      string vendorname, string devicename,
			      boolean ask_before_loading,
			      boolean with_modprobe ) ``{
      // always look whether the module is already loaded
      map current_modules = $[];
      if (is (SCR::Read(.proc.modules), map))
          current_modules = (map) SCR::Read(.proc.modules);
      if (size (current_modules[modulename]:$[]) > 0)
      {
	    // already loaded
	    return true;
      }
      else {
	    y2milestone ("loading module: %1", modulename);
	    if ( ModuleLoading::Load (modulename, moduleargs, vendorname,
				     devicename, ask_before_loading,
				     with_modprobe ) == `ok )
	    {
		loaded_modules = add( loaded_modules, modulename );
	        return true;
	    }
	    else return false;
      }
  }

  /**
   * Unload one kernel module.
   * @param modname name of the kernel module that should be unloaded
   */
  global define boolean Unload(string modname ) ``{

    if (modname == "") return true;

    if ((integer) WFM::Execute(.local.bash, sformat("/sbin/rmmod %1", modname))
	!= 0 )
    {
        y2warning("Can't remove module %1", modname );
	return false;
    }
    return true;
  }

  /**
   * Unload all loaded kernel modules.
   */
  global define boolean UnloadAll()``{
      integer index = size(loaded_modules );
      boolean error = false;

      // unload all with OSR code loaded modules
      while ( index != 0 && ! error  ) {
	  if( ! Unload( loaded_modules[index - 1]:"" )) error = true;
	  else {
	      index = index - 1;
	  }
      }

      // unload all with other code loaded modules
      list<string> end_loaded_modules = (list<string>)
	maplist (string key, any v, (map<string,any>) SCR::Read(.proc.modules), ``(key));

      list<string> unload_modules	= (list<string>)
	filter (string key, end_loaded_modules,
	    ``( ! contains( startup_loaded_modules, key ))
	);

      foreach (string module_to_unload, unload_modules, ``{
          if ( !Unload (module_to_unload))
            error = true;
      });
      return ! error;
  }

}//EOF
